mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +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>
85 lines
3.8 KiB
JavaScript
85 lines
3.8 KiB
JavaScript
const { test, expect } = require("@playwright/test");
|
|
const { resolveTimeout } = require("../timeouts");
|
|
|
|
const { skipUnlessAddonEnabled } = require("../addon-gating");
|
|
const { skipUnlessServiceEnabled } = require("../service-gating");
|
|
const {
|
|
decodeDotenvQuotedValue,
|
|
normalizeBaseUrl,
|
|
gotoOnion,
|
|
} = require("../personas");
|
|
|
|
test.use({ ignoreHTTPSErrors: true });
|
|
|
|
const appBaseUrl = normalizeBaseUrl(process.env.APP_BASE_URL || "");
|
|
const canonicalDomain = decodeDotenvQuotedValue(process.env.CANONICAL_DOMAIN || "");
|
|
|
|
test("oidc-authenticator: XWiki login is coupled to the Keycloak OIDC provider", async ({ page }) => {
|
|
skipUnlessAddonEnabled("oidc-authenticator");
|
|
skipUnlessServiceEnabled("sso");
|
|
|
|
expect(appBaseUrl, "APP_BASE_URL must be set").toBeTruthy();
|
|
expect(canonicalDomain, "CANONICAL_DOMAIN must be set").toBeTruthy();
|
|
|
|
await page.context().clearCookies();
|
|
|
|
const base = appBaseUrl.replace(/\/$/, "");
|
|
const xwikiHost = new URL(base).hostname;
|
|
|
|
// With the OIDC authenticator wired (authservice=oidc, oidc.provider /
|
|
// oidc.endpoint.authorization / oidc.clientid set in xwiki.properties and
|
|
// oidc.skipped=false), hitting the XWiki `login` action makes the
|
|
// OIDCAuthServiceImpl redirect the browser straight to the configured
|
|
// Keycloak authorization endpoint — no intermediate button click. If the
|
|
// extension/config were NOT wired, the login action would instead render
|
|
// XWiki's local username/password form on the XWiki host and never reach
|
|
// the provider, so the assertions below would fail.
|
|
await gotoOnion(page, `${base}/bin/login/XWiki/XWikiLogin`, {
|
|
waitUntil: "domcontentloaded",
|
|
timeout: resolveTimeout(60_000),
|
|
});
|
|
|
|
// Follow the OIDC hand-off to Keycloak's authorization endpoint. The
|
|
// redirect is automatic for a preconfigured provider; the explicit wait
|
|
// tolerates a slow IdP round-trip.
|
|
await page
|
|
.waitForURL(/\/protocol\/openid-connect\/auth/, { timeout: resolveTimeout(45_000) })
|
|
.catch(() => {});
|
|
await page.waitForLoadState("domcontentloaded", { timeout: resolveTimeout(30_000) }).catch(() => {});
|
|
|
|
const authUrl = page.url();
|
|
expect(
|
|
/\/realms\/[^/]+\/protocol\/openid-connect\/auth/.test(authUrl),
|
|
`expected the XWiki login action to hand off to the Keycloak OIDC authorization endpoint (proves oidc.provider/endpoint.authorization/clientid are wired and authservice=oidc is active), got ${authUrl}`,
|
|
).toBe(true);
|
|
|
|
// The authorization endpoint must live on the external Keycloak/IdP host,
|
|
// not on the XWiki host itself — proving the redirect targets the
|
|
// configured provider rather than looping back to a local login form.
|
|
// Both hosts share the deployment's registrable parent domain (XWiki is
|
|
// served at x.wiki.<DOMAIN_PRIMARY>, Keycloak at auth.<DOMAIN_PRIMARY>),
|
|
// so the IdP host must differ from the XWiki host yet share that parent.
|
|
const idpHost = new URL(authUrl).hostname;
|
|
const parentDomain = xwikiHost.split(".").slice(-2).join(".");
|
|
expect(
|
|
idpHost,
|
|
`expected the OIDC authorization endpoint to live on the external Keycloak host, not the XWiki host (${xwikiHost}); got ${idpHost}`,
|
|
).not.toBe(xwikiHost);
|
|
expect(
|
|
idpHost.endsWith(parentDomain),
|
|
`expected the OIDC authorization endpoint host (${idpHost}) to belong to the deployment domain (${parentDomain}, derived from ${xwikiHost})`,
|
|
).toBe(true);
|
|
|
|
// The Keycloak login form (not an error page) must render for the
|
|
// registered client, confirming the client_id/redirect_uri coupling.
|
|
const keycloakLoginForm = page
|
|
.getByRole("textbox", { name: /username|email/i })
|
|
.or(page.locator("input[name='username'], input#username"))
|
|
.first();
|
|
|
|
await expect(
|
|
keycloakLoginForm,
|
|
"the Keycloak login form must render for the registered XWiki client, confirming the OIDC client coupling",
|
|
).toBeVisible({ timeout: resolveTimeout(30_000) });
|
|
});
|