ui_test.go

  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}