1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package domain_test
4
5import (
6 "strings"
7 "testing"
8
9 "github.com/stretchr/testify/assert"
10 "github.com/stretchr/testify/require"
11
12 "bnema.dev/ermite/internal/domain"
13)
14
15func TestNormalizeTopics(t *testing.T) {
16 t.Parallel()
17 many := func(n int) []string {
18 var out []string
19 for i := range n {
20 out = append(out, "t"+strings.Repeat("x", i))
21 }
22 return out
23 }
24 tests := []struct {
25 name string
26 in []string
27 want []string
28 bad bool
29 }{
30 {name: "nil", in: nil, want: nil},
31 {name: "empty", in: []string{}, want: nil},
32 {name: "lowercased", in: []string{"Go"}, want: []string{"go"}},
33 {name: "sorted", in: []string{"zig", "c", "go"}, want: []string{"c", "go", "zig"}},
34 {name: "deduplicated after lowercasing", in: []string{"Go", "go", "GO"}, want: []string{"go"}},
35 {name: "digits and hyphens", in: []string{"3d-printing", "0"}, want: []string{"0", "3d-printing"}},
36 {name: "50 characters", in: []string{strings.Repeat("a", 50)}, want: []string{strings.Repeat("a", 50)}},
37 {name: "exactly 20", in: many(20), want: many(20)},
38 {name: "duplicates do not count twice", in: append(many(20), "t", "tx"), want: many(20)},
39 {name: "21", in: many(21), bad: true},
40 {name: "51 characters", in: []string{strings.Repeat("a", 51)}, bad: true},
41 {name: "empty topic", in: []string{""}, bad: true},
42 {name: "leading hyphen", in: []string{"-go"}, bad: true},
43 {name: "underscore", in: []string{"a_b"}, bad: true},
44 {name: "space", in: []string{"a b"}, bad: true},
45 {name: "dot", in: []string{"a.b"}, bad: true},
46 {name: "non-ASCII", in: []string{"café"}, bad: true},
47 {name: "one bad among good", in: []string{"go", "no!"}, bad: true},
48 }
49 for _, tt := range tests {
50 t.Run(tt.name, func(t *testing.T) {
51 t.Parallel()
52 got, err := domain.NormalizeTopics(tt.in)
53 if tt.bad {
54 require.ErrorIs(t, err, domain.ErrInvalid)
55 assert.Nil(t, got)
56 return
57 }
58 require.NoError(t, err)
59 assert.Equal(t, tt.want, got)
60 })
61 }
62}
63
64func TestRepoEffectiveSettings(t *testing.T) {
65 custom := domain.RepoSettings{AllowedMergeModes: []domain.MergeMode{domain.MergeMode("squash")}, Issues: domain.IssuesPublic}
66 for _, tc := range []struct {
67 name string
68 settings, want domain.RepoSettings
69 }{
70 {"unset", domain.RepoSettings{}, domain.DefaultRepoSettings()},
71 {"custom", custom, custom},
72 } {
73 t.Run(tc.name, func(t *testing.T) {
74 repo := domain.Repo{Settings: tc.settings}
75 assert.Equal(t, tc.want, repo.EffectiveSettings())
76 assert.Equal(t, tc.settings, repo.Settings)
77 })
78 }
79}
80
81func TestRepoIssuePresentationRules(t *testing.T) {
82 for _, tc := range []struct {
83 mode domain.IssuesMode
84 enabled, receipt bool
85 }{
86 {"", false, false}, {domain.IssuesOff, false, false},
87 {domain.IssuesOwner, true, false}, {domain.IssuesPublic, true, true},
88 } {
89 t.Run(string(tc.mode), func(t *testing.T) {
90 s := domain.RepoSettings{Issues: tc.mode}
91 assert.Equal(t, tc.enabled, s.IssuesEnabled())
92 assert.Equal(t, tc.receipt, s.ShowsIssueSubmissionReceipt())
93 assert.Equal(t, tc.receipt, s.AcceptsAnonymousIssues())
94 })
95 }
96}