Как добавить поддержку <canvas> в мои тесты в Jest?

В моем Jest unit test Я представляю компонент с ColorPicker. Компонент ColorPicker создает объект canvas и 2d-контекст, но возвращает 'undefined', который выдает ошибку "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"

У меня возникают проблемы, выясняя, почему я не могу получить 2d-контекст. Может быть, есть проблема с моей тестовой конфигурацией?

"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
}

Ответ 1

Это потому, что ваш тест не работает в реальном браузере. Jest использует jsdom для насмешки над необходимыми частями DOM, чтобы иметь возможность запускать тесты в Node, таким образом избегая расчета стилей и рендеринга, что обычно делает браузер. Это круто, потому что это делает тесты быстрыми.

С другой стороны, если вам нужны браузерные API в ваших компонентах, это сложнее, чем в браузере. К счастью, в jsdom есть поддержка canvas. Вы просто должны настроить это:

jsdom включает поддержку использования пакета canvas для расширения любых элементов <canvas> с помощью API canvas. Чтобы это работало, вам нужно включить canvas в ваш проект как зависимость от jsdom. Если jsdom может найти пакет canvas, он будет его использовать, но если он не представлен, то элементы <canvas> будут вести себя как <div> s.

В качестве альтернативы вы можете заменить Jest каким-нибудь браузерным тестером, например, Karma. Шут в любом случае довольно глючит.

Ответ 2

Для тех, кто ищет примеры использования приложения create-реагировать

устанавливать

yarn add --dev jest-canvas-mock

Создайте новый ${rootDir}/src/setupTests.js с

import 'jest-canvas-mock';

Ответ 3

У меня была такая же проблема. Я развертываю в gitlab ci для запуска своих тестов, а так как на холсте npm требуется установка Cairo, использование этого не было жизнеспособным вариантом.

Все, что я действительно хотел сделать, это издеваться над реализацией через Jest, чтобы он фактически не пытался создать реальный контекст. Вот как я это решил:

добавлено в package.json

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

тесты/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);

Ответ 4

В моем случае использования я сделал простую палочку для обезьян, как это

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

Не нужно устанавливать предварительно созданный холст или синус.

Ответ 5

npm install -D [email protected]

Это обеспечивает поддержку canvas для jest. Это даже работает, если кто-то получает ошибку из-за Lottie.js.

Ответ 6

Думаю, вам нужно jest-canvas-mock.

Установка

Это должно быть установлено только как зависимость развития (devDependencies), поскольку она предназначена только для тестирования.

npm я --save-dev jest-canvas-mock

Настройка

В вашем пакете. json под шутки создайте массив setupFiles и добавьте jest-canvas-mock в массив.

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

Если у вас уже есть атрибут setupFiles, вы также можете добавить jest-canvas-mock в массив.

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

Ответ 7

Чтобы проверить вывод холста в jest, вам нужно сделать следующее:

Убедитесь, что вы используете хотя бы jsdom 13. Вы можете сделать это, включив пакет jsom для jest, для 14 это:

jest-environment-jsdom-fourteen

И настройка Jest для использования этого

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

или в package.json

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

Включите пакет canvas npm. (начиная с версии 2.x это включает в себя встроенную версию, поэтому предварительная сборка не рекомендуется).