Я пытаюсь добавить поддержку Jest для тестирования кода в своем приложении на основе веб-пакета. Я думаю, что у меня правильная базовая конфигурация, поскольку тест, не основанный на компонентах (например, «добавляет числа» ниже), проходит. Однако, когда я пытаюсь взаимодействовать с DOM, возникает ошибка. Я пробую вариант сценария smoketest, описанного в документах Документы по созданию-реагированию-приложений (раздел «Тестовые компоненты»). Мой тестовый файл выглядит так:
import React from 'react';
import ReactDOM from 'react-dom';
it('adds number', () => {
expect(2 + 2).toBe(4);
});
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<div/>, div);
});
и вывод:
v adds number (10ms)
× renders without crashing (3ms)
renders without crashing
TypeError: Cannot read property 'render' of undefined
44 | it('renders without crashing', () => { 45 | const div = document.createElement('div'); 46 | ReactDOM.render(<div/>, div); | ^ 47 | });
at Object.<anonymous> (/pathto/TestFile.test.tsx:46:12)
Мое приложение не создано с помощью приложения create-реагировать. Вместо этого я попытался следовать инструкциям в Документация веб-пакета Jest, изменив его для поддержки Typescript. Должен ли я ожидать, что пример «рендеринга без сбоев» будет работать в моем приложении? Нужно ли мне устанавливать какую-либо конфигурацию браузера Jest для поддержки этого? Это основная конфигурация в моем package.json, связанная с Jest:
"jest": {
"roots": [
"src/app/react"
],
"moduleNameMapper": {
"\\.(css)$": "identity-obj-proxy"
},
"transform": {
"^.+\\.tsx?$": "ts-jest",
"^.+\\.(js|jsx)$": "babel-jest",
".+\\.(scss)$": "./node_modules/jest-css-modules-transform"
},
"moduleFileExtensions": [
"js",
"ts",
"tsx"
]
},
Добавьте это в свой tsconfig.json
:
{
"compilerOptions": {
...
"esModuleInterop": true
},
...
}
Подробности
Проблема связана с тем, как эта строка транспилируется:
import ReactDOM from 'react-dom';
Эта строка означает импорт default
экспорта из модуля react-dom
как ReactDOM
.
react-dom
поставляется как модуль CommonJS, поэтому технически у него нет default
экспорта.
Установка флага esModuleInterop
в true
позволяет импортировать одно экспортированное значение, как если бы это был default
экспорт модуля TypeScript или ES6.
Постучав головой о стол некоторое время, я наконец увидел ваш ответ и исправил его. Действительно ценю это
Если вы по какой-то причине не хотите добавлять esModuleInterop
config, правильный синтаксис для импорта модуля в TypeScript как одно имя:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
Большое спасибо! Хорошее объяснение :)