[英]React components render correctly in browser, but Jest test errors when rendering: “Only a ReactOwner can have refs”
I have two components in React that render just fine and produce expected behavior in the browser, but can't seem to be rendered when running a test via Jest. 我在React中有两个组件,它们可以很好地呈现并在浏览器中产生预期的行为,但是通过Jest运行测试时似乎无法呈现。
var React = require('react/addons');
var $ = require('jquery');
var Description = require('./description.js');
var Descriptions = React.createClass({
getInitialState: function () { //container always starts with at least one description field that is empty, or whatever is contained in props
var descriptions = [];
if (this.props.info == null) {
descriptions.push({num: 0, data: ''});
} else {
$.each(this.props.info, function (i, string) {
descriptions.push({num: i, data: string});
});
if (descriptions.length == 0) { //we want at least one description field at all times
descriptions.push({num: 0, data: ''});
}
}
return {descriptions: descriptions, focus: -1};
},
componentWillReceiveProps: function (nextProps) { //props are updated
var descriptions = []; //we don't care about previous values, so we will make a new list
$.each(nextProps.info, function (i, string) {
descriptions.push({num: i, data: string});
});
if (descriptions.length == 0) { //we want at least one description field at all times
descriptions.push({num: 0, data: ''});
}
this.setState({descriptions: descriptions});
},
addDescription: function (pos) { //adds a new description underneath the last one in the container
var descriptions = this.state.descriptions;
var max = 0;
$.each(descriptions, function (i, item) {
if (item.num > max) max = item.num;
});
descriptions.splice(pos + 1, 0, {num: max + 1, data: ''});
this.setState({descriptions: descriptions, focus: pos + 1}); //focus the new description
},
removeDescription: function (pos) { //remove a description from the array given its array position
var descriptions = this.state.descriptions;
if (descriptions.length != 1) {
descriptions.splice(pos, 1);
this.setState({descriptions: descriptions, focus: pos == 0 ? 0 : pos - 1});
}
},
render: function () {
var items = this.state.descriptions.map(function (item, i) { //add one Description for every item in the array
return (
<Description key={item.num} addDescription={this.addDescription}
removeDescription={this.removeDescription}
descriptionNum={i} focus={i == this.state.focus} data={item.data}/>
);
}.bind(this));
return (
<div className="descriptions">
{items}
</div>
);
}
});
module.exports = Descriptions;
Essentially, this component is a container for one or more child "Description" components, and the amount of "Description" components that need to be rendered depends on the passed info
prop, which holds an array of strings. 本质上,此组件是一个或多个子“描述”组件的容器,并且需要呈现的“描述”组件的数量取决于传递的
info
道具,该info
道具包含一串字符串。
var React = require('react/addons');
var Description = React.createClass({
mixins: [React.addons.LinkedStateMixin],
componentDidMount: function () { //focus the input if it was added after page load
if (this.props.focus) {
this.refs.descInput.getDOMNode().focus();
}
},
componentWillReceiveProps: function (nextProps) {
if (nextProps.focus) {
this.refs.descInput.getDOMNode().focus();
}
this.setState({description: nextProps.data});
},
getInitialState: function () {
return({description: this.props.data});
},
handleKeyDown: function (e) {
var key = e.keyCode;
if (key == 13) { //enter is pressed, we need to add a new line underneath this one
e.preventDefault();
this.props.addDescription(this.props.descriptionNum);
} else if (key == 8) { //backspace was pressed, check to see if line is empty and remove if so
var value = this.refs.descInput.getDOMNode().value;
if (value == null || value == '') {
e.preventDefault();
this.props.removeDescription(this.props.descriptionNum);
}
}
},
render: function () {
return (
<div className="description">
<input type="text" onKeyDown={this.handleKeyDown} valueLink={this.linkState('description')} ref="descInput"/>
</div>
)
}
});
module.exports = Description;
This component receives a string (or nothing), sets its state to contain that string, and uses the LinkedStateMixin
to update the state whenever the value of the input changes, and vice-versa. 此组件接收字符串(或不接收任何字符串),将其状态设置为包含该字符串,并在每次输入的值更改时使用
LinkedStateMixin
更新状态,反之亦然。
I thought I had no issues with these components, but the following Jest test... 我以为这些组件没有问题,但是下面的Jest测试...
jest.dontMock('../js/descriptions.js');
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
describe('Descriptions', function () {
it('creates exactly two Description components when given a string array of length 2', function() {
jest.dontMock('../js/description.js');
var Description = require('../js/description.js');
var info = ['foo','bar'];
var Descriptions = require('../js/descriptions.js');
var descriptions = TestUtils.renderIntoDocument(<Descriptions info={info}/>);
var array = TestUtils.scryRenderedComponentsWithType(descriptions, Description);
expect(array.length).toEqual(2);
});
});
...fails with the following error: ...失败,并出现以下错误:
● Descriptions › it mocks Description exactly twice when given info array of length 2
- Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. This usually means that you're trying to add a ref to a component that doesn't have an owner (that is, was not created inside of another component's `render` method). Try rendering this component inside of a new top-level component which will hold the ref.
...on this line: ...在此行上:
var descriptions = TestUtils.renderIntoDocument(<Descriptions info={info}/>);
This makes no sense to me as the components render fine in the browser without any issues. 这对我来说毫无意义,因为这些组件在浏览器中可以正常显示而没有任何问题。 It seems to only break when React's TestUtils attempts to do it.
它似乎只有在React的TestUtils尝试执行时才会中断。
Here are my dependencies: 这是我的依赖项:
"dependencies": {
"jquery": "^2.1.4",
"react": "^0.13.3",
"react-tools": "^0.13.3"
},
"devDependencies": {
"browserify": "^10.2.1",
"gulp": "^3.8.11",
"gulp-react": "^3.0.1",
"gulp-shell": "^0.4.1",
"gulp-streamify": "0.0.5",
"gulp-uglify": "~1.1.0",
"jest-cli": "^0.4.5",
"node-libs-browser": "^0.5.2",
"reactify": "^1.1.1",
"vinyl-source-stream": "^1.1.0",
"watchify": "^3.2.1",
"webpack": "^1.9.10"
}
Does anyone know what might be causing this error? 有人知道什么可能导致此错误吗?
Move the require
out of the test function. 将
require
移出测试功能。
jest.dontMock('../js/descriptions.js');
var React = require('react/addons');
var Description = require('../js/description.js');
var Descriptions = require('../js/descriptions.js');
describe('Descriptions', function () {
it('creates exactly two Description components when given a string array of length 2', function() {
var TestUtils = React.addons.TestUtils;
var info = ['foo','bar'];
var descriptions = TestUtils.renderIntoDocument(<Descriptions info={info}/>);
var array = TestUtils.scryRenderedComponentsWithType(descriptions, Description);
expect(array.length).toEqual(2);
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.