diff --git a/packages/vitest/src/integrations/env/jsdom.ts b/packages/vitest/src/integrations/env/jsdom.ts index 870a63c13fa0..c585ea4237a9 100644 --- a/packages/vitest/src/integrations/env/jsdom.ts +++ b/packages/vitest/src/integrations/env/jsdom.ts @@ -328,7 +328,7 @@ function patchAddEventListener(window: DOMWindow) { callback: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean, ) { - if (typeof options === 'object' && options.signal != null) { + if (typeof options === 'object' && options?.signal != null) { const { signal, ...otherOptions } = options // - this happens because AbortSignal is provided by Node.js, // but jsdom APIs require jsdom's AbortSignal, while Node APIs diff --git a/test/core/test/environments/jsdom.spec.ts b/test/core/test/environments/jsdom.spec.ts index 5b157423630a..89dbf908ffdc 100644 --- a/test/core/test/environments/jsdom.spec.ts +++ b/test/core/test/environments/jsdom.spec.ts @@ -226,6 +226,20 @@ test('can pass down the same abort signal many times without a warning', ({ onTe })) }) +test('DOM APIs addEventListener allow null as third parameter', () => { + const element = document.createElement('div') + document.body.append(element) + const spy = vi.fn() + + // eslint-disable-next-line ts/ban-ts-comment + // @ts-expect-error + element.addEventListener('click', spy, null) + + element.click() + + expect(spy).toHaveBeenCalledTimes(1) +}) + test('atob and btoa are available', () => { expect(atob('aGVsbG8gd29ybGQ=')).toBe('hello world') expect(btoa('hello world')).toBe('aGVsbG8gd29ybGQ=')