summaryrefslogtreecommitdiff
path: root/internal/engine/explain_test.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-16 00:55:01 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-16 00:55:01 +0200
commit86e55e31f6905ae997619aa095706674e2ffe623 (patch)
tree35397d5b33b453b87473fac849d2fdb21ece36fa /internal/engine/explain_test.go
parent9a77de31dc9759708ce9c2d14ea7c0876c214e71 (diff)
downloadkrino-86e55e31f6905ae997619aa095706674e2ffe623.tar.gz
krino-86e55e31f6905ae997619aa095706674e2ffe623.zip
explain reports captures and the chain a file would get
Diffstat (limited to 'internal/engine/explain_test.go')
-rw-r--r--internal/engine/explain_test.go65
1 files changed, 65 insertions, 0 deletions
diff --git a/internal/engine/explain_test.go b/internal/engine/explain_test.go
new file mode 100644
index 0000000..4d304f9
--- /dev/null
+++ b/internal/engine/explain_test.go
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package engine
+
+import (
+ "context"
+ "path/filepath"
+ "reflect"
+ "strings"
+ "testing"
+
+ "krino/internal/plan"
+)
+
+// TestExplainReportsCapturesAndChain: explain returns what each matching
+// rule captured and the steps the file would get, so a GUI can show
+// "{1}=2026" and the destination without planning the whole directory
+// (GUI design ยง1.3).
+func TestExplainReportsCapturesAndChain(t *testing.T) {
+ h, dl := excludeTree(t, map[string]string{"Screenshot_2026-09-01.png": "x"})
+ main := writeConfig(t, h, `(include "dl")`, map[string]string{"dl": `
+(path "~/dl")
+(rule "shots" (when (name "^Screenshot_(\d{4})-(\d{2})")) (move "Pictures/{1}-{2}") (stop))
+`})
+ e, errs := Load(main)
+ if len(errs) > 0 {
+ t.Fatal(errs)
+ }
+ x, err := e.Explain(context.Background(), filepath.Join(dl, "Screenshot_2026-09-01.png"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(x.Rules) != 1 || !reflect.DeepEqual(x.Rules[0].Captures, []string{"Screenshot_2026-09", "2026", "09"}) {
+ t.Fatalf("captures = %+v", x.Rules)
+ }
+ if len(x.Chain) != 1 || x.Chain[0].Kind != plan.Move || !strings.HasSuffix(x.Chain[0].Dst, "/dl/Pictures/2026-09/Screenshot_2026-09-01.png") {
+ t.Fatalf("chain = %+v", x.Chain)
+ }
+}
+
+// TestExplainChainMatchesThePlan: the chain explain reports is the one the
+// directory's plan gives the same file, conflicts and skips included.
+func TestExplainChainMatchesThePlan(t *testing.T) {
+ h, dl := excludeTree(t, map[string]string{"a.pdf": "one", "Out/a.pdf": "taken"})
+ main := writeConfig(t, h, `(include "dl")`, map[string]string{"dl": `
+(path "~/dl")
+(ignore "Out/")
+(rule "r" (when (name "^a")) (rename "b.pdf") (move "Out"))
+`})
+ e, errs := Load(main)
+ if len(errs) > 0 {
+ t.Fatal(errs)
+ }
+ dp, err := e.Plan(context.Background(), e.Dirs[0], plan.NewClaims())
+ if err != nil {
+ t.Fatal(err)
+ }
+ x, err := e.Explain(context.Background(), filepath.Join(dl, "a.pdf"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(dp.Chains) != 1 || !reflect.DeepEqual(x.Chain, dp.Chains[0].Steps) {
+ t.Errorf("explain chain %+v\nplan chain %+v", x.Chain, dp.Chains[0].Steps)
+ }
+}