Skip to content

Commit 718c9d7

Browse files
committed
test(validations): add comprehensive tests for streakParamsSchema
1 parent b251324 commit 718c9d7

1 file changed

Lines changed: 189 additions & 0 deletions

File tree

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { streakParamsSchema } from './validations';
3+
4+
describe('streakParamsSchema', () => {
5+
// ── Valid inputs ──────────────────────────────────────────────────────────
6+
7+
it('parses a minimal valid input with only user', () => {
8+
const result = streakParamsSchema.safeParse({ user: 'octocat' });
9+
expect(result.success).toBe(true);
10+
if (result.success) {
11+
expect(result.data.user).toBe('octocat');
12+
// Defaults must be applied
13+
expect(result.data.theme).toBe('dark');
14+
expect(result.data.size).toBe('medium');
15+
expect(result.data.scale).toBe('linear');
16+
expect(result.data.grace).toBe(1);
17+
}
18+
});
19+
20+
it('parses a full valid input with common optional params', () => {
21+
const result = streakParamsSchema.safeParse({
22+
user: 'octocat',
23+
theme: 'neon',
24+
size: 'large',
25+
scale: 'log',
26+
grace: '2',
27+
hide_title: 'true',
28+
hide_stats: '1',
29+
lang: 'hi',
30+
tz: 'Asia/Kolkata',
31+
view: 'monthly',
32+
});
33+
expect(result.success).toBe(true);
34+
if (result.success) {
35+
expect(result.data.size).toBe('large');
36+
expect(result.data.scale).toBe('log');
37+
expect(result.data.grace).toBe(2);
38+
expect(result.data.hide_title).toBe(true);
39+
expect(result.data.hide_stats).toBe(true);
40+
expect(result.data.lang).toBe('hi');
41+
expect(result.data.tz).toBe('Asia/Kolkata');
42+
expect(result.data.view).toBe('monthly');
43+
}
44+
});
45+
46+
it('accepts a valid hex bg color without #', () => {
47+
const result = streakParamsSchema.safeParse({ user: 'octocat', bg: '0d1117' });
48+
expect(result.success).toBe(true);
49+
});
50+
51+
it('accepts a comma-separated accent list', () => {
52+
const result = streakParamsSchema.safeParse({ user: 'octocat', accent: 'ff0000,00ff00' });
53+
expect(result.success).toBe(true);
54+
if (result.success) {
55+
expect(Array.isArray(result.data.accent)).toBe(true);
56+
}
57+
});
58+
59+
it('accepts valid from/to date range', () => {
60+
const result = streakParamsSchema.safeParse({
61+
user: 'octocat',
62+
from: '2024-01-01',
63+
to: '2024-12-31',
64+
});
65+
expect(result.success).toBe(true);
66+
});
67+
68+
// ── Invalid / negative cases ──────────────────────────────────────────────
69+
70+
it('fails when user is missing', () => {
71+
const result = streakParamsSchema.safeParse({});
72+
expect(result.success).toBe(false);
73+
});
74+
75+
it('fails when user is an empty string', () => {
76+
const result = streakParamsSchema.safeParse({ user: '' });
77+
expect(result.success).toBe(false);
78+
});
79+
80+
it('fails when username exceeds 39 characters', () => {
81+
const result = streakParamsSchema.safeParse({ user: 'a'.repeat(40) });
82+
expect(result.success).toBe(false);
83+
if (!result.success) {
84+
const messages = result.error.issues.map((i) => i.message);
85+
expect(messages.some((m) => m.includes('39'))).toBe(true);
86+
}
87+
});
88+
89+
it('fails when username contains invalid characters', () => {
90+
const result = streakParamsSchema.safeParse({ user: 'invalid user!' });
91+
expect(result.success).toBe(false);
92+
});
93+
94+
it('fails for invalid bg hex color', () => {
95+
const result = streakParamsSchema.safeParse({ user: 'octocat', bg: 'zzzzzz' });
96+
expect(result.success).toBe(false);
97+
});
98+
99+
it('fails when grace is out of range (> 7)', () => {
100+
const result = streakParamsSchema.safeParse({ user: 'octocat', grace: '8' });
101+
expect(result.success).toBe(false);
102+
if (!result.success) {
103+
const messages = result.error.issues.map((i) => i.message);
104+
expect(messages.some((m) => m.includes('grace'))).toBe(true);
105+
}
106+
});
107+
108+
it('fails when grace is negative', () => {
109+
const result = streakParamsSchema.safeParse({ user: 'octocat', grace: '-1' });
110+
expect(result.success).toBe(false);
111+
});
112+
113+
it('fails when "to" date is before "from" date', () => {
114+
const result = streakParamsSchema.safeParse({
115+
user: 'octocat',
116+
from: '2024-12-31',
117+
to: '2024-01-01',
118+
});
119+
expect(result.success).toBe(false);
120+
if (!result.success) {
121+
const messages = result.error.issues.map((i) => i.message);
122+
expect(messages.some((m) => m.includes('"to" date must be after'))).toBe(true);
123+
}
124+
});
125+
126+
it('fails for an invalid year (before 2008)', () => {
127+
const result = streakParamsSchema.safeParse({ user: 'octocat', year: '2007' });
128+
expect(result.success).toBe(false);
129+
if (!result.success) {
130+
const messages = result.error.issues.map((i) => i.message);
131+
expect(messages.some((m) => m.includes('2008'))).toBe(true);
132+
}
133+
});
134+
135+
it('fails for an invalid timezone string', () => {
136+
const result = streakParamsSchema.safeParse({ user: 'octocat', tz: 'Not/ATimezone' });
137+
expect(result.success).toBe(false);
138+
});
139+
140+
// ── Default / fallback behaviour ──────────────────────────────────────────
141+
142+
it('falls back to "medium" for an unknown size value', () => {
143+
const result = streakParamsSchema.safeParse({ user: 'octocat', size: 'gigantic' });
144+
expect(result.success).toBe(true);
145+
if (result.success) {
146+
expect(result.data.size).toBe('medium');
147+
}
148+
});
149+
150+
it('falls back to "linear" for an unknown scale value', () => {
151+
const result = streakParamsSchema.safeParse({ user: 'octocat', scale: 'cubic' });
152+
expect(result.success).toBe(true);
153+
if (result.success) {
154+
expect(result.data.scale).toBe('linear');
155+
}
156+
});
157+
158+
it('defaults grace to 1 when omitted', () => {
159+
const result = streakParamsSchema.safeParse({ user: 'octocat' });
160+
expect(result.success).toBe(true);
161+
if (result.success) {
162+
expect(result.data.grace).toBe(1);
163+
}
164+
});
165+
166+
it('defaults opacity to 1.0 when omitted', () => {
167+
const result = streakParamsSchema.safeParse({ user: 'octocat' });
168+
expect(result.success).toBe(true);
169+
if (result.success) {
170+
expect(result.data.opacity).toBe(1.0);
171+
}
172+
});
173+
174+
it('transforms refresh "true" string to boolean true', () => {
175+
const result = streakParamsSchema.safeParse({ user: 'octocat', refresh: 'true' });
176+
expect(result.success).toBe(true);
177+
if (result.success) {
178+
expect(result.data.refresh).toBe(true);
179+
}
180+
});
181+
182+
it('transforms hide_background "1" string to boolean true', () => {
183+
const result = streakParamsSchema.safeParse({ user: 'octocat', hide_background: '1' });
184+
expect(result.success).toBe(true);
185+
if (result.success) {
186+
expect(result.data.hide_background).toBe(true);
187+
}
188+
});
189+
});

0 commit comments

Comments
 (0)