2016-05-24 11 views
5
  • Reagire v15.1.0
  • Jest v12.1.1
  • Enzyme v2.3.0

sto cercando di capire come testare un componente che chiama una promessa in una funzione invocata da un clic. Mi aspettavo la funzione runAllTicks() di Jest per aiutarmi, ma sembra che non stia eseguendo la promessa.Test con Reagire di Jest e l'enzima quando scatti simulati chiamano una funzione che chiama una promessa

Componente:

import React from 'react'; 
import Promise from 'bluebird'; 

function doSomethingWithAPromise() { 
    return new Promise((resolve) => { 
    setTimeout(() => { 
     resolve(); 
    }, 50); 
    }); 
} 

export default class AsyncTest extends React.Component { 
    constructor(props) { 
    super(props); 

    this.state = { 
     promiseText: '', 
     timeoutText: '' 
    }; 

    this.setTextWithPromise = this.setTextWithPromise.bind(this); 
    this.setTextWithTimeout = this.setTextWithTimeout.bind(this); 
    } 

    setTextWithPromise() { 
    return doSomethingWithAPromise() 
     .then(() => { 
     this.setState({ promiseText: 'there is text!' }); 
     }); 
    } 

    setTextWithTimeout() { 
    setTimeout(() => { 
     this.setState({ timeoutText: 'there is text!' }); 
    }, 50); 
    } 

    render() { 
    return (
     <div> 
     <div id="promiseText">{this.state.promiseText}</div> 
     <button id="promiseBtn" onClick={this.setTextWithPromise}>Promise</button> 
     <div id="timeoutText">{this.state.timeoutText}</div> 
     <button id="timeoutBtn" onClick={this.setTextWithTimeout}>Timeout</button> 
     </div> 
    ); 
    } 
} 

E i test: non

import AsyncTest from '../async'; 
import { shallow } from 'enzyme'; 
import React from 'react'; 

jest.unmock('../async'); 

describe('async-test.js',() => { 
    let wrapper; 

    beforeEach(() => { 
    wrapper = shallow(<AsyncTest />); 
    }); 

    // FAIL 
    it('displays the promise text after click of the button',() => { 
    wrapper.find('#promiseBtn').simulate('click'); 

    jest.runAllTicks(); 
    jest.runAllTimers(); 

    wrapper.update(); 

    expect(wrapper.find('#promiseText').text()).toEqual('there is text!'); 
    }); 

    // PASS 
    it('displays the timeout text after click of the button',() => { 
    wrapper.find('#timeoutBtn').simulate('click'); 

    jest.runAllTimers(); 

    wrapper.update(); 

    expect(wrapper.find('#timeoutText').text()).toEqual('there is text!'); 
    }); 
}); 
+0

è possibile invece passare la funzione doSomethingWithAPromise come componente del componente AsyncTest in modo da poterlo prendere in giro nel test: http://stackoverflow.com/questions/38308214/react-enzyme-test-componentdidmount-async-call/40875174 # 40875174 – bodrin

risposta

1

c'è molto intorno dover attendere in qualche modo per la promessa di soddisfare prima di terminare la prova. Ci sono due modi principali di farlo dal tuo codice che posso vedere.

  1. test indipendente che onClick e i metodi di promessa. Quindi controlla che onClick chiami la funzione corretta, ma spiando setTextWithPromise, attivando un clic e asserendo che è stato chiamato setTextWithPromise. Quindi puoi anche ottenere l'istanza del componente e chiamare quel metodo che restituisce la promessa che puoi allegare un gestore e asserire che ha fatto la cosa giusta.

  2. esporre un puntello di richiamata che è possibile passare in quello che viene chiamato quando la promessa si risolve.

17

Ho risolto con successo il problema combinando i seguenti elementi:

  • Mock la promessa e renderlo risolvere immediatamente
  • Usa di setImmediate di rinviare il test fino a quando il segno di spunta accanto Nodo, che è quando la promessa si risolverà.
  • Call Jest's done per completare il test in modo asincrono.

Nel tuo esempio, che potrebbe essere simile a questo:

global.doSomethingWithAPromise =() => Promise.resolve({}); 

it('displays the promise text after click of the button', (done) => { 
    wrapper.find('#promiseBtn').simulate('click'); 

    setImmediate(() => { 
    expect(wrapper.find('#promiseText').text()).toEqual('there is text!'); 
    done(); 
    }) 
}); 

dell'enzima update() è né sufficiente né necessaria quando si utilizza questo metodo, perché le promesse non si risolvono nello stesso segno di spunta sono creati - in base alla progettazione . Per una spiegazione molto dettagliata di cosa sta succedendo qui, vedi this question.

+0

BINGO! 'setImmediate' era quello che dovevo usare nella mia funzione di callback che veniva attivata tramite uno dei metodi del ciclo di vita' componentDidUpdate' del mio componente. –

+0

Ho avuto un problema simile ma l'ho risolto con 'setTimeout (() => {...}, 0)'. Per qualche ragione 'setImmediate' ha reso i test falliti in modo tale che persino il comando' yarn test' è terminato bruscamente. – Ernesto

Problemi correlati