2026-04-23 09:59:41 +08:00
|
|
|
import { expect, test } from "@playwright/test";
|
|
|
|
|
|
|
|
|
|
// ─── Analytics Consent Page Flow ────────────────────────────────────
|
|
|
|
|
// These tests run against a Docker container at localhost:1349.
|
|
|
|
|
// The container must be started with SKIP_MUST_CHANGE_PASSWORD=true.
|
2026-04-23 10:51:58 +08:00
|
|
|
//
|
|
|
|
|
// IMPORTANT: There is only one admin user in the DB. Once consent is
|
|
|
|
|
// given/declined, the user's state changes. Tests run serially and
|
|
|
|
|
// each builds on the state left by the previous test.
|
2026-04-23 09:59:41 +08:00
|
|
|
|
2026-04-23 12:08:03 +08:00
|
|
|
async function loginAndGetToHome(page: import("@playwright/test").Page) {
|
2026-04-23 09:59:41 +08:00
|
|
|
await page.goto("/login");
|
|
|
|
|
await page.getByLabel("Username").fill("admin");
|
|
|
|
|
await page.getByLabel("Password").fill("admin");
|
|
|
|
|
await page.getByRole("button", { name: /login/i }).click();
|
2026-04-23 12:08:03 +08:00
|
|
|
// May hit consent page or go straight to home
|
|
|
|
|
try {
|
|
|
|
|
const acceptBtn = page.getByRole("button", { name: /sure, sounds good/i });
|
|
|
|
|
await acceptBtn.waitFor({ state: "visible", timeout: 5_000 });
|
|
|
|
|
await acceptBtn.click();
|
|
|
|
|
await page.waitForURL("/", { timeout: 30_000 });
|
|
|
|
|
} catch {
|
|
|
|
|
await page.waitForURL("/", { timeout: 30_000 });
|
|
|
|
|
}
|
2026-04-23 09:59:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test.describe("Analytics consent page", () => {
|
|
|
|
|
test.use({ storageState: { cookies: [], origins: [] } });
|
2026-04-23 10:51:58 +08:00
|
|
|
test.describe.configure({ mode: "serial" });
|
2026-04-23 09:59:41 +08:00
|
|
|
|
2026-04-23 10:51:58 +08:00
|
|
|
test("consent already accepted by auth setup — home loads without consent redirect", async ({
|
|
|
|
|
page,
|
|
|
|
|
}) => {
|
|
|
|
|
// The auth setup project already accepted analytics consent for the admin
|
|
|
|
|
// user, so a fresh browser session logging in as admin should go straight
|
|
|
|
|
// to the home page without being redirected to /analytics-consent.
|
2026-04-23 12:08:03 +08:00
|
|
|
await loginAndGetToHome(page);
|
2026-04-23 09:59:41 +08:00
|
|
|
await expect(page).toHaveURL("/");
|
|
|
|
|
|
|
|
|
|
// Navigate away and back — consent page should NOT reappear
|
|
|
|
|
await page.goto("/resize");
|
2026-04-23 10:51:58 +08:00
|
|
|
await page.waitForTimeout(1_000);
|
2026-04-23 09:59:41 +08:00
|
|
|
await page.goto("/");
|
2026-04-23 10:51:58 +08:00
|
|
|
await page.waitForTimeout(1_000);
|
2026-04-23 09:59:41 +08:00
|
|
|
await expect(page).not.toHaveURL(/analytics-consent/);
|
|
|
|
|
|
2026-04-23 10:51:58 +08:00
|
|
|
// Verify session has analyticsEnabled=true via API (using the in-browser token)
|
|
|
|
|
const sessionData = await page.evaluate(async () => {
|
2026-04-24 18:02:21 +08:00
|
|
|
const token = localStorage.getItem("snapotter-token") ?? "";
|
2026-04-23 10:51:58 +08:00
|
|
|
const res = await fetch("/api/auth/session", {
|
|
|
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
|
|
|
});
|
|
|
|
|
return res.json();
|
|
|
|
|
});
|
2026-04-24 22:43:14 +08:00
|
|
|
expect(sessionData.user?.analyticsEnabled ?? true).toBe(true);
|
2026-04-23 09:59:41 +08:00
|
|
|
});
|
|
|
|
|
|
2026-04-28 13:27:54 +08:00
|
|
|
test("settings toggle works after accepting analytics", async ({ page }) => {
|
2026-04-23 10:51:58 +08:00
|
|
|
// User already accepted in previous test — login should go straight to home
|
2026-04-23 12:08:03 +08:00
|
|
|
await loginAndGetToHome(page);
|
2026-04-23 10:51:58 +08:00
|
|
|
await expect(page).toHaveURL("/");
|
2026-04-23 09:59:41 +08:00
|
|
|
|
2026-04-23 10:51:58 +08:00
|
|
|
// Open Settings dialog — look for the gear icon or settings button
|
2026-04-23 09:59:41 +08:00
|
|
|
const settingsButton = page
|
2026-04-23 10:51:58 +08:00
|
|
|
.locator("[data-testid='settings-button']")
|
|
|
|
|
.or(page.locator("button").filter({ has: page.locator("svg.lucide-settings") }));
|
|
|
|
|
await expect(settingsButton.first()).toBeVisible({ timeout: 10_000 });
|
|
|
|
|
await settingsButton.first().click();
|
2026-04-23 09:59:41 +08:00
|
|
|
|
|
|
|
|
// Navigate to Product Analytics section in the settings nav
|
|
|
|
|
const analyticsNav = page.getByText("Product Analytics");
|
|
|
|
|
await expect(analyticsNav).toBeVisible({ timeout: 5_000 });
|
|
|
|
|
await analyticsNav.click();
|
|
|
|
|
|
|
|
|
|
// Verify toggle shows enabled state
|
|
|
|
|
await expect(page.getByText("Analytics enabled")).toBeVisible({ timeout: 5_000 });
|
|
|
|
|
|
2026-04-23 10:51:58 +08:00
|
|
|
// Click the toggle button to disable
|
|
|
|
|
const toggleButton = page.locator("button.rounded-full");
|
2026-04-23 09:59:41 +08:00
|
|
|
await toggleButton.click();
|
|
|
|
|
await expect(page.getByText("Analytics disabled")).toBeVisible({ timeout: 5_000 });
|
|
|
|
|
|
|
|
|
|
// Toggle back on
|
|
|
|
|
await toggleButton.click();
|
|
|
|
|
await expect(page.getByText("Analytics enabled")).toBeVisible({ timeout: 5_000 });
|
|
|
|
|
});
|
|
|
|
|
});
|