Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions e2e/auth-bypass.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
});

Expand All @@ -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 });
});

Expand All @@ -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 });
});

Expand Down
22 changes: 19 additions & 3 deletions e2e/dashboard-widgets.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -117,11 +124,20 @@ 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 }) => {
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 });
Expand All @@ -137,7 +153,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);
Expand All @@ -152,7 +168,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");
Expand Down
18 changes: 11 additions & 7 deletions e2e/landing.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
2 changes: 1 addition & 1 deletion src/components/KeyboardShortcuts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default function KeyboardShortcuts() {
return;
}

if (e.key.toLowerCase() === "t") {
if (e.altKey && e.key.toLowerCase() === "t") {
keyboardToggleRef.current = true;
toggleTheme();
e.preventDefault();
Expand Down
2 changes: 1 addition & 1 deletion src/components/ShortcutsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface ShortcutItem {
}

const SHORTCUTS: ShortcutItem[] = [
{ key: "T", action: "Toggle theme" },
{ key: "Alt + T", action: "Toggle theme" },
{ key: "B", action: "Toggle chart" },
{ key: "R", action: "Reload data" },
{ key: "?", action: "Show shortcuts" },
Expand Down
Loading