vitest: Running multiple test files crashes when canvas is installed (Error: Module did not self-register: '.../canvas/build/Release/canvas.node'.)
Describe the bug
I’ve started exprimenting with Vitest and got all tests to pass individually; however, running npx vitest run .
(or any set of test files together like npx vitest run src/*.test.js
) crashes with the following error:
RUN /home/phil/dev/packages/vue-accessible-color-picker
node:internal/process/promises:265
triggerUncaughtException(err, true /* fromPromise */);
^
Error: Module did not self-register: '/home/phil/dev/packages/vue-accessible-color-picker/node_modules/canvas/build/Release/canvas.node'.
at Object.Module._extensions..node (node:internal/modules/cjs/loader:1185:18)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (/home/phil/dev/packages/vue-accessible-color-picker/node_modules/canvas/lib/bindings.js:3:18)
at Module._compile (node:internal/modules/cjs/loader:1103:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1155:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
I’ve removed the node_modules
directory contents several times, re-installed the dependencies, and the issue still happens. I’m writing this only because that’s the only tangible workaround I found for this problem.
Reproduction
git clone https://github.com/kleinfreund/vue-accessible-color-picker.git
cd vue-accessible-color-picker
npm install
npm test
# or
npx vitest run .
Expected behavior:
Test suite runs with all tests passing.
Actual behavior:
Vitest crashes and no tests are run.
Workaround: turn off threads
In https://github.com/vitest-dev/vitest/issues/740#issuecomment-1042648373, a workaround was presented. Turning off threads stops the issue from happening. Using the following configuration, the tests start working:
/// <reference types="vitest" />
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [
Vue(),
],
test: {
threads: false,
environment: 'jsdom',
},
})
Notes
- Related issues:
- Canvas not being supported in happy-dom: https://github.com/capricorn86/happy-dom/issues/241
System Info
System:
OS: Linux 5.13 Ubuntu 20.04.3 LTS (Focal Fossa)
Container: Yes
Shell: 5.8 - /usr/bin/zsh
Binaries:
Node: 16.14.0 - /usr/bin/node
Yarn: 1.22.5 - ~/.yarn/bin/yarn
npm: 8.5.0 - ~/dev/packages/vue-accessible-color-picker/node_modules/.bin/npm
npmPackages:
@vitejs/plugin-vue: ^2.2.0 => 2.2.0
vite: ^2.8.1 => 2.8.1
vitest: ^0.3.4 => 0.3.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: closed
- Created 2 years ago
- Reactions: 25
- Comments: 22 (7 by maintainers)
Commits related to this issue
- feat(useRefHistory): new option `eventFilter`, new functions `useThrottledRefHistory` and `useDebouncedRefHistory` (#740) Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com> Co-authored-by: patak ... — committed to chaii3/vitest by harmyderoman 3 years ago
- Fix "Error: Module did not self-register" See https://github.com/vitest-dev/vitest/issues/740 — committed to wojtekmaj/react-pdf by wojtekmaj a year ago
workaround: in your config set
threads: false
Is there any way to use
threads: true
while mocking or disabling jsdom? Disabling threads means losing many of vitest’s benefits.Apparently, npm 7+ always installs
canvas
since it’s a peer dependency ofjsdom
. So this code in jsdom require()scanvas
even if it is not mentioned in mypackage.json
dependencies.I’m using
vite-plugin-svelte
and run into the “Module did not self-register” error if a test just includes a “Hello world” Svelte Component, without using the canvas API at all.I‘ve tried
vi.mock('canvas', () => ({}));
. But this does not work, I guess because Vitest cannot mock what jsdom require()s. Any other ideas? Thanks.@MichaelFBA try calling
require('sharp')
in config file. Or inglobalSetup
. These are the only places user can call code outside of a worker thread.threads: false
makes things even worse. I’m using@testing-library/react
and somehow settingthreads: false
breaks down all thescreen
usages while keepingthreads: true
breakscanvas
😅 so far the only solution I’ve found is this configuration:in the above example
canvas
seems to be happy and all the tests run without any changes. Nevertheless in this configuration everything is extremely slow.I also tried older versions of
canvas
, all with the same result.UPDATE
As we can see here (thanks to @molily) and here
jsdom
only tries to includecanvas
if it was already installed directly as dependency inpackage.json
, or indirectly by some other module. In my case the other module turned out to beascii-art
which installedcanvas
as it’s dependency andjsdom
included it automatically - welcome to the 2022 ¯\(ツ)/¯TEMPORARY SOLUTION
works only if you can uninstall library which included
canvas
for you. And of course it’s only a messy workaround, not a real solution to the problem.if you see anything other than “empty” try to identify which library included
canvas
as it’s dependency and uninstall it with canvas:then remove lock:
and try again:
Had the same problem with
pdfjs-dist
including canvas as optional,npm i --no-optional
did the work for meThis problem now happens even if you disable threads with
threads: false
@SebCorbin Did you manage to find the issue? I’m also dealing with the same issue with
pdfjs-dist
Since canvas is an optional peer dependency, we’re considering a workaround to just not install peer dependencies locally and in our build agent. This only works for us because we don’t have any other optional peer dependencies that we need to use locally or during testing. Though, if you did find yourself in that situation, you could list your optional peer dependencies as explicit dependencies.
Yes I tried adding it to our global setup file for vitest. The issue seems to occur when running watch and only when you change a test does it break
Just want to add that because I am also using setup files, having threads turned off has additional performance hits.
https://vitest.dev/config/#setupfiles
What kind of benefits?
As a workaround, maybe there is an old version of this module that doesn’t throw? And you can pin it in your
package.json
.Also, you can try using
happy-dom
😃I have a feeling this might be caused by https://github.com/Automattic/node-canvas/issues/1394.
This is caused by the package canvas being installed in my dependencies and used in my tests. JSDom automatically detects the package being present (see https://github.com/jsdom/jsdom#canvas-support) and allows me to test code that relies on
document.createElement('canvas').getContext('2d')
.Removing it allows me to run multiple tests at once (e.g
npm test -- src/utilities/color-conversions/*
works), but naturally, the tests relying on the canvas integration into JSDom fail now.Interestingly, if ran individually, the tests relying on canvas work fine with Vitest (e.g.
npm t -- src/ColorPicker.test.js
passes). Just running them collectively results in the error reported originally.