net::ERR_NO_BUFFER_SPACE stopped a release at its first page with nothing else running, and the unchanged rerun passed. Every page load of the suite now goes through one helper, held by a test.
62 lines
2.4 KiB
TypeScript
62 lines
2.4 KiB
TypeScript
import { test, expect, type Page } from "@playwright/test";
|
|
import { openApp } from "./helpers";
|
|
import { gotoRetrying } from "./retryConnect";
|
|
|
|
// A request can be lost on the way on a loaded machine or a poor line. A lost stylesheet leaves the
|
|
// whole page unstyled, and every test that finds its elements by testid still passes on it: only an
|
|
// axe run ever noticed (8 controls under the target size). So this looks at the styles themselves.
|
|
|
|
/** Lose the first request for every stylesheet of the page; the ones after it go through. */
|
|
async function loseEachStylesheetOnce(page: Page): Promise<string[]> {
|
|
const lost: string[] = [];
|
|
await page.route(/\/assets\/[^/]+\.css/, async (route) => {
|
|
const url = route.request().url();
|
|
if (lost.includes(url)) return route.continue();
|
|
lost.push(url);
|
|
return route.abort("failed");
|
|
});
|
|
return lost;
|
|
}
|
|
|
|
/** Every stylesheet link of the page holds rules (a lost one still has a `sheet`, whose rules throw
|
|
* on reading), and the page's own tokens are in force: `--bg` comes from the stylesheet alone, while
|
|
* `--font-scale` would prove nothing, the app also sets it from script. */
|
|
async function expectStyled(page: Page): Promise<void> {
|
|
await expect
|
|
.poll(() =>
|
|
page.evaluate(() => {
|
|
const hasRules = (l: HTMLLinkElement) => {
|
|
try {
|
|
return (l.sheet?.cssRules.length ?? 0) > 0;
|
|
} catch {
|
|
return false;
|
|
}
|
|
};
|
|
const links = [...document.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]')];
|
|
const root = getComputedStyle(document.documentElement);
|
|
return {
|
|
links: links.length > 0,
|
|
rules: links.every(hasRules),
|
|
tokens: root.getPropertyValue("--bg").trim() !== "",
|
|
};
|
|
}),
|
|
)
|
|
.toEqual({ links: true, rules: true, tokens: true });
|
|
}
|
|
|
|
test("the app gets back a stylesheet lost on the way", async ({ page }) => {
|
|
const lost = await loseEachStylesheetOnce(page);
|
|
await openApp(page);
|
|
expect(lost.length).toBeGreaterThan(0);
|
|
await expectStyled(page);
|
|
});
|
|
|
|
test("a public /watch link gets back a stylesheet lost on the way", async ({ page }) => {
|
|
const lost = await loseEachStylesheetOnce(page);
|
|
// No such link: the page says so, and it is the same entry with the same stylesheet.
|
|
await gotoRetrying(page, "/watch/no-such-token");
|
|
await expect(page.locator("#root")).not.toBeEmpty();
|
|
expect(lost.length).toBeGreaterThan(0);
|
|
await expectStyled(page);
|
|
});
|