После того, как мой 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