score:0
I found a way to do what I originally asked. I have no opinion (yet) whether it is good strategy or not (in fact I had to refactor the component immediately afterwards, so this question is no longer relevant to what I'm doing). Anyway, here is the testing code (explanation below):
import React from 'react';
import { mount } from 'enzyme';
import { MyComponent } from 'wherever';
import fetchMock from 'fetch-mock';
let _resolveHoldingPromise = false;
class WrappedMyComponent extends MyComponent {
render() {
const result = super.render();
_resolveHoldingPromise && _resolveHoldingPromise();
_resolveHoldingPromise = false;
return result;
}
static waitUntilRender() {
// Create a promise that can be manually resolved
let _holdingPromise = new Promise(resolve =>
_resolveHoldingPromise = resolve);
// Return a promise that will resolve when the component renders
return Promise.all([_holdingPromise]);
}
}
describe('MyComponent', () => {
fetchMock.get('*', 'some_response');
const onError = () => { throw 'Internal test error'; };
it('renders MyComponent appropriately', done => {
let component = <WrappedMyComponent />;
let wrapper = mount(component);
WrappedMyComponent.waitUntilRender().then(
() => {
expect(wrapper.find('whatever')).toBe('whatever');
done();
},
onError);
});
});
The main idea is that, in the testing code, I subclass the component (if this was Python I'd probably monkey-patch it, which works more or less the same way in this case) so that its render()
method sends a signal that it executed. The way to send the signal is by manually resolving a promise. When a promise is created, it creates two functions, resolve and reject, which when called terminate the promise. The way to have code outside the promise resolve the promise is by having the promise store a reference to its resolve function in an external variable.
Thanks to fetch-mock author Rhys Evans who kindly explained the manually-resolve-promise trick to me.
score:1
I'd separate concerns, mainly because is easier to maintain and to test. Instead of declaring the fetch inside the component I'd do it somewhere else, for example in a redux action (if using redux).
Then test individually the fetch and the component, after all this is unit testing.
For async tests you can use the done
parameter on the test. For example:
describe('Some tests', () => {
fetchMock.get('*', some_response);
it('should fetch data', (done) => { // <---- Param
fetchSomething({ some: 'Params' })
.then(result => {
expect(result).toBe({ whatever: 'here' });
done(); // <--- When you are done
});
});
})
The you can tests your component by just sending the loaded data in the props.
describe('MyComponent', () => {
it('renders something', () => {
const mockResponse = { some: 'data' };
let wrapper = mount(<MyComponent data={mockResponse}/>);
expect(wrapper.find(...)).to.have.something();
});
});
When it comes to testing you need to keep it simple, if your component is difficult to test, then there's something wrong with your design ;)
score:1
I've had some success with this, as it doesn't require wrapping or modifying components. It is however assuming there's only one fetch()
in the component, but it can be easily modified if needed.
// testhelper.js
class testhelper
{
static async waitUntil(fnWait) {
return new Promise((resolve, reject) => {
let count = 0;
function check() {
if (++count > 20) {
reject(new TypeError('Timeout waiting for fetch call to begin'));
return;
}
if (fnWait()) resolve();
setTimeout(check, 10);
}
check();
});
}
static async waitForFetch(fetchMock)
{
// Wait until at least one fetch() call has started.
await this.waitUntil(() => fetchMock.called());
// Wait until active fetch calls have completed.
await fetchMock.flush();
}
}
export default testhelper;
Then you can use it just before your assertions:
import testhelper from './testhelper.js';
it('example', async () => {
const wrapper = mount(<MyComponent/>);
// Wait until all fetch() calls have completed
await testhelper.waitForFetch(fetchMock);
expect(wrapper.html()).toMatchSnapshot();
});
Source: stackoverflow.com
Related Query
- How to unit test a React component that renders after fetch has finished?
- How can I write a unit test for a react component that calls reduxjs's mapStateToProps?
- How to test that Redux's dispatch() has been called in React Component (Jest + Enzyme)
- How to test React state after calling a component method that updates state - using Enzyme
- How to test a React component that has Router, Redux and two HOCs... with Jest and Enzyme?
- how to test a react component after data is fetch in componentDidMount?
- Mocha & Enzyme - How to test that React component has no children?
- How to test a React component that renders a Redux-connected component as a child without providing mock Redux store?
- Test React component (Jest & Enzyme) that renders differently after Ajax
- How do i unit test using mocha/chai/sinon if a variable has a react component as value?
- How to unit test a component that has a ref prop
- How to unit test react hooks component that fetches data in useEffect using Enzyme?
- How do i unit test a react app that has all the text fields in the children components?
- How can I ensure that a React component is loaded only after some API call has been made?
- How to test button that on click renders html element within the same component in React testing library, Jest?
- How to test a react component that is dependent on useContext hook?
- How to unit test React Component shouldComponentUpdate method
- How to unit test a react event handler that contains history.push using Jest and Enzyme?
- How to unit test a style of a React Component using Jest.js?
- How do you mock a react component with Jest that has props?
- How to TEST async calls made in componentDidMount that set the state of React Component
- React: How can we know that all component has been mounted/rendered after setState()?
- React: How does React make sure that useEffect is called after the browser has had a chance to paint?
- How to serve a React component library dependent on Styled Components to another library that also has a Styled Comopnents dependency?
- How can I unit test parent react components that call methods on children
- How do I test component methods on a React component that are defined as arrow functions (class properties)?
- How to test state update and component rerender after async call in react
- How to check what react component displays after delay in a test
- How to ensure that page has finished loading on a React site
- How to check if a component has been clicked after an onblur event in React
More Query from same tag
- Simulate a custom Event using Jest and Enzyme
- How to run a function when user clicks the back button, in React.js?
- React-leaflet how to dynamically change Rectangle Color?
- Chart js in React/Gatsby
- Is this useEffect() unecessarily expensive?
- How do I access the value returned by promise firestore?
- How to center text within a border-radius?
- React - Create grid using bootstrap
- ReactDOM.unmountComponentAtNode() in Test causes Warning
- How do I use firebase storage from a client side React app?
- creating a popup without onclick
- Why can't I set an array to API data using useState()?
- Pills in bootstrap is not working in react project
- TypeError: can't convert undefined to object, using React
- Add vendor prefixes for inline css in React for background Linear Gradient
- How to drag-n-drop TableItem from one component to another in material UI?
- How to influence which authentication method is used against MS ADAL (IWA or Form-based) when using react-adal library?
- Selecting rows of `date` in the last 24 hours
- React nested routes - undefined match
- How to programmatically expand or collapse Tree Item in Material Ui?
- React useState keep giving me undefined
- How to call props function in axios response in react.js
- TypeError: _enzyme2.default.configure is not a function
- Redux observable with axios in react
- React Redux - Error on render because expecting props that didn't arrive yet
- React Component not reload in browser after save the changes in localhost
- What is the correct way to add to an array with splice in react
- React-Router: How to redirect Route to another url conditionally?
- How to best type a TypeScript collection of React wrappers
- How to insert link for hashtags and mentions in react quill?