aboutsummaryrefslogtreecommitdiff
path: root/internal/validate/local_test.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-28 02:40:30 -0400
committerhistoria <[not public]>2026-06-28 02:40:30 -0400
commita1b6613c6c6a2f8d6e1ecd47e766bd40f92ac295 (patch)
tree4ff8fefb029c93f2aa3db7361658b0b4e9805b66 /internal/validate/local_test.go
parent87dacfbb3dd16e7f55a82361eace98f9a39d75c8 (diff)
downloadthehouseoficarus-a1b6613c6c6a2f8d6e1ecd47e766bd40f92ac295.tar.gz
feat: admin accounts, god mode, OLC commands like dig/room, 'inline' objects changed to 'local' objects
Diffstat (limited to 'internal/validate/local_test.go')
-rw-r--r--internal/validate/local_test.go134
1 files changed, 134 insertions, 0 deletions
diff --git a/internal/validate/local_test.go b/internal/validate/local_test.go
new file mode 100644
index 0000000..23bf8ca
--- /dev/null
+++ b/internal/validate/local_test.go
@@ -0,0 +1,134 @@
+package validate
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+
+ "thehouseoficarus/internal/behavior"
+ "thehouseoficarus/internal/item"
+ "thehouseoficarus/internal/object"
+ "thehouseoficarus/internal/world"
+)
+
+func TestValidateLocalObjectPassiveOK(t *testing.T) {
+ robj := world.RoomObject{ID: "window", Local: &object.ObjectDef{
+ Name: "window",
+ Hidden: true,
+ Description: behavior.DescList{{Text: "A small window."}},
+ }}
+ issues := validateLocalObject(1001, robj, nil, nil)
+ if len(issues) != 0 {
+ t.Errorf("expected no issues for passive local object, got: %+v", issues)
+ }
+}
+
+func TestValidateLocalObjectRejectsInteractable(t *testing.T) {
+ robj := world.RoomObject{ID: "rock", Local: &object.ObjectDef{
+ Name: "rock",
+ Gather: &behavior.GatherConfig{},
+ }}
+ issues := validateLocalObject(1001, robj, nil, nil)
+ if !containsMsg(issues, "interactable behavior") {
+ t.Errorf("expected interactable-behavior error, got: %+v", issues)
+ }
+}
+
+func TestValidateLocalObjectRequiresName(t *testing.T) {
+ robj := world.RoomObject{ID: "x", Local: &object.ObjectDef{
+ Description: behavior.DescList{{Text: "no name"}},
+ }}
+ issues := validateLocalObject(1001, robj, nil, nil)
+ if !containsMsg(issues, "has no name") {
+ t.Errorf("expected has-no-name error, got: %+v", issues)
+ }
+}
+
+func TestValidateLocalObjectStrayIDWarns(t *testing.T) {
+ robj := world.RoomObject{ID: "anvil", Local: &object.ObjectDef{Name: "anvil", ID: "anvil"}}
+ issues := validateLocalObject(1001, robj, nil, nil)
+ if !containsMsg(issues, "ignored on local objects") {
+ t.Errorf("expected stray-id warning, got: %+v", issues)
+ }
+}
+
+func newSource(dir string) Source {
+ return Source{
+ DataDir: dir,
+ Items: item.NewItemStore(dir),
+ Objects: object.NewObjectStore(dir),
+ Mobs: world.NewMobStore(dir),
+ World: world.New(dir),
+ }
+}
+
+func writeFile(t *testing.T, path, body string) {
+ t.Helper()
+ if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile(path, []byte(body), 0o644); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestValidateRoomsSameNameCollision(t *testing.T) {
+ dir := t.TempDir()
+ writeFile(t, filepath.Join(dir, "rooms", "1.yaml"), `name: Test Room
+objects:
+ - id: ghost_object
+ - name: sign
+ description: "one"
+ - name: sign
+ description: "two"
+`)
+ issues := validateRooms(newSource(dir))
+
+ if !containsMsg(issues, "nonexistent object \"ghost_object\"") {
+ t.Errorf("expected missing-reference error, got: %+v", issues)
+ }
+ if !containsMsg(issues, "objects share the name \"sign\"") {
+ t.Errorf("expected same-name collision error, got: %+v", issues)
+ }
+}
+
+func TestValidateRoomsDefIDCollisionAndDuplicateRefs(t *testing.T) {
+ dir := t.TempDir()
+ writeFile(t, filepath.Join(dir, "objects", "anvil.yaml"), "name: heavy anvil\n")
+ writeFile(t, filepath.Join(dir, "objects", "copper_rock.yaml"), "name: copper rock\n")
+ writeFile(t, filepath.Join(dir, "rooms", "1.yaml"), `name: Test Room
+objects:
+ - id: copper_rock
+ - id: copper_rock
+ - id: anvil
+ - name: anvil
+ description: "a local thing that collides with the file id"
+`)
+ issues := validateRooms(newSource(dir))
+
+ // Local name "anvil" normalizes to the referenced file id "anvil".
+ if !containsMsg(issues, "object id collision \"anvil\"") {
+ t.Errorf("expected defID collision error, got: %+v", issues)
+ }
+ // Two references to the same copper_rock file are allowed.
+ if containsMsg(issues, "name \"copper rock\"") || containsMsg(issues, "collision \"copper_rock\"") {
+ t.Errorf("repeated references to one file object should not collide, got: %+v", issues)
+ }
+}
+
+func TestValidateRoomsPartialNameSiblingsOK(t *testing.T) {
+ dir := t.TempDir()
+ writeFile(t, filepath.Join(dir, "rooms", "1.yaml"), `name: Test Room
+objects:
+ - name: rusty sign
+ description: "rusty"
+ - name: shiny sign
+ description: "shiny"
+`)
+ issues := validateRooms(newSource(dir))
+ for _, iss := range issues {
+ if iss.Type == "duplicate" {
+ t.Errorf("partial-name siblings should not collide, got: %+v", iss)
+ }
+ }
+}