diff --git a/src/spy.ts b/src/spy.ts index e3632bb..3f9cbf2 100644 --- a/src/spy.ts +++ b/src/spy.ts @@ -28,9 +28,12 @@ export interface SpyImpl extends Spy { export interface SpyFn extends Spy { (...args: A): R + new (...args: A): R } -export function spy(cb?: (...args: A) => R): SpyFn { +export function spy( + cb?: ((...args: A) => R) | { new (...args: A): R } +): SpyFn { assert( isType('function', cb) || isType('undefined', cb), 'cannot spy on a non-function value' @@ -100,7 +103,7 @@ export function spy(cb?: (...args: A) => R): SpyFn { fn.calls = [] } reset() - fn.impl = cb + fn.impl = cb as any fn.reset = reset fn.nextError = (error: any) => { fn.next = ['error', error] diff --git a/test/class.test.ts b/test/class.test.ts index ac938da..5b4f7fe 100644 --- a/test/class.test.ts +++ b/test/class.test.ts @@ -30,7 +30,7 @@ describe('class mock', () => { expect(() => new fnArrow()).toThrowError() }) - test('respects new.target', () => { + test('respects new.target in a function', () => { let target: unknown = null let args: unknown[] = [] const fnScoped = spy(function (...fnArgs: unknown[]) { @@ -43,4 +43,22 @@ describe('class mock', () => { expect(args).toEqual(['some', 'text', 1]) expect(fnScoped.calls).toEqual([['some', 'text', 1]]) }) + + test('respects new.target in a class', () => { + let target: unknown = null + let args: unknown[] = [] + const fnScoped = spy( + class { + constructor(...fnArgs: unknown[]) { + target = new.target + args = fnArgs + } + } + ) + + new fnScoped('some', 'text', 1) + expect(target).toBeTypeOf('function') + expect(args).toEqual(['some', 'text', 1]) + expect(fnScoped.calls).toEqual([['some', 'text', 1]]) + }) })