Add Git overlay, operation tools, and virtualized preview so large folders stay responsive.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
166
tests/Explorer.Application.Tests/ReorganizePlannerTests.cs
Normal file
166
tests/Explorer.Application.Tests/ReorganizePlannerTests.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using Explorer.Application;
|
||||
using Explorer.Domain;
|
||||
using Explorer.Domain.Abstractions;
|
||||
|
||||
namespace Explorer.Application.Tests;
|
||||
|
||||
public class ReorganizePlannerTests
|
||||
{
|
||||
private static readonly DateTimeOffset T0 = DateTimeOffset.Parse("2024-06-01T12:00:00Z");
|
||||
|
||||
[Fact]
|
||||
public void Proposes_moves_and_leaves_unknown_and_build_output()
|
||||
{
|
||||
var fs = Tree()
|
||||
.Dir(@"C:\Downloads")
|
||||
.File(@"C:\Downloads\setup.exe", 10, T0)
|
||||
.File(@"C:\Downloads\photo.jpg", 20, T0)
|
||||
.File(@"C:\Downloads\clip.mkv", 30, T0)
|
||||
.File(@"C:\Downloads\notes.pdf", 8, T0)
|
||||
.File(@"C:\Downloads\pack.zip", 4, T0)
|
||||
.File(@"C:\Downloads\weird.bin", 1, T0)
|
||||
.Dir(@"C:\Downloads\node_modules")
|
||||
.File(@"C:\Downloads\node_modules\pkg.js", 1, T0)
|
||||
.Dir(@"C:\Software")
|
||||
.Dir(@"C:\Pictures")
|
||||
.Dir(@"C:\Videos")
|
||||
.Dir(@"C:\Docs")
|
||||
.Dir(@"C:\Archive");
|
||||
|
||||
var plan = Build(fs);
|
||||
Assert.True(plan.CanEnqueue);
|
||||
Assert.Contains(plan.Operations, o => o.Op == TransferOp.Move && o.SourcePath.EndsWith("setup.exe") && o.DestinationPath == @"C:\Software\setup.exe");
|
||||
Assert.Contains(plan.Operations, o => o.DestinationPath == @"C:\Pictures\photo.jpg");
|
||||
Assert.Contains(plan.Operations, o => o.DestinationPath == @"C:\Videos\clip.mkv");
|
||||
Assert.Contains(plan.Operations, o => o.DestinationPath == @"C:\Docs\notes.pdf");
|
||||
Assert.Contains(plan.Operations, o => o.DestinationPath == @"C:\Archive\pack.zip");
|
||||
Assert.DoesNotContain(plan.Operations, o => o.SourcePath.Contains("weird.bin", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.DoesNotContain(plan.Operations, o => o.SourcePath.Contains("node_modules", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(plan.OrganizePreview, r => r.Name == "weird.bin" && r.Action == "Skip");
|
||||
Assert.Contains(plan.OrganizePreview, r => r.Name == "node_modules" && r.Action == "Skip");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Git_repo_moves_as_a_unit_to_development()
|
||||
{
|
||||
var fs = Tree()
|
||||
.Dir(@"C:\Downloads")
|
||||
.Dir(@"C:\Downloads\Explorer")
|
||||
.File(@"C:\Downloads\Explorer\README.md", 1, T0)
|
||||
.Dir(@"C:\Dev");
|
||||
|
||||
var plan = Build(fs, dest => dest.Development = @"C:\Dev", isRepoRoot: path => path.EndsWith(@"\Explorer", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(plan.Operations, o => o.SourcePath == @"C:\Downloads\Explorer" && o.DestinationPath == @"C:\Dev\Explorer");
|
||||
Assert.DoesNotContain(plan.Operations, o => o.SourcePath.Contains("README", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Missing_destination_skips_that_category()
|
||||
{
|
||||
var fs = Tree()
|
||||
.Dir(@"C:\Downloads")
|
||||
.File(@"C:\Downloads\setup.exe", 10, T0)
|
||||
.File(@"C:\Downloads\photo.jpg", 20, T0)
|
||||
.Dir(@"C:\Pictures");
|
||||
|
||||
var plan = Build(fs, dest => dest.Installers = "");
|
||||
Assert.Contains(plan.Operations, o => o.DestinationPath == @"C:\Pictures\photo.jpg");
|
||||
Assert.DoesNotContain(plan.Operations, o => o.SourcePath.EndsWith("setup.exe"));
|
||||
Assert.Contains(plan.OrganizePreview, r => r.Name == "setup.exe" && r.Action == "Skip");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Old_installer_is_a_warning_still_proposed()
|
||||
{
|
||||
var old = T0.AddYears(-2);
|
||||
var fs = Tree()
|
||||
.Dir(@"C:\Downloads")
|
||||
.File(@"C:\Downloads\old.msi", 10, old)
|
||||
.Dir(@"C:\Software");
|
||||
|
||||
var plan = Build(fs, now: T0);
|
||||
Assert.True(plan.CanEnqueue);
|
||||
Assert.Contains(plan.Operations, o => o.SourcePath.EndsWith("old.msi"));
|
||||
Assert.Contains(plan.Issues, i => i.Severity == PlanIssueSeverity.Warning && i.Message.Contains("Old", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(plan.OrganizePreview, r => r.Name == "old.msi" && r.Detail == "Older than 1 year.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Offline_destination_is_an_error_and_does_not_enqueue()
|
||||
{
|
||||
var fs = Tree()
|
||||
.Dir(@"C:\Downloads")
|
||||
.File(@"C:\Downloads\photo.jpg", 20, T0)
|
||||
.Dir(@"Z:\Pictures");
|
||||
|
||||
var plan = new ReorganizePlanner().Build(
|
||||
@"C:\Downloads",
|
||||
Map(d => d.Pictures = @"Z:\Pictures"),
|
||||
fs,
|
||||
path => path.StartsWith(@"C:\", StringComparison.OrdinalIgnoreCase),
|
||||
_ => false);
|
||||
Assert.False(plan.CanEnqueue);
|
||||
Assert.Empty(plan.Operations);
|
||||
Assert.Contains(plan.Issues, i => i.Message == "Destination is not available.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Destination_inside_the_source_is_allowed()
|
||||
{
|
||||
var fs = Tree()
|
||||
.Dir(@"C:\Downloads")
|
||||
.File(@"C:\Downloads\setup.exe", 10, T0)
|
||||
.Dir(@"C:\Downloads\Software");
|
||||
|
||||
var plan = Build(fs, dest => dest.Installers = @"C:\Downloads\Software");
|
||||
Assert.True(plan.CanEnqueue);
|
||||
Assert.Contains(plan.Operations, o => o.DestinationPath == @"C:\Downloads\Software\setup.exe");
|
||||
Assert.DoesNotContain(plan.Operations, o => o.SourcePath == @"C:\Downloads\Software");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Planner_does_not_move_files_itself()
|
||||
{
|
||||
var fs = Tree()
|
||||
.Dir(@"C:\Downloads")
|
||||
.File(@"C:\Downloads\photo.jpg", 20, T0)
|
||||
.Dir(@"C:\Pictures");
|
||||
|
||||
var plan = Build(fs);
|
||||
Assert.NotEmpty(plan.Operations);
|
||||
Assert.NotNull(fs.GetItem(@"C:\Downloads\photo.jpg"));
|
||||
Assert.Null(fs.GetItem(@"C:\Pictures\photo.jpg"));
|
||||
}
|
||||
|
||||
private static OperationPlan Build(
|
||||
IFileSystemEnumerator fs,
|
||||
Action<OrganizeDestinations>? configure = null,
|
||||
Func<string, bool>? isRepoRoot = null,
|
||||
DateTimeOffset? now = null)
|
||||
=> new ReorganizePlanner().Build(
|
||||
@"C:\Downloads",
|
||||
Map(configure),
|
||||
fs,
|
||||
_ => true,
|
||||
isRepoRoot ?? (_ => false),
|
||||
now: now ?? T0,
|
||||
pathExists: _ => false);
|
||||
|
||||
private static OrganizeDestinations Map(Action<OrganizeDestinations>? configure = null)
|
||||
{
|
||||
var dest = new OrganizeDestinations
|
||||
{
|
||||
Pictures = @"C:\Pictures",
|
||||
Videos = @"C:\Videos",
|
||||
Audio = @"C:\Music",
|
||||
Documents = @"C:\Docs",
|
||||
Installers = @"C:\Software",
|
||||
Archives = @"C:\Archive",
|
||||
Development = @"C:\Dev"
|
||||
};
|
||||
configure?.Invoke(dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
private static TreeEnumerator Tree() => new();
|
||||
}
|
||||
Reference in New Issue
Block a user