mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-07 11:22:31 +00:00
New lint test_no_raw_goto.py forbids raw `page.goto(...)` in role playwright specs + persona flows (the gotoOnion wrapper in personas/utils is exempt) so navigation retries transient Tor-transport errors over onion. Migrates every raw call across ~75 roles (343 sites) to `gotoOnion(page, ...)` and teaches gotoOnion to detect relative onion URLs (`isOnionCanonical`). gotoOnion is a behaviour-identical drop-in on clearnet (single attempt, same return). Verified: no-raw-goto lint green, eslint 0 errors, make test green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
76 lines
2.8 KiB
JavaScript
76 lines
2.8 KiB
JavaScript
const { expect } = require("@playwright/test");
|
|
const { resolveTimeout } = require("./timeouts");
|
|
|
|
const {
|
|
decodeDotenvQuotedValue,
|
|
gotoOnion,
|
|
normalizeBaseUrl,
|
|
runAdminFlow,
|
|
runBiberFlow,
|
|
runGuestFlow,
|
|
} = require("./personas");
|
|
const { skipUnlessServiceEnabled } = require("./service-gating");
|
|
|
|
const appBaseUrl = normalizeBaseUrl(process.env.APP_BASE_URL || "");
|
|
const canonicalDomain = decodeDotenvQuotedValue(process.env.CANONICAL_DOMAIN);
|
|
|
|
// Drive the Jitsi Meet pre-join chrome for an authenticated persona: navigate
|
|
// to a room URL and wait for the SPA's prejoin lobby to render. The spec MUST
|
|
// NOT actually start a media call (the headless Playwright runner has no
|
|
// camera permission) but reaching the prejoin lobby behind the oauth2-proxy
|
|
// gate proves the user is on the role's authenticated surface.
|
|
async function reachJitsiPrejoin(page, personaLabel, roomSuffix) {
|
|
const roomName = `e2e-${personaLabel}-${roomSuffix}`.toLowerCase().replace(/[^a-z0-9-]/g, "");
|
|
await gotoOnion(page, `${appBaseUrl}/${roomName}`, { waitUntil: "domcontentloaded" });
|
|
const prejoin = page
|
|
.getByRole("button", { name: /join meeting|join|beitreten/i })
|
|
.or(page.locator('[data-testid="prejoin.joinMeeting"], #premeeting-screen'))
|
|
.first();
|
|
await expect(prejoin, `${personaLabel}: prejoin surface must render`).toBeVisible({
|
|
timeout: resolveTimeout(60_000),
|
|
});
|
|
await expect
|
|
.poll(() => page.url(), {
|
|
timeout: resolveTimeout(30_000),
|
|
message: `${personaLabel}: URL must include the room path`,
|
|
})
|
|
.toContain(`/${roomName}`);
|
|
}
|
|
|
|
// Open the prejoin "more options" / Settings panel so the admin scenario lands
|
|
// on a surface that biber does NOT exercise. Jitsi exposes a Settings link in
|
|
// the prejoin and in-meeting toolbar; presence of the panel satisfies the
|
|
// "admin authorisation: Settings link visible in the DOM" rule from the
|
|
// per-role playwright contract.
|
|
async function openJitsiSettingsPanel(page, personaLabel) {
|
|
const settingsTrigger = page
|
|
.getByRole("button", { name: /settings|einstellungen|more options|optionen/i })
|
|
.or(page.locator('[aria-label*="settings" i], [aria-label*="einstellungen" i], [data-testid*="settings" i]'))
|
|
.first();
|
|
await expect(
|
|
settingsTrigger,
|
|
`${personaLabel}: a Settings / More-options control must be visible in the DOM`,
|
|
).toBeVisible({ timeout: resolveTimeout(30_000) });
|
|
}
|
|
|
|
async function beforeEach({ page }) {
|
|
await page.setViewportSize({ width: 1440, height: 1100 });
|
|
expect(appBaseUrl, "APP_BASE_URL must be set").toBeTruthy();
|
|
expect(canonicalDomain, "CANONICAL_DOMAIN must be set").toBeTruthy();
|
|
await page.context().clearCookies();
|
|
}
|
|
|
|
module.exports = {
|
|
env: {
|
|
appBaseUrl,
|
|
canonicalDomain,
|
|
},
|
|
reachJitsiPrejoin,
|
|
openJitsiSettingsPanel,
|
|
runGuestFlow,
|
|
runBiberFlow,
|
|
runAdminFlow,
|
|
skipUnlessServiceEnabled,
|
|
beforeEach,
|
|
};
|