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

Popular posts from this blog

Java 3D LWJGL collision -

spring - SubProtocolWebSocketHandler - No handlers -

methods - python can't use function in submodule -