package web import "testing" // T4: skipFileBrowserPath skips ONLY an external drive path (under StableParentDir) that is not a live // mountpoint. A mounted external path and any system/local path are never skipped. // Companion red-proof: dropping the gate (always-false) makes the absent-usb case fail. func TestSkipFileBrowserPath(t *testing.T) { // flash is mounted; usb is not. isMount := func(p string) bool { return p == StableParentDir+"/flash" } cases := []struct { path string want bool }{ {StableParentDir + "/flash", false}, // external + mounted → keep {StableParentDir + "/usb", true}, // external + NOT mounted → skip {"/mnt/sys_drive/felhom-data", false}, // system path (not under StableParentDir) → never skip } for _, c := range cases { if got := skipFileBrowserPath(c.path, isMount); got != c.want { t.Errorf("skipFileBrowserPath(%q) = %v, want %v", c.path, got, c.want) } } } // F2: fbNeedsRecreate gates the FileBrowser --force-recreate so a no-op controller restart / storage // sync no longer bounces the customer's file UI. Recreate only when config OR compose actually changed; // the first-ever run (empty old files) differs from the generated content → recreate (creates it). // Companion red-proof: hard-wiring the helper to always return true (the OLD unconditional behaviour) // makes the "unchanged → no recreate" case fail — restoring the byte-equality gate turns it green. func TestFbNeedsRecreate(t *testing.T) { cfg := []byte("sources:\n - /srv/usb\n") compose := []byte("services:\n filebrowser:\n image: x\n") cases := []struct { name string oldCfg, newCfg, oldCmp, newCmp []byte want bool }{ {"unchanged → no recreate", cfg, cfg, compose, compose, false}, {"config differs → recreate", cfg, []byte("sources:\n - /srv/hdd\n"), compose, compose, true}, {"compose differs → recreate", cfg, cfg, compose, []byte("services:\n filebrowser:\n image: y\n"), true}, {"first run (no old files) → recreate", nil, cfg, nil, compose, true}, } for _, c := range cases { if got := fbNeedsRecreate(c.oldCfg, c.newCfg, c.oldCmp, c.newCmp); got != c.want { t.Errorf("%s: fbNeedsRecreate = %v, want %v", c.name, got, c.want) } } }