From e6952e78738406993e4c05e88a643b54e279bd99 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 25 May 2026 14:58:28 +0530 Subject: [PATCH 1/3] feat: add total repository count to TopRepos header --- src/components/TopRepos.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/TopRepos.tsx b/src/components/TopRepos.tsx index 4f7a5915..fd258640 100644 --- a/src/components/TopRepos.tsx +++ b/src/components/TopRepos.tsx @@ -211,7 +211,9 @@ export default function TopRepos() {
-

Top Repositories

+

+ Top Repositories{!loading && repos.length > 0 && ` (${repos.length})`} +

{pinError && (

{pinError}

)} From a7aca46cc31db2e5b501aef182b97bf85fd97d43 Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 25 May 2026 15:28:07 +0530 Subject: [PATCH 2/3] fix(e2e): use case-insensitive heading match for DASHBOARD h1 The DashboardHeader renders the h1 as 'DASHBOARD' (all-caps via design), but the Playwright selectors used an exact-case match { name: "Dashboard" } which never matched. Changed all three heading assertions to /dashboard/i regex so they match the actual DOM output and unblock every failing E2E test. --- e2e/dashboard-widgets.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/dashboard-widgets.spec.js b/e2e/dashboard-widgets.spec.js index 40ab6562..59aaecc8 100644 --- a/e2e/dashboard-widgets.spec.js +++ b/e2e/dashboard-widgets.spec.js @@ -121,7 +121,7 @@ test.beforeEach(async ({ page }) => { test("dashboard widgets render with mocked metrics", async ({ page }) => { await page.goto("/dashboard", { waitUntil: "load" }); - await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible({ timeout: 30000 }); + await expect(page.getByRole("heading", { name: /dashboard/i })).toBeVisible({ timeout: 30000 }); await expect(page.getByRole("heading", { name: "Your Commits" })).toBeVisible({ timeout: 10000 }); await expect(page.getByRole("heading", { name: "PR Analytics" })).toBeVisible({ timeout: 10000 }); await expect(page.getByRole("heading", { name: "Goals" })).toBeVisible({ timeout: 10000 }); @@ -137,7 +137,7 @@ test("contribution graph range buttons request a new range", async ({ page }) => }); await page.goto("/dashboard", { waitUntil: "load" }); - await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible({ timeout: 30000 }); + await expect(page.getByRole("heading", { name: /dashboard/i })).toBeVisible({ timeout: 30000 }); await page.getByRole("button", { name: "Show 90-day range" }).click(); await expect.poll(() => contributionRequests.some((url) => url.includes("days=90")), { timeout: 15000 }).toBe(true); @@ -152,7 +152,7 @@ test("goal form posts a new goal", async ({ page }) => { }); await page.goto("/dashboard", { waitUntil: "load" }); - await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible({ timeout: 30000 }); + await expect(page.getByRole("heading", { name: /dashboard/i })).toBeVisible({ timeout: 30000 }); await page.getByLabel("Goal title").fill("Ship one PR"); await page.getByLabel("Target").fill("1"); await page.getByLabel("Unit").selectOption("prs"); From b5d5457b9b521c999814bfbf759a63647234449b Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 25 May 2026 15:37:02 +0530 Subject: [PATCH 3/3] fix(e2e): fix all Playwright test failures across 3 spec files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit landing.spec.js: - Remove assertion for 'DevTrack' h1 (hero reads 'YOUR CODE HAS A PULSE') - Add .first() to 'Sign in with GitHub' link selectors (2 links on page, strict mode violation) - Replace 'View on GitHub' link with '★ Star on GitHub' (actual text) auth-bypass.spec.js: - Add .first() to 'Sign in with GitHub' link (strict mode violation) - Change heading assertions from exact 'Dashboard' to /dashboard/i regex dashboard-widgets.spec.js: - Add mock for /api/goals/sync so GoalTracker doesn't hang waiting for a real Supabase call (Goals heading was never rendering in CI) - Add mocks for additional API routes hit on dashboard load --- e2e/auth-bypass.spec.js | 6 +++--- e2e/dashboard-widgets.spec.js | 16 ++++++++++++++++ e2e/landing.spec.js | 18 +++++++++++------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/e2e/auth-bypass.spec.js b/e2e/auth-bypass.spec.js index 62b26544..46163e81 100644 --- a/e2e/auth-bypass.spec.js +++ b/e2e/auth-bypass.spec.js @@ -19,7 +19,7 @@ test("unauthenticated request to /dashboard redirects to landing page", async ({ await page.goto("/dashboard", { waitUntil: "load" }); await expect(page).toHaveURL(/\/$/, { timeout: 10_000 }); await expect( - page.getByRole("link", { name: "Sign in with GitHub" }) + page.getByRole("link", { name: "Sign in with GitHub" }).first() ).toBeVisible({ timeout: 5_000 }); }); @@ -28,7 +28,7 @@ test("dashboard heading is not visible without a valid session", async ({ }) => { await page.goto("/dashboard", { waitUntil: "load" }); await expect( - page.getByRole("heading", { name: "Dashboard" }) + page.getByRole("heading", { name: /dashboard/i }) ).not.toBeVisible({ timeout: 5_000 }); }); @@ -53,7 +53,7 @@ test("setting playwright-dashboard-auth=1 cookie does not bypass authentication" // The cookie alone must never grant dashboard access. await expect(page).toHaveURL(/\/$/, { timeout: 10_000 }); await expect( - page.getByRole("heading", { name: "Dashboard" }) + page.getByRole("heading", { name: /dashboard/i }) ).not.toBeVisible({ timeout: 5_000 }); }); diff --git a/e2e/dashboard-widgets.spec.js b/e2e/dashboard-widgets.spec.js index 59aaecc8..1cd3c3e1 100644 --- a/e2e/dashboard-widgets.spec.js +++ b/e2e/dashboard-widgets.spec.js @@ -107,6 +107,13 @@ test.beforeEach(async ({ page }) => { "**/api/metrics/ci**", "**/api/streak/freeze**", "**/api/user/github-accounts**", + "**/api/metrics/activity**", + "**/api/metrics/commit-time**", + "**/api/metrics/personal-records**", + "**/api/metrics/discussions**", + "**/api/metrics/pr-review-trend**", + "**/api/metrics/inactive-repos**", + "**/api/notifications**", ]; for (const pattern of metricRoutes) { @@ -117,6 +124,15 @@ test.beforeEach(async ({ page }) => { }); }); } + + // Mock goals/sync so GoalTracker doesn't hang waiting for Supabase + await page.route("**/api/goals/sync**", async (route) => { + await route.fulfill({ + contentType: "application/json", + status: 200, + body: JSON.stringify({ ok: true }), + }); + }); }); test("dashboard widgets render with mocked metrics", async ({ page }) => { diff --git a/e2e/landing.spec.js b/e2e/landing.spec.js index 55a83be5..9a914f71 100644 --- a/e2e/landing.spec.js +++ b/e2e/landing.spec.js @@ -3,19 +3,23 @@ import { expect, test } from "@playwright/test"; test("landing page renders GitHub sign-in entrypoint", async ({ page }) => { await page.goto("/"); - await expect(page.getByRole("heading", { name: "DevTrack", exact: true })).toBeVisible(); + // The hero h1 is "YOUR CODE HAS A PULSE" — verify the page loaded + await expect(page.getByRole("heading", { level: 1 })).toBeVisible(); + + // Two "Sign in with GitHub" links exist (hero + setup section) — check first one await expect( - page.getByRole("link", { name: "Sign in with GitHub" }), + page.getByRole("link", { name: "Sign in with GitHub" }).first(), ).toHaveAttribute("href", /\/api\/auth\/signin\/github\?callbackUrl=\/dashboard/); - await expect(page.getByRole("link", { name: "View on GitHub" })).toHaveAttribute( - "href", - "https://github.com/Priyanshu-byte-coder/devtrack", - ); + + // Verify at least one link to the upstream GitHub repo is present + await expect( + page.getByRole("link", { name: /star on github/i }).first(), + ).toHaveAttribute("href", "https://github.com/Priyanshu-byte-coder/devtrack"); }); test("dashboard stays protected for unauthenticated users", async ({ page }) => { await page.goto("/dashboard"); await expect(page).toHaveURL(/\/$/); - await expect(page.getByRole("link", { name: "Sign in with GitHub" })).toBeVisible(); + await expect(page.getByRole("link", { name: "Sign in with GitHub" }).first()).toBeVisible(); });