1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package init //nolint:testpackage // testing internal validators
6
7import (
8 "errors"
9 "testing"
10)
11
12func TestValidateKeyFormat_Valid(t *testing.T) {
13 t.Parallel()
14
15 tests := []struct {
16 name string
17 input string
18 }{
19 {"simple key", "work"},
20 {"key with hyphen", "q1-goals"},
21 {"key with numbers", "area2"},
22 {"multiple hyphens", "my-special-area"},
23 }
24
25 for _, tc := range tests {
26 t.Run(tc.name, func(t *testing.T) {
27 t.Parallel()
28
29 if err := validateKeyFormat(tc.input); err != nil {
30 t.Errorf("validateKeyFormat(%q) = %v, want nil", tc.input, err)
31 }
32 })
33 }
34}
35
36func TestValidateKeyFormat_Invalid(t *testing.T) {
37 t.Parallel()
38
39 tests := []struct {
40 name string
41 input string
42 wantErr error
43 }{
44 {"empty key", "", errKeyRequired},
45 {"uppercase letters", "Work", errKeyFormat},
46 {"spaces", "my area", errKeyFormat},
47 {"underscores", "my_area", errKeyFormat},
48 {"leading hyphen", "-work", errKeyFormat},
49 {"trailing hyphen", "work-", errKeyFormat},
50 {"double hyphen", "my--area", errKeyFormat},
51 {"special characters", "work@home", errKeyFormat},
52 }
53
54 for _, tc := range tests {
55 t.Run(tc.name, func(t *testing.T) {
56 t.Parallel()
57
58 if err := validateKeyFormat(tc.input); !errors.Is(err, tc.wantErr) {
59 t.Errorf("validateKeyFormat(%q) = %v, want %v", tc.input, err, tc.wantErr)
60 }
61 })
62 }
63}
64
65func TestValidateID_Valid(t *testing.T) {
66 t.Parallel()
67
68 tests := []struct {
69 name string
70 input string
71 }{
72 {"valid UUID lowercase", "123e4567-e89b-12d3-a456-426614174000"},
73 {"valid UUID uppercase", "123E4567-E89B-12D3-A456-426614174000"},
74 }
75
76 for _, tc := range tests {
77 t.Run(tc.name, func(t *testing.T) {
78 t.Parallel()
79
80 if err := validateID(tc.input); err != nil {
81 t.Errorf("validateID(%q) = %v, want nil", tc.input, err)
82 }
83 })
84 }
85}
86
87func TestValidateID_Invalid(t *testing.T) {
88 t.Parallel()
89
90 tests := []struct {
91 name string
92 input string
93 wantErr error
94 }{
95 {"empty ID", "", errIDRequired},
96 {"too short", "123e4567-e89b", errIDFormat},
97 {"random string", "not-a-uuid", errIDFormat},
98 {"wrong characters", "123e4567-e89b-12d3-a456-42661417zzzz", errIDFormat},
99 }
100
101 for _, tc := range tests {
102 t.Run(tc.name, func(t *testing.T) {
103 t.Parallel()
104
105 if err := validateID(tc.input); !errors.Is(err, tc.wantErr) {
106 t.Errorf("validateID(%q) = %v, want %v", tc.input, err, tc.wantErr)
107 }
108 })
109 }
110}
111
112func TestParseEditIndex_Valid(t *testing.T) {
113 t.Parallel()
114
115 tests := []struct {
116 name string
117 input string
118 wantIdx int
119 }{
120 {"index 0", "edit:0", 0},
121 {"index 5", "edit:5", 5},
122 {"large index", "edit:999", 999},
123 {"negative index", "edit:-1", -1},
124 }
125
126 for _, testCase := range tests {
127 t.Run(testCase.name, func(t *testing.T) {
128 t.Parallel()
129
130 idx, valid := parseEditIndex(testCase.input)
131 if !valid {
132 t.Errorf("parseEditIndex(%q) valid = false, want true", testCase.input)
133 }
134
135 if idx != testCase.wantIdx {
136 t.Errorf("parseEditIndex(%q) idx = %d, want %d", testCase.input, idx, testCase.wantIdx)
137 }
138 })
139 }
140}
141
142func TestParseEditIndex_Invalid(t *testing.T) {
143 t.Parallel()
144
145 tests := []struct {
146 name string
147 input string
148 }{
149 {"back choice", "back"},
150 {"add choice", "add"},
151 {"done choice", "done"},
152 {"empty prefix", "edit:"},
153 {"non-numeric", "edit:abc"},
154 {"empty string", ""},
155 }
156
157 for _, testCase := range tests {
158 t.Run(testCase.name, func(t *testing.T) {
159 t.Parallel()
160
161 _, valid := parseEditIndex(testCase.input)
162 if valid {
163 t.Errorf("parseEditIndex(%q) valid = true, want false", testCase.input)
164 }
165 })
166 }
167}
168
169func TestTitleCase(t *testing.T) {
170 t.Parallel()
171
172 tests := []struct {
173 input string
174 want string
175 }{
176 {"area", "Area"},
177 {"goal", "Goal"},
178 {"notebook", "Notebook"},
179 {"habit", "Habit"},
180 {"a", "A"},
181 {"", ""},
182 {"already Capitalized", "Already Capitalized"},
183 }
184
185 for _, tc := range tests {
186 t.Run(tc.input, func(t *testing.T) {
187 t.Parallel()
188
189 if got := titleCase(tc.input); got != tc.want {
190 t.Errorf("titleCase(%q) = %q, want %q", tc.input, got, tc.want)
191 }
192 })
193 }
194}