Enzyme: How would you test element created by ajax

Created on 3 Jul 2016  路  12Comments  路  Source: enzymejs/enzyme

My select component is like below

class Select extends React.component(){
    render(){
        return(
            <select>
                some options element return by ajax appended in here
            </select>
        )
    }
}

How do check if select have some option in it after it has been updated by other ajax function

Most helpful comment

const promise = Promise.resolve(['de','am','hl']);
sinon.stub(axios, 'get', () => promise);
const wrapper = shallow(<Select />);
return promise.then(() => {
  wrapper.update();
  // your assertions here
});

All 12 comments

@craigcosmo how is it "updated"? In React, you'd generally have your ajax callback setState on the component, and then the render function would pivot based on this.state. If so, then you test it by using setState in enzyme, and making assertions on the wrapper.

Here is the code:

import axios from 'axios'
class Select extends React.component(){
    constructor(){
        super()
        this.state.item=[]
    }
    componentWillMount(){
        axios.get('http://domain.com/country_list')
        .then(function (response) {
            this.setState({item:response.data})
            // reponse data ['america','singapore','vietnam']
        })
    }   
    render(){
        return(
            <select>
                this.state.item.map((i) => {
                    <option value={i}>{i}</option>
                })
            </select>
        )
    }
}

Can you give me an example of the test code?

off the top of my head:

// do whatever you need to mock axios
const wrapper = shallow(<Select />); // componentWillMount will be called
// after axios has called the "then" callback:
wrapper.update();
// make your assertions

does that not work?

I'm afraid I'm gonna have to extend the question. How would you mock axios in this case? I updated the code above to be more specific. And it would be great If you can show a specific sample.

That's specific to axios. Perhaps sinon.stub(axios, 'get', () => Promise.resolve(fakeResponse))?

Since your component doesn't use any sort of dependency injection, if your test file can't access axios, you can use something like nock to fake the HTTP answer.

However, I would encourage you to split your component in two, one that simply takes care of this call, and then passes the corresponding data to its child, it will make it easier to test, and usually easier to reason about, see the smart/dumb component distinction.

This is what I get out so far:

import {expect} from 'chai'
import {shallow} from 'enzyme'
import sinon from 'sinon'
import Select from 'Select'
import axios from 'axios'
describe('select list', () => {
    it('should have options', () => {
        sinon.stub(axios, 'get', () => Promise.resolve(['de','am','hl']))
        const wrapper = shallow(<Select />)
        wrapper.update()
        const actual = wrapper.find('option').length
        expect(actual).to.not.equal(0)
    })
})

Error: Attempted to wrap get which is already wrapped

screen shot 2016-07-04 at 4 08 20 pm

@craigcosmo it's an async test. you need to either return a promise or have the mocha test take a done argument - and in this case, you need to wait until the axios-stubbed promise is done before calling update().

At this point this is not an enzyme issue, so I'm going to close it. Feel free to continue exploring how to use mocha here.

How would you actually do it?

const promise = Promise.resolve(['de','am','hl']);
sinon.stub(axios, 'get', () => promise);
const wrapper = shallow(<Select />);
return promise.then(() => {
  wrapper.update();
  // your assertions here
});

@craigcosmo Did you actually find a solution?
This is how the componentWillMount lifecycle method looks...

componentWillMount(){
        axios.get('api/v1/getcall')
        .then(function (response) {
            this.setState({ item:response.data })
        })

I am using axios-mock-adaptor to mock the axios calls, but ran into the same state as yours.

@parminder7 Ljharb's solution is the solution.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

blainekasten picture blainekasten  路  3Comments

mattkauffman23 picture mattkauffman23  路  3Comments

blainekasten picture blainekasten  路  3Comments

potapovDim picture potapovDim  路  3Comments

dschinkel picture dschinkel  路  3Comments