javascript - React components render correctly in browser, but Jest test errors when rendering: "Only a ReactOwner can have refs" -
i have 2 components in react render fine , produce expected behavior in browser, can't seem rendered when running test via jest.
descriptions.js
var react = require('react/addons'); var $ = require('jquery'); var description = require('./description.js'); var descriptions = react.createclass({ getinitialstate: function () { //container starts @ least 1 description field empty, or whatever 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 @ least 1 description field @ times descriptions.push({num: 0, data: ''}); } } return {descriptions: descriptions, focus: -1}; }, componentwillreceiveprops: function (nextprops) { //props updated var descriptions = []; //we don't care previous values, make new list $.each(nextprops.info, function (i, string) { descriptions.push({num: i, data: string}); }); if (descriptions.length == 0) { //we want @ least 1 description field @ times descriptions.push({num: 0, data: ''}); } this.setstate({descriptions: descriptions}); }, adddescription: function (pos) { //adds new description underneath last 1 in 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 new description }, removedescription: function (pos) { //remove description array given 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 1 description every item in 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, component container 1 or more child "description" components, , amount of "description" components need rendered depends on passed info
prop, holds array of strings.
description.js
var react = require('react/addons'); var description = react.createclass({ mixins: [react.addons.linkedstatemixin], componentdidmount: function () { //focus input if 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 pressed, need add new line underneath 1 e.preventdefault(); this.props.adddescription(this.props.descriptionnum); } else if (key == 8) { //backspace pressed, check see if line empty , remove if 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 string (or nothing), sets state contain string, , uses linkedstatemixin
update state whenever value of input changes, , vice-versa.
i thought had no issues these components, following jest test...
descriptions-test.js
jest.dontmock('../js/descriptions.js'); var react = require('react/addons'); var testutils = react.addons.testutils; describe('descriptions', function () { it('creates 2 description components when given 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 following error:
● descriptions › mocks description twice when given info array of length 2 - error: invariant violation: addcomponentasrefto(...): reactowner can have refs. means you're trying add ref component doesn't have owner (that is, not created inside of component's `render` method). try rendering component inside of new top-level component hold ref.
...on line:
var descriptions = testutils.renderintodocument(<descriptions info={info}/>);
this makes no sense me components render fine in browser without issues. seems break when react's testutils attempts it.
here dependencies:
package.json
"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 know might causing error?
move require
out of test function.
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 2 description components when given 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); }); });
Comments
Post a Comment