package behavior // Structural room-reference remapping for non-room content files. The walker // must rewrite only known room-ID keys and must not touch author values that // merely happen to equal a room ID. import ( "os" "path/filepath" "strings" "testing" "gopkg.in/yaml.v3" ) func decode(t *testing.T, src string) any { t.Helper() var v any if err := yaml.Unmarshal([]byte(src), &v); err != nil { t.Fatalf("unmarshal: %v", err) } return v } func TestRemapRoomRefsRewritesStructuralKeys(t *testing.T) { src := ` destination: 10 on_fail: 11 room_id: 12 start_room: 13 wander_rooms: [14, 15] despawn_rooms: [16] teleport: 17 nested: room: 18 condition: room: 19 ` v := decode(t, src) idMap := map[int]int{ 10: 110, 11: 111, 12: 112, 13: 113, 14: 114, 15: 115, 16: 116, 17: 117, 18: 118, 19: 119, } if !RemapRoomRefs(v, idMap) { t.Fatal("expected changed=true") } out, err := MarshalYAMLMap(v.(map[string]any)) if err != nil { t.Fatal(err) } s := string(out) for _, want := range []string{ "destination: 110", "on_fail: 111", "room_id: 112", "start_room: 113", "teleport: 117", } { if !strings.Contains(s, want) { t.Errorf("missing rewritten %q in:\n%s", want, s) } } // Lists are rewritten in place. for _, want := range []string{"- 114", "- 115", "- 116"} { if !strings.Contains(s, want) { t.Errorf("missing rewritten list entry %q in:\n%s", want, s) } } for _, want := range []string{"room: 118", "room: 119"} { if !strings.Contains(s, want) { t.Errorf("missing nested rewritten %q in:\n%s", want, s) } } } func TestRemapRoomRefsLeavesAuthorValues(t *testing.T) { // A delay, quantity, color index, and author flag value that equal room // IDs must never be rewritten: only structural keys are room references. src := ` value: 10 delay: 11 quantity: 12 color: "13" set_global_flags: last_room: 14 steps: - wait: 15 credits: 16 ` v := decode(t, src) idMap := map[int]int{10: 110, 11: 111, 12: 112, 13: 113, 14: 114, 15: 115, 16: 116} if RemapRoomRefs(v, idMap) { t.Fatal("author values were remapped; only structural room keys may change") } } func TestRewriteRoomRefsInDir(t *testing.T) { dir := t.TempDir() write := func(name, body string) { t.Helper() if err := os.WriteFile(filepath.Join(dir, name), []byte(body), 0o644); err != nil { t.Fatal(err) } } write("course.yaml", "start_room: 5\nobstacles:\n - room_id: 6\n") write("unrelated.yaml", "value: 5\nname: keeps its value\n") changes, err := RewriteRoomRefsInDir(dir, map[int]int{5: 50, 6: 60}) if err != nil { t.Fatal(err) } if len(changes) != 1 { t.Fatalf("changed %d files, want 1: %+v", len(changes), changes) } if !strings.Contains(string(changes[0].Content), "start_room: 50") || !strings.Contains(string(changes[0].Content), "room_id: 60") { t.Fatalf("course not rewritten: %s", changes[0].Content) } if changes[0].Old == nil { t.Fatal("before-image not captured for undo") } } // Missing content directories are not an error (a family may be absent). func TestRewriteRoomRefsInDirMissingDir(t *testing.T) { changes, err := RewriteRoomRefsInDir(t.TempDir()+"/nope", map[int]int{1: 2}) if err != nil { t.Fatalf("missing dir must not error: %v", err) } if len(changes) != 0 { t.Fatalf("expected no changes, got %+v", changes) } }