web-dev-qa-db-fra.com

la valeur setState utilisée dans composantDidMount n'est pas reflétée dans le test enzymatique

Component.js

import React from 'react'
import request from 'superagent'

export default React.createClass({
    getInitialState() {
        return {cats: []}
    },

    componentDidMount() {
        request('/api', (err, res) => {
            if (err) return;
            this.setState({
                cats: res.body.results
            })
        })
    },

    render() {
        let cats = this.state.cats
        let catsList = (
            <ul>
                {cats.map((c) => <li key={c.id}>cat</li>)}
            </ul>
        )
        return (
            <div>
                {cats.length ? catsList : null}
            </div>
        )
    }
})

Component.test.js

jest.unmock('../app.js')
jest.unmock('superagent')

import React from 'react'
import {mount} from 'enzyme'
import nock from 'nock'
import App from '../app.js'

describe('App', () => {
    let ajaxFn
    beforeEach(() => {
        ajaxFn = nock('http://localhost')
            .get('/api')
            .reply(200, {
                results: [{id: 1}, {id: 2}, {id: 3}]
            })
    })

    it('renders correct number of cats', () => {
        let wrapper = mount(<App />)
        expect(wrapper.state('cats').length).toBe(3)
    })
})

Le test ne passe pas. wrapper.state('cats').length est toujours 0.

Je comprends que setState ne garantit pas la mise à jour immédiate de l’état, Toutefois, si je consigne les "chats" dans le composant, je peux le voir se mettre à jour.

Si vous définissez l'état de votre composant dans un contexte inconnu de l'enzyme, vous devrez appeler manuellement .update() sur le wrapper pour qu'il obtienne la version mise à jour de l'arborescence de rendu.

it('renders correct number of cats', () => {
    let wrapper = mount(<App />)
    expect(wrapper.update().state('cats').length).toBe(3)
})
9
Leland Richardson

J'ai eu un problème similaire et il était nécessaire de renvoyer une promesse du rappel it et de vérifier l'espérance dans la méthode then de la promesse. 

Dans votre cas (en supposant que ajaxFn était une promesse, ou vous pourriez en faire une), je pense que ce serait approximativement:

it('renders correct number of cats', () => {
    let wrapper = mount(<App />) 
    return ajaxFn.then(() => {
        expect(wrapper.state('cats').length).toBe(3);
    }
})
2
Simon Hardman

Je ne connais pas toutes les bibliothèques que vous utilisez, mais comme votre code est exécuté de manière asynchrone, le test se termine avant que l'état ne puisse être mis à jour. J'ai pu résoudre ce problème en ajoutant async/wait au test:

it('renders correct number of cats', async () => {
    let wrapper = await mount(<App />)
    expect(wrapper.state('cats').length).toBe(3)
})
1
Developer Davo