javascript / intermediate
Snippet
Asserting Custom Emitted Events and Async State with Vitest and Vue Test Utils
When testing asynchronous Vue components with Vue Test Utils and Vitest, triggered DOM interactions queue microtasks that update reactive states and emit custom events. Using `flushPromises()` resolves all pending promises in the queue, allowing deterministic assertions on emitted payloads and button disabled states without arbitrary timers.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { mount, flushPromises } from '@vue/test-utils';import { describe, it, expect, vi } from 'vitest';import AsyncSubmitButton from './AsyncSubmitButton.vue';describe('AsyncSubmitButton.vue', () => {it('emits success payload after asynchronous operation resolves', async () => {const mockApi = vi.fn().mockResolvedValue({ status: 200, id: 'tx-99' });const wrapper = mount(AsyncSubmitButton, {props: { actionHandler: mockApi }});const button = wrapper.find('button');await button.trigger('click');expect(button.attributes('disabled')).toBeDefined();await flushPromises();expect(mockApi).toHaveBeenCalledTimes(1);expect(wrapper.emitted('completed')).toBeTruthy();expect(wrapper.emitted('completed')?.[0]).toEqual([{ status: 200, id: 'tx-99' }]);expect(button.attributes('disabled')).toBeUndefined();});});
vue
Breakdown
1
const mockApi = vi.fn().mockResolvedValue({ status: 200, id: 'tx-99' });
Creates a Vitest spy that simulates a successful asynchronous network request.
2
await button.trigger('click');
Dispatches a click event to the rendered DOM element and awaits the resulting event cycle.
3
await flushPromises();
Flushes all unresolved microtasks and promises queued by the component logic.
4
expect(wrapper.emitted('completed')?.[0]).toEqual([{ status: 200, id: 'tx-99' }]);
Verifies that the custom event fired exactly once with the expected payload structure.