2016-01-29 16 views
5

Es tut mir leid, aber ich hatte die schwierigste Zeit, zu versuchen, mein React Modal zu schließen, indem ich auf eine Schaltfläche klicke. Das Modal ist so einfach wie nur möglich, und ich habe alles versucht, was ich denken oder finden kann, aber ich kann seine Kinder immer noch nicht abfragen.Testen einer React Modal-Komponente

Die Modal-Komponente:

var React = require('react'); 
var Modal = require('react-bootstrap').Modal; 
var Button = require('react-bootstrap').Button; 

var MyModal = React.createClass({ 
    ... 
    render: function() { 
    return (
     <Modal className="my-modal-class" show={this.props.show}> 
     <Modal.Header> 
      <Modal.Title>My Modal</Modal.Title> 
     </Modal.Header> 
     <Modal.Body> 
      Hello, World! 
     </Modal.Body> 
     <Modal.Footer> 
      <Button onClick={this.props.onHide}>Close</Button> 
     </Modal.Footer> 
     </Modal> 
    ); 
    } 
}); 

Mein Ziel ist es zu prüfen, ob die Schaltfläche Schließen der onHide() Funktion wird ausgelöst, wenn es angeklickt wird.

Meine Testdatei:

describe('MyModal.jsx', function() { 
    it('tests the Close Button', function() { 
    var spy = sinon.spy(); 
    var MyModalComponent = TestUtils.renderIntoDocument(
     <MyModal show onHide={spy}/> 
    ); 

    // This passes 
    TestUtils.findRenderedComponentWithType(MyModalComponent, MyModal); 

    // This fails 
    var CloseButton = TestUtils.findRenderedDOMComponentWithTag(MyModalComponent, 'button'); 

    // Never gets here 
    TestUtils.Simulate.click(CloseButton); 
    expect(spy.calledOnce).to.be.true; 
    }); 
}); 

Egal, was ich versuche, ich kann nicht scheinen, um die Close Button zu finden.

+0

Sie Scherz verwenden? Ich habe nie Scherz benutzt, aber ich denke, dass es die abhängigen Komponenten automatisch verspottet. Kann das das Problem sein? –

+0

@AbhishekJain Ich benutze Mocha – user1778856

+0

ist '

Antwort

6

Ich schrieb eine jsFiddle mit der React Base Fiddle (JSX), um herauszufinden, was in Ihrem Test vorging (Ich habe meinen eigenen 'Spion' erstellt, der einfach an der Konsole angemeldet, wenn er angerufen wird).

Ich fand heraus, dass der Grund, warum Sie Ihren Knopf nicht finden, ist, weil es nicht existiert, wo Sie es erwarten könnten.

Die Bootstrap Modal Component (<Modal/>) tatsächlich innerhalb einer React-Overlays modal Komponente enthält (BaseModal im Code genannt, der aus here ist). Dies wiederum macht eine Komponente namens Portal, deren render method einfach null zurückgibt. Es ist dieser null Wert, den Sie versuchen, gerenderte Komponenten zu finden.

Da das Modal nicht als traditioneller React-Weg gerendert wird, kann React das Modal nicht sehen, um TestUtils zu verwenden. Ein ganz eigener <div/> Kind-Knoten ist in dem document Körper platziert und dieser neue <div/> wird verwendet, um das Modal aufzubauen.

Damit Sie einen Klick mit Reacts TestUtils simulieren können (der Klick-Handler auf der Schaltfläche ist weiterhin an das click-Ereignis der Schaltfläche gebunden), können Sie das DOM stattdessen mit Standard-JS-Methoden durchsuchen. Richten Sie Ihren Test wie folgt:

describe('MyModal.jsx', function() { 
    it('tests the Close Button', function() { 
    var spy = sinon.spy(); 
    var MyModalComponent = TestUtils.renderIntoDocument(
     <MyModal show onHide={spy}/> 
    ); 

    // This passes 
    TestUtils.findRenderedComponentWithType(MyModalComponent, MyModal); 

    // This will get the actual DOM node of the button 
    var closeButton = document.body.getElementsByClassName("my-modal-class")[0].getElementsByClassName("btn btn-default")[0]; 

    // Will now get here 
    TestUtils.Simulate.click(CloseButton); 
    expect(spy.calledOnce).to.be.true; 
    }); 
}); 

Die Funktion getElementsByClassName eine Sammlung von Elementen mit dieser Klasse zurückgibt, so dass Sie die erste nehmen muss (und in Ihrem Testfall Ihre einzige) von jeder Sammlung.

Ihr Test soll jetzt passieren^_^

+0

'findRenderedDOMComponentWithTag' schlägt fehl, weil es 0 findet statt 1 :( – user1778856

+0

Oh nein, ich dachte, ich hätte es! Ich werde das hier lassen jetzt aber ich werde weiter arbeiten Ich bearbeite meine Antwort, wenn ich etwas Neues finde =) –

+0

Ich habe meine Antwort mit einer neuen Lösung aktualisiert. Lassen Sie mich wissen, wenn Sie irgendwelche Probleme haben =) –

1

Dies ist die Lösung, die ich mit dem Gehen landete. Es stottert den Weg, den React ein Modal rendert, um stattdessen <div> zu rendern.

test-utils.js:

var sinon = require('sinon'); 
var React = require('react'); 
var Modal = require('react-bootstrap').Modal; 

module.exports = { 
    stubModal: function() { 
    var createElement = React.createElement; 
    modalStub = sinon.stub(React, 'createElement', function(elem) { 
     return elem === Modal ? 
     React.DOM.div.apply(this, [].slice.call(arguments, 1)) : 
     createElement.apply(this, arguments); 
    }); 
    return modalStub; 
    }, 
    stubModalRestore: function() { 
    if (modalStub) { 
     modalStub.restore(); 
     modalStub = undefined; 
    } else { 
     console.error('Cannot restore nonexistent modalStub'); 
    } 
    } 
}; 

modal-test.jsx

var testUtils = require('./test-utils'); 

describe('test a Modal!', function() { 
    before(testUtils.stubModal); 
    after(testUtils.stubModalRestore); 

    it('renders stuff', function() { 
    var MyModalComponent = TestUtils.renderIntoDocument(
     <MyModal show/> 
    ); 
    // Do more stuff you normally expect you can do 
    }); 
}); 
Verwandte Themen