package validate // Regression: the "a failable recipe must not yield nothing" invariant was // enforced only for smelting (and only by a shipped-data test), so a future // cooking/fletching/combine recipe with a success formula (or a declared // fail_message) and no fail product would silently consume materials and // return nothing. validateCraftBlocks now warns on it. import ( "path/filepath" "testing" ) func writePolishCraftRecipe(t *testing.T, dir, craftBody string) { t.Helper() writeFile(t, filepath.Join(dir, "items", "polish_in.yaml"), "id: polish_in\nname: polish in\n") writeFile(t, filepath.Join(dir, "items", "polish_out.yaml"), "id: polish_out\nname: polish out\ncraft:\n - type: cooking\n"+craftBody+ " ingredients:\n - items: [polish_in]\n quantity: 1\n") } func TestCraftFailableWithoutFailProductIsWarned(t *testing.T) { cases := []struct { name string craftBody string }{ {"success formula", " success:\n base: 0.5\n cap: 0.95\n per_level: 0.02\n"}, {"declared fail_message", " fail_message: You burn it.\n"}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { dir := t.TempDir() writePolishCraftRecipe(t, dir, c.craftBody) issues := validateCraftBlocks(newSource(dir)) if !containsMsg(issues, "failure destroys materials with no fail product") { t.Fatalf("expected a destructive-failure warning, got: %+v", issues) } for _, issue := range issues { if issue.Level != "WARN" { t.Fatalf("destructive failure must be a WARN, got: %+v", issue) } } }) } } func TestCraftWithFailProductOrGuaranteedSuccessDoesNotWarn(t *testing.T) { cases := []struct { name string craftBody string }{ {"declares a fail product", " fail: polish_in\n success:\n base: 0.5\n cap: 0.95\n per_level: 0.02\n"}, {"success cannot fall below 1", " success:\n base: 1.0\n cap: 1.0\n per_level: 0\n"}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { dir := t.TempDir() writePolishCraftRecipe(t, dir, c.craftBody) if issues := validateCraftBlocks(newSource(dir)); containsMsg(issues, "failure destroys materials with no fail product") { t.Fatalf("did not expect a destructive-failure warning, got: %+v", issues) } }) } }