From 2cd4d9d257e0525d96c0c00a72ab9c13245b8236 Mon Sep 17 00:00:00 2001 From: Test User Date: Sat, 23 May 2026 10:22:24 +0530 Subject: [PATCH 1/2] fix: validate githubId parameter in user github-accounts DELETE handler --- e2e/landing.spec.js | 6 ++++++ src/app/api/user/github-accounts/[githubId]/route.ts | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/e2e/landing.spec.js b/e2e/landing.spec.js index 55a83be5..61f13910 100644 --- a/e2e/landing.spec.js +++ b/e2e/landing.spec.js @@ -19,3 +19,9 @@ test("dashboard stays protected for unauthenticated users", async ({ page }) => await expect(page).toHaveURL(/\/$/); await expect(page.getByRole("link", { name: "Sign in with GitHub" })).toBeVisible(); }); + +test("landing has dashboard link", async ({ page }) => { + await page.goto("/"); + + await expect(page.getByRole("link", { name: "Dashboard" })).toBeVisible(); +}); diff --git a/src/app/api/user/github-accounts/[githubId]/route.ts b/src/app/api/user/github-accounts/[githubId]/route.ts index cf365d5a..ae2a1e0d 100644 --- a/src/app/api/user/github-accounts/[githubId]/route.ts +++ b/src/app/api/user/github-accounts/[githubId]/route.ts @@ -16,6 +16,10 @@ export async function DELETE( return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } + if (!params.githubId || typeof params.githubId !== "string" || !/^\d+$/.test(params.githubId)) { + return NextResponse.json({ error: "Invalid githubId parameter" }, { status: 400 }); + } + const userRow = await resolveAppUser(session.githubId, session.githubLogin); if (!userRow) { From 316fc38004549a55a4cccad641fe6e8cc86f312f Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 25 May 2026 08:15:38 +0530 Subject: [PATCH 2/2] fix: add missing E2E dashboard widget mocks --- e2e/dashboard-widgets.spec.js | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/e2e/dashboard-widgets.spec.js b/e2e/dashboard-widgets.spec.js index 40ab6562..7ec3ee59 100644 --- a/e2e/dashboard-widgets.spec.js +++ b/e2e/dashboard-widgets.spec.js @@ -15,6 +15,7 @@ test.beforeEach(async ({ page }) => { accessToken: "test-token", }, maxAge: 60 * 60, + cookieName: "next-auth.session-token", }); await page.context().addCookies([ @@ -93,6 +94,45 @@ test.beforeEach(async ({ page }) => { }); }); + await page.route("**/api/goals/sync", async (route) => { + await route.fulfill({ + contentType: "application/json", + body: JSON.stringify({ updated: 1, commitCount: 4 }), + }); + }); + + await page.route("**/api/ai-insights**", async (route) => { + await route.fulfill({ + contentType: "application/json", + body: JSON.stringify({ + data: { + insights: [ + { + id: "insight-1", + type: "productivity", + title: "High Consistency", + description: "You have coded 5 days this week!", + severity: "positive", + }, + ], + trend: { direction: "up", percentage: 15 }, + aiSummary: "Great job shipping features this week. Keep up the high standard!", + generatedAt: "2026-05-18T12:00:00.000Z", + }, + }), + }); + }); + + await page.route("**/api/notifications**", async (route) => { + await route.fulfill({ + contentType: "application/json", + body: JSON.stringify({ + notifications: [], + unreadCount: 0, + }), + }); + }); + const metricRoutes = [ "**/api/metrics/prs**", "**/api/metrics/pr-breakdown**",