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