util_test.go
⎇
Raw
1package util
2
3import "testing"
4
5func TestFormatDate(t *testing.T) {
6 tests := []struct {
7 iso, date, dateTime string
8 }{
9 {"2024-03-05T07:08:09.123Z", "2024-03-05", "2024-03-05 07:08:09 UTC"},
10 {"2024-12-31T23:59:59Z", "2024-12-31", "2024-12-31 23:59:59 UTC"},
11 // A non-UTC offset is converted to UTC, which moves the day.
12 {"2024-01-01T01:00:00+02:00", "2023-12-31", "2023-12-31 23:00:00 UTC"},
13 // git's %ci / %ai format, converted to UTC.
14 {"2025-01-02 10:00:00 +0000", "2025-01-02", "2025-01-02 10:00:00 UTC"},
15 {"2024-05-01 12:00:00 +0200", "2024-05-01", "2024-05-01 10:00:00 UTC"},
16 // A stored commit date in RFC 1123 form.
17 {"Thu, 2 Jan 2025 10:00:00 +0000", "2025-01-02", "2025-01-02 10:00:00 UTC"},
18 {"not a date", "not a date", "not a date"},
19 {"", "", ""},
20 }
21 for _, tt := range tests {
22 if got := FormatDate(tt.iso); got != tt.date {
23 t.Errorf("FormatDate(%q) = %q, want %q", tt.iso, got, tt.date)
24 }
25 if got := FormatDateTime(tt.iso); got != tt.dateTime {
26 t.Errorf("FormatDateTime(%q) = %q, want %q", tt.iso, got, tt.dateTime)
27 }
28 }
29}
30
31func TestLabelTextColor(t *testing.T) {
32 tests := []struct{ hex, want string }{
33 {"#ffffff", "#000000"},
34 {"#000000", "#ffffff"},
35 {"#ffff00", "#000000"},
36 {"#0000ff", "#ffffff"},
37 {"#808080", "#000000"}, // 128/255 is just above the 0.5 threshold
38 {"bogus", "#ffffff"},
39 }
40 for _, tt := range tests {
41 if got := LabelTextColor(tt.hex); got != tt.want {
42 t.Errorf("LabelTextColor(%q) = %q, want %q", tt.hex, got, tt.want)
43 }
44 }
45}
46
47func TestPaginate(t *testing.T) {
48 tests := []struct {
49 raw, total, per int
50 want Page
51 }{
52 {1, 0, 20, Page{1, 1, 0}},
53 {999, 45, 20, Page{3, 3, 40}},
54 {0, 45, 20, Page{1, 3, 0}},
55 {2, 45, 20, Page{2, 3, 20}},
56 }
57 for _, tt := range tests {
58 if got := Paginate(tt.raw, tt.total, tt.per); got != tt.want {
59 t.Errorf("Paginate(%d,%d,%d) = %+v, want %+v", tt.raw, tt.total, tt.per, got, tt.want)
60 }
61 }
62}
63
64func TestContentDisposition(t *testing.T) {
65 tests := []struct{ in, want string }{
66 {"a.txt", `attachment; filename="a.txt"; filename*=UTF-8''a.txt`},
67 {`dir/e"vil.txt`, `attachment; filename="e_vil.txt"; filename*=UTF-8''e%22vil.txt`},
68 {"ü.txt", `attachment; filename="ü.txt"; filename*=UTF-8''%C3%BC.txt`},
69 {"", `attachment; filename="file"; filename*=UTF-8''`},
70 {"it's.txt", `attachment; filename="it's.txt"; filename*=UTF-8''it%27s.txt`},
71 }
72 for _, tt := range tests {
73 if got := ContentDisposition("attachment", tt.in); got != tt.want {
74 t.Errorf("ContentDisposition(%q) =\n%q\nwant\n%q", tt.in, got, tt.want)
75 }
76 }
77}
78
79func TestValidNames(t *testing.T) {
80 for _, s := range []string{"ab", "a-b_1"} {
81 if !ValidUsername(s) {
82 t.Errorf("ValidUsername(%q) = false", s)
83 }
84 }
85 for _, s := range []string{"", "a.b", "a b", "a/b"} {
86 if ValidUsername(s) {
87 t.Errorf("ValidUsername(%q) = true", s)
88 }
89 }
90}
91
92func TestFormatDateTimeSQLite(t *testing.T) {
93 if got := FormatDateTime("2026-09-15 12:14:56"); got != "2026-09-15 12:14:56 UTC" {
94 t.Fatalf("got %q", got)
95 }
96}
97