[英]React components render correctly in browser, but Jest test errors when rendering: “Only a ReactOwner can have refs”
我在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;
本質上,此組件是一個或多個子“描述”組件的容器,並且需要呈現的“描述”組件的數量取決於傳遞的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;
此組件接收字符串(或不接收任何字符串),將其狀態設置為包含該字符串,並在每次輸入的值更改時使用LinkedStateMixin
更新狀態,反之亦然。
我以為這些組件沒有問題,但是下面的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);
});
});
...失敗,並出現以下錯誤:
● 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.
...在此行上:
var descriptions = TestUtils.renderIntoDocument(<Descriptions info={info}/>);
這對我來說毫無意義,因為這些組件在瀏覽器中可以正常顯示而沒有任何問題。 它似乎只有在React的TestUtils嘗試執行時才會中斷。
這是我的依賴項:
"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"
}
有人知道什么可能導致此錯誤嗎?
將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.