package sharedassets import ( "io/fs" "strings" "testing" "testing/fstest" ) func TestModulePromptFSCombinesModuleAndSharedPrompts(t *testing.T) { fsys, err := ModulePromptFS("dnd.test", fstest.MapFS{ "assets/prompts/dnd.test.yaml": {Data: []byte("id: dnd.test")}, "assets/prompts/task.md": {Data: []byte("task")}, }, []ModulePromptFile{ {Name: "dnd.test.yaml", Path: "assets/prompts/dnd.test.yaml"}, {Name: "task.md", Path: "assets/prompts/task.md"}, }) if err != nil { t.Fatalf("ModulePromptFS() error = %v, want nil", err) } tests := map[string]string{ "assets/prompts/dnd.test/dnd.test.yaml": "id: dnd.test", "assets/prompts/dnd.test/task.md": "task", "assets/prompts/dnd.test/sharedassets/common-dnd-system.md": "", "assets/prompts/dnd.test/sharedassets/common-dnd-transcript.md": "", "assets/prompts/dnd.test/sharedassets/common-dnd-references.md": "", } 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 len(data) == 0 { t.Fatalf("ReadFile(%q) returned empty content", path) } if want != "" && !strings.Contains(string(data), want) { t.Fatalf("ReadFile(%q) = %q, want substring %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) } } func TestModulePromptFSRejectsMissingModuleFile(t *testing.T) { _, err := ModulePromptFS("dnd.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("dnd.test", fstest.MapFS{ "assets/prompts/task.md": {Data: []byte("task")}, }, []ModulePromptFile{ {Name: "task.md", Path: "assets/prompts/task.md"}, }, fstest.MapFS{}) if err == nil || !strings.Contains(err.Error(), "read shared prompt asset common-dnd-system.md") { t.Fatalf("modulePromptFS() error = %v, want missing shared asset context", err) } } func TestModulePromptFSRejectsNestedVirtualFileName(t *testing.T) { _, err := ModulePromptFS("dnd.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) } }