Skip to content

Commit b818618

Browse files
authored
verified/tested the strict parameter validation for the ?theme= query parameter (JhaSourav07#2090)
## Description Fixes JhaSourav07#1463 ## Pillar - [ ] 🎨 Pillar 1 — New Theme Design - [ ] 📐 Pillar 2 — Geometric SVG Improvement - [ ] 🕐 Pillar 3 — Timezone Logic Optimization - [x] 🛠️ Other (Bug fix, refactoring, docs) ## Visual Preview *(Not applicable: API validation behavior update)* ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`). - [x] I have run `npm run format` and `npm run lint` locally and resolved all errors (CI will fail otherwise). - [x] My commits follow the Conventional Commits format (e.g., `feat(themes): ...`, `fix(calculate): ...`). - [x] I have updated `README.md` if I added a new theme or URL parameter. - [x] I have starred the repo. - [x] I have made sure that I have only one commit to merge in this PR. - [x] The SVG output matches the CommitPulse "premium quality" aesthetic standard (no raw elements, smooth animations, correct fonts). - [x] (Recommended) I joined the CommitPulse Discord community for contributor discussions, mentorship, and faster PR support.
2 parents 2476b24 + 0ffcc8a commit b818618

3 files changed

Lines changed: 41 additions & 6 deletions

File tree

app/api/streak/route.test.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -724,12 +724,17 @@ describe('GET /api/streak', () => {
724724
expect(body).toContain('--cp-bg');
725725
});
726726

727-
it('falls back to the dark theme without crashing when an unknown theme is given', async () => {
728-
const response = await GET(makeRequest({ user: 'octocat', theme: 'does-not-exist' }));
729-
const body = await response.text();
727+
it('returns 400 Bad Request listing allowed themes when an invalid theme is provided', async () => {
728+
const response = await GET(makeRequest({ user: 'octocat', theme: 'nonexistent_theme_name' }));
729+
expect(response.status).toBe(400);
730730

731-
expect(response.status).toBe(200);
732-
expect(body).toContain('58a6ff');
731+
const body = await response.json();
732+
expect(body.error).toBe('Invalid parameters');
733+
const fieldError = body.details.fieldErrors.theme[0];
734+
expect(fieldError).toContain('Invalid theme. Supported themes:');
735+
expect(fieldError).toContain('dark');
736+
expect(fieldError).toContain('light');
737+
expect(fieldError).toContain('neon');
733738
});
734739
});
735740

lib/validations.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,24 @@ describe('ogParamsSchema', () => {
757757
});
758758
});
759759

760+
describe('streakParamsSchema — theme validation', () => {
761+
it('rejects an invalid theme value with 400 validation error listing allowed themes', () => {
762+
const result = streakParamsSchema.safeParse({
763+
user: 'octocat',
764+
theme: 'nonexistent_theme_name',
765+
});
766+
767+
expect(result.success).toBe(false);
768+
if (!result.success) {
769+
const fieldError = result.error.flatten().fieldErrors.theme?.[0];
770+
expect(fieldError).toContain('Invalid theme. Supported themes:');
771+
expect(fieldError).toContain('dark');
772+
expect(fieldError).toContain('light');
773+
expect(fieldError).toContain('neon');
774+
}
775+
});
776+
});
777+
760778
describe('streakParamsSchema — view fallback behavior', () => {
761779
it('accepts "default" as a valid view value', () => {
762780
expect(parse({ view: 'default' }).view).toBe('default');

lib/validations.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,19 @@ const baseStreakParamsSchema = z.object({
7070
message: 'Invalid GitHub username',
7171
}),
7272

73-
theme: z.string().default('dark'),
73+
theme: z
74+
.string()
75+
.optional()
76+
.refine(
77+
(val) => {
78+
if (val === undefined || val === '') return true;
79+
return val === 'auto' || val === 'random' || Object.hasOwn(themes, val);
80+
},
81+
{
82+
message: `Invalid theme. Supported themes: ${['auto', 'random', ...Object.keys(themes)].join(', ')}`,
83+
}
84+
)
85+
.default('dark'),
7486
bg: z
7587
.string()
7688
.optional()

0 commit comments

Comments
 (0)