diff options
Diffstat (limited to 'internal/admin/room_rename_state_test.go')
| -rw-r--r-- | internal/admin/room_rename_state_test.go | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/internal/admin/room_rename_state_test.go b/internal/admin/room_rename_state_test.go new file mode 100644 index 0000000..8c5be93 --- /dev/null +++ b/internal/admin/room_rename_state_test.go @@ -0,0 +1,68 @@ +package admin + +// Room-rename runtime-state regressions: renaming a room must move its live +// contents (ground items, seeded spawn markers, object state) to the new ID +// — never clear them — and undo must bring them back. + +import ( + "testing" +) + +// TestRoomRenameMovesRuntimeState: renaming a room with ground items moves +// them to the new room ID. The old implementation cleared the state before +// the migration callback could rekey it, destroying the room's contents. +func TestRoomRenameMovesRuntimeState(t *testing.T) { + s := newTestAdminServer(t, map[int]string{ + 1: "id: 1\nname: Room\nexits:\n east:\n room: 2\n", + 2: "id: 2\nname: Neighbor\nexits:\n west:\n room: 1\n", + }) + s.world.AddGroundItem(1, "chips", 50) + s.world.AddGroundItem(1, "chips", 10) // second entry: rekey must move the whole list + s.rewriteRoomIDs = func(idMap map[int]int) { s.world.RekeyRooms(idMap) } + s.undoStack.SetMigrateRoomIDs(s.rewriteRoomIDs) + + if rec := renameRoom(t, s, 1, 3); rec.Code != 200 { + t.Fatalf("rename failed: %d %s", rec.Code, rec.Body.String()) + } + if got := s.world.GroundItems(3)["chips"]; got != 60 { + t.Fatalf("ground items after rename = %d, want 60 in room 3", got) + } + if got := s.world.GroundItems(1)["chips"]; got != 0 { + t.Fatalf("ground items left behind in the old room: %d", got) + } + + // Undo restores the files AND the runtime state through the inverse map. + if s.undoStack.Undo() == nil { + t.Fatal("undo failed") + } + if got := s.world.GroundItems(1)["chips"]; got != 60 { + t.Fatalf("ground items after undo = %d, want 60 back in room 1", got) + } +} + +// TestRoomRenameUndoDoesNotClearSurvivingRoomState: undoing a rename must +// not clear runtime state of rooms whose files still exist afterwards +// (only undo-of-create / redo-of-delete drops state). +func TestRoomRenameUndoDoesNotClearSurvivingRoomState(t *testing.T) { + s := newTestAdminServer(t, map[int]string{ + 1: "id: 1\nname: Room\n", + 2: "id: 2\nname: Unrelated\n", + }) + s.world.AddGroundItem(2, "chips", 5) + s.rewriteRoomIDs = func(idMap map[int]int) { s.world.RekeyRooms(idMap) } + s.undoStack.SetMigrateRoomIDs(s.rewriteRoomIDs) + + if rec := renameRoom(t, s, 1, 3); rec.Code != 200 { + t.Fatalf("rename failed: %d %s", rec.Code, rec.Body.String()) + } + // The unrelated room's state must survive the rename and its undo. + if got := s.world.GroundItems(2)["chips"]; got != 5 { + t.Fatalf("unrelated room state lost during rename: %d", got) + } + if s.undoStack.Undo() == nil { + t.Fatal("undo failed") + } + if got := s.world.GroundItems(2)["chips"]; got != 5 { + t.Fatalf("unrelated room state lost during undo: %d", got) + } +} |
