mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-07 19:32:17 +00:00
Playwright declares the timeout option on locator.isVisible() and isHidden() as deprecated and ignored: both return immediately and never wait. Passing resolveTimeout(10_000) to one therefore changes nothing at runtime and only tells the reader a wait happened that never did. That reading is what let7538b8a0bconclude two genuine call sites were fine, and what hid the false negativeb97cf8888had to fix. Sixty call sites across fifty-eight role-local specs lose the argument and nothing else. Every added line in this commit is a bare isVisible(); a grep for added lines that are not one returns zero, so a behaviour change cannot have entered here. Files whose diff also alters waiting semantics are deliberately not part of this commit. A repository lint added inb97cf8888keeps the construct out. It matches isVisible and isHidden only, because isChecked, isDisabled, isEditable and isEnabled take a real timeout. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
74 lines
3.3 KiB
JavaScript
74 lines
3.3 KiB
JavaScript
const { test, expect } = require("@playwright/test");
|
|
const { resolveTimeout } = require("./timeouts");
|
|
|
|
const { decodeDotenvQuotedValue, gotoOnion, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow } = require("./personas");
|
|
test.use({ ignoreHTTPSErrors: true });
|
|
|
|
const appBaseUrl = normalizeBaseUrl(process.env.APP_BASE_URL || "");
|
|
const canonicalDomain = decodeDotenvQuotedValue(process.env.CANONICAL_DOMAIN || "");
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
expect(appBaseUrl, "APP_BASE_URL must be set").toBeTruthy();
|
|
expect(canonicalDomain, "CANONICAL_DOMAIN must be set").toBeTruthy();
|
|
await page.context().clearCookies();
|
|
});
|
|
|
|
test("bridgy-fed responds under canonical domain with TLS", async ({ page }) => {
|
|
// Bridgy Fed serves a 404 on `/` by design: the canonical landing
|
|
// surfaces are the federation-protocol endpoints (e.g. `/robots.txt`,
|
|
// `/.well-known/host-meta`, `/web/<actor>`), not a generic homepage.
|
|
// The deploy contract this role MUST satisfy is that the HTTP server
|
|
// answers on the canonical domain over TLS, regardless of whether
|
|
// the requested path resolves. A 5xx is the only signal of an
|
|
// unhealthy app.
|
|
const response = await gotoOnion(page, `${appBaseUrl}/`);
|
|
expect(response, "Expected bridgy-fed response").toBeTruthy();
|
|
expect(response.status(), "Expected bridgy-fed status < 500 (4xx are by design)").toBeLessThan(500);
|
|
expect(
|
|
response.url().includes(canonicalDomain),
|
|
`Expected canonical domain "${canonicalDomain}" to back the bridgy-fed URL`
|
|
).toBe(true);
|
|
});
|
|
|
|
test("bridgy-fed serves /robots.txt successfully", async ({ request }) => {
|
|
// Bridgy Fed has no local user accounts and authenticates federation
|
|
// peers via their source-platform credentials, so login / logout
|
|
// scenarios are not applicable. The SSO and RBAC exception is
|
|
// documented in README.md and lifecycle.md.
|
|
// /robots.txt is the canonical "service is alive" probe for this
|
|
// role; the homepage at `/` is a 404 by design.
|
|
const response = await request.get(`${appBaseUrl}/robots.txt`, { timeout: resolveTimeout(30_000) });
|
|
expect(response.status(), "Expected bridgy-fed /robots.txt status < 400").toBeLessThan(400);
|
|
});
|
|
|
|
// Persona scenarios.
|
|
// Bodies live in the shared helper roles/test-e2e-playwright/files/personas.js
|
|
// so every role's persona flow stays consistent.
|
|
|
|
test("guest: public-landing → auth chain → never authenticated", async ({ page }) => {
|
|
await runGuestFlow(page);
|
|
});
|
|
|
|
test("biber: app → universal logout", async ({ page }) => {
|
|
await runBiberFlow(page);
|
|
});
|
|
|
|
test("administrator: app → universal logout", async ({ page }) => {
|
|
await runAdminFlow(page, {
|
|
adminInteraction: async (interactivePage) => {
|
|
// web-app-bridgy-fed admin-only interaction: open a management surface.
|
|
const link = interactivePage
|
|
.getByRole("link", { name: /^(admin|status|federation)$/i })
|
|
.first();
|
|
if (await link.isVisible().catch(() => false)) {
|
|
await link.click({ timeout: resolveTimeout(30_000) }).catch(() => {});
|
|
await interactivePage.waitForLoadState("domcontentloaded", { timeout: resolveTimeout(30_000) }).catch(() => {});
|
|
await expect(interactivePage.locator("body")).toContainText(
|
|
/status|federation|web|fediverse/i,
|
|
{ timeout: resolveTimeout(30_000) },
|
|
);
|
|
}
|
|
},
|
|
});
|
|
});
|