CI / check (push) Successful in 39s
CI / tests-imaging-browsers (push) Successful in 1m46s
CI / tests-unit (push) Successful in 2m16s
CI / tests-integration (push) Successful in 2m12s
CI / tests-ui (push) Failing after 3m45s
CI / preflight (push) Skipped
CI / deploy (push) Skipped
- unit: captcha env fallback/precedence (DB wins, explicit "none") and perf-ttls defaults, overrides and invalid values - e2e: public page render + image health, register form and Turnstile widget consistency, anonymous auth-guard redirects, plus warm latency budgets and cache-control contracts
84 lines
2.8 KiB
TypeScript
84 lines
2.8 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import {
|
|
expectNoApplicationError,
|
|
expectNoBrokenImages,
|
|
expectNoHorizontalOverflow,
|
|
isMaintenanceRedirect,
|
|
scrollThroughPage,
|
|
} from "./helpers";
|
|
|
|
// The register form is the gate for every new player, so it gets a deeper
|
|
// read-only pass than the generic public-page spec. It also pins the captcha
|
|
// contract that is configured through `CAPTCHA_PROVIDER` / `TURNSTILE_*` env
|
|
// vars (see `src/lib/services/captcha.ts`): whatever provider the running CMS
|
|
// resolves, the DOM must expose exactly one widget whose sitekey is non-empty.
|
|
const CAPTCHA_SELECTOR = ".cf-turnstile, .g-recaptcha, .h-captcha";
|
|
|
|
// Optional explicit expectation for a deploy, e.g. `E2E_EXPECT_CAPTCHA=turnstile`
|
|
// or `E2E_EXPECT_CAPTCHA=none`. Left unset, the spec only checks consistency.
|
|
const EXPECT = process.env.E2E_EXPECT_CAPTCHA?.trim();
|
|
|
|
test.describe("register", () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
const response = await page.goto("/register");
|
|
test.skip(
|
|
isMaintenanceRedirect(page.url()) || response?.status() === 404,
|
|
"register is not reachable on this deploy",
|
|
);
|
|
});
|
|
|
|
test("renders every field a new player has to fill in", async ({ page }) => {
|
|
await expect(page.locator('input[name="username"]')).toBeVisible();
|
|
await expect(page.locator('input[name="mail"]')).toBeVisible();
|
|
await expect(page.locator('input[name="password"]').first()).toBeVisible();
|
|
await expect(
|
|
page.locator('input[name="password_confirmation"]'),
|
|
).toBeVisible();
|
|
await expect(page.locator('input[name="terms"]')).toBeVisible();
|
|
await expect(page.locator('button[type="submit"]').first()).toBeVisible();
|
|
await expectNoApplicationError(page);
|
|
});
|
|
|
|
test("loads its theme/avatar images and fits the viewport", async ({
|
|
page,
|
|
}) => {
|
|
await scrollThroughPage(page);
|
|
await expectNoBrokenImages(page);
|
|
await expectNoHorizontalOverflow(page);
|
|
});
|
|
|
|
test("exposes exactly one captcha widget with a site key", async ({
|
|
page,
|
|
}) => {
|
|
const widgets = page.locator(CAPTCHA_SELECTOR);
|
|
|
|
if (EXPECT === "none") {
|
|
await expect(widgets).toHaveCount(0);
|
|
return;
|
|
}
|
|
|
|
if (EXPECT === "turnstile") {
|
|
await expect(page.locator(".cf-turnstile")).toHaveCount(1);
|
|
}
|
|
|
|
const count = await widgets.count();
|
|
expect(
|
|
count,
|
|
`expected at most one captcha provider, found ${count}`,
|
|
).toBeLessThanOrEqual(1);
|
|
|
|
for (let index = 0; index < count; index += 1) {
|
|
const siteKey = await widgets.nth(index).getAttribute("data-sitekey");
|
|
expect(siteKey, "captcha widget without data-sitekey").toBeTruthy();
|
|
expect(siteKey?.trim().length).toBeGreaterThan(0);
|
|
}
|
|
|
|
if (count > 0 && (await page.locator(".cf-turnstile").count()) > 0) {
|
|
const script = page.locator(
|
|
'script[src*="challenges.cloudflare.com/turnstile"]',
|
|
);
|
|
await expect(script).toHaveCount(1);
|
|
}
|
|
});
|
|
});
|