test: avoid prototype patching in harnesses

This commit is contained in:
Peter Steinberger
2026-04-20 16:26:44 +01:00
parent 975b989de6
commit 18021818ce
2 changed files with 35 additions and 12 deletions

View File

@@ -30,11 +30,7 @@ type SessionData = {
type ParsedHtml = {
document: Document;
window: {
HTMLElement?: {
prototype?: {
scrollIntoView?: () => void;
};
};
HTMLElement?: unknown;
};
};
@@ -59,6 +55,34 @@ async function loadParseHTML(): Promise<LinkedomModule["parseHTML"]> {
return parseHtmlPromise;
}
function installScrollIntoViewStub(document: Document) {
const patchElement = <T extends Element | null>(element: T): T => {
if (element && !("scrollIntoView" in element)) {
Object.defineProperty(element, "scrollIntoView", {
configurable: true,
value: () => {},
});
}
return element;
};
for (const element of document.querySelectorAll("*")) {
patchElement(element);
}
const getElementById = document.getElementById.bind(document);
document.getElementById = ((id: string) =>
patchElement(getElementById(id))) as typeof document.getElementById;
const querySelector = document.querySelector.bind(document);
document.querySelector = ((selectors: string) =>
patchElement(querySelector(selectors))) as typeof document.querySelector;
const createElement = document.createElement.bind(document);
document.createElement = ((tagName: string, options?: ElementCreationOptions) =>
patchElement(createElement(tagName, options))) as typeof document.createElement;
}
async function renderTemplate(sessionData: SessionData) {
const html = templateHtml
.replace("{{CSS}}", "")
@@ -69,8 +93,8 @@ async function renderTemplate(sessionData: SessionData) {
const parseHTML = await loadParseHTML();
const { document, window } = parseHTML(html);
if (window.HTMLElement?.prototype) {
window.HTMLElement.prototype.scrollIntoView = () => {};
if (window.HTMLElement) {
installScrollIntoViewStub(document);
}
const immediateTimeout = (fn: (...args: unknown[]) => void) => {

View File

@@ -47,7 +47,10 @@ describe("gaxios fetch compat", () => {
vi.stubGlobal("fetch", fetchMock);
class MockGaxios {
_defaultAdapter!: (config: MockRequestConfig) => Promise<Response>;
async _defaultAdapter(config: MockRequestConfig): Promise<Response> {
const fetchImplementation = config.fetchImplementation ?? fetch;
return await fetchImplementation(config.url, config);
}
async request(config: MockRequestConfig) {
const response = await this._defaultAdapter(config);
@@ -59,10 +62,6 @@ describe("gaxios fetch compat", () => {
}
MockGaxiosCtor = MockGaxios;
MockGaxios.prototype._defaultAdapter = async (config: MockRequestConfig) => {
const fetchImplementation = config.fetchImplementation ?? fetch;
return await fetchImplementation(config.url, config);
};
(globalThis as Record<string, unknown>)[TEST_GAXIOS_CONSTRUCTOR_OVERRIDE] = MockGaxios;
await installGaxiosFetchCompat();