Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
This reproduces the behavior I originally noticed in Vitest 1.0.0 and 1.0.1
whereby it fails to load vitest/utils in the browser, as noted in:

- mbland/tomcat-servlet-testing-example@8c3b52c

```text
Reload Error:
Error: Vitest failed to load "vitest/utils" after 10 retries.
 ❯ WebSocket.<anonymous>
   ../../../../../../../../../__vitest_browser__/index-JmUxqpfn.js:958:36

 Caused by: TypeError: Failed to fetch dynamically imported module:
   http://localhost:5173/@id/vitest/utils
```

The test passes using vitest and @vitest/browser v1.0.0-beta.4. It will
hang when using v1.0.0-beta.{5,6}, because it's caught in a reload loop.
Therefore, I think the problem was introduced somehow between v1.0.0-beta.4 and
v1.0.0-beta.5.

I've narrowed it down to whether vite.config.js (or vitest.config.js)
contains a 'base' property. Removing 'base' causes things to work again.
(I don't yet understand how that doesn't break my current
mbland/tomcat-servlet-testing-example tests, but that's for later.)

Running 'pnpm test' will reproduce the error. Either removing the 'base'
config property or downgrading vitest and @vitest/browser to
v1.0.0-beta.4 will cause things to work.

I've added the 'pnpm test:bisect' target to help narrow down which
change introduced the problem. I plan to run it on a local copy of
vitest and @vitest/browser between v1.0.0-beta.4 and v1.0.0-beta.5, as
skimming the diff reveals nothing obvious.

---

More investigation...

This part of the diff between v1.0.0-beta.4 and v1.0.0-beta.5 accounts
for why there's a redirect loop, but it doesn't account for why the
error happens. It was introduced in:

- vitest-dev/vitest#4518

```diff
diff --git a/packages/browser/src/client/main.ts b/packages/browser/src/client/main.ts
index 778cff64..94a279c3 100644
--- a/packages/browser/src/client/main.ts
+++ b/packages/browser/src/client/main.ts
@@ -94,8 +94,16 @@ async function reportUnexpectedError(rpc: typeof client.rpc, type: string, error
 ws.addEventListener('open', async () => {
   await loadConfig()

-  const { getSafeTimers } = await importId('vitest/utils') as typeof import('vitest/utils')
-  const safeRpc = createSafeRpc(client, getSafeTimers)
+  let safeRpc: typeof client.rpc
+  try {
+    // if importing /@id/ failed, we reload the page waiting until Vite prebundles it
+    const { getSafeTimers } = await importId('vitest/utils') as typeof import('vitest/utils')
+    safeRpc = createSafeRpc(client, getSafeTimers)
+  }
+  catch (err) {
+    location.reload()
+    return
+  }

   stopErrorHandler()
   stopRejectionHandler()
```

The current code caps the number of retries at 10, added in the
following pull request between v1.0.0-beta.6 and v1.0.0:

- vitest-dev/vitest#4618

```diff
diff --git a/packages/browser/src/client/main.ts b/packages/browser/src/client/main.ts
index 94a279c3..1e8420e0 100644
--- a/packages/browser/src/client/main.ts
+++ b/packages/browser/src/client/main.ts
@@ -100,15 +131,27 @@ ws.addEventListener('open', async () => {
     const { getSafeTimers } = await importId('vitest/utils') as typeof import('vitest/utils')
     safeRpc = createSafeRpc(client, getSafeTimers)
   }
-  catch (err) {
-    location.reload()
+  catch (err: any) {
+    if (reloadTries >= 10) {
+      const error = serializeError(new Error('Vitest failed to load "vitest/utils" after 10 retries.'))
+      error.cause = serializeError(err)
+
+      await client.rpc.onUnhandledError(error, 'Reload Error')
+      await client.rpc.onDone(testId)
+      return
+    }
+
+    const tries = reloadTries + 1
+    const newUrl = new URL(location.href)
+    newUrl.searchParams.set('reloadTries', String(tries))
+    location.href = newUrl.href
     return
   }

   stopErrorHandler()
   stopRejectionHandler()

-  on('error', event => reportUnexpectedError(safeRpc, 'Error', event.error))
+  catchWindowErrors(event => reportUnexpectedError(safeRpc, 'Error', event.error))
   on('unhandledrejection', event => reportUnexpectedError(safeRpc, 'Unhandled Rejection', event.reason))

   // @ts-expect-error untyped global for internal use
```
  • Loading branch information
mbland committed Dec 5, 2023
0 parents commit 5ed256a
Show file tree
Hide file tree
Showing 6 changed files with 2,627 additions and 0 deletions.
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
11 changes: 11 additions & 0 deletions demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vitest v1.0.1 @vitest/utils import failure demo</title>
</head>
<body>
<p>Hello, World!</p>
</body>
</html>
10 changes: 10 additions & 0 deletions demo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { test } from 'vitest'

test('OK in v1.0.0-beta.4, hangs in beta.{5,6}, breaks in v1.0.1', async () => {
//let w = window.open('/demo.html')
//await new Promise(resolve => w.addEventListener('load', resolve))

//let e = w.document.querySelector('body p')

//expect(e.textContent).toContain('Hello, World!')
})
19 changes: 19 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "vitest-utils-browser-import",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"test": "vitest",
"test:bisect": "vitest --run --browser.headless"
},
"devDependencies": {
"@vitest/browser": "^1.0.1",
"vite": "^5.0.5",
"vitest": "^1.0.1",
"webdriverio": "^8.24.6"
}
}
Loading

0 comments on commit 5ed256a

Please sign in to comment.