vitest: Tests are failing after updating to Vite 4.1.0
Describe the bug
I’m using SvelteKit with Vitest. I updated SvelteKit and Vitest to their latest versions - 1.5.0 and 0.28.4 respectfully. However, updating Vite from 4.0.4 to 4.1.0 caused 15% of my tests to fail (60/400).
Most of the errors seem unreasonable. For example, removing a DOM element throws a Failed to execute removeChild on Node
error. Or Found multiple elements with the text: ...
where there’s just a single element containing that exact copy; Error: Unable to fire a "click" event - please provide a DOM element.
, Error: unable to find element with text
, etc.
Reproduction
Here’s a simple StackBlitz example.
- Open the link
- Wait for the installation to complete
- Stop the execution in the terminal (Cmd + C)
- Run
npm run test
- The test fails
Then do the following:
- Open
package.json
- Change the version of
vite
from4.1.0
to4.0.4
- Update the dependencies
- Open the terminal again and run
npm run test
- The test succeeds
The example explained
It’s a simple component with an if statement:
<script lang="ts">
import { onMount } from "svelte"
let showMessage = false
onMount(() => {
showMessage = true
})
</script>
{#if showMessage}
<div>Hello</div>
{/if}
Test file:
import { render } from "@testing-library/svelte"
import Hello from "../Hello.svelte"
describe("Hello component", () => {
it("should show message", async () => {
const { getByText } = render(Hello)
expect(getByText("Hello")).toBeInTheDocument()
})
})
Result with Vite 4.1.0:
TestingLibraryElementError: Unable to find an element with the text: Hello. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
This is just a single example but similar issues occur where there’s some sort of an asynchronous code used (or conditionals), like promises, setTimeout
, useFakeTimers()
and advanceTimersByTime()
, TestingLIbrary’s waitFor()
function, etc.
More dependencies & config
See StackBlitz example for more info
package.json
"@sveltejs/kit": "^1.5.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/svelte": "^3.2.2",
"jsdom": "^21.1.0",
vite.config.ts
export default defineConfig({
plugins: [sveltekit()],
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],
globals: true,
environment: "jsdom",
setupFiles: ["src/setupTest.js"],
}
});
setupTest.js
import "@testing-library/jest-dom"
System Info
System:
OS: macOS 13.1
CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 1.84 GB / 16.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 19.2.0 - /usr/local/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 8.13.1
Browsers:
Brave Browser: 109.1.47.186
Chrome: 109.0.5414.119
Firefox: 105.0.1
Safari: 16.2
npmPackages:
vite: 4.1.0 => 4.1.0
vitest: ^0.28.4 => 0.28.4
Used Package Manager
npm
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn’t already an issue that reports the same bug to avoid creating a duplicate.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.
About this issue
- Original URL
- State: open
- Created a year ago
- Reactions: 19
- Comments: 30 (15 by maintainers)
Commits related to this issue
- fix tests from vitest broken svelte/internal module resolution https://github.com/vitest-dev/vitest/issues/2834 — committed to janosh/svelte-toc by janosh a year ago
- Fix ToC scroll abort (#37) * fix scroll to active ToC li aborting scroll from within-page links * readme document new prop scrollBehavior: 'auto' | 'smooth' = `smooth` * fix tests from vitest b... — committed to janosh/svelte-toc by janosh a year ago
- update vite/vitest Note that vite 4.1+ requires browser condition to run onMount() in svelte components properly during tests https://github.com/vitest-dev/vitest/issues/2834#issuecomment-1429611184 — committed to codeborne/svelte-sample by angryziber a year ago
- [client-svelte] Test env fixes Configure @testing-library/jest-dom correctly to resolve the type definitions in the test files, even the plugin is extended in a global setup file. The Svelte compone... — committed to samson84/view-lib-comparison by samson84 6 months ago
I guess it needs to be:
to be more accurate.
Test passes with following:
Maybe related to https://github.com/sveltejs/svelte/issues/5534? I’m not sure why this passes when
vite
version is lowered though.Add “browser” to your
resolve.conditions
property in the config file.Just wanna leave a hack here that worked for us, without having to change all the imports.
Create or add this to your test setup file
Started to rollback local
vite
commit by commit. Test works after reverting https://github.com/vitejs/vite/pull/11595 (👋 @bluwy).It seems that entrypoint for Svelte is resolved to
svelte/ssr.mjs
instead ofsvelte/index.mjs
. Invite@4.0.4
the decision was made based onpackage.json
’smodule
field but invite@4.1.0
it’s done based onexports
.Parameters used here below: https://github.com/vitejs/vite/blob/d953536aae448e2bea0f3a7cb3c0062b16d45597/packages/vite/src/node/plugins/resolve.ts#L1108-L1112
Svelte’s entrypoints: https://github.com/sveltejs/svelte/blob/82d2982845df188631993db6b18c2842e3613acf/package.json#L23-L87
It does make sense that
ssr.mjs
is imported in Node. I guess theonMount
intentionally does not run on SSR? Not sure what should be done here. Maybevite-plugin-svelte
should detect test environment and flip the import? Or if Svelte intentionally does not runonMount
on SSR, maybe it should do it when it’s run in tests. 😕Another work-around for projects for now so that test code does not need changes:
Just chipping in that this issue is still present as of vitest 0.34.6.
For now I recommend using a workaround with
conditions
.This is much deeper problem than Svelte issue. Vitest processes
svelte
/vue
/… files with web mode, and processes it with SSR transforms afterwards. But typescript and javascript files are processed with SSR mode enabled (plugins receivessr
flag).This creates an issue, if code is imported from the same package in two different modes, - especially if code depends on a singleton. Currently to bypass this Vitest hardcodes
node
condition, but this is not reliable of course (as we can see here Svelte expects Svelte to always run in SSR mode, if it’s running insidenode
, which is not true for Vitest - it’s always running in Node, not in browser).One of the reason why Vitest doesn’t process everything with web mode is performance - Vite is (at least, was) really slow to transform a single ts/js file. The other issue is that library authors also expect browser condition to be run in a browser, so they don’t follow node ESM spec (file in
browser
condition doesn’t have correct extension).@sheremet-va it still has an issue. experimentalOptimizer doesn’t help
This should be fixed in the latest version. If you still have problems, considered enabling
deps.experimentalOptimizer
.If I set
resolve.conditions
tobrowser
invite.config.js
I get another error multiple times, when running the unit tests
@sheremet-va, nice catch! How did you find that?
I can confirm that this was the cause of my bug since after changing all
onMount
andonDestroy
imports in the relevant files, all 60 tests that were failing succeed now.