Files
BlackBean/pigo/internal/cli/prompts/prompts_config_test.go
T
2026-08-14 23:41:57 +08:00

116 lines
3.6 KiB
Go

package prompts
// Tests for settings-tier prompt templates (US-007, #338): LoadPromptPaths
// loads file/dir entries (warning on missing), and BuildSlashRegistry
// registers them at the settings tier (overridden by global same-name
// templates). The applyFileConfig parse test stays in package main
// (cmd/pigo/prompts_config_test.go) since it drives cliOptions.
import (
"os"
"path/filepath"
"testing"
"github.com/smallnest/pigo/internal/cli"
"github.com/smallnest/pigo/internal/cli/testutil"
"github.com/smallnest/pigo/internal/runtime"
)
func TestLoadSettingsPromptsFileDirMissing(t *testing.T) {
home := t.TempDir()
// file entry -> 1 cmd.
filePath := filepath.Join(home, "single.md")
if err := os.WriteFile(filePath, []byte("Single: $ARGUMENTS"), 0o644); err != nil {
t.Fatal(err)
}
// dir entry -> 2 cmds.
dirPath := filepath.Join(home, "promptsdir")
if err := os.MkdirAll(dirPath, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dirPath, "a.md"), []byte("A: $1"), 0o644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dirPath, "b.md"), []byte("B: $1"), 0o644); err != nil {
t.Fatal(err)
}
// missing entry -> 0 cmds (warned, not fatal).
missing := filepath.Join(home, "nope")
cmds := LoadPromptPaths([]string{filePath, dirPath, missing})
if len(cmds) != 3 {
t.Fatalf("got %d cmds, want 3 (file=1 + dir=2 + missing=0)", len(cmds))
}
names := map[string]bool{}
for _, c := range cmds {
names[c.Name] = true
}
for _, want := range []string{"single", "a", "b"} {
if !names[want] {
t.Errorf("missing cmd %q; got %v", want, names)
}
}
}
func TestBuildSlashRegistryLoadsSettingsPrompts(t *testing.T) {
home := t.TempDir()
t.Setenv("PIGO_HOME", home)
// A settings-tier prompt dir (loaded via configPrompts).
settingsDir := filepath.Join(home, "settings-prompts")
if err := os.MkdirAll(settingsDir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(settingsDir, "review.md"), []byte("FROM SETTINGS"), 0o644); err != nil {
t.Fatal(err)
}
reg, err := BuildSlashRegistry(&cli.LiveConfig{Model: "test", ProviderName: "test"}, nil, nil,
PromptTemplateSources{Settings: []string{settingsDir}})
if err != nil {
t.Fatalf("BuildSlashRegistry: %v", err)
}
cmd, ok := reg.Lookup("review")
if !ok {
t.Fatal("/review not found")
}
if got := cmd.Expand(""); got != "FROM SETTINGS" {
t.Errorf("settings prompt: got %q, want \"FROM SETTINGS\"", got)
}
}
func TestBuildSlashRegistryGlobalOverridesSettings(t *testing.T) {
home := t.TempDir()
t.Setenv("PIGO_HOME", home)
// global prompt (TierGlobal) under ~/.pigo/prompts.
testutil.WritePrompt(t, home, "prompts", "dup.md", "FROM GLOBAL")
// settings-tier prompt (file) of the same name, placed at the home root
// (not under prompts/, so the global loop does not also load it).
settingsFile := filepath.Join(home, "dup.md")
if err := os.WriteFile(settingsFile, []byte("FROM SETTINGS"), 0o644); err != nil {
t.Fatal(err)
}
reg, err := BuildSlashRegistry(&cli.LiveConfig{Model: "test", ProviderName: "test"}, nil, nil,
PromptTemplateSources{Settings: []string{settingsFile}})
if err != nil {
t.Fatalf("BuildSlashRegistry: %v", err)
}
cmd, ok := reg.Lookup("dup")
if !ok {
t.Fatal("/dup not found")
}
if got := cmd.Expand(""); got != "FROM GLOBAL" {
t.Errorf("global should override settings, got %q", got)
}
// The settings loser is shadowed with TierSettings.
found := false
for _, e := range reg.Shadowed() {
if e.Name == "dup" && e.Tier == runtime.TierSettings {
found = true
}
}
if !found {
t.Errorf("settings dup should be shadowed with TierSettings, got %v", reg.Shadowed())
}
}