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") } }