Reputation: 993
I am writing tests using Jest for components that use canvas elements. I keep getting an error when I run my tests that looks like this.
Error: Not implemented: HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)
From my understanding Jest uses jsdom for its testing and that jsdom is compatible with canvas if you install the canvas or canvas-prebuilt packages.
I have tried installing each of these packages and neither of them have resolved the error. The only thing that I think could be going wrong is that jsdom cannot find the canvas or canvas-prebuilt packages. Does anyone know a way to fix this error or test to see if jsdom is finding the other packages? Thanks a lot!
Upvotes: 93
Views: 62566
Reputation: 21
"I'm using Jest version 29.0.3, and the following is working perfectly."
HTMLCanvasElement.prototype.getContext = jest.fn()
Upvotes: 1
Reputation: 4971
OK, so I'm coming from the left-field with my answer:
==> Use StoryBook <==
Canvas is a very visual component
And testing systems should mimic the real world as closely as possible.
Therefore, if you're actually testing something that concerns and advantages the seeing user only then you're probably going to find it quicker and easier overall with a well written StoryBook file rather than a test that mocks off the functionality. I would take the position that this mimics real life more closely than using a computer, and therefore as a testing system, it is a better choice.
An example I would use here is a disabled
prop may be testable in a Jest-like space, to check if an aria property is added to the HTML for example, but if someone breaks the CSS, then the test will miss it.
In fact, canvas is only visual, if you want to make it accessible you pretty much have to write a whole new component that describes the data displayed in a way that a non-seeing entity (human or not) can digest. Otherwise you just blocked 25% of the world's population and everything you might want to crawl your site (though AI will be at a level to make this point obsolete in the order of months IMO).
However, another solution would build on the mocking one, and that would be to take clear control of JS that builds the canvas, factoring it out into util files for example so that they could be easily unit tested.
But, I'll get back into the left-field by noting that SVG is an alternate option that actually improves the experience in pretty much all cases. It's all there in the DOM for starters, and with ForeignObject you can add HTML in too. And you can stick to a Jest-like environment, though I'd still personally recommend StoryBook, (and a QA person too, probably sourced from the user-pool or client with product knowledge being more important than technical).
The advice I've read is that Canvas is best for either displaying huge numbers of data points (10000s or more) or for games/animations etc. There's more canvas vs svg stuff on this excellent blog post written by James Williams of JointJS including summary points, for link rot reasons:
Apologies for meandering somewhat off topic.
Upvotes: -1
Reputation: 409
you can create it as mock and you don't install a new package:
HTMLCanvasElement.prototype.getContext = jest.fn();
Upvotes: 10
Reputation: 8142
I've solved it by installing jest-canvas-mock
npm i --save-dev jest-canvas-mock
And adding this configuration on package.json
{
"jest": {
"setupFiles": [
"jest-canvas-mock"
],
}
}
Upvotes: 22
Reputation: 41
I experienced the same problem using react-scripts
3.0.1 and solved it by installing jest-canvas-mock
as a dev
dependency and importing it (import 'jest-canvas-mock'
) on my app.test.js file (where I got that error from) only as importing it on setupTests.js
would unnecessarily import the package in every single test file.
Upvotes: 0
Reputation: 15005
My team is using create-react-app
and we had previously addressed this problem by adding the npm package jest-canvas-mock
. Now after upgrading to react-scripts 3.4.1, we also had to add a specific import to our src/setupTests.ts
file:
import 'jest-canvas-mock';
Upvotes: 102
Reputation: 125
Both answers above work. However, just wanted to add that in case of create-react-app, it doesn't support the 'setupFiles' required by jest conf in package.json for jest-canvas-mock.
I got around this by adding the import statement in each of the test files that were invoking the canvas element(in my case 3). Then, I moved the import statement to the setupTests.js file and removed that requirement as well.
Upvotes: 6
Reputation: 648
I had similar problem with my Jest tests, and solved it by installing jest-canvas-mock.
Upvotes: 14
Reputation: 4310
You can create your own mock of the function in a jest setup script
HTMLCanvasElement.prototype.getContext = () => {
// return whatever getContext has to return
};
Upvotes: 65