mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-20 09:09:35 +02:00
53 lines
2.4 KiB
TypeScript
53 lines
2.4 KiB
TypeScript
/**
|
|||
|
|
* A persistent full-screen overlay must not carry `backdrop-filter` while it is
|
||
|
|
* hidden.
|
||
|
|
*
|
||
|
|
* The property promotes the element to its own compositing layer, and a
|
||
|
|
* full-screen `position: fixed` layer that is created and then hidden has been
|
||
|
|
* observed to leave a stale HIT-TEST region behind in Chrome: the page renders
|
||
|
|
* correctly while pointer events over the viewport land on nothing. Reported on
|
||
|
|
* a long-lived tab against a remote server (where a connection blip shows and
|
||
|
|
* then hides #offlineOverlay): terminal scrolling AND unrelated click-to-expand
|
||
|
|
* controls died together, a freshly opened tab was fine, and a console
|
||
|
|
* one-liner doing nothing but READING layout restored it.
|
||
|
|
*/
|
||
|
|
import { readFileSync } from 'node:fs';
|
||
|
|
import { resolve } from 'node:path';
|
||
|
|
import { describe, expect, it } from 'vitest';
|
||
|
|
|
||
|
|
const css = readFileSync(resolve(import.meta.dirname, '../src/web/public/styles.css'), 'utf8');
|
||
|
|
|
||
|
|
function ruleBody(selector: string): string {
|
||
|
|
const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||
|
|
const m = new RegExp(`(?:^|\\})\\s*${escaped}\\s*\\{([^}]*)\\}`, 'm').exec(css);
|
||
|
|
if (!m) throw new Error(`no rule for ${selector}`);
|
||
|
|
return m[1];
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Persistent, full-screen, fixed overlays and the selector that shows each. */
|
||
|
|
const PERSISTENT_OVERLAYS: Array<{ base: string; shown: string }> = [
|
||
|
|
{ base: '.offline-overlay', shown: '.offline-overlay:not([hidden])' },
|
||
|
|
{ base: '.file-preview-overlay', shown: '.file-preview-overlay.visible' },
|
||
|
|
];
|
||
|
|
|
||
|
|
describe('persistent full-screen overlays do not composite while hidden', () => {
|
||
|
|
for (const { base, shown } of PERSISTENT_OVERLAYS) {
|
||
|
|
it(`${base} keeps backdrop-filter off its base rule`, () => {
|
||
|
|
expect(ruleBody(base)).not.toMatch(/backdrop-filter/);
|
||
|
|
});
|
||
|
|
|
||
|
|
it(`${base} still blurs once shown, via ${shown}`, () => {
|
||
|
|
// Moving the property must not silently DELETE the effect: the overlay is
|
||
|
|
// meant to blur what is behind it while it is up.
|
||
|
|
const body = ruleBody(shown);
|
||
|
|
expect(body).toMatch(/(^|\s)backdrop-filter:\s*blur\(/m);
|
||
|
|
expect(body).toMatch(/-webkit-backdrop-filter:\s*blur\(/);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
it('the offline overlay still forces display:none when hidden', () => {
|
||
|
|
// The base rule is `display: flex`, so [hidden] alone would not hide it —
|
||
|
|
// this is the guard that rule stays put while the block is edited.
|
||
|
|
expect(ruleBody('.offline-overlay[hidden]')).toMatch(/display:\s*none\s*!important/);
|
||
|
|
});
|
||
|
|
});
|