Files
kevinveenbirkenbachandClaude Opus 4.8 07c6ad8e7c test(e2e): scale every nav click + timeout literal for onion targets
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>
2026-07-14 11:35:53 +02:00

39 lines
1.6 KiB
JavaScript

const { expect } = require("@playwright/test");
const { resolveTimeout } = require("./timeouts");
const { isServiceEnabled } = require("./service-gating");
const { decodeDotenvQuotedValue } = require("./personas");
const env = {
filerUrl: decodeDotenvQuotedValue(process.env.SEAWEEDFS_FILER_URL),
masterUrl: decodeDotenvQuotedValue(process.env.SEAWEEDFS_MASTER_URL),
adminUsername: decodeDotenvQuotedValue(process.env.ADMIN_USERNAME),
adminPassword: decodeDotenvQuotedValue(process.env.ADMIN_PASSWORD),
biberUsername: decodeDotenvQuotedValue(process.env.BIBER_USERNAME),
biberPassword: decodeDotenvQuotedValue(process.env.BIBER_PASSWORD),
ssoEnabled: isServiceEnabled("sso"),
frontendEnabled: isServiceEnabled("frontend"),
consumerBuckets: (() => {
try {
return JSON.parse(decodeDotenvQuotedValue(process.env.SEAWEEDFS_CONSUMER_BUCKETS) || "[]");
} catch {
return [];
}
})(),
};
async function keycloakLogin(page, username, password) {
await page.waitForLoadState("domcontentloaded");
const user = page.locator("#username, input[name='username']").first();
await user.waitFor({ state: "visible", timeout: resolveTimeout(60_000) });
await user.fill(username);
await page.locator("#password, input[name='password']").first().fill(password);
await page.locator("#kc-login, button[type='submit'], input[type='submit']").first().click({ timeout: resolveTimeout(30_000) });
await page.waitForLoadState("networkidle").catch(() => {});
}
function isAuthChain(url) {
return /\/oauth2\/|\/realms\/|\/protocol\/openid-connect\//.test(url);
}
module.exports = { env, keycloakLogin, isAuthChain, expect };