2015-10-03 15 views
9

Ho appena iniziato l'unità testando un componente React 0.10.0 con mocha 2.3.3, jsdom 6.5.1 e Node.js 4.1.1 . Ho questo per il mio test di unità:mocha + jsdom + React TypeError: Impossibile leggere la proprietà 'addEventListener' di indefinito

var React = require('react/addons'); 
var TestUtils = React.addons.TestUtils; 
var sinon = require('sinon'); 
var expect = require('chai').expect; 
var jsdom = require('jsdom'); 
var view = require('../student-name-view.js'); 

describe('The student name view', function() { 

    var renderedComponent = null; 
    var nameChangedStub = sinon.stub(); 
    var nameSubmittedStub = sinon.stub(); 

    before(function() { 
     global.document = jsdom.jsdom('<!doctype html><html><body></body></html>'); 
     global.window = document.parentWindow; 
     this.renderedComponent = TestUtils.renderIntoDocument(
      view({ 
       nameChanged: nameChangedStub, 
       nameSubmitted: nameSubmittedStub 
      }) 
     ); 
     this.nameInput = TestUtils.findRenderedDOMComponentWithTag(renderedComponent, 'input').getDOMNode(); 
    }); 

    describe('should notify the controller', function() { 

     it('when the name field changes', function() { 
      TestUtils.Simulate.change(this.nameInput); 
      expect(nameChangedStub.called).to.be.true; 
     }); 

    }); 

}); 

E questa è la mia semplice vista Reagire:

var React = require('react'); 

var StudentNameView = React.createClass({ 

    render: function() { 
     return React.DOM.div({ 
      id: 'name-container', 
      children: [ 
       React.DOM.p({ 
        children: 'Enter your name' 
       }), 
       React.DOM.input({ 
        id: 'nameInput', 
        onChange: this.props.nameChanged 
       }), 
       React.DOM.button({ 
        id: 'doneButton' 
       }) 
      ] 
     }) 
    } 

}); 

module.exports = StudentNameView; 

Quando eseguo il test, ho questa analisi dello stack:

TypeError: Cannot read property 'addEventListener' of undefined 
    at Object.EventListener.listen (node_modules/react/lib/EventListener.js:21:15) 
    at Object.merge.ensureScrollValueMonitoring (node_modules/react/lib/ReactEventEmitter.js:315:21) 
    at Object.ReactMount._registerComponent (node_modules/react/lib/ReactMount.js:282:23) 
    at Object.<anonymous> (node_modules/react/lib/ReactMount.js:305:36) 
    at Object._renderNewRootComponent (node_modules/react/lib/ReactPerf.js:57:21) 
    at Object.ReactMount.renderComponent (node_modules/react/lib/ReactMount.js:359:32) 
    at Object.renderComponent (node_modules/react/lib/ReactPerf.js:57:21) 
    at Object.ReactTestUtils.renderIntoDocument (node_modules/react/lib/ReactTestUtils.js:57:18) 
    at Context.<anonymous> (test/student-name-view-test.js:19:44) 

Qualsiasi idee cosa sto facendo di sbagliato?

+0

Quale versione di jsdom stai usando? –

+0

Ho aggiornato la domanda per avere tutti i numeri di versione. –

+3

Cosa succede se si cambia da 'jsdom.jsdom(). ParentWindow' a' jsdom.jsdom(). DefaultView'? –

risposta

24

Sto postando la soluzione nel caso in cui aiuti qualcun altro. È spiegato nel dettaglio here, ma in breve: è necessario assicurarsi che il DOM sia pronto prima che React venga caricato dal caricatore dei moduli di Node. Puoi forzarlo usando l'opzione --require di mocha e specificando un file che contiene l'installazione di jsdom.

Nel mio caso, ho creato un file chiamato setup.js nel mio indice test con i seguenti contenuti:

var jsdom = require('jsdom'); 

global.document = jsdom.jsdom('<!doctype html><html><body></body></html>'); 
global.window = document.defaultView; 
global.navigator = {userAgent: 'node.js'}; 

E ora il mio test viene eseguito con successo con questo comando:

mocha --require ./test/setup.js

+2

Per le persone che utilizzano es2015, non importare jsdom. Ho passato un paio d'ore a cercare di farlo funzionare, e l'utilizzo di require anziché import ha funzionato. Non so perché, sono solo felice che funzioni finalmente ... – nhjk

+0

Sto usando jsdom con la sintassi 'import' bene. Dipende dalla configurazione di Babel. –

+0

Perché non 'global.navigator = global.window.navigator'? –