package processing_test import ( "context" "os" "strings" "testing" "time" "github.com/descrybe/descrybe-v2/apps/api/internal/aiprompts" "github.com/descrybe/descrybe-v2/apps/api/internal/processing" ) // Live proof against local mock-llm (OPENAI_BASE_URL). Skipped unless LIVE_MOCK_LLM=1. func TestLive_MockLLM_rejectsCategoryEnhanceInstructionTitle(t *testing.T) { if strings.TrimSpace(os.Getenv("LIVE_MOCK_LLM")) == "" { t.Skip("set LIVE_MOCK_LLM=1 with mock-llm on OPENAI_BASE_URL") } base := strings.TrimSpace(os.Getenv("OPENAI_BASE_URL")) key := strings.TrimSpace(os.Getenv("OPENAI_API_KEY")) model := strings.TrimSpace(os.Getenv("OPENAI_MODEL")) if base == "" || key == "" { t.Fatal("OPENAI_BASE_URL and OPENAI_API_KEY required") } if model == "" { model = "mock-llm" } client := processing.NewOpenAIClient(key, base, model, 0, 2) eng := &processing.Engine{ Completer: client, Vector: processing.NoopVectorCategorizer{}, } ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second) defer cancel() out, err := eng.RunSteps(ctx, "live-probe", processing.ProductInput{ GTIN: "8712285326882", Name: "Vox SWA-8000W", Description: "Washer dryer combo", Mapped: map[string]any{"name": "Vox SWA-8000W", "description": "Washer dryer combo", "category": "demo-electronics", "brand": "Vox"}, Language: "en", EnhanceUserTemplate: aiprompts.CategoryEnhanceUserTemplate, EnhanceSystemTemplate: `Retail product copywriter. Reply with ONLY JSON. Schema: {"name":"string","description":"string"}`, TitleTemplate: map[string]any{ "separator": " ", "elements": []any{ map[string]any{"type": "variable", "value": "brand"}, map[string]any{"type": "text", "value": " "}, map[string]any{"type": "variable", "value": "product_model"}, }, }, }, "enhance_only", nil, processing.StepPolicy{AllowAI: true}) if err != nil { t.Fatal(err) } t.Logf("ProcessedName=%q AIProviderMode=%q", out.ProcessedName, out.AIProviderMode) lower := strings.ToLower(out.ProcessedName) for _, p := range []string{"title formula", "follow any", "short retail title", "use attrs", "schema:", "reply with only json"} { if strings.Contains(lower, p) { t.Fatalf("polluted title %q contains %q", out.ProcessedName, p) } } if !strings.Contains(lower, "vox") { t.Fatalf("ProcessedName=%q want Vox feed title", out.ProcessedName) } }