How to add <canvas> support to my tests in Jest?

In my Jest unit test, I present a component with ColorPicker . The ColorPicker creates a canvas object and a 2d context, but returns 'undefined' , which throws the error "Cannot set property 'fillStyle' of undefined"

 if (typeof document == 'undefined') return null; // Dont Render On Server var canvas = document.createElement('canvas'); canvas.width = canvas.height = size * 2; var ctx = canvas.getContext('2d'); // returns 'undefined' ctx.fillStyle = c1; // "Cannot set property 'fillStyle' of undefined" 

I am having problems figuring out why I cannot get a 2d context. Maybe there is a problem with my test configuration?

 "jest": { "scriptPreprocessor": "<rootDir>/node_modules/babel-jest", "unmockedModulePathPatterns": [ "<rootDir>/node_modules/react", "<rootDir>/node_modules/react-dom", "<rootDir>/node_modules/react-addons-test-utils", "<rootDir>/node_modules/react-tools" ], "moduleFileExtensions": [ "jsx", "js", "json", "es6" ], "testFileExtensions": [ "jsx" ], "collectCoverage": true } 
+15
html5-canvas reactjs jestjs jsdom
source share
7 answers

This is because your test does not work in a real browser. Jest uses jsdom to taunt the necessary parts of the DOM to be able to run tests in Node, thus avoiding the styling and rendering that the browser usually does. This is cool because it makes tests quick.

On the other hand, if you need browser-based APIs in your components, this is more complicated than in a browser. Fortunately, jsdom has canvas support . You just have to configure this:

jsdom includes support for using the canvas package to extend any <canvas> using the canvas API. For this to work, you need to include canvas in your project as a jsdom dependency. If jsdom can find the canvas package, it will use it, but if it is not presented, the <canvas> elements will behave like <div> s.

Alternatively, you can replace Jest with some browser tester, for example, Karma . The jester is pretty buggy anyway .

+12
source share

For those who are looking for application examples create-respond

install

 yarn add --dev jest-canvas-mock 

Create a new ${rootDir}/src/setupTests.js with

 import 'jest-canvas-mock'; 
+13
source share

I had the same problem. I am deploying to gitlab ci to run my tests, and since Cairo needs to be installed on the npm canvas, using this was not a viable option.

All I really wanted to do was mock the implementation through Jest so that it would not actually try to create a real context. Here's how I solved it:

added to package.json

 "jest": { "setupFiles": ["./tests/setup.js"], } 

tests / setup.js

 import sinon from 'sinon'; const createElement = global.document.createElement; const FAKECanvasElement = { getContext: jest.fn(() => { return { fillStyle: null, fillRect: jest.fn(), drawImage: jest.fn(), getImageData: jest.fn(), }; }), }; /** * Using Sinon to stub the createElement function call with the original method * unless we match the 'canvas' argument. If that the case, return the Fake * Canvas object. */ sinon.stub(global.document, 'createElement') .callsFake(createElement) .withArgs('canvas') .returns(FAKECanvasElement); 
+3
source share

In my use case, I made a simple monkey wand like this

 beforeEach(() => { const createElement = document.createElement.bind(document); document.createElement = (tagName) => { if (tagName === 'canvas') { return { getContext: () => ({}), measureText: () => ({}) }; } return createElement(tagName); }; }); 

No need to install a pre-created canvas or sine.

+3
source share
 npm install -D canvas-prebuilt@1 

This provides canvas support for jest. It even works if someone gets an error due to Lottie.js.

+1
source share

I think you need jest-canvas-mock .

Installation

This should only be set as a development dependency (devDependencies), as it is for testing only.

npm i --save-dev jest-canvas-mock

Customization

In your package. json jokingly create an array setupFiles and add jest-canvas-mock to the array.

 { "jest": { "setupFiles": ["jest-canvas-mock"] } } 

If you already have the setupFiles attribute, you can also add jest-canvas-mock to the array.

 { "jest": { "setupFiles": ["./__setups__/other.js", "jest-canvas-mock"] } } 
0
source share

To check the canvas output in jest, you need to do the following:

Make sure you use at least jsdom 13. You can do this by including the jsom package for jest, for 14 this is:

jest-environment-jsdom-fourteen

And setting up Jest to use this

jest --env=jest-environment-jsdom-fourteen

or in package.json

 "jest": { ... "testEnvironment": "jest-environment-jsdom-fourteen", 

Include the canvas npm package. (since version 2.x this includes an embedded version, so pre-assembly is not recommended).

0
source share

All Articles