I am facing a situation where I have a component with behavior similar to the one below:
@Component
export default class MyComponent extends Vue {
public result: number = 0;
public ready: boolean = false;
// for test purpose only. In the real code, this promise is the result of a call to a dependency service.
public promise!: Promise<void>;
private myMethod(): void {
this.promise
.then(() => {
this.result = 1;
})
.catch(() => {
this.result = 2;
})
.finally(() => {
this.ready = true;
// setTimeout(() => {
// this.finallyExecuted = true;
// }, 50);
});
}
}
The execution of a method, triggered from a click on the following button, depends on the resolution of a promise.
<button id="myButton" type="button" @click="myMethod()">My button</button>
I aim to unit test this behavior using Jest.
// variable 'wrapper' contains the result of a shallow mount of the component, using vue-test-utils
// variable 'component' contains 'wrapper.vm', after the component has been shallow mounted
it('should set the result to 1 and be ready', async () => {
// Given
component.promise = Promise.resolve();
// When
wrapper.find('#myButton').trigger('click');
await expect(component.promise).resolves.toBeUndefined();
// Then
expect(component.result).toBe(1);
expect(component.ready).toBe(true);
});
it('should set the result to 2 and be ready', async () => {
// Given
component.promise = Promise.reject();
// When
wrapper.find('#myButton').trigger('click');
await expect(component.promise).rejects.toBeUndefined();
// Then
expect(component.result).toBe(2);
expect(component.ready).toBe(true);
});
Unfortunately, both of these unit tests fail because Jest does not wait for the finally
clause to be executed before performing the last assertion. The assertion on result
passes, but ready
is incorrectly seen as false
in both cases.
I need a solution to make Jest wait for the promise to be fully handled, including the finally
clause. Ideally, I would like to achieve this without relying on an additional library.