2016-01-29 19 views
5

Przykro mi, ale najtrudniej było mi próbować zamknąć mój Modę Reagową, klikając przycisk. Modal jest tak proste, jak tylko możliwe, i próbowałem wszystkiego, co potrafię wymyślić lub znaleźć, ale wciąż nie mogę zapytać o to swoich dzieci.Testowanie komponentu React Modal

modalnego komponent:

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

Moim celem jest sprawdzenie, czy to przycisk Zamknij odpala funkcję onHide() gdy zostanie kliknięty.

Mój plik testowy:

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

Bez względu na to, co staram, nie mogę wydawać się znaleźć przycisk Zamknij.

+0

Używasz żart? Nigdy nie użyłem żartu, ale myślę, że automatycznie koryguje zależne komponenty. Czy to może być problem? –

+0

@AbhishekJain Używam Mocha – user1778856

+0

jest "

Odpowiedz

6

Napisałem jsFiddle używając React Base Fiddle (JSX), aby dowiedzieć się, co działo się w teście (stworzyłem mojego "szpiega", który po prostu zalogował się do konsoli po wywołaniu).

Dowiedziałem się, że powodem, dla którego nie możesz znaleźć swojego przycisku, jest to, że nie istnieje tam, gdzie możesz się tego spodziewać.

Bootstrap Modal Component (<Modal/>) faktycznie zawarte w składniku React-Overlays modalnego (zwany BaseModal w kodzie, który jest z here). To z kolei renderuje komponent o nazwie Portal, którego render method po prostu zwraca null. Jest to wartość, na którą próbujesz znaleźć wyrenderowane komponenty.

Z uwagi na to, że modal nie jest renderowany w tradycyjny sposób React, React nie widzi modala, aby użyć TestUtils na. Całkowicie oddzielny węzeł potomny <div/> jest umieszczony w ciele document i ten nowy <div/> jest wykorzystywany do budowy modalu.

Aby umożliwić symulację kliknięcia za pomocą przycisku React o numerze TestUtils (obsługa kliknięcia przycisku nadal wiąże się z kliknięciem przycisku), można użyć standardowych metod JS w celu przeszukania DOM. Konfigurowanie testu w następujący sposób:

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

Funkcją getElementsByClassName zwraca kolekcję elementów z tej klasy, więc trzeba wziąć pierwsza (i w danym przypadku test, swój jedyny) z każdej kolekcji.

test powinien teraz przejść^_^

+0

'findRenderedDOMComponentWithTag' kończy się niepowodzeniem, ponieważ znajduje 0 zamiast 1 :( – user1778856

+0

O nie! Myślałem, że mam to! Zostawię to tutaj na razie, ale będę pracował dalej na nim. Edytuję swoją odpowiedź, gdy znajdę coś nowego =) –

+0

Zaktualizowałem swoją odpowiedź za pomocą nowego rozwiązania. Daj mi znać, jeśli masz jakieś problemy =) –

1

To rozwiązanie skończyło się dzieje z. To powoduje, że React renderuje Modala, aby zamiast niego renderować <div>.

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 
    }); 
}); 
Powiązane problemy