mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
Over Tor the redirect chain behind a login/logout/OIDC click routinely exceeds Playwright's fixed 30s action timeout, so the click throws before the flow's scaled waits run. Sweep all role Playwright suites and the shared persona helpers: give every navigation/auth-transition click an onion-scaled timeout (.click({ timeout: resolveTimeout(30_000) })) and route the remaining raw millisecond literals (timeout options, waitForTimeout, sleep-promise setTimeout, positional wait args) through resolveTimeout. Local UI clicks (menus, toggles, modal dismissals, DOM clicks inside evaluate) stay untouched.
Two new lints keep it that way: test_no_raw_timeout_literals forbids raw numeric timeout literals in Playwright specs (opt-out: nocheck: raw-timeout), test_persona_clicks_scaled requires every click in the shared persona auth flows to carry a resolveTimeout timeout (opt-out: nocheck: unscaled-click).
Verified: node --check on all 133 changed JS files, all 13 playwright lints green, make autoformat clean, make test green (2745+196+163+4 tests OK).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
42 lines
1.7 KiB
JavaScript
42 lines
1.7 KiB
JavaScript
const { test, expect } = require("@playwright/test");
|
|
const { resolveTimeout } = require("./timeouts");
|
|
|
|
exports.register = function (shared) {
|
|
test("biber (customer): creates a ticket via the SPA after OIDC login", async ({ page }) => {
|
|
shared.skipUnlessServiceEnabled("sso");
|
|
expect(shared.env.biberUsername, "BIBER_USERNAME must be set").toBeTruthy();
|
|
expect(shared.env.biberPassword, "BIBER_PASSWORD must be set").toBeTruthy();
|
|
|
|
await shared.signInViaZammadOidc(page, shared.env.biberUsername, shared.env.biberPassword, "biber");
|
|
|
|
const subject = `playwright-customer-${Date.now()}`;
|
|
|
|
await page
|
|
.goto(`${shared.env.zammadBaseUrl}/#customer_ticket_new`, { waitUntil: "domcontentloaded" })
|
|
.catch(() => {});
|
|
|
|
const titleField = page
|
|
.getByRole("textbox", { name: /title|subject|betreff/i })
|
|
.or(page.locator("input[name='title'], input[id*='title']"))
|
|
.first();
|
|
await titleField.waitFor({ state: "visible", timeout: resolveTimeout(60_000) });
|
|
await titleField.fill(subject);
|
|
|
|
const bodyField = page
|
|
.getByRole("textbox", { name: /body|message|text|nachricht|description/i })
|
|
.or(page.locator("div[contenteditable='true'], textarea"))
|
|
.first();
|
|
await bodyField.waitFor({ state: "visible", timeout: resolveTimeout(30_000) });
|
|
await bodyField.fill("Ticket from the Infinito.Nexus customer-persona Playwright suite.");
|
|
|
|
const submitButton = page
|
|
.getByRole("button", { name: /create|submit|send|absenden|erstellen/i })
|
|
.first();
|
|
await submitButton.click({ timeout: resolveTimeout(30_000) });
|
|
|
|
await expect(page.locator("body")).toContainText(subject, { timeout: resolveTimeout(60_000) });
|
|
|
|
await shared.zammadLogout(page);
|
|
});
|
|
};
|