Skip to content

Commit 6af827f

Browse files
fix: add grace validation test and enforce range check
1 parent e635e85 commit 6af827f

3 files changed

Lines changed: 47 additions & 6 deletions

File tree

app/api/streak/route.test.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,24 @@ describe('GET /api/streak', () => {
163163
expect(fetchGitHubContributions).not.toHaveBeenCalled();
164164
});
165165

166+
it('returns 400 when grace is below the minimum value', async () => {
167+
const response = await GET(
168+
makeRequest({
169+
user: 'octocat',
170+
grace: '-1',
171+
})
172+
);
173+
174+
expect(response.status).toBe(400);
175+
176+
const body = await response.json();
177+
178+
expect(body.error).toBe('Invalid parameters');
179+
expect(body.details.fieldErrors.grace[0]).toBe('grace must be an integer between 0 and 7');
180+
181+
expect(fetchGitHubContributions).not.toHaveBeenCalled();
182+
});
183+
166184
it('should return 200 OK and valid SVG when the optional repo query parameter is provided', async () => {
167185
// 1. Make request with both parameters present
168186
const response = await GET(makeRequest({ user: 'octocat', repo: 'commitpulse' }));
@@ -246,18 +264,15 @@ describe('GET /api/streak', () => {
246264
expect(fetchGitHubContributions).toHaveBeenCalled();
247265
});
248266

249-
it('returns valid SVG when grace exceeds max value', async () => {
267+
it('returns 400 when grace exceeds max value', async () => {
250268
const response = await GET(
251269
makeRequest({
252270
user: 'octocat',
253271
grace: '999',
254272
})
255273
);
256274

257-
expect(response.status).toBe(200);
258-
259-
const body = await response.text();
260-
expect(body).toContain('<svg');
275+
expect(response.status).toBe(400);
261276
});
262277

263278
it('embeds the username (uppercased) in the SVG title', async () => {

lib/validations.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,20 @@ describe('streakParamsSchema', () => {
113113
}
114114
});
115115

116+
it('should fail when grace is below the minimum value of 0', () => {
117+
const result = streakParamsSchema.safeParse({
118+
user: 'octocat',
119+
grace: '-1',
120+
});
121+
122+
expect(result.success).toBe(false);
123+
if (!result.success) {
124+
expect(result.error.flatten().fieldErrors.grace?.[0]).toBe(
125+
'grace must be an integer between 0 and 7'
126+
);
127+
}
128+
});
129+
116130
it('accepts a valid width value', () => {
117131
const result = streakParamsSchema.safeParse({
118132
user: 'octocat',

lib/validations.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,19 @@ export const streakParamsSchema = z.object({
178178
delta_format: z.enum(['percent', 'absolute', 'both']).catch('percent').default('percent'),
179179
width: dimensionParam('width', 100, 1200),
180180
height: dimensionParam('height', 80, 800),
181-
grace: z.string().optional().transform(toGraceValue).default(1),
181+
grace: z
182+
.string()
183+
.optional()
184+
.refine(
185+
(val) => {
186+
if (!val) return true;
187+
const parsed = Number(val);
188+
return !isNaN(parsed) && Number.isInteger(parsed) && parsed >= 0 && parsed <= 7;
189+
},
190+
{ message: 'grace must be an integer between 0 and 7' }
191+
)
192+
.transform(toGraceValue)
193+
.default(1),
182194
mode: z.enum(['commits', 'loc']).catch('commits').default('commits'),
183195
repo: z.string().optional(),
184196
org: z

0 commit comments

Comments
 (0)