package processing import ( "context" "encoding/json" "strings" "testing" "github.com/descrybe/descrybe-v2/apps/api/internal/aiprompts" "github.com/descrybe/descrybe-v2/apps/api/internal/company" ) // A categorised product with no formula of its own enhances through the English // platform default rather than the generic "1-3 paragraphs" rule. func TestWithDefaultCategoryFormula_appliesToCategorisedProduct(t *testing.T) { t.Parallel() got := withDefaultCategoryFormula(ProductInput{ CategoryUniqueID: "high-chairs", CategoryDisplayName: "High chairs", }) if got.CategoryEnhancePrompt == "" { t.Fatal("expected the platform default overlay") } if FormatTitleFormulaConstraint(got.TitleTemplate) == "" { t.Fatalf("expected a default title formula, got %#v", got.TitleTemplate) } if FormatDescriptionFormulaConstraint(got.DescriptionTemplate) == "" { t.Fatalf("expected a default description formula, got %#v", got.DescriptionTemplate) } } func TestWithDefaultCategoryFormula_doesNotOverride(t *testing.T) { t.Parallel() cases := map[string]ProductInput{ "no category at all": {}, "category prompt already set": { CategoryUniqueID: "high-chairs", CategoryEnhancePrompt: "--- Title ---\nKeep the supplier title.\n--- End Title ---", }, "tenant-authored enhance template": { CategoryUniqueID: "high-chairs", EnhanceUserTemplate: "Write a haiku about {{name}}", }, "category has its own title formula": { CategoryUniqueID: "high-chairs", TitleTemplate: map[string]any{"separator": " ", "elements": []any{ map[string]any{"type": "variable", "value": "product_type"}, map[string]any{"type": "variable", "value": "brand"}, }}, }, } for name, in := range cases { t.Run(name, func(t *testing.T) { got := withDefaultCategoryFormula(in) if got.CategoryEnhancePrompt != in.CategoryEnhancePrompt { t.Fatalf("platform default overrode an explicit choice: %q", got.CategoryEnhancePrompt) } }) } } // A1's Slovenian formulas keep the Slovenian scaffolding and system prompt they had // in generator.php; the English defaults get an English frame. Output language is // set by {{language}} in both cases. func TestResolveProductPromptTemplates_scaffoldingFollowsFormulaLanguage(t *testing.T) { t.Parallel() slovenian := aiprompts.SplitLegacyCombinedEnhancePrompt(a1StolckiLegacyPrompt) sysSL, userSL := resolveProductPromptTemplates(ProductInput{ CategoryUniqueID: "stolcki", CategoryDisplayName: "StolĨki", CategoryEnhancePrompt: slovenian, Language: "sl", }) if !strings.Contains(sysSL, "Si tekstopisec") { t.Fatalf("Slovenian formula must keep the Slovenian system prompt:\n%s", sysSL) } for _, want := range []string{"GPT predloga:", "Staro_ime_izdelka: {{name}}", "{"} { if !strings.Contains(userSL, want) { t.Fatalf("Slovenian scaffolding missing %q:\n%s", want, userSL) } } sysEN, userEN := resolveProductPromptTemplates(ProductInput{ CategoryUniqueID: "high-chairs", CategoryDisplayName: "High chairs", }) if !strings.Contains(sysEN, "You are a copywriter") { t.Fatalf("English default must use the English system prompt:\n%s", sysEN) } for _, want := range []string{"Product template:", "Old_product_name: {{name}}", "{"} { if !strings.Contains(userEN, want) { t.Fatalf("English scaffolding missing %q:\n%s", want, userEN) } } if strings.Contains(userEN, "GPT predloga") || strings.Contains(userEN, "Staro_ime_izdelka") { t.Fatalf("English default leaked Slovenian scaffolding:\n%s", userEN) } } // End to end through RunSteps: a category with no stored formula still produces // formula-shaped HTML and a rebuilt name, and the feed is only used as evidence. func TestRunSteps_defaultFormulaDrivesGeneration(t *testing.T) { t.Parallel() reply, _ := json.Marshal(map[string]any{ "name": "BRUNNER folding chair ONE SHOT 0404164N.C20", "description": "

BRUNNER folding chair for life on the road

" + strings.Repeat("A light aluminium frame opens in one motion and stays steady on uneven ground. ", 4) + "

Built to last a season outdoors

" + strings.Repeat("Reinforced joints take the load where it matters and wipe clean in seconds. ", 4) + "

Technical specifications", "attrs": map[string]any{"brand": "BRUNNER", "product_model": "ONE SHOT 0404164N.C20"}, }) c := &formulaRegressionCompleter{reply: string(reply)} feedName := "BRUNNER folding camping chair ONE SHOT grey black 0404164N.C20" feedDesc := "An elegant and very light chair designed for art directors. Folding aluminium frame and armrests." out, err := (&Engine{Completer: c}).RunSteps(context.Background(), "co", ProductInput{ GTIN: "8022068075495", Name: feedName, Description: feedDesc, Mapped: map[string]any{ "name": feedName, "description": feedDesc, "brand": "BRUNNER", "category": "high-chairs", "specifications": map[string]any{"Material": "aluminium"}, }, Language: "en", ContentLanguages: []string{"en"}, CategoryNamesByUID: map[string]string{"high-chairs": "High chairs"}, }, "full", []string{"high-chairs"}, StepPolicy{AllowAI: true}) if err != nil { t.Fatal(err) } if c.calls != 1 { t.Fatalf("a compliant reply must not need a retry, calls=%d", c.calls) } if !strings.Contains(c.user, "Product template:") || !strings.Contains(c.user, "

{") { t.Fatalf("default formula never reached the prompt:\n%s", c.user) } if out.ProcessedName == out.Name || out.ProcessedDescription == out.Description { t.Fatal("enriched output must differ from the feed") } if !strings.Contains(out.ProcessedDescription, "

") || !strings.Contains(out.ProcessedDescription, "
    ") { t.Fatalf("processed description is not formula HTML: %q", out.ProcessedDescription) } if out.Name != feedName || out.Description != feedDesc { t.Fatalf("Original must stay the feed: name=%q desc=%q", out.Name, out.Description) } if h, _ := out.FieldSources[FieldEnhanceInputHash].(string); h == "" { t.Fatal("quality enhance under the default formula must persist a hash") } _ = company.DefaultLanguage }