priority_test.go

  1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2//
  3// SPDX-License-Identifier: AGPL-3.0-or-later
  4
  5package lunatask_test
  6
  7import (
  8	"encoding/json"
  9	"testing"
 10
 11	lunatask "git.secluded.site/go-lunatask"
 12)
 13
 14// --- AllPriorities Function ---
 15
 16func TestAllPriorities(t *testing.T) {
 17	t.Parallel()
 18
 19	priorities := lunatask.AllPriorities()
 20
 21	// Check count
 22	if got := len(priorities); got != 5 {
 23		t.Fatalf("AllPriorities() returned %d values, want 5", got)
 24	}
 25
 26	// Check order (lowest to highest)
 27	expected := []lunatask.Priority{
 28		lunatask.PriorityLowest,
 29		lunatask.PriorityLow,
 30		lunatask.PriorityNormal,
 31		lunatask.PriorityHigh,
 32		lunatask.PriorityHighest,
 33	}
 34	for i, want := range expected {
 35		if priorities[i] != want {
 36			t.Errorf("AllPriorities()[%d] = %d, want %d", i, priorities[i], want)
 37		}
 38	}
 39
 40	// Check roundtrip: each value should be parseable
 41	for _, priority := range priorities {
 42		parsed, err := lunatask.ParsePriority(priority.String())
 43		if err != nil {
 44			t.Errorf("ParsePriority(%q) failed: %v", priority.String(), err)
 45		}
 46
 47		if parsed != priority {
 48			t.Errorf("ParsePriority(%q) = %d, want %d", priority.String(), parsed, priority)
 49		}
 50	}
 51}
 52
 53// --- Priority Type Constants ---
 54
 55func TestPriority_Constants(t *testing.T) {
 56	t.Parallel()
 57
 58	tests := []struct {
 59		name  string
 60		value lunatask.Priority
 61		want  int
 62	}{
 63		{"lowest", lunatask.PriorityLowest, -2},
 64		{"low", lunatask.PriorityLow, -1},
 65		{"normal", lunatask.PriorityNormal, 0},
 66		{"high", lunatask.PriorityHigh, 1},
 67		{"highest", lunatask.PriorityHighest, 2},
 68	}
 69
 70	for _, tc := range tests {
 71		t.Run(tc.name, func(t *testing.T) {
 72			t.Parallel()
 73
 74			if int(tc.value) != tc.want {
 75				t.Errorf("Priority constant = %d, want %d", tc.value, tc.want)
 76			}
 77		})
 78	}
 79}
 80
 81// --- Priority String Method ---
 82
 83func TestPriority_String(t *testing.T) {
 84	t.Parallel()
 85
 86	tests := []struct {
 87		name  string
 88		value lunatask.Priority
 89		want  string
 90	}{
 91		{"lowest", lunatask.PriorityLowest, "lowest"},
 92		{"low", lunatask.PriorityLow, "low"},
 93		{"normal", lunatask.PriorityNormal, "normal"},
 94		{"high", lunatask.PriorityHigh, "high"},
 95		{"highest", lunatask.PriorityHighest, "highest"},
 96	}
 97
 98	for _, tc := range tests {
 99		t.Run(tc.name, func(t *testing.T) {
100			t.Parallel()
101
102			if got := tc.value.String(); got != tc.want {
103				t.Errorf("Priority(%d).String() = %q, want %q", tc.value, got, tc.want)
104			}
105		})
106	}
107}
108
109func TestPriority_String_Unknown(t *testing.T) {
110	t.Parallel()
111
112	p := lunatask.Priority(99)
113	if got := p.String(); got != "Priority(99)" {
114		t.Errorf("Priority(99).String() = %q, want %q", got, "Priority(99)")
115	}
116}
117
118// --- Priority Valid Method ---
119
120func TestPriority_Valid(t *testing.T) {
121	t.Parallel()
122
123	tests := []struct {
124		name  string
125		value lunatask.Priority
126		want  bool
127	}{
128		{"lowest", lunatask.PriorityLowest, true},
129		{"low", lunatask.PriorityLow, true},
130		{"normal", lunatask.PriorityNormal, true},
131		{"high", lunatask.PriorityHigh, true},
132		{"highest", lunatask.PriorityHighest, true},
133		{"below_range", lunatask.Priority(-3), false},
134		{"above_range", lunatask.Priority(3), false},
135		{"way_above", lunatask.Priority(99), false},
136	}
137
138	for _, tc := range tests {
139		t.Run(tc.name, func(t *testing.T) {
140			t.Parallel()
141
142			if got := tc.value.Valid(); got != tc.want {
143				t.Errorf("Priority(%d).Valid() = %v, want %v", tc.value, got, tc.want)
144			}
145		})
146	}
147}
148
149// --- ParsePriority Function ---
150
151func TestParsePriority(t *testing.T) {
152	t.Parallel()
153
154	tests := []struct {
155		name    string
156		input   string
157		want    lunatask.Priority
158		wantErr bool
159	}{
160		{"lowest_lower", "lowest", lunatask.PriorityLowest, false},
161		{"lowest_upper", "LOWEST", lunatask.PriorityLowest, false},
162		{"lowest_mixed", "LoWeSt", lunatask.PriorityLowest, false},
163		{"low_lower", "low", lunatask.PriorityLow, false},
164		{"low_upper", "LOW", lunatask.PriorityLow, false},
165		{"normal_lower", "normal", lunatask.PriorityNormal, false},
166		{"normal_upper", "NORMAL", lunatask.PriorityNormal, false},
167		{"high_lower", "high", lunatask.PriorityHigh, false},
168		{"high_upper", "HIGH", lunatask.PriorityHigh, false},
169		{"highest_lower", "highest", lunatask.PriorityHighest, false},
170		{"highest_upper", "HIGHEST", lunatask.PriorityHighest, false},
171		{"invalid", "invalid", 0, true},
172		{"empty", "", 0, true},
173		{"numeric", "1", 0, true},
174	}
175
176	for _, testCase := range tests {
177		t.Run(testCase.name, func(t *testing.T) {
178			t.Parallel()
179
180			got, err := lunatask.ParsePriority(testCase.input)
181			if (err != nil) != testCase.wantErr {
182				t.Errorf("ParsePriority(%q) error = %v, wantErr %v", testCase.input, err, testCase.wantErr)
183
184				return
185			}
186
187			if !testCase.wantErr && got != testCase.want {
188				t.Errorf("ParsePriority(%q) = %d, want %d", testCase.input, got, testCase.want)
189			}
190		})
191	}
192}
193
194// --- Priority JSON Marshaling ---
195
196func TestPriority_MarshalJSON(t *testing.T) {
197	t.Parallel()
198
199	tests := []struct {
200		name  string
201		value lunatask.Priority
202		want  string
203	}{
204		{"lowest", lunatask.PriorityLowest, "-2"},
205		{"low", lunatask.PriorityLow, "-1"},
206		{"normal", lunatask.PriorityNormal, "0"},
207		{"high", lunatask.PriorityHigh, "1"},
208		{"highest", lunatask.PriorityHighest, "2"},
209	}
210
211	for _, testCase := range tests {
212		t.Run(testCase.name, func(t *testing.T) {
213			t.Parallel()
214
215			got, err := json.Marshal(testCase.value)
216			if err != nil {
217				t.Fatalf("Marshal error: %v", err)
218			}
219
220			if string(got) != testCase.want {
221				t.Errorf("json.Marshal(Priority) = %s, want %s", got, testCase.want)
222			}
223		})
224	}
225}
226
227func TestPriority_UnmarshalJSON(t *testing.T) {
228	t.Parallel()
229
230	tests := []struct {
231		name    string
232		input   string
233		want    lunatask.Priority
234		wantErr bool
235	}{
236		{"lowest", "-2", lunatask.PriorityLowest, false},
237		{"low", "-1", lunatask.PriorityLow, false},
238		{"normal", "0", lunatask.PriorityNormal, false},
239		{"high", "1", lunatask.PriorityHigh, false},
240		{"highest", "2", lunatask.PriorityHighest, false},
241		{"null", "null", lunatask.PriorityNormal, false},
242		{"out_of_range_high", "5", 0, true},
243		{"out_of_range_low", "-5", 0, true},
244		{"string", `"high"`, 0, true},
245	}
246
247	for _, testCase := range tests {
248		t.Run(testCase.name, func(t *testing.T) {
249			t.Parallel()
250
251			var got lunatask.Priority
252
253			err := json.Unmarshal([]byte(testCase.input), &got)
254
255			if (err != nil) != testCase.wantErr {
256				t.Errorf("Unmarshal error = %v, wantErr %v", err, testCase.wantErr)
257
258				return
259			}
260
261			if !testCase.wantErr && got != testCase.want {
262				t.Errorf("Unmarshal(%s) = %d, want %d", testCase.input, got, testCase.want)
263			}
264		})
265	}
266}
267
268// --- TaskBuilder Priority Method ---
269
270func TestTaskBuilder_Priority(t *testing.T) {
271	t.Parallel()
272
273	server, capture := newPOSTServer(t, "/tasks", singleTaskResponseBody)
274	defer server.Close()
275
276	client := lunatask.NewClient(testToken, lunatask.BaseURL(server.URL))
277
278	_, err := client.NewTask("High priority task").
279		Priority(lunatask.PriorityHigh).
280		Create(ctx())
281	if err != nil {
282		t.Fatalf("error = %v", err)
283	}
284
285	assertBodyFieldFloat(t, capture.Body, "priority", 1)
286}
287
288func TestTaskBuilder_Priority_AllValues(t *testing.T) {
289	t.Parallel()
290
291	tests := []struct {
292		name     string
293		priority lunatask.Priority
294		want     float64
295	}{
296		{"lowest", lunatask.PriorityLowest, -2},
297		{"low", lunatask.PriorityLow, -1},
298		{"normal", lunatask.PriorityNormal, 0},
299		{"high", lunatask.PriorityHigh, 1},
300		{"highest", lunatask.PriorityHighest, 2},
301	}
302
303	for _, testCase := range tests {
304		t.Run(testCase.name, func(t *testing.T) {
305			t.Parallel()
306
307			server, capture := newPOSTServer(t, "/tasks", singleTaskResponseBody)
308			defer server.Close()
309
310			client := lunatask.NewClient(testToken, lunatask.BaseURL(server.URL))
311
312			_, err := client.NewTask("Task").
313				Priority(testCase.priority).
314				Create(ctx())
315			if err != nil {
316				t.Fatalf("error = %v", err)
317			}
318
319			assertBodyFieldFloat(t, capture.Body, "priority", testCase.want)
320		})
321	}
322}
323
324// --- TaskUpdateBuilder Priority Method ---
325
326func TestTaskUpdateBuilder_Priority(t *testing.T) {
327	t.Parallel()
328
329	server, capture := newPUTServer(t, "/tasks/"+taskID, singleTaskResponseBody)
330	defer server.Close()
331
332	client := lunatask.NewClient(testToken, lunatask.BaseURL(server.URL))
333
334	_, err := client.NewTaskUpdate(taskID).
335		Priority(lunatask.PriorityLowest).
336		Update(ctx())
337	if err != nil {
338		t.Fatalf("error = %v", err)
339	}
340
341	assertBodyFieldFloat(t, capture.Body, "priority", -2)
342}
343
344func TestTaskUpdateBuilder_Priority_AllValues(t *testing.T) {
345	t.Parallel()
346
347	tests := []struct {
348		name     string
349		priority lunatask.Priority
350		want     float64
351	}{
352		{"lowest", lunatask.PriorityLowest, -2},
353		{"low", lunatask.PriorityLow, -1},
354		{"normal", lunatask.PriorityNormal, 0},
355		{"high", lunatask.PriorityHigh, 1},
356		{"highest", lunatask.PriorityHighest, 2},
357	}
358
359	for _, testCase := range tests {
360		t.Run(testCase.name, func(t *testing.T) {
361			t.Parallel()
362
363			server, capture := newPUTServer(t, "/tasks/"+taskID, singleTaskResponseBody)
364			defer server.Close()
365
366			client := lunatask.NewClient(testToken, lunatask.BaseURL(server.URL))
367
368			_, err := client.NewTaskUpdate(taskID).
369				Priority(testCase.priority).
370				Update(ctx())
371			if err != nil {
372				t.Fatalf("error = %v", err)
373			}
374
375			assertBodyFieldFloat(t, capture.Body, "priority", testCase.want)
376		})
377	}
378}