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}