2015-10-03 17 views
9

Ich beginne gerade mit dem Komponententest einer React 0.10.0-Komponente mit Mocha 2.3.3, jsdom 6.5.1 und Node.js 4.1.1 . Ich habe dies für meine Unit-Test:mocha + jsdom + React TypeError: Die Eigenschaft 'addEventListener' von undefined kann nicht gelesen werden

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; 
     }); 

    }); 

}); 

Und das ist meine einfache React Ansicht:

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; 

Wenn ich den Test ausführen, ich diese Stack-Trace erhalten:

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) 

Beliebig Ideen, was ich falsch mache?

+0

Welche Version von jsdom benutzt du? –

+0

Ich habe die Frage aktualisiert, um alle Versionsnummern zu haben. –

+3

Was passiert, wenn Sie von 'jsdom.jsdom(). ParentWindow 'in' jsdom.jsdom(). DefaultView' wechseln? –

Antwort

24

Ich poste die Lösung für den Fall, dass es jemand anderen hilft. Es wird ausführlich erklärt here, aber kurz gesagt: Sie müssen sicherstellen, dass das DOM bereit ist, bevor React von Node-Modullader geladen wird. Sie können dies erzwingen, indem Sie die Option --require von mocha verwenden und eine Datei angeben, die das jsdom-Setup enthält.

In meinem Fall habe ich eine Datei setup.js in meinem test Verzeichnis mit folgendem Inhalt benannt:

var jsdom = require('jsdom'); 

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

Und nun meine Testläufe erfolgreich mit diesem Befehl:

mocha --require ./test/setup.js

+2

Für Leute, die es2015 verwenden, importieren Sie jsdom nicht. Ich habe ein paar Stunden damit verbracht, das zum Laufen zu bringen, und mit require statt import hat es funktioniert. Ich weiß nicht warum, ich bin einfach nur glücklich, dass es endlich funktioniert ... – nhjk

+0

Ich benutze jsdom mit 'import' Syntax einfach gut. Das hängt von Ihrer Babel-Konfiguration ab. –

+0

Warum nicht 'global.navigator = global.window.navigator'? –

Verwandte Themen