v0.4.0 3027a40

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

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 2

Tags 45

↑↓ moveenter openesc close