返回 DeepSeek-Reasonix
command_extra_test.go
根目录 / internal / command / command_extra_test.go
1 package command
2
3 import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8 )
9
10 // --- splitFrontmatter ---
11
12 func TestSplitFrontmatterNoFence(t *testing.T) {
13 fm, body := splitFrontmatter("just body text\nno fence")
14 if len(fm) != 0 {
15 t.Errorf("expected empty fm, got %v", fm)
16 }
17 if !strings.Contains(body, "just body text") {
18 t.Errorf("body = %q", body)
19 }
20 }
21
22 func TestSplitFrontmatterUnclosed(t *testing.T) {
23 fm, body := splitFrontmatter("---\nkey: val\n\nbody without closing")
24 if len(fm) != 0 {
25 t.Errorf("unclosed fence should return empty fm, got %v", fm)
26 }
27 if !strings.Contains(body, "---") {
28 t.Errorf("body should contain original content: %q", body)
29 }
30 }
31
32 func TestSplitFrontmatterEmptyBody(t *testing.T) {
33 fm, body := splitFrontmatter("---\nkey: val\n---\n")
34 if fm["key"] != "val" {
35 t.Errorf("key = %q", fm["key"])
36 }
37 if strings.TrimSpace(body) != "" {
38 t.Errorf("expected empty body, got %q", body)
39 }
40 }
41
42 func TestSplitFrontmatterQuotedValues(t *testing.T) {
43 fm, _ := splitFrontmatter("---\ndescription: \"quoted\"\n---\n")
44 if fm["description"] != "quoted" {
45 t.Errorf("description should be unquoted: %q", fm["description"])
46 }
47 }
48
49 func TestSplitFrontmatterCRLF(t *testing.T) {
50 fm, body := splitFrontmatter("---\r\nkey: val\r\n---\r\nbody\r\n")
51 if fm["key"] != "val" {
52 t.Errorf("key = %q", fm["key"])
53 }
54 if !strings.Contains(body, "body") {
55 t.Errorf("body = %q", body)
56 }
57 }
58
59 // --- Render edge cases ---
60
61 func TestRenderManyPositionals(t *testing.T) {
62 c := Command{Body: "$1 $2 $3 $4 $5 $6 $7 $8 $9"}
63 args := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i"}
64 got := c.Render(args)
65 if got != "a b c d e f g h i" {
66 t.Errorf("Render = %q", got)
67 }
68 }
69
70 func TestRenderSpecialChars(t *testing.T) {
71 c := Command{Body: "cmd: $1"}
72 got := c.Render([]string{`"hello" world`})
73 if !strings.Contains(got, `"hello" world`) {
74 t.Errorf("Render with quotes = %q", got)
75 }
76 }
77
78 func TestRenderBackslash(t *testing.T) {
79 c := Command{Body: "path: $1"}
80 got := c.Render([]string{`C:\Users\test`})
81 if !strings.Contains(got, `C:\Users\test`) {
82 t.Errorf("Render with backslash = %q", got)
83 }
84 }
85
86 func TestRenderDollarDollar(t *testing.T) {
87 c := Command{Body: "Price: $$100"}
88 got := c.Render(nil)
89 if got != "Price: $100" {
90 t.Errorf("Render $$ = %q", got)
91 }
92 }
93
94 func TestRenderNoTokens(t *testing.T) {
95 c := Command{Body: "no tokens here"}
96 got := c.Render([]string{"arg1", "arg2"})
97 if got != "no tokens here" {
98 t.Errorf("Render = %q", got)
99 }
100 }
101
102 // --- Load edge cases ---
103
104 func TestLoadEmptyDir(t *testing.T) {
105 dir := t.TempDir()
106 cmds, err := Load(dir)
107 if err != nil {
108 t.Fatalf("Load: %v", err)
109 }
110 if len(cmds) != 0 {
111 t.Errorf("empty dir should return 0 commands, got %d", len(cmds))
112 }
113 }
114
115 func TestLoadNestedSubdirs(t *testing.T) {
116 dir := t.TempDir()
117 write(t, dir, "a/b/c/deep.md", "---\ndescription: deep\n---\nDeep command.")
118 cmds, err := Load(dir)
119 if err != nil {
120 t.Fatalf("Load: %v", err)
121 }
122 if len(cmds) != 1 || cmds[0].Name != "a:b:c:deep" {
123 t.Errorf("deep nesting: %+v", cmds)
124 }
125 }
126
127 func TestLoadBOM(t *testing.T) {
128 dir := t.TempDir()
129 // Write a file with a UTF-8 BOM.
130 bom := string(rune(0xFEFF))
131 write(t, dir, "bom.md", bom+"---\ndescription: BOM test\n---\nBody with BOM.")
132 cmds, err := Load(dir)
133 if err != nil {
134 t.Fatalf("Load: %v", err)
135 }
136 if len(cmds) != 1 {
137 t.Fatalf("want 1 command, got %d", len(cmds))
138 }
139 if cmds[0].Description != "BOM test" {
140 t.Errorf("BOM not stripped: description = %q", cmds[0].Description)
141 }
142 if strings.Contains(cmds[0].Body, bom) {
143 t.Error("BOM should be stripped from body")
144 }
145 }
146
147 func TestLoadMalformedFile(t *testing.T) {
148 dir := t.TempDir()
149 // A file that can't be read (directory with .md extension — won't happen in
150 // practice but tests the error path).
151 os.MkdirAll(filepath.Join(dir, "bad.md"), 0o755)
152 // walkCommands skips directories even if named .md, so no error.
153 cmds, err := Load(dir)
154 if err != nil {
155 t.Fatalf("Load: %v", err)
156 }
157 if len(cmds) != 0 {
158 t.Errorf("directory named .md should be skipped, got %d", len(cmds))
159 }
160 }
161
162 func TestLoadSortedByName(t *testing.T) {
163 dir := t.TempDir()
164 write(t, dir, "zebra.md", "Z")
165 write(t, dir, "alpha.md", "A")
166 write(t, dir, "middle.md", "M")
167 cmds, err := Load(dir)
168 if err != nil {
169 t.Fatalf("Load: %v", err)
170 }
171 if len(cmds) != 3 {
172 t.Fatalf("want 3, got %d", len(cmds))
173 }
174 if cmds[0].Name != "alpha" || cmds[1].Name != "middle" || cmds[2].Name != "zebra" {
175 t.Errorf("not sorted: %v %v %v", cmds[0].Name, cmds[1].Name, cmds[2].Name)
176 }
177 }
178
178 lines GO