После того, как мой Phaser настроил работу с React, я понял, что мне нужно хорошо разбираться в том, как мое веб-приложение будет расти, и реализовать среду тестирования.
Я выбрал Jest в качестве движка для тестирования, поскольку Jest кажется предпочтительным фреймворком для тестирования приложений React (create-response-app поставляется вместе с ним). Однако, несмотря на заявление на домашней странице о том, что для большинства проектов JavaScript не требуется конфигурирования, мне все же пришлось подправить свой package.json и решить некоторые проблемы с зависимостями. Если вы используете Phaser и React, у вас тоже может быть несколько из них. Конец репо можно увидеть: https://github.com/nodes777/phaser3-react-template
Сначала добавим Jest. А если вы используете React, возможно, вы пишете файлы jsx, поэтому нам нужно будет их преобразовать, чтобы Jest тоже мог их протестировать. Документы Jest довольно прямолинейны по этому поводу.
npm i --dev jest babel-jest @babel/preset-env @babel/preset-react react-test-renderer
Это дает package.json, которому требуется значение конфигурации jest, и конфигурацию сценария, для которой требуется свойство и значение test. См. Документацию для полного пакета package.json и babel.config.js
Если вы начнете писать тест на этом этапе и используете require
, чтобы извлечь что-то из своего проекта для тестирования, вы можете получить синтаксическую ошибку.
const { config } = require(“../src/index.js”);
Это проблема и у меня тоже была, и на какое-то время она не решалась. Решение здесь - npm install --save-dev @babel/plugin-proposal-class-properties @babel/plugin-transform-modules-commonjs
и включите их как пресеты в свой babelrc.js
const presets = [ [ "@babel/env", { targets: { browsers: [">0.25%", "not ie 11", "not op_mini all"] }, modules: false } ], "@babel/preset-react" ]; const plugins = [ "@babel/plugin-proposal-class-properties", "@babel/plugin-transform-modules-commonjs" ]; module.exports = { presets, plugins };
Ошибка возникает из-за того, что require
- это синтаксис среды узла для импорта переменных, а Jest выполняется в узле. Более подробную информацию о различиях между import / require и node можно увидеть в этом вопросе SO.
Поскольку Jest не является средством запуска тестов на основе браузера, он может работать быстрее, но за счет отсутствия некоторых функций, которые вы могли бы получить из коробки с чем-то вроде Karma. Вероятно, теперь вы получаете новую ошибку TypeError: Cannot set property ‘fillStyle’ of null
при импорте Phaser.
Этот null фактически должен быть элементом холста. Jest использует jsdom как псевдо-модель DOM, но не сразу включает холст. Вы должны добавить поддержку холста, чтобы jsdom смог ее найти. К счастью, для этого есть пакет npm.
npm i --save-dev jest-canvas-mock
Согласно документации jest-canvas-mock, мы также должны добавить файлы setupFiles в наш package.json:
"jest": { "setupFiles": ["jest-canvas-mock"] }
На этом этапе вы можете столкнуться с синтаксическими ошибками с любыми файлами, не относящимися к JavaScript.
Для этого я сопоставил изображения и файлы CSS с имитацией файла. Каждый раз, когда тест импортирует изображение или файл CSS, он просто получает фиктивный файл с пустым объектом. Теперь моя шутка в package.json выглядит так:
"jest": { "transform": { "^.+\\.jsx?$": "babel-jest" }, "setupFiles": [ "jest-canvas-mock" ], "moduleFileExtensions": [ "js", "jsx" ], "moduleNameMapper": { "\\.(css|less|sass|scss)$": "<rootDir>/test/mocks/styleMock.js", "\\.(gif|ttf|eot|svg|png)$": "<rootDir>/test/mocks/fileMock.js" } }
И вы также должны добавить styleMock.js и fileMock.js в места, описанные выше. Это простые файлы:
styleMock.js
module.exports = {};
fileMock.js
module.exports = “test-file-stub”;
На этом этапе вы, вероятно, готовы просто начать писать несколько тестов. Если вы хотите начать писать их на index.js, как я, вы будете вознаграждены еще одной ошибкой!
Вот мой index.test.js
const { config } = require("../src/index.js"); test("string is a string", () => { expect(typeof "string").toBe("string"); }); test("config is an object", () => { expect(typeof config).toBe("object"); });
Ошибка начинается при импорте конфигурации из index.js.
Invariant Violation: Target container is not a DOM element.
Судя по моим поискам, это частая ошибка во многих источниках. Похоже, что рендеринг в #root, который существует в моем index.html, не существует при тестировании в jsdom. Я только действительно нашел обходной путь, в моем index.js у меня есть ||
operator для создания div, если он не существует.
ReactDOM.render( <App />, document.getElementById("root") || document.createElement("div") );
Наконец, вы сможете запустить несколько тестов и начать создавать надежный код! Дайте мне знать, если у вас есть лучшее решение этой ошибки нарушения инвариантности, я какое-то время рвал волосы из-за этого, и на тот момент мне было достаточно обходного пути.
Полный репозиторий шаблона: https://github.com/nodes777/phaser3-react-template