`flushPromises` from `vue-test-utils` must be called multiple times
See original GitHub issueDiscussed in https://github.com/mswjs/msw/discussions/988
Please read discussion first for full details.
<div type='discussions-op-text'>Originally posted by vincerubinetti November 17, 2021
I have a Vue and vue-test-utils project that I’m trying to use MSW with. I have unit tests for components that call api functions when mounted. Vue exports a function called flushPromises
, which is intended to be a simple function you can await to make sure the api calls have returned and the component has finished rendering before continuing with the test.
import { flushPromises, mount } from "@vue/test-utils";
mount(someComponent, mountOptions);
await flushPromises();
await flushPromises(); // <-- need this extra call for MSW to work properly, but not axios-mock-adapter
// some assertions
The component that I’m testing looks like this:
export default defineComponent({
data() {
return {
status: null
};
},
async mounted() {
this.status = "loading";
try {
this.blah = await axios.get(...blah...);
this.status = null;
} catch (error) {
this.status = "error";
}
},
});
For some reason, with MSW, I need two flushPromises
calls for my tests to pass. The odd thing is, I was using axios-mock-adapter
before trying out MSW, and it was working with just one call. Can anyone think of any reason why MSW might be different?
Another funny thing is that MSW is working in my e2e tests in Cypress (setupWorker), but the problem I describe above is happening in my unit tests in Jest (setupServer), which is setup like this:
const server = setupServer(...handlers);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
</div>
Minimum reproducible example
Here is a barebones Vue CLI project with jest unit tests and cypress e2e tests set up: https://github.com/vincerubinetti/msw-test (archived for posterity)
You can run the unit tests with yarn test:unit
and the e2e (with gui) tests with yarn test:e2e
. This demonstrates the behavior that msw
needs two calls to flushPromises
whereas axios-mock-adapter
only needs one.
You can verify that msw
and axios-mock-adapter
are both correctly mocking the call by adding expect(wrapper.text()).toMatch("foo"); expect(wrapper.text()).toMatch("bar");
.
Issue Analytics
- State:
- Created 2 years ago
- Comments:16 (5 by maintainers)
Top GitHub Comments
Summary, if I may, for anyone stumbling upon this in the future:
vue-test-utils
implementsflushPromises
as a dead simple way to “wait for external promises to resolve”flushPromises
makes a fairly important assumption about the external promisesmsw
does notmsw
implementation, precisely 2 calls are needed.msw
dev will not change their implementation to conform (possibly justified if it will cause unexpected breaking changes)vue-test-utils
devs will add documentation update with a warning aboutvue-test-utils
+msw
Feel free to edit this comment if any of this is incorrect.
For a race condition, it has been extraordinarily consistent, across multiple OS’s, new/old devices, and 100+ runs.
I asked the
vue-test-utils
folks about this. See https://github.com/vuejs/test-utils/issues/137 I also looked intomsw
’s compiled code, and it seems like every request is behind asetTimeout(func, 0)
promise (or more, if using thedelay()
feature), which is basically like one instance offlushPromises
. As such, their explanation for why you need twoflushPromises
makes more sense to me.Again yes,
axios-mock-adapter
. Perhaps that library is mocking things synchronously somehow, leading to the difference.Ultimately it seems to come down to this. I’m begging for
msw
andvue-test-utils
to just add a simple note somewhere. One sentence could’ve saved me hours and hours of discussion, investigating, making min-reproductions, etc.I can see that you disagree with
vue-test-utils
’s approach, but it is the default testing library forvue-cli
projects (equivalent to the ubiquitouscreate-react-app
). In other words, a ton of people use it. I would really appreciate it if you could just add a simple warning about usingvue-test-utils
withmsw
.