1package url
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7)
8
9func TestNormalize(t *testing.T) {
10 tests := []struct {
11 name string
12 input string
13 want string
14 }{
15 {
16 name: "empty string",
17 input: "",
18 want: "",
19 },
20 {
21 name: "http scheme unchanged",
22 input: "http://example.com",
23 want: "http://example.com",
24 },
25 {
26 name: "https scheme unchanged",
27 input: "https://example.com",
28 want: "https://example.com",
29 },
30 {
31 name: "file scheme unchanged",
32 input: "file:///path/to/file.html",
33 want: "file:///path/to/file.html",
34 },
35 {
36 name: "dumb scheme unchanged",
37 input: "dumb://home",
38 want: "dumb://home",
39 },
40 {
41 name: "about scheme unchanged",
42 input: "about:blank",
43 want: "about:blank",
44 },
45 {
46 name: "domain gets https",
47 input: "example.com",
48 want: "https://example.com",
49 },
50 {
51 name: "domain with path gets https",
52 input: "example.com/path",
53 want: "https://example.com/path",
54 },
55 {
56 name: "search query unchanged",
57 input: "hello world",
58 want: "hello world",
59 },
60 {
61 name: "single word unchanged",
62 input: "hello",
63 want: "hello",
64 },
65 }
66
67 for _, tt := range tests {
68 t.Run(tt.name, func(t *testing.T) {
69 got := Normalize(tt.input)
70 if got != tt.want {
71 t.Errorf("Normalize(%q) = %q, want %q", tt.input, got, tt.want)
72 }
73 })
74 }
75}
76
77func TestNormalize_LocalFiles(t *testing.T) {
78 // Create a temporary file for testing
79 tmpDir := t.TempDir()
80 tmpFile := filepath.Join(tmpDir, "test.html")
81 if err := os.WriteFile(tmpFile, []byte("<html></html>"), 0644); err != nil {
82 t.Fatalf("failed to create temp file: %v", err)
83 }
84
85 // Create a subdirectory with a file
86 subDir := filepath.Join(tmpDir, "subdir")
87 if err := os.Mkdir(subDir, 0755); err != nil {
88 t.Fatalf("failed to create subdir: %v", err)
89 }
90 subFile := filepath.Join(subDir, "page.html")
91 if err := os.WriteFile(subFile, []byte("<html></html>"), 0644); err != nil {
92 t.Fatalf("failed to create subdir file: %v", err)
93 }
94
95 tests := []struct {
96 name string
97 input string
98 want string
99 }{
100 {
101 name: "absolute path to existing file",
102 input: tmpFile,
103 want: "file://" + tmpFile,
104 },
105 {
106 name: "absolute path to existing directory",
107 input: tmpDir,
108 want: "file://" + tmpDir,
109 },
110 {
111 name: "non-existent absolute path returned unchanged",
112 input: "/nonexistent/file.html",
113 want: "/nonexistent/file.html",
114 },
115 {
116 name: "non-existent relative path with dot prefix returned unchanged",
117 input: "./nonexistent/file.html",
118 want: "./nonexistent/file.html",
119 },
120 {
121 name: "non-existent home path returned unchanged",
122 input: "~/nonexistent/file.html",
123 want: "~/nonexistent/file.html",
124 },
125 }
126
127 for _, tt := range tests {
128 t.Run(tt.name, func(t *testing.T) {
129 got := Normalize(tt.input)
130 if got != tt.want {
131 t.Errorf("Normalize(%q) = %q, want %q", tt.input, got, tt.want)
132 }
133 })
134 }
135}
136
137func TestNormalize_RelativePaths(t *testing.T) {
138 // Create a temp file in current directory
139 tmpFile, err := os.CreateTemp(".", "test-*.html")
140 if err != nil {
141 t.Fatalf("failed to create temp file: %v", err)
142 }
143 tmpFile.Close()
144 defer os.Remove(tmpFile.Name())
145
146 // Get absolute path for comparison
147 absPath, err := filepath.Abs(tmpFile.Name())
148 if err != nil {
149 t.Fatalf("failed to get abs path: %v", err)
150 }
151
152 t.Run("relative path to existing file", func(t *testing.T) {
153 got := Normalize(tmpFile.Name())
154 want := "file://" + absPath
155 if got != want {
156 t.Errorf("Normalize(%q) = %q, want %q", tmpFile.Name(), got, want)
157 }
158 })
159}
160
161func TestExpandHome(t *testing.T) {
162 home, err := os.UserHomeDir()
163 if err != nil {
164 t.Skip("cannot get home directory")
165 }
166
167 tests := []struct {
168 name string
169 input string
170 want string
171 }{
172 {
173 name: "tilde expansion",
174 input: "~/Documents",
175 want: filepath.Join(home, "Documents"),
176 },
177 {
178 name: "no tilde unchanged",
179 input: "/absolute/path",
180 want: "/absolute/path",
181 },
182 {
183 name: "relative path unchanged",
184 input: "./relative/path",
185 want: "./relative/path",
186 },
187 {
188 name: "tilde in middle unchanged",
189 input: "/path/~/file",
190 want: "/path/~/file",
191 },
192 }
193
194 for _, tt := range tests {
195 t.Run(tt.name, func(t *testing.T) {
196 got := expandHome(tt.input)
197 if got != tt.want {
198 t.Errorf("expandHome(%q) = %q, want %q", tt.input, got, tt.want)
199 }
200 })
201 }
202}
203
204func TestLooksLikeURL(t *testing.T) {
205 tests := []struct {
206 name string
207 input string
208 want bool
209 }{
210 {
211 name: "empty string",
212 input: "",
213 want: false,
214 },
215 {
216 name: "http URL",
217 input: "http://example.com",
218 want: true,
219 },
220 {
221 name: "https URL",
222 input: "https://example.com",
223 want: true,
224 },
225 {
226 name: "file URL",
227 input: "file:///path/to/file",
228 want: true,
229 },
230 {
231 name: "dumb URL",
232 input: "dumb://home",
233 want: true,
234 },
235 {
236 name: "about URL",
237 input: "about:blank",
238 want: true,
239 },
240 {
241 name: "domain",
242 input: "example.com",
243 want: true,
244 },
245 {
246 name: "domain with path",
247 input: "example.com/path",
248 want: true,
249 },
250 {
251 name: "search query",
252 input: "hello world",
253 want: false,
254 },
255 {
256 name: "single word",
257 input: "hello",
258 want: false,
259 },
260 }
261
262 for _, tt := range tests {
263 t.Run(tt.name, func(t *testing.T) {
264 got := LooksLikeURL(tt.input)
265 if got != tt.want {
266 t.Errorf("LooksLikeURL(%q) = %v, want %v", tt.input, got, tt.want)
267 }
268 })
269 }
270}