using Explorer.Application; using Explorer.Domain; using Explorer.Domain.Abstractions; namespace Explorer.Application.Tests; public class UiPreferencesStoreTests { [Fact] public void Parse_reads_theme_and_independent_group_flags() { var prefs = UiPreferencesStore.Parse( [ "theme=Light", "group-network=true", "group-cloud=false", "index-archives=true", "auto-clear-queue=true", "seven-zip=C:\\Program Files\\7-Zip\\7z.exe" ]); Assert.Equal("Light", prefs.Theme); Assert.True(prefs.GroupNetworkPlaces); Assert.False(prefs.GroupCloudPlaces); Assert.True(prefs.IndexArchiveContents); Assert.True(prefs.AutoClearQueueWhenDone); Assert.Equal(@"C:\Program Files\7-Zip\7z.exe", prefs.SevenZipPath); Assert.Null(prefs.GitPath); Assert.Null(prefs.FfmpegPath); } [Fact] public void Parse_reads_organize_destinations() { var prefs = UiPreferencesStore.Parse(["organize-installers=D:\\Software", "organize-pictures=D:\\Pictures"]); Assert.Equal(@"D:\Software", prefs.OrganizeInstallers); Assert.Equal(@"D:\Pictures", prefs.OrganizePictures); Assert.Null(prefs.OrganizeArchives); } [Fact] public void Parse_reads_git_path() { var prefs = UiPreferencesStore.Parse(["git=C:\\Program Files\\Git\\cmd\\git.exe"]); Assert.Equal(@"C:\Program Files\Git\cmd\git.exe", prefs.GitPath); } [Fact] public void Parse_reads_ffmpeg_path() { var prefs = UiPreferencesStore.Parse(["ffmpeg=C:\\Tools\\ffmpeg.exe"]); Assert.Equal(@"C:\Tools\ffmpeg.exe", prefs.FfmpegPath); } [Fact] public void Parse_reads_host_and_removable_index_flags() { var prefs = UiPreferencesStore.Parse( [ "auto-index-removable=true", "background-host-at-logon=true" ]); Assert.True(prefs.AutoIndexRemovable); Assert.True(prefs.BackgroundHostAtLogon); } [Fact] public void Parse_defaults_missing_keys() { var prefs = UiPreferencesStore.Parse(["theme=dark"]); Assert.Equal("Dark", prefs.Theme); Assert.False(prefs.GroupNetworkPlaces); Assert.False(prefs.GroupCloudPlaces); Assert.False(prefs.IndexArchiveContents); Assert.True(prefs.ShowHiddenFiles); Assert.False(prefs.ShowProtectedSystemLocations); Assert.False(prefs.AutoClearQueueWhenDone); Assert.False(prefs.AutoIndexRemovable); Assert.False(prefs.BackgroundHostAtLogon); Assert.Null(prefs.SevenZipPath); Assert.Null(prefs.GitPath); Assert.Null(prefs.FfmpegPath); Assert.True(prefs.SessionTabs is null || prefs.SessionTabs.Count == 0); } [Fact] public void Parse_reads_window_layout() { var prefs = UiPreferencesStore.Parse( [ "theme=Dark", "window-width=1440.5", "window-height=900", "window-left=12", "window-top=24", "window-maximized=true", "tree-width=320" ]); Assert.Equal(1440.5, prefs.WindowWidth); Assert.Equal(900, prefs.WindowHeight); Assert.Equal(12, prefs.WindowLeft); Assert.Equal(24, prefs.WindowTop); Assert.True(prefs.WindowMaximized); Assert.Equal(320, prefs.TreeWidth); Assert.True(prefs.SessionTabs is null || prefs.SessionTabs.Count == 0); } [Fact] public void Parse_reads_session_tabs_and_active_index() { var left = @"C:\Users\Dominique\Documents"; var right = @"D:\Photos"; var prefs = UiPreferencesStore.Parse( [ "session-active-tab=1", "session-tab=" + UiPreferencesStore.FormatSessionTab(new SessionTabState(LocationRoots.ThisPc)), "session-tab=" + UiPreferencesStore.FormatSessionTab(new SessionTabState(left, right, true, 0.42, true)) ]); Assert.Equal(1, prefs.SessionActiveTab); Assert.NotNull(prefs.SessionTabs); Assert.Equal(2, prefs.SessionTabs.Count); Assert.Equal(LocationRoots.ThisPc, prefs.SessionTabs[0].LeftPath); Assert.False(prefs.SessionTabs[0].IsSplit); Assert.Equal(left, prefs.SessionTabs[1].LeftPath); Assert.Equal(right, prefs.SessionTabs[1].RightPath); Assert.True(prefs.SessionTabs[1].IsSplit); Assert.Equal(0.42, prefs.SessionTabs[1].SplitRatio); Assert.True(prefs.SessionTabs[1].ActiveIsRight); } [Fact] public void Session_tab_roundtrip_escapes_semicolons_in_paths() { var state = new SessionTabState(@"C:\weird;name", @"\\server\share", true, 0.3, false); var parsed = UiPreferencesStore.TryParseSessionTab(UiPreferencesStore.FormatSessionTab(state)); Assert.NotNull(parsed); Assert.Equal(state.LeftPath, parsed.LeftPath); Assert.Equal(state.RightPath, parsed.RightPath); Assert.True(parsed.IsSplit); Assert.Equal(0.3, parsed.SplitRatio); Assert.False(parsed.ActiveIsRight); } [Fact] public void Load_and_save_roundtrip() { var dir = Path.Combine(Path.GetTempPath(), "ew-ui-prefs", Guid.NewGuid().ToString("N")); try { var store = new UiPreferencesStore(new PrefsEnv(dir)); store.Save(new UiPreferences( "Light", true, false, true, AutoClearQueueWhenDone: true, WindowWidth: 1100, WindowHeight: 720, TreeWidth: 300, SessionTabs: [ new SessionTabState(@"C:\Temp", @"D:\", true, 0.6, true) ], SessionActiveTab: 0)); var loaded = store.Load(); Assert.Equal("Light", loaded.Theme); Assert.True(loaded.GroupNetworkPlaces); Assert.False(loaded.GroupCloudPlaces); Assert.True(loaded.IndexArchiveContents); Assert.True(loaded.ShowHiddenFiles); Assert.False(loaded.ShowProtectedSystemLocations); Assert.True(loaded.AutoClearQueueWhenDone); Assert.False(loaded.AutoIndexRemovable); Assert.False(loaded.BackgroundHostAtLogon); Assert.Equal(1100, loaded.WindowWidth); Assert.Equal(720, loaded.WindowHeight); Assert.Equal(300, loaded.TreeWidth); Assert.NotNull(loaded.SessionTabs); var tab = Assert.Single(loaded.SessionTabs); Assert.Equal(@"C:\Temp", tab.LeftPath); Assert.Equal(@"D:\", tab.RightPath); Assert.True(tab.IsSplit); Assert.Equal(0.6, tab.SplitRatio); Assert.True(tab.ActiveIsRight); } finally { try { Directory.Delete(dir, true); } catch { /* ignore */ } } } } public class LocationVisibilityTests { [Fact] public void Hides_protected_when_setting_is_off() { var prefs = UiPreferences.Default; var svi = LocationClassifier.Classify( @"C:\System Volume Information", "System Volume Information", AttributeFlags.Directory | AttributeFlags.Hidden | AttributeFlags.System, true); Assert.False(LocationVisibility.ShouldShow(svi, prefs)); Assert.True(LocationVisibility.ShouldShow(svi, prefs with { ShowProtectedSystemLocations = true })); } [Fact] public void Unknown_size_when_access_denied_and_zero() { var info = new LocationInfo(true, true, true, true, false); Assert.Equal(SizeKnowledge.Unknown, LocationVisibility.ResolveSizeKnowledge(info, true, 0, true)); Assert.Equal(SizeKnowledge.Partial, LocationVisibility.ResolveSizeKnowledge(info, true, 1000, true)); } [Fact] public void Recycle_bin_folder_is_never_shown() { var recycle = LocationClassifier.Classify( @"C:\$RECYCLE.BIN", "$RECYCLE.BIN", AttributeFlags.Directory | AttributeFlags.Hidden | AttributeFlags.System, true); Assert.False(LocationVisibility.ShouldShow(recycle, UiPreferences.Default)); Assert.False(LocationVisibility.ShouldShow(recycle, UiPreferences.Default with { ShowHiddenFiles = true, ShowProtectedSystemLocations = true })); } [Fact] public void Recycle_bin_summary_clamps_negative_query_values() { var summary = RecycleBinSummary.FromQuery(-12, -3); Assert.Equal(0, summary.ItemCount); Assert.Equal(0, summary.UsedBytes); var ok = RecycleBinSummary.FromQuery(4096, 3); Assert.Equal(3, ok.ItemCount); Assert.Equal(4096, ok.UsedBytes); } } file sealed class PrefsEnv : IAppEnvironment { public PrefsEnv(string dir) { DataDirectory = dir; Directory.CreateDirectory(dir); DatabasePath = Path.Combine(dir, "index.db"); LogDirectory = Path.Combine(dir, "logs"); Directory.CreateDirectory(LogDirectory); } public string DataDirectory { get; } public string DatabasePath { get; } public string LogDirectory { get; } }