diff --git a/src/auto-reply/reply/export-html/template.security.test.ts b/src/auto-reply/reply/export-html/template.security.test.ts index 8a2844af32d..981289f0dea 100644 --- a/src/auto-reply/reply/export-html/template.security.test.ts +++ b/src/auto-reply/reply/export-html/template.security.test.ts @@ -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 { return parseHtmlPromise; } +function installScrollIntoViewStub(document: Document) { + const patchElement = (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) => { diff --git a/src/infra/gaxios-fetch-compat.test.ts b/src/infra/gaxios-fetch-compat.test.ts index 60934c040f0..b3714d80af3 100644 --- a/src/infra/gaxios-fetch-compat.test.ts +++ b/src/infra/gaxios-fetch-compat.test.ts @@ -47,7 +47,10 @@ describe("gaxios fetch compat", () => { vi.stubGlobal("fetch", fetchMock); class MockGaxios { - _defaultAdapter!: (config: MockRequestConfig) => Promise; + async _defaultAdapter(config: MockRequestConfig): Promise { + 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)[TEST_GAXIOS_CONSTRUCTOR_OVERRIDE] = MockGaxios; await installGaxiosFetchCompat();