v0.35.2 80d5067

name_test.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package domain_test
4
5import (
6	"errors"
7	"strings"
8	"testing"
9
10	"github.com/stretchr/testify/assert"
11	"github.com/stretchr/testify/require"
12
13	"bnema.dev/ermite/internal/domain"
14)
15
16func TestParseRepoName(t *testing.T) {
17	t.Parallel()
18	tests := []struct {
19		in         string
20		valid      bool
21		suggestion string
22	}{
23		{in: "ermite", valid: true},
24		{in: "a", valid: true},
25		{in: "my-repo_1.0", valid: true},
26		{in: "x.y", valid: true},
27		{in: "0", valid: true},
28		{in: strings.Repeat("a", 100), valid: true},
29		{in: strings.Repeat("a", 101)},
30		{in: ""},
31		{in: "Ermite", suggestion: "ermite"},
32		{in: "My-Repo", suggestion: "my-repo"},
33		{in: "UPPER.git"}, // lowercase would still end in .git: no suggestion
34		{in: ".hidden"},
35		{in: "trailing."},
36		{in: "a..b"},
37		{in: "tools.git"},
38		{in: "-"},
39		{in: "robots.txt"},
40		{in: "favicon.ico"},
41		{in: "-dash-ok", valid: true},
42		{in: "has space"},
43		{in: "a/b"},
44		{in: "caf\u00e9"},
45		{in: "a\x00b"},
46	}
47	for _, tt := range tests {
48		t.Run(tt.in, func(t *testing.T) {
49			t.Parallel()
50			n, err := domain.ParseRepoName(tt.in)
51			if tt.valid {
52				require.NoError(t, err)
53				assert.Equal(t, tt.in, n.String())
54				assert.False(t, n.IsZero())
55				return
56			}
57			require.Error(t, err)
58			assert.ErrorIs(t, err, domain.ErrInvalidName)
59			assert.True(t, n.IsZero())
60			var ine *domain.InvalidNameError
61			require.True(t, errors.As(err, &ine))
62			assert.Equal(t, tt.suggestion, ine.Suggestion)
63			if tt.suggestion != "" {
64				assert.Contains(t, err.Error(), tt.suggestion)
65			}
66		})
67	}
68}
69
70func TestParseRepoPath(t *testing.T) {
71	t.Parallel()
72	tests := []struct {
73		in    string
74		want  string
75		valid bool
76	}{
77		{"tools", "tools", true},
78		{"tools.git", "tools", true},
79		{"tools.git.git", "", false}, // only one suffix is stripped
80		{".git", "", false},
81		{"Tools.git", "", false},
82		{"", "", false},
83	}
84	for _, tt := range tests {
85		t.Run(tt.in, func(t *testing.T) {
86			t.Parallel()
87			n, err := domain.ParseRepoPath(tt.in)
88			if !tt.valid {
89				assert.ErrorIs(t, err, domain.ErrInvalidName)
90				return
91			}
92			require.NoError(t, err)
93			assert.Equal(t, tt.want, n.String())
94		})
95	}
96}
97
98func TestParseVisibility(t *testing.T) {
99	t.Parallel()
100	for in, want := range map[string]domain.Visibility{"public": domain.VisibilityPublic, "private": domain.VisibilityPrivate} {
101		got, err := domain.ParseVisibility(in)
102		require.NoError(t, err)
103		assert.Equal(t, want, got)
104	}
105	for _, in := range []string{"", "Public", "secret"} {
106		_, err := domain.ParseVisibility(in)
107		assert.ErrorIs(t, err, domain.ErrInvalidVisibility, in)
108	}
109}
110
111func TestPrincipal(t *testing.T) {
112	t.Parallel()
113	var zero domain.Principal
114	assert.True(t, zero.IsAnonymous())
115	assert.False(t, zero.IsRoot())
116	assert.True(t, domain.Root().IsRoot())
117	assert.Equal(t, "anonymous", domain.Anonymous().Label())
118}

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 4

Tags 45

↑↓ moveenter openesc close