using Explorer.Application; using Explorer.Domain; namespace Explorer.Application.Tests; public class DestinationPatternTests { private static RenameSubject File(string path, bool directory = false) => new(path, PathRules.GetFileName(path), directory); [Fact] public void Plex_style_folder_gets_the_file_inside() { Assert.True(DestinationPattern.TryResolve( @"\\10.0.0.31\media\movies\%filename_noext%", File(@"D:\downloads\Inception.mkv"), out var dest, out var error)); Assert.Null(error); Assert.Equal(@"\\10.0.0.31\media\movies\Inception\Inception.mkv", dest); } [Fact] public void Explicit_filename_token_is_the_full_path() { Assert.True(DestinationPattern.TryResolve( @"\\10.0.0.31\media\movies\%filename_noext%\%filename%", File(@"D:\downloads\Inception.mkv"), out var dest, out _)); Assert.Equal(@"\\10.0.0.31\media\movies\Inception\Inception.mkv", dest); } [Fact] public void Folder_moves_to_the_expanded_directory() { Assert.True(DestinationPattern.TryResolve( @"\\10.0.0.31\media\movies\%filename_noext%", File(@"D:\downloads\Inception", directory: true), out var dest, out _)); Assert.Equal(@"\\10.0.0.31\media\movies\Inception", dest); } [Fact] public void Source_drive_year_and_parent_expand() { var fields = new MoveToFields( "clip.mp4", "clip", "mp4", "Vacation", "E:", new DateTimeOffset(new DateTime(2024, 8, 26, 0, 0, 0, DateTimeKind.Local)), null); Assert.True(DestinationPattern.TryExpand( @"%source_drive%\sorted\%year%\%month%\%parent%", fields, out var expanded, out _)); Assert.Equal(@"E:\sorted\2024\08\Vacation", expanded); } [Fact] public void Brace_tokens_match_percent_tokens() { Assert.True(DestinationPattern.TryResolve( @"{source_drive}\Media\{filename_noext}\{filename}", File(@"C:\tmp\Photo.jpg"), out var dest, out _)); Assert.Equal(@"C:\Media\Photo\Photo.jpg", dest); } [Fact] public void Relative_paths_are_rejected() { Assert.False(DestinationPattern.TryResolve( @"%filename_noext%\%filename%", File(@"C:\tmp\a.mkv"), out _, out var error)); Assert.Contains("full destination", error, StringComparison.OrdinalIgnoreCase); } [Fact] public void Unknown_placeholder_is_an_error() { Assert.False(DestinationPattern.TryExpand( @"C:\out\%nope%", new MoveToFields("a.txt", "a", "txt", "tmp", "C:", null, null), out _, out var error)); Assert.Contains("%nope%", error, StringComparison.OrdinalIgnoreCase); } } public class DestinationPatternsTests { [Fact] public void Combine_puts_saved_ahead_of_built_in() { var combined = DestinationPatterns.Combine([@"\\10.0.0.31\media\movies\%filename_noext%"]); Assert.Equal(@"\\10.0.0.31\media\movies\%filename_noext%", combined[0]); Assert.Contains(DestinationPatterns.BuiltIn[0], combined); } [Fact] public void Normalize_does_not_persist_built_in_examples() { Assert.Empty(DestinationPatterns.Normalize([@"\\host\share\movies\%filename_noext%"])); } } public class MoveToPlannerTests { [Fact] public void Queues_a_move_into_the_named_folder() { var plan = new MoveToPlanner().Build( [new RenameSubject(@"D:\downloads\Inception.mkv", "Inception.mkv", false)], @"\\10.0.0.31\media\movies\%filename_noext%"); Assert.True(plan.CanEnqueue); Assert.Equal(TransferOp.Move, plan.Operations[0].Op); Assert.Equal(@"\\10.0.0.31\media\movies\Inception\Inception.mkv", plan.Operations[0].DestinationPath); } [Fact] public void Collision_is_an_error() { var plan = new MoveToPlanner().Build( [ new RenameSubject(@"D:\a\Inception.mkv", "Inception.mkv", false), new RenameSubject(@"D:\b\Inception.mkv", "Inception.mkv", false) ], @"\\server\media\movies\%filename_noext%"); Assert.False(plan.CanEnqueue); Assert.Contains(plan.Issues, i => i.Message.Contains("already exists", StringComparison.OrdinalIgnoreCase)); } [Fact] public void Online_only_is_an_error() { var plan = new MoveToPlanner().Build( [new RenameSubject(@"C:\cloud\clip.mp4", "clip.mp4", false)], @"D:\out\%filename_noext%", wouldHydrate: _ => true); Assert.False(plan.CanEnqueue); Assert.Contains(plan.Issues, i => i.Message.Contains("online-only", StringComparison.OrdinalIgnoreCase)); } [Fact] public void Example_host_is_rejected() { var plan = new MoveToPlanner().Build( [new RenameSubject(@"D:\downloads\Inception.mkv", "Inception.mkv", false)], @"\\host\share\movies\%filename_noext%"); Assert.False(plan.CanEnqueue); Assert.Contains(plan.Issues, i => i.Message.Contains("Browse", StringComparison.OrdinalIgnoreCase)); } }