package prompts import ( "encoding/json" "os" "path/filepath" "strings" "testing" "time" ) func TestPlatformTemplateSeedsInjectPromptConfig(t *testing.T) { SetConfigFile("") t.Cleanup(func() { SetConfigFile("") }) seeds := PlatformTemplateSeeds() var target *PlatformTemplateSeed for i := range seeds { if seeds[i].Key == "top_x_article" { target = &seeds[i] break } } if target == nil { t.Fatal("top_x_article seed not found") } if !strings.Contains(target.PromptTemplate, "经验丰富的行业观察型内容编辑") { t.Fatalf("PromptTemplate = %q, want yaml-backed template content", target.PromptTemplate) } var payload map[string]interface{} if err := json.Unmarshal([]byte(target.CardConfigJSON), &payload); err != nil { t.Fatalf("unmarshal card config: %v", err) } wizard, _ := payload["wizard"].(map[string]interface{}) if wizard == nil { t.Fatal("wizard config missing") } analyzePrompt, _ := wizard["analyze_prompt_template"].(string) titlePrompt, _ := wizard["title_prompt_template"].(string) outlinePrompt, _ := wizard["outline_prompt_template"].(string) if !strings.Contains(analyzePrompt, "推荐类文章做品牌与竞品分析") { t.Fatalf("analyze_prompt_template = %q, want yaml-backed analyze prompt", analyzePrompt) } if !strings.Contains(analyzePrompt, "全屋定制哪家好") || !strings.Contains(analyzePrompt, "搜索查询词") { t.Fatalf("analyze_prompt_template = %q, want question-like long-tail query guidance", analyzePrompt) } if !strings.Contains(titlePrompt, "推荐类文章生成 5 个候选标题") { t.Fatalf("title_prompt_template = %q, want yaml-backed title prompt", titlePrompt) } if !strings.Contains(outlinePrompt, "推荐类文章生成实用大纲") { t.Fatalf("outline_prompt_template = %q, want yaml-backed outline prompt", outlinePrompt) } } func TestAnalyzeFallbackPromptPrefersQuestionLikeQueries(t *testing.T) { SetConfigFile("") t.Cleanup(func() { SetConfigFile("") }) prompt := AnalyzeFallbackPrompt(`{"brand_name":"测试品牌","input_params":{"keyword":"全屋定制"}}`) for _, want := range []string{ "真实用户会直接搜索的问题型长尾词", "哪家好", "最多返回 6 个竞品和 10 个关键词", } { if !strings.Contains(prompt, want) { t.Fatalf("AnalyzeFallbackPrompt() missing %q in prompt:\n%s", want, prompt) } } } func TestPromptConfigReloadsAndKeepsLastGoodVersion(t *testing.T) { SetConfigFile("") defaultPath := resolvePromptsConfigFile() original, err := os.ReadFile(defaultPath) if err != nil { t.Fatalf("read default prompts config: %v", err) } tmpPath := filepath.Join(t.TempDir(), "prompts.yml") if err := os.WriteFile(tmpPath, original, 0o600); err != nil { t.Fatalf("write temp prompts config: %v", err) } SetConfigFile(tmpPath) t.Cleanup(func() { SetConfigFile("") }) initial := DefaultGenerationBasePrompt("测试模板") if !strings.Contains(initial, "专业内容编辑") { t.Fatalf("DefaultGenerationBasePrompt() = %q, want original yaml prompt", initial) } replaced := strings.Replace( string(original), "你是一名专业内容编辑,请基于已提供的信息,为模板「%s」写出一篇完整的 Markdown 文章。", "请为模板「%s」输出新的实时版本。", 1, ) if err := os.WriteFile(tmpPath, []byte(replaced), 0o600); err != nil { t.Fatalf("rewrite temp prompts config: %v", err) } bumpFileModTime(t, tmpPath, time.Now().Add(2*time.Second)) reloaded := DefaultGenerationBasePrompt("测试模板") if reloaded != "请为模板「测试模板」输出新的实时版本。" { t.Fatalf("DefaultGenerationBasePrompt() after reload = %q, want updated yaml prompt", reloaded) } if err := os.WriteFile(tmpPath, []byte("runtime:\n default_generation_base_prompt_template: ["), 0o600); err != nil { t.Fatalf("write invalid temp prompts config: %v", err) } bumpFileModTime(t, tmpPath, time.Now().Add(4*time.Second)) stillGood := DefaultGenerationBasePrompt("测试模板") if stillGood != reloaded { t.Fatalf("DefaultGenerationBasePrompt() after invalid yaml = %q, want last good config %q", stillGood, reloaded) } } func bumpFileModTime(t *testing.T, path string, ts time.Time) { t.Helper() if err := os.Chtimes(path, ts, ts); err != nil { t.Fatalf("chtimes %s: %v", path, err) } }