Apologies in advance for the lengthy question. I am striving to provide a clear explanation of the issue I am currently encountering.
During the development of my decorators utilities library, I came across an unexpected behavior while working on one specific decorator (https://github.com/vlio20/utils-decorators/blob/master/src/after/after.ts).
The decorator is named "after," and its purpose is to invoke a different function after the decorated method's execution. However, I noticed that if the function returns a promise, the decorator should wait for the promise to resolve before calling the after function.
Here is relevant code snippet:
if (resolvedConfig.wait) {
const response = await originalMethod.apply(this, args);
afterFunc({
args,
response
});
} else {
const response = originalMethod.apply(this, args);
afterFunc({
args,
response
});
}
In the code above, I am using a flag to indicate whether the decorated method is asynchronous and returns a Promise. Ideally, I would like to eliminate the need for this flag by restructuring the code as follows:
const response = await originalMethod.apply(this, args);
afterFunc({
args,
response
});
Essentially, I aim to always use the await
keyword before executing the original method, under the understanding that it doesn't affect synchronous methods.
The issue arises when I make this modification as suggested above; a particular unit test fails:
it('should verify after method invocation when method is provided', () => {
let counter = 0;
const afterFunc = jest.fn(() => {
expect(counter).toBe(1);
});
class T {
@after<T, void>({
func: afterFunc
})
foo(x: number): void {
return this.goo(x);
}
goo(x: number): void {
expect(counter++).toBe(0);
return;
}
}
const t = new T();
const spyGoo = jest.spyOn(T.prototype, 'goo');
t.foo(1);
expect(spyGoo).toBeCalledTimes(1);
expect(spyGoo).toBeCalledWith(1);
expect(afterFunc.mock.calls.length).toBe(1); // this line fails
});
I have created a fork of the library where this specific test case is failing (https://github.com/vlio20/utils-decorators/pull/new/after-issue).
I'm puzzled about where my understanding might be incorrect. Any insights would be greatly appreciated.