test: cover captcha env fallback, cache TTLs and public e2e flows
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
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
This commit is contained in:
1 parent
9f024dc6ac
commit
62de3e3a8b
7 files changed
+401
No files matched your search
@@ -0,0 +1,83 @@
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user