aboutsummaryrefslogtreecommitdiff
path: root/internal/validate/correct_data_craft_validation_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/validate/correct_data_craft_validation_test.go')
-rw-r--r--internal/validate/correct_data_craft_validation_test.go102
1 files changed, 102 insertions, 0 deletions
diff --git a/internal/validate/correct_data_craft_validation_test.go b/internal/validate/correct_data_craft_validation_test.go
new file mode 100644
index 0000000..6b5e7f6
--- /dev/null
+++ b/internal/validate/correct_data_craft_validation_test.go
@@ -0,0 +1,102 @@
+package validate
+
+import (
+ "testing"
+)
+
+// Regression: CraftDef.Tool was validated against item ids, but it is a tool
+// *type* ("knife", "pickaxe", "fire"): runtime consumers match it with
+// ItemDef.ToolType() (g.hasToolType). Tool types such as pickaxe, axe, fire,
+// big_net and fly_rod have no same-named item file, so the old check rejected
+// legitimate recipes. These tests pin the tool-type namespace and the
+// byproduct/index pairing rule.
+
+func TestCraftToolTypeAcceptedWithoutSameNamedItem(t *testing.T) {
+ dir := t.TempDir()
+ // A pickaxe item defines tool.type: pickaxe but there is no item "pickaxe".
+ writeCraftItem(t, dir, "bronze_pickaxe", `id: bronze_pickaxe
+name: bronze pickaxe
+tool:
+ type: pickaxe
+ speed: 2
+`)
+ writeCraftItem(t, dir, "test_in", "id: test_in\nname: test in\n")
+ writeCraftItem(t, dir, "test_out", `id: test_out
+name: test out
+craft:
+ - type: crafting
+ tool: pickaxe
+ ingredients:
+ - items: [test_in]
+ quantity: 1
+`)
+
+ issues := validateCraftBlocks(newSource(dir))
+ for _, issue := range issues {
+ if issue.Level == "ERROR" {
+ t.Fatalf("a bare tool type must validate, got: %+v", issue)
+ }
+ }
+}
+
+func TestCraftToolTypeUnknownIsRejected(t *testing.T) {
+ dir := t.TempDir()
+ writeCraftItem(t, dir, "bronze_pickaxe", "id: bronze_pickaxe\nname: bronze pickaxe\ntool:\n type: pickaxe\n")
+ writeCraftItem(t, dir, "test_in", "id: test_in\nname: test in\n")
+ writeCraftItem(t, dir, "test_out", `id: test_out
+name: test out
+craft:
+ - type: crafting
+ tool: made_up_type
+ ingredients:
+ - items: [test_in]
+ quantity: 1
+`)
+
+ if issues := validateCraftBlocks(newSource(dir)); !containsMsg(issues, "nonexistent tool") {
+ t.Fatalf("expected nonexistent-tool error, got: %+v", issues)
+ }
+}
+
+func TestCraftByproductLengthMismatchIsFlagged(t *testing.T) {
+ dir := t.TempDir()
+ writeCraftItem(t, dir, "test_in", "id: test_in\nname: test in\n")
+ writeCraftItem(t, dir, "test_alt", "id: test_alt\nname: test alt\n")
+ writeCraftItem(t, dir, "empty_container", "id: empty_container\nname: empty container\n")
+ // Two alternatives paired with a single byproduct: consuming the second
+ // alternative returns nothing (collectByproducts indexes by position).
+ writeCraftItem(t, dir, "test_out", `id: test_out
+name: test out
+craft:
+ - type: combine
+ ingredients:
+ - items: [test_in, test_alt]
+ quantity: 1
+ byproducts: [empty_container]
+`)
+
+ if issues := validateCraftBlocks(newSource(dir)); !containsMsg(issues, "pair with items by index") {
+ t.Fatalf("expected byproduct length-mismatch error, got: %+v", issues)
+ }
+}
+
+func TestCraftByproductLengthMatchIsAccepted(t *testing.T) {
+ dir := t.TempDir()
+ writeCraftItem(t, dir, "test_in", "id: test_in\nname: test in\n")
+ writeCraftItem(t, dir, "test_alt", "id: test_alt\nname: test alt\n")
+ writeCraftItem(t, dir, "empty_one", "id: empty_one\nname: empty one\n")
+ writeCraftItem(t, dir, "empty_two", "id: empty_two\nname: empty two\n")
+ writeCraftItem(t, dir, "test_out", `id: test_out
+name: test out
+craft:
+ - type: combine
+ ingredients:
+ - items: [test_in, test_alt]
+ quantity: 1
+ byproducts: [empty_one, empty_two]
+`)
+
+ if issues := validateCraftBlocks(newSource(dir)); len(issues) != 0 {
+ t.Fatalf("positionally paired byproducts must validate cleanly, got: %+v", issues)
+ }
+}