Show the whole nav tree without :has(), raise text contrast to 4.5:1, drop unused auth rules #182
@@ -174,13 +174,8 @@ test("the public landing at / is ungated and links to sign in + register", async
|
|||||||
await shot(page, "live-05-public-landing");
|
await shot(page, "live-05-public-landing");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Measured on the rendered button, so a theme block that drops --on-accent fails here.
|
// Measured on the rendered elements, so a theme block that drops --on-accent fails here.
|
||||||
for (const colorScheme of ["light", "dark"] as const) {
|
const contrastOf = (el: Element): number => {
|
||||||
test(`the primary button's text reaches 4.5:1 in ${colorScheme} mode`, async ({ page, context }) => {
|
|
||||||
await context.clearCookies();
|
|
||||||
await page.emulateMedia({ colorScheme });
|
|
||||||
await page.goto("/");
|
|
||||||
const ratio = await page.locator(".landing .btn-primary").first().evaluate((el) => {
|
|
||||||
const luminance = (rgb: string): number => {
|
const luminance = (rgb: string): number => {
|
||||||
const [r = 0, g = 0, b = 0] = (rgb.match(/[\d.]+/g) ?? []).map((c) => {
|
const [r = 0, g = 0, b = 0] = (rgb.match(/[\d.]+/g) ?? []).map((c) => {
|
||||||
const v = Number(c) / 255;
|
const v = Number(c) / 255;
|
||||||
@@ -191,8 +186,18 @@ for (const colorScheme of ["light", "dark"] as const) {
|
|||||||
const style = getComputedStyle(el);
|
const style = getComputedStyle(el);
|
||||||
const [hi = 0, lo = 0] = [luminance(style.color), luminance(style.backgroundColor)].sort((x, y) => y - x);
|
const [hi = 0, lo = 0] = [luminance(style.color), luminance(style.backgroundColor)].sort((x, y) => y - x);
|
||||||
return (hi + 0.05) / (lo + 0.05);
|
return (hi + 0.05) / (lo + 0.05);
|
||||||
});
|
};
|
||||||
expect(ratio).toBeGreaterThanOrEqual(4.5);
|
for (const [name, colorScheme, forceDark] of [["light", "light", false], ["dark", "dark", false], ["forced dark", "light", true]] as const) {
|
||||||
|
test(`text on the accent reaches 4.5:1 in ${name} mode`, async ({ page, context }) => {
|
||||||
|
await context.clearCookies();
|
||||||
|
await page.emulateMedia({ colorScheme });
|
||||||
|
await page.goto("/");
|
||||||
|
if (forceDark) await page.locator("#theme-dark").check({ force: true });
|
||||||
|
// No page of this stack has a second page of results, so add the current-page button.
|
||||||
|
await page.locator("#main-content").evaluate((el) => el.insertAdjacentHTML("beforeend", '<a class="page-btn" aria-current="page" href="#">2</a>'));
|
||||||
|
for (const selector of [".landing .btn-primary", ".brand-mark", ".page-btn"]) {
|
||||||
|
await expect.poll(() => page.locator(selector).first().evaluate(contrastOf), { message: selector }).toBeGreaterThanOrEqual(4.5); // polls past the colour transition
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ test("styles.css folds .nav-children only inside @supports selector(:has(a))", (
|
|||||||
test("styles.css hides the theme switch and the nav toggles where :has() is missing, after their base rules", () => {
|
test("styles.css hides the theme switch and the nav toggles where :has() is missing, after their base rules", () => {
|
||||||
const guard = stylesheet.indexOf("@supports not selector(:has(a)) {");
|
const guard = stylesheet.indexOf("@supports not selector(:has(a)) {");
|
||||||
assert.ok(guard >= 0, "no @supports not selector(:has(a)) block");
|
assert.ok(guard >= 0, "no @supports not selector(:has(a)) block");
|
||||||
assert.ok(guard > stylesheet.lastIndexOf(".theme-switch {", guard), "the guard precedes the base .theme-switch rule");
|
const base = stylesheet.search(/^\.theme-switch\s*\{/m);
|
||||||
|
assert.ok(base >= 0 && base < guard, "the guard precedes the base .theme-switch rule");
|
||||||
const block = stylesheet.slice(guard, stylesheet.indexOf("\n}", guard));
|
const block = stylesheet.slice(guard, stylesheet.indexOf("\n}", guard));
|
||||||
assert.match(block, /\.theme-switch\s*\{\s*display:\s*none/);
|
assert.match(block, /\.theme-switch\s*\{\s*display:\s*none/);
|
||||||
assert.match(block, /\.nav-disc\s*\{\s*visibility:\s*hidden/);
|
assert.match(block, /\.nav-disc\s*\{\s*visibility:\s*hidden/);
|
||||||
|
|||||||
Reference in New Issue
Block a user