Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Browser tests break when importing path-to-regexp@8 and mocking modules in React tests #6540

Open
6 tasks done
Janpot opened this issue Sep 20, 2024 · 4 comments
Open
6 tasks done
Labels
feat: browser Issues and PRs related to the browser runner p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@Janpot
Copy link

Janpot commented Sep 20, 2024

Describe the bug

Testing a component that imports latest path-to-regexp, and that also mocks some modules.

This results in error:

TypeError: Failed to fetch dynamically imported module: http://localhost:5173/node_modules/.vite/deps/react_jsx-dev-runtime.js?v=0d22d530

Looking at the devtools, it seems like mock service worker is using an unintended version of path-to-regexp:

devUtils.mjs?v=0d22d530:11 [MSW] Uncaught exception in the request handler for "GET http://localhost:5173/node_modules/.vite/deps/react_jsx-dev-runtime.js?v=0d22d530":

TypeError: str is not iterable
    at lexer (http://localhost:5173/node_modules/.vite/deps/path-to-regexp.js?v=0d22d530:52:25)
    at lexer.next (<anonymous>)
    at Iter.peek (http://localhost:5173/node_modules/.vite/deps/path-to-regexp.js?v=0d22d530:110:36)
    at Iter.tryConsume (http://localhost:5173/node_modules/.vite/deps/path-to-regexp.js?v=0d22d530:116:28)
    at Iter.text (http://localhost:5173/node_modules/.vite/deps/path-to-regexp.js?v=0d22d530:132:29)
    at consume (http://localhost:5173/node_modules/.vite/deps/path-to-regexp.js?v=0d22d530:151:27)
    at parse (http://localhost:5173/node_modules/.vite/deps/path-to-regexp.js?v=0d22d530:182:22)
    at http://localhost:5173/node_modules/.vite/deps/path-to-regexp.js?v=0d22d530:282:79
    at Array.map (<anonymous>)
    at pathToRegexp (http://localhost:5173/node_modules/.vite/deps/path-to-regexp.js?v=0d22d530:282:27)

This exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/recipes/mocking-error-responses

Reproduction

  1. Clone https://github.com/Janpot/vitest-path-to-regexp-repro
  2. pnpm install
  3. pnpm test

System Info

System:
    OS: macOS 14.6.1
    CPU: (8) arm64 Apple M1
    Memory: 73.31 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.17.0 - ~/.nvm/versions/node/v20.17.0/bin/node
    npm: 10.8.2 - ~/.nvm/versions/node/v20.17.0/bin/npm
    pnpm: 9.10.0 - ~/.nvm/versions/node/v20.17.0/bin/pnpm
  Browsers:
    Chrome: 128.0.6613.138
    Safari: 17.6
  npmPackages:
    @vitejs/plugin-react: ^4.3.1 => 4.3.1 
    @vitest/browser: ^2.1.1 => 2.1.1 
    vitest: ^2.1.1 => 2.1.1

Used Package Manager

pnpm

Validations

@hi-ogawa hi-ogawa added feat: browser Issues and PRs related to the browser runner p3-minor-bug An edge case that only affects very specific usage (priority) and removed pending triage labels Sep 21, 2024
@hi-ogawa
Copy link
Contributor

hi-ogawa commented Sep 21, 2024

Vitest's browser mocking relies msw, which has a dependency path-to-regexp@6. It looks like user code's path-to-regexp@8 mixes up dependency versions due to Vite cjs dependency optimization.

@eduardhasanaj
Copy link

I am encountering same issue when using vitetest browser mode.

Failed to fetch dynamically imported module: http://localhost:5173/@fs/C:/Users/web-client/virtual:wxt-setup?import&v=1727619790892

In my case I could not use any environment such jsdom due to poor support of selectors in querySelector API.
Error:

// jsdom
SyntaxError: unknown pseudo-class selector ':not([type]'
//happy-dom
DOMException: Failed to execute 'matches' on 'HTMLButtonElement': 'button:not' is not a valid selector.

This code has no errors when I run in browser.

@sheremet-va sheremet-va moved this to Approved in Team Board Oct 1, 2024
@kettanaito
Copy link
Contributor

@hi-ogawa, does that happen because MSW is not treated as ESM by Vite? Otherwise, why would Vite attempt to optimize CJS dependency?

@hi-ogawa
Copy link
Contributor

hi-ogawa commented Oct 16, 2024

does that happen because MSW is not treated as ESM by Vite? Otherwise, why would Vite attempt to optimize CJS dependency?

The issue might be a bit more complicated.

Vitest configures optimizeDeps.exclude so that msw (and its dependencies including path-to-regexp@6) won't be optimized and thus they are served to browser directly as ESM

'msw',
'msw/browser',

However, when users have its own path-to-regexp@8 in their Vite app (or Vitest browser test), Vite currently picks up the one from the user, which is considered a bug on Vite vitejs/vite#9948

I thought users can explicitly do optimizeDeps.exclude: ["path-to-regexp"] as a workaround, but it looks like the latest path-to-regexp@8 dropped "esm-ish" export "module": "dist.es2015/index.js", which was available on path-to-regexp@6, so Vite have no choice but to optimize cjs-only path-to-regexp@8, which is then deduping path-to-regexp@6 inside msw.

This was my observation so far and unfortunately I haven't found a way to make this setup work (or even workaround) yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: browser Issues and PRs related to the browser runner p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
Status: Approved
Development

No branches or pull requests

4 participants