aboutsummaryrefslogtreecommitdiff
path: root/gui/internal/model/plan_test.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-17 14:16:19 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-17 14:16:19 +0200
commitf74a02254ac15a84d38c9a254ead293ebaad2377 (patch)
treea5e4139e91aa2afea5769dff856d887cda735a83 /gui/internal/model/plan_test.go
parent6d28cf285f9944eb26c7ed0efcce558521b51cb9 (diff)
downloadkrino-f74a02254ac15a84d38c9a254ead293ebaad2377.tar.gz
krino-f74a02254ac15a84d38c9a254ead293ebaad2377.zip
Settings changes take effect, and keep this copy respects the plan
Five of the Settings window's controls - the sort order, the three column toggles and the preview height - were read when it built its new preferences but never connected to anything, so changing them did nothing until some other control happened to fire, and then they all landed at once out of nowhere. Every control is connected now. The same closure composed a whole Prefs from its own widgets, which wrote the remembered divider positions back as zeros: dragging the panes to taste and then ticking any checkbox threw them away. A settings change is now applied over the preferences as they are, by model.Prefs.WithDisplay - which is where it can be tested, and is. "Keep this copy, replace the other" wrote a Displaces straight into the chain. internal/plan refuses to build two steps that displace one path, because the second destroys what the first put there; the window went round that code, so choosing it for two duplicates of one file left both rows saying "done" with the first file in the Trash. It now refuses the second, naming the file that has the place.
Diffstat (limited to 'gui/internal/model/plan_test.go')
-rw-r--r--gui/internal/model/plan_test.go38
1 files changed, 38 insertions, 0 deletions
diff --git a/gui/internal/model/plan_test.go b/gui/internal/model/plan_test.go
index 1bae2c5..241a049 100644
--- a/gui/internal/model/plan_test.go
+++ b/gui/internal/model/plan_test.go
@@ -505,3 +505,41 @@ func TestCloseDuringApplyIsRefused(t *testing.T) {
t.Errorf("the apply itself failed: %v", applyErr)
}
}
+
+// TestKeepThisCopyTwiceIsRefused: "keep this copy" writes a Displaces
+// straight into the chain. The engine refuses to plan two steps that
+// displace one path - the second would destroy what the first just put
+// there - but the window went round that code. Both rows then reported
+// "done" while the first file was in the Trash.
+func TestKeepThisCopyTwiceIsRefused(t *testing.T) {
+ conf := "(path \"~/dl\")\n(rule \"dupes\" (when (duplicate)) (move \"Dupes\"))\n"
+ e, h := sandboxDir(t, conf, map[string]string{
+ "x.pdf": "the same bytes", "y.pdf": "the same bytes", "a.pdf": "the same bytes",
+ })
+ _ = h
+ tab, err := Plan(context.Background(), e, e.Dirs[0])
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Cleanup(func() { tab.Close() })
+
+ var dupes []int
+ for i, r := range tab.Rows {
+ if r.DuplicateOf != "" {
+ dupes = append(dupes, i)
+ }
+ }
+ if len(dupes) < 2 {
+ t.Skipf("fixture produced %d duplicate rows, need two", len(dupes))
+ }
+ if err := tab.KeepThisCopy(dupes[0]); err != nil {
+ t.Fatalf("the first choice was refused: %v", err)
+ }
+ err = tab.KeepThisCopy(dupes[1])
+ if err == nil {
+ t.Fatal("two files were allowed to replace the same one; the second would trash what the first filed")
+ }
+ if !strings.Contains(err.Error(), "already") {
+ t.Errorf("refusal reads %q; it should say the place is already spoken for", err)
+ }
+}