v0.21.0 73bf644

normalize_test.go RawHistoryFolder

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}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close