I'm currently creating a new React component for one of our projects and I'm pretty much stuck with writing a proper test for it. I've read quite a few docs and blog posts and more but I can't seem to get it running.
TL;DR
To me, it seems the Promise is not executed. When I run the test with a debugger, it won't stop in the Promise's function and neither in the then() function. It will, however, stop in the then/catch functions in the test itself.
The Code
So, the component is actually fairly simple. For the time being it is supposed to search for a location via an API. The test for it looks like this:
import axios from 'axios';
import React from 'react';
import {shallowWithIntl} from "../../../Helpers/react-intl-helper";
import Foo from "../../../../src/Components/Foo/Foo";
import {mount} from "enzyme";
const queryTerm = 'exampleQueryTerm';
const locationAgs = 'exampleLocationKey';
const fakeLocationObject = {
search: '?for=' + queryTerm + '&in=' + locationAgs
};
jest.mock('axios', () => {
const exampleLocations = [{
"id": "expected-location-id"
}];
return {
get: jest.fn().mockReturnValue(() => {
return Promise.resolve(exampleLocations)
})
};
});
let fooWrapper, instance;
beforeEach(() => {
global.settings = {
"some-setting-key": "some-setting-value"
};
global.URLSearchParams = jest.fn().mockImplementation(() => {
return {
get: function(param) {
if (param === 'for') return queryTerm;
else if (param === 'in') return locationAgs;
return '';
}
}
});
fooWrapper = shallowWithIntl(<Foo location={fakeLocationObject} settings={ global.settings } />).dive();
instance = fooWrapper.instance();
});
it('loads location and starts result search', function() {
expect.assertions(1);
return instance
.searchLocation()
.then((data) => {
expect(axios.get).toHaveBeenCalled();
expect(fooWrapper.state('location')).not.toBeNull();
})
.catch((error) => {
expect(fooWrapper.state('location')).toBe(error);
});
});
So, as you can see the test is supposed to call searchLocation on the Foo component instance, which returns a Promise object, as you can (almost) see in its implementation.
import React, { Component } from 'react';
import { injectIntl } from "react-intl";
import {searchLocationByKey} from "../../Services/Vsm";
class Foo extends Component {
constructor(props) {
super(props);
this.state = {
location: null,
searchingLocation: false,
searchParams: new URLSearchParams(this.props.location.search)
};
}
componentDidUpdate(prevProps) {
if (!prevProps.settings && this.props.settings) {
this.searchLocation();
}
}
searchLocation() {
this.setState({
searchingLocation: true
});
const key = this.state.searchParams.get('in');
return searchLocationByKey(key)
.then(locations => {
this.setState({ location: locations[0], searchingLocation: false })
})
.catch(error => console.error(error));
}
render() {
// Renders something
};
}
export default injectIntl(Foo);
Enter searchLocationByKey:
function requestLocation(url, resolve, reject) {
axios.get(url).then(response => {
let locations = response.data.map(
location => ({
id: location.collectionKey || location.value,
rs: location.rs,
label: location.label,
searchable: location.isSearchable,
rawData: location
})
);
resolve(locations);
}).catch(error => reject(error));
}
export const searchLocationByKey = function(key) {
return new Promise((resolve, reject) => {
let url = someGlobalBaseUrl + '?regional_key=' + encodeURIComponent(key);
requestLocation(url, resolve, reject);
});
};
The Problem
This is the output of the test:
Error: expect(received).toBe(expected)
Expected value to be (using ===):
[Error: expect(received).not.toBeNull()
Expected value not to be null, instead received
null]
Received:
null
I have to admit that I'm pretty new to Promises, React and JavaScript testing, so I might have mixed up several things. As I wrote above, it seems that the Promise is not executed properly. When debugging, it will not stop in the then() function defined in Foo.searchLocation. Instead, apparently, both the then() and catch() functions defined in the test are executed.
I've spent way too much time on this issue already and I'm clueless on how to go on. What am I doing wrong?
Aucun commentaire:
Enregistrer un commentaire