diff options
Diffstat (limited to 'internal/admin/fixes_regression_test.go')
| -rw-r--r-- | internal/admin/fixes_regression_test.go | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/internal/admin/fixes_regression_test.go b/internal/admin/fixes_regression_test.go new file mode 100644 index 0000000..3d7d19f --- /dev/null +++ b/internal/admin/fixes_regression_test.go @@ -0,0 +1,49 @@ +package admin + +import ( + "path/filepath" + "testing" +) + +// TestResolveRoomSubdirRejectsEscape covers the traversal guard used by the +// room-directory API handlers (rename dir, move room, create empty room, bulk +// edit). Every escaping form must be rejected. +func TestResolveRoomSubdirRejectsEscape(t *testing.T) { + s := &AdminServer{dataDir: t.TempDir()} + for _, bad := range []string{"..", "../items", "../../etc", "/etc", "a/../../b", `..\items`, "town/../../x"} { + if _, err := s.resolveRoomSubdir(bad); err == nil { + t.Fatalf("accepted escaping dir %q", bad) + } + } + for _, ok := range []string{"", ".", "town", "town/sub"} { + got, err := s.resolveRoomSubdir(ok) + if err != nil { + t.Fatalf("rejected valid dir %q: %v", ok, err) + } + if ok != "" && ok != "." && got != filepath.FromSlash(ok) { + t.Fatalf("dir %q resolved to %q", ok, got) + } + } +} + +// TestUndoHistorySurvivesReload: the editor documents that undo history is +// persisted across sessions; NewUndoStack must load what save wrote. +func TestUndoHistorySurvivesReload(t *testing.T) { + dir := t.TempDir() + us := NewUndoStack(dir) + us.Push(ChangeDesc{ + Description: "edit x", + FilePath: filepath.Join(dir, "x.yaml"), + OldContent: []byte("old"), + NewContent: []byte("new"), + }) + + reloaded := NewUndoStack(dir) + info := reloaded.Info() + if !info.CanUndo || info.StackSize != 1 { + t.Fatalf("history did not survive reload: %+v", info) + } + if info.UndoDesc == "" { + t.Fatal("undo description empty after reload") + } +} |
