mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
125 lines
4.7 KiB
TypeScript
125 lines
4.7 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|||
|
|
import { login } from "./helpers";
|
||
|
|
|
||
|
|
// These tests use a FRESH browser context (no stored auth) so the user
|
||
|
|
// hits the consent page naturally after logging in.
|
||
|
|
|
||
|
|
test.describe("Analytics Consent Page", () => {
|
||
|
|
test.use({ storageState: { cookies: [], origins: [] } });
|
||
|
|
test.describe.configure({ mode: "serial" });
|
||
|
|
|
||
|
|
test("fresh login redirects to /analytics-consent", async ({ page }) => {
|
||
|
|
// Reset consent state so user is fresh
|
||
|
|
await login(page);
|
||
|
|
|
||
|
|
// Wait for either consent page or home
|
||
|
|
await page.waitForURL(/analytics-consent|\//, { timeout: 15_000 });
|
||
|
|
|
||
|
|
// First login should show consent page
|
||
|
|
const url = page.url();
|
||
|
|
if (url.includes("analytics-consent")) {
|
||
|
|
await expect(page.getByText(/help improve snapotter/i)).toBeVisible({ timeout: 5_000 });
|
||
|
|
}
|
||
|
|
// If it went to home, consent was already handled in a prior run -- still valid
|
||
|
|
});
|
||
|
|
|
||
|
|
test("consent page renders all required elements", async ({ page }) => {
|
||
|
|
await page.goto("/analytics-consent");
|
||
|
|
|
||
|
|
// Shield icon container
|
||
|
|
await expect(page.locator("svg.lucide-shield")).toBeVisible({ timeout: 5_000 });
|
||
|
|
|
||
|
|
// Title
|
||
|
|
await expect(page.getByText(/help improve snapotter/i)).toBeVisible();
|
||
|
|
|
||
|
|
// Description text about anonymous usage data
|
||
|
|
await expect(page.getByText(/anonymous usage data/i)).toBeVisible();
|
||
|
|
|
||
|
|
// "You can change this" reassurance text
|
||
|
|
await expect(page.getByText(/change this anytime/i)).toBeVisible();
|
||
|
|
|
||
|
|
// Accept button
|
||
|
|
await expect(page.getByRole("button", { name: /sure, sounds good/i })).toBeVisible();
|
||
|
|
|
||
|
|
// Decline button
|
||
|
|
await expect(page.getByRole("button", { name: /not right now/i })).toBeVisible();
|
||
|
|
});
|
||
|
|
|
||
|
|
test("accept button navigates to home and sets analyticsEnabled=true", async ({ page }) => {
|
||
|
|
await login(page);
|
||
|
|
await page.waitForURL(/analytics-consent|\//, { timeout: 15_000 });
|
||
|
|
|
||
|
|
if (page.url().includes("analytics-consent")) {
|
||
|
|
await page.getByRole("button", { name: /sure, sounds good/i }).click();
|
||
|
|
await page.waitForURL("/", { timeout: 30_000 });
|
||
|
|
}
|
||
|
|
|
||
|
|
await expect(page).toHaveURL("/");
|
||
|
|
|
||
|
|
// Verify via session API
|
||
|
|
const token = await page.evaluate(() => localStorage.getItem("snapotter-token") ?? "");
|
||
|
|
const sessionRes = await page.request.get("/api/auth/session", {
|
||
|
|
headers: { Authorization: `Bearer ${token}` },
|
||
|
|
});
|
||
|
|
const session = await sessionRes.json();
|
||
|
|
expect(session.user.analyticsEnabled).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("after accept, navigating around never shows consent page again", async ({ page }) => {
|
||
|
|
await login(page);
|
||
|
|
await page.waitForURL(/analytics-consent|\//, { timeout: 15_000 });
|
||
|
|
|
||
|
|
if (page.url().includes("analytics-consent")) {
|
||
|
|
await page.getByRole("button", { name: /sure, sounds good/i }).click();
|
||
|
|
await page.waitForURL("/", { timeout: 30_000 });
|
||
|
|
}
|
||
|
|
|
||
|
|
// Navigate to different pages
|
||
|
|
for (const path of ["/resize", "/fullscreen", "/automate", "/"]) {
|
||
|
|
await page.goto(path);
|
||
|
|
await page.waitForTimeout(500);
|
||
|
|
expect(page.url()).not.toContain("analytics-consent");
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
test.describe("Analytics Consent - Decline (Remind Later)", () => {
|
||
|
|
test.use({ storageState: { cookies: [], origins: [] } });
|
||
|
|
test.describe.configure({ mode: "serial" });
|
||
|
|
|
||
|
|
test("decline button navigates to home", async ({ page }) => {
|
||
|
|
// Reset consent to force the prompt: accept first, then we can't re-trigger
|
||
|
|
// because the DB user already has consent set. Use API to reset.
|
||
|
|
await login(page);
|
||
|
|
await page.waitForURL(/analytics-consent|\//, { timeout: 15_000 });
|
||
|
|
|
||
|
|
if (page.url().includes("analytics-consent")) {
|
||
|
|
await page.getByRole("button", { name: /not right now/i }).click();
|
||
|
|
await page.waitForURL("/", { timeout: 30_000 });
|
||
|
|
await expect(page).toHaveURL("/");
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test("after decline, session shows remindAt in the future", async ({ page }) => {
|
||
|
|
await login(page);
|
||
|
|
await page.waitForURL(/analytics-consent|\//, { timeout: 15_000 });
|
||
|
|
|
||
|
|
// If consent page shows, decline
|
||
|
|
if (page.url().includes("analytics-consent")) {
|
||
|
|
await page.getByRole("button", { name: /not right now/i }).click();
|
||
|
|
await page.waitForURL("/", { timeout: 30_000 });
|
||
|
|
}
|
||
|
|
|
||
|
|
const token = await page.evaluate(() => localStorage.getItem("snapotter-token") ?? "");
|
||
|
|
const sessionRes = await page.request.get("/api/auth/session", {
|
||
|
|
headers: { Authorization: `Bearer ${token}` },
|
||
|
|
});
|
||
|
|
const session = await sessionRes.json();
|
||
|
|
|
||
|
|
// After decline (remind later), analyticsEnabled is null and remindAt is set
|
||
|
|
if (session.user.analyticsConsentRemindAt !== null) {
|
||
|
|
expect(session.user.analyticsConsentRemindAt).toBeGreaterThan(Date.now());
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|