package sharedassets import ( "io/fs" "strings" "testing" "testing/fstest" ) func TestModulePromptFSCombinesModuleAndSharedPrompts(t *testing.T) { sharedFS := fstest.MapFS{ "shared/system.md": {Data: []byte("system")}, "shared/reference.md": {Data: []byte("reference")}, "nested/transcript.md": {Data: []byte("transcript")}, } fsys, err := ModulePromptFS("module.test", fstest.MapFS{ "assets/prompts/module.test.yaml": {Data: []byte("id: module.test")}, "assets/prompts/task.md": {Data: []byte("task")}, }, []ModulePromptFile{ {Name: "module.test.yaml", Path: "assets/prompts/module.test.yaml"}, {Name: "task.md", Path: "assets/prompts/task.md"}, }, SharedPromptFile{Name: "system.md", FS: sharedFS, Path: "shared/system.md"}, SharedPromptFile{Name: "reference.md", FS: sharedFS, Path: "shared/reference.md"}, SharedPromptFile{Name: "transcript.md", FS: sharedFS, Path: "nested/transcript.md"}, ) if err != nil { t.Fatalf("ModulePromptFS() error = %v, want nil", err) } tests := map[string]string{ "assets/prompts/module.test/module.test.yaml": "id: module.test", "assets/prompts/module.test/task.md": "task", "assets/prompts/module.test/sharedassets/system.md": "system", "assets/prompts/module.test/sharedassets/reference.md": "reference", "assets/prompts/module.test/sharedassets/transcript.md": "transcript", } for path, want := range tests { data, err := fs.ReadFile(fsys, path) if err != nil { t.Fatalf("ReadFile(%q) error = %v, want nil", path, err) } if string(data) != want { t.Fatalf("ReadFile(%q) = %q, want %q", path, data, want) } } entries, err := fs.ReadDir(fsys, ".") if err != nil { t.Fatalf("ReadDir(.) error = %v, want nil", err) } if len(entries) != 1 || entries[0].Name() != "assets" || !entries[0].IsDir() { t.Fatalf("ReadDir(.) = %#v, want assets directory", entries) } entries, err = fs.ReadDir(fsys, "assets/prompts/module.test/sharedassets") if err != nil { t.Fatalf("ReadDir(sharedassets) error = %v, want nil", err) } if len(entries) != 3 || entries[0].Name() != "reference.md" || entries[1].Name() != "system.md" || entries[2].Name() != "transcript.md" { t.Fatalf("ReadDir(sharedassets) = %#v, want sorted shared prompt entries", entries) } } func TestModulePromptFSRejectsMissingModuleFile(t *testing.T) { _, err := ModulePromptFS("module.test", fstest.MapFS{}, []ModulePromptFile{ {Name: "task.md", Path: "assets/prompts/task.md"}, }) if err == nil || !strings.Contains(err.Error(), "read module prompt asset assets/prompts/task.md") { t.Fatalf("ModulePromptFS() error = %v, want missing module asset context", err) } } func TestModulePromptFSRejectsMissingSharedFile(t *testing.T) { _, err := ModulePromptFS("module.test", fstest.MapFS{ "assets/prompts/task.md": {Data: []byte("task")}, }, []ModulePromptFile{ {Name: "task.md", Path: "assets/prompts/task.md"}, }, SharedPromptFile{Name: "system.md", FS: fstest.MapFS{}, Path: "shared/system.md"}) if err == nil || !strings.Contains(err.Error(), "read shared prompt asset shared/system.md") { t.Fatalf("ModulePromptFS() error = %v, want missing shared asset context", err) } } func TestModulePromptFSRejectsNestedVirtualFileName(t *testing.T) { _, err := ModulePromptFS("module.test", fstest.MapFS{ "assets/prompts/task.md": {Data: []byte("task")}, }, []ModulePromptFile{ {Name: "nested/task.md", Path: "assets/prompts/task.md"}, }) if err == nil || !strings.Contains(err.Error(), "must not contain path separators") { t.Fatalf("ModulePromptFS() error = %v, want nested file name error", err) } } func TestModulePromptFSRejectsNestedSharedFileName(t *testing.T) { _, err := ModulePromptFS("module.test", fstest.MapFS{ "assets/prompts/task.md": {Data: []byte("task")}, }, []ModulePromptFile{ {Name: "task.md", Path: "assets/prompts/task.md"}, }, SharedPromptFile{Name: "nested/system.md", FS: fstest.MapFS{}, Path: "shared/system.md"}) if err == nil || !strings.Contains(err.Error(), "shared prompt file name") || !strings.Contains(err.Error(), "must not contain path separators") { t.Fatalf("ModulePromptFS() error = %v, want nested shared file name error", err) } } func TestModulePromptFSRejectsInvalidModuleDir(t *testing.T) { _, err := ModulePromptFS(".", fstest.MapFS{}, nil) if err == nil || !strings.Contains(err.Error(), "module prompt directory") { t.Fatalf("ModulePromptFS() error = %v, want module directory context", err) } } func TestModulePromptFSRejectsNilFilesystems(t *testing.T) { _, err := ModulePromptFS("module.test", nil, nil) if err == nil || !strings.Contains(err.Error(), "module prompt filesystem must not be nil") { t.Fatalf("ModulePromptFS() error = %v, want nil module filesystem error", err) } _, err = ModulePromptFS("module.test", fstest.MapFS{}, nil, SharedPromptFile{Name: "system.md", Path: "shared/system.md"}) if err == nil || !strings.Contains(err.Error(), "shared prompt file \"system.md\" filesystem must not be nil") { t.Fatalf("ModulePromptFS() error = %v, want nil shared filesystem error", err) } }