import { readFileSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; const here = dirname(fileURLToPath(import.meta.url)); const FOCUSABLE_SEL = 'a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex="-1"])'; class FakeClassList { readonly tokens = new Set(); constructor( private readonly owner: FakeEl, initial?: string, ) { if (initial) for (const t of initial.split(/\s+/).filter(Boolean)) this.tokens.add(t); } add(...names: string[]): void { for (const n of names) this.tokens.add(n); this.owner.syncHidden(); } remove(...names: string[]): void { for (const n of names) this.tokens.delete(n); this.owner.syncHidden(); } contains(name: string): boolean { return this.tokens.has(name); } toggle(name: string, force?: boolean): boolean { if (force === true) this.add(name); else if (force === false) this.remove(name); else if (this.tokens.has(name)) this.remove(name); else this.add(name); return this.tokens.has(name); } get value(): string { return [...this.tokens].join(" "); } } class FakeEl { tagName: string; id = ""; classList: FakeClassList; children: FakeEl[] = []; parent: FakeEl | null = null; attrs = new Map(); listeners = new Map void>>(); style: Record = {}; dataset: Record = {}; disabled = false; href = ""; _text = ""; _html = ""; offsetParent: FakeEl | null; ownerDocument: FakeDoc; constructor(tag: string, doc: FakeDoc) { this.tagName = tag.toUpperCase(); this.ownerDocument = doc; this.classList = new FakeClassList(this); this.offsetParent = this; } get className(): string { return this.classList.value; } set className(value: string) { this.classList = new FakeClassList(this, value); this.syncHidden(); } get textContent(): string { if (this.children.length) return this.children.map((c) => c.textContent).join(""); return this._text; } set textContent(value: string) { this.children = []; this._text = value == null ? "" : String(value); } get innerHTML(): string { return this._html || this.textContent; } set innerHTML(value: string) { this._html = value; this.children = []; // To a fixed point: one pass leaves `<script>` as `