Ответ 1
App.jsx
экспортирует класс App и больше ничего не делает, render
следует называть в другом месте.
Если вы удалите вызов render
из ошибки App.jsx, он исчезнет, потому что тестовая среда не предоставляет DOM с идентификатором app
.
Я пытаюсь протестировать компонент React с помощью Jest/Enzyme при использовании Webpack.
У меня очень простой тест @
import React from 'react';
import { shallow } from 'enzyme';
import App from './App';
it('App', () => {
const app = shallow(<App />);
expect(1).toEqual(1);
});
Относительный компонент, который он собирает:
import React, { Component } from 'react';
import { render } from 'react-dom';
// import './styles/normalize.css';
class App extends Component {
render() {
return (
<div>app</div>
);
}
}
render(<App />, document.getElementById('app'));
Однако при запуске jest
происходит сбой:
Invariant Violation: _registerComponent(...): Target container is not a DOM element.
С ошибками @
at Object.<anonymous> (src/App.js:14:48) at Object.<anonymous> (src/App.test.js:4:38)
В тестовых файлах ссылается строка 4, которая представляет собой импорт <App/>
, который вызывает сбой. Трассировка стека говорит, что строка 14 из App.js
является причиной сбоя - это не что иное, как вызов рендеринга от react-dom
, с которым я никогда не сталкивался (приложение правильно отображается из моей настройки Webpack),
Для заинтересованных (код Webpack):
module.exports = {
entry: './src/App',
output: {
filename: 'bundle.js',
path: './dist'
},
module: {
loaders: [
{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
},
{
test: /\.css$/,
loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
},
{
test: /\.scss$/,
loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!sass'
}
]
}
}
И мой package.json
:
{
"name": "tic-tac-dux",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --devtool eval --progress --colors --inline --hot --content-base dist/",
"test": "jest"
},
"jest": {
"moduleNameMapper": {
"^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"^.+\\.(css|sass)$": "<rootDir>/__mocks__/styleMock.js"
}
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.17.0",
"babel-jest": "^16.0.0",
"babel-loader": "^6.2.5",
"babel-polyfill": "^6.16.0",
"babel-preset-es2015": "^6.16.0",
"babel-preset-react": "^6.16.0",
"css-loader": "^0.25.0",
"enzyme": "^2.4.1",
"jest": "^16.0.1",
"jest-cli": "^16.0.1",
"node-sass": "^3.10.1",
"react-addons-test-utils": "^15.3.2",
"react-dom": "^15.3.2",
"sass-loader": "^4.0.2",
"style-loader": "^0.13.1",
"webpack": "^1.13.2",
"webpack-dev-server": "^1.16.2"
},
"dependencies": {
"react": "^15.3.2",
"react-dom": "^15.3.2"
}
}
О, и если кто-то скажет, что элемент div не загружается перед скриптом, вот мой index.html
:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>App</title>
</head>
<body>
<div id="app"></div>
<script src="/bundle.js"></script>
</body>
</html>
Что может быть причиной этой специфической проблемы рендеринга? Что-то связано с новым обновлением Jest до 15.0?
App.jsx
экспортирует класс App и больше ничего не делает, render
следует называть в другом месте.
Если вы удалите вызов render
из ошибки App.jsx, он исчезнет, потому что тестовая среда не предоставляет DOM с идентификатором app
.
Для тех, кто расчесывал интернет, как я был, - ища решение этого при тестировании с помощью Jest - я верну ответ на @biphobe, сказав, что Jest вызовет эту ошибку, когда вы экспортируете что-то внутри тот же файл, который вызывает ReactDOM.render.
В моем случае я экспортировал объект в свой index.js, где я также вызывал ReactDOM.render. Я удалил этот экспорт и вуаля!
Как я вижу, эта ошибка возникает во многих случаях и требует различных подходов к ее решению. Мой сценарий не совпадает с приведенным выше примером, я использую redux & router, хотя я боролся с той же ошибкой. Что помогло мне решить эту проблему, так это изменить index.js
:
ReactDOM.render(
<Provider store={store}>
<AppRouter />
</Provider>,
document.getElementById("root")
);
registerServiceWorker();
чтобы:
ReactDOM.render(
(<Provider store={store}>
<AppRouter/>
</Provider>),
document.getElementById('root') || document.createElement('div') // for testing purposes
);
registerServiceWorker();