fix(browser): log `ErrorEvent.message` when unhandled `ErrorEvent.err… · vitest-dev/vitest@5d84eeb

File tree

5 files changed

lines changed

  • packages/browser/src/client/public

    • fixtures/unhandled-non-error

5 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -31,7 +31,11 @@ function catchWindowErrors(errorEvent, prop, cb) {

3131

cb(e)

3232

}

3333

else {

34-

console.error(e[prop])

34+

// `ErrorEvent` doesn't necessary have `ErrotEvent.error` defined

35+

// but some has `ErrorEvent.message` defined, e.g. ResizeObserver error.

36+

// https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent/error

37+

// https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors

38+

console.error(e.message ? new Error(e.message) : e)

3539

}

3640

}

3741

const addEventListener = window.addEventListener.bind(window)

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,24 @@

1+

import { test } from "vitest";

2+
3+

test("ResizeObserver error", async () => {

4+

const divElem = document.createElement("div");

5+

divElem.style.width = "100px";

6+

divElem.style.height = "100px";

7+

document.body.appendChild(divElem);

8+
9+

const resizeObserver = new ResizeObserver((entries) => {

10+

for (const entry of entries) {

11+

(entry.target as HTMLElement).style.width =

12+

`${entry.contentBoxSize[0].inlineSize + 10}px`;

13+

}

14+

});

15+

const promise = Promise.withResolvers();

16+

window.addEventListener("error", (event) => {

17+

if (event.message.includes("ResizeObserver loop")) {

18+

promise.resolve(null);

19+

}

20+

});

21+

resizeObserver.observe(divElem);

22+

await promise.promise;

23+

resizeObserver.unobserve(divElem);

24+

});

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,15 @@

1+

import { fileURLToPath } from 'node:url'

2+

import { defineConfig } from 'vitest/config'

3+

import { instances, provider } from '../../settings'

4+
5+

export default defineConfig({

6+

cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)),

7+

test: {

8+

browser: {

9+

enabled: true,

10+

provider,

11+

instances,

12+

headless: true,

13+

},

14+

},

15+

})

Original file line numberDiff line numberDiff line change

@@ -20,7 +20,9 @@ const devInstances: BrowserInstanceOption[] = [

2020

const playwrightInstances: BrowserInstanceOption[] = [

2121

{ browser: 'chromium' },

2222

{ browser: 'firefox' },

23-

{ browser: 'webkit' },

23+

// hard to setup playwright webkit on some machines (e.g. ArchLinux)

24+

// this allows skipping it locally by BROWSER_NO_WEBKIT=true

25+

...(process.env.BROWSER_NO_WEBKIT ? [] : [{ browser: 'webkit' as const }]),

2426

]

2527
2628

const webdriverioInstances: BrowserInstanceOption[] = [

Original file line numberDiff line numberDiff line change

@@ -37,3 +37,17 @@ test('disables tracking', async () => {

3737

})

3838

expect(stderr).toBe('')

3939

})

40+
41+

test('print unhandled non error', async () => {

42+

const { testTree, stderr } = await runBrowserTests({

43+

root: './fixtures/unhandled-non-error',

44+

})

45+

expect(stderr).toContain('[Error: ResizeObserver loop completed with undelivered notifications.]')

46+

expect(testTree()).toMatchInlineSnapshot(`

47+

{

48+

"basic.test.ts": {

49+

"ResizeObserver error": "passed",

50+

},

51+

}

52+

`)

53+

})