Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mocked() no longer seems to function correctly #998

Closed
robcresswell opened this issue Feb 23, 2019 · 15 comments
Closed

mocked() no longer seems to function correctly #998

robcresswell opened this issue Feb 23, 2019 · 15 comments

Comments

@robcresswell
Copy link

robcresswell commented Feb 23, 2019

I'm sort of surprised nobody else has encountered this, but I'm seeing it in two repos with quite different setups.

Issue

As of the latest Jest / ts-jest and @types/jest, any test runs throw errors for mock properties not existing on MockedFunction<>. For example:

error TS2339: Property 'mockRejectedValue' does not exist on type 'MockedFunction<RequestAPI<RequestPromise<any>, RequestPromiseOptions, RequiredUriUrl>>'.

    29     requestMock.mockRejectedValue(new Error());

The setup itself is very very simple;

import { mocked } from 'ts-jest/utils';

jest.mock('request-promise-native');
import * as request from 'request-promise-native';

const requestMock = mocked(request);

afterEach(() => requestMock.mockRestore());

This looks like it might be similar to #991

Expected behavior

mocked() works as in ts-jest 23.x

@sdn90
Copy link

sdn90 commented Feb 28, 2019

I'm using ts-jest 23.x. Downgrading @types/jest to 23.3.13 worked for me. Seems like the issue was in @types/jest 23.3.14.

@superhawk610
Copy link

superhawk610 commented Mar 9, 2019

mocked() returns an interface MockWithArgs<T> that extends jest.MockInstance<T>. Recently, jest updated jest.MockInstance to accept 2 type arguments

// @types/jest/index.d.ts line 845
interface MockInstance<T, Y extends any[]> {

To remain compatible, mocked should return an interface that also accepts a second argument. I'll work on a PR for this tonight.

EDIT: Y is the type of the ...args passed to the mocked function.

EDIT 2: Looks like it was changed a month or so ago here.

@superhawk610
Copy link

#994 should close this.

@superhawk610
Copy link

superhawk610 commented Mar 9, 2019

If you want a quick temporary fix, replace the contents of node_modules/ts-jest/dist/util/testing.d.ts with this:

/// <reference types="jest" />
declare type MockableFunction = (...args: any[]) => any
declare type MethodKeysOf<T> = { [K in keyof T]: T[K] extends MockableFunction ? K : never }[keyof T]
declare type PropertyKeysOf<T> = { [K in keyof T]: T[K] extends MockableFunction ? never : K }[keyof T]
declare type ArgumentsOf<T> = T extends (...args: infer A) => any ? A : never
declare type ConstructorArgumentsOf<T> = T extends new (...args: infer A) => any ? A : never

interface MockWithArgs<T extends MockableFunction> extends jest.MockInstance<ReturnType<T>, ArgumentsOf<T>> {
  new (...args: ConstructorArgumentsOf<T>): T
  (...args: ArgumentsOf<T>): ReturnType<T>
}

declare type MaybeMockedConstructor<T> = T extends new (...args: any[]) => infer R
  ? jest.MockInstance<R, ConstructorArgumentsOf<T>>
  : {}
declare type MockedFunction<T extends MockableFunction> = MockWithArgs<T> & { [K in keyof T]: T[K] }
declare type MockedFunctionDeep<T extends MockableFunction> = MockWithArgs<T> & MockedObjectDeep<T>
declare type MockedObject<T> = MaybeMockedConstructor<T> &
  { [K in MethodKeysOf<T>]: T[K] extends MockableFunction ? MockedFunction<T[K]> : T[K] } &
  { [K in PropertyKeysOf<T>]: T[K] }
declare type MockedObjectDeep<T> = MaybeMockedConstructor<T> &
  { [K in MethodKeysOf<T>]: T[K] extends MockableFunction ? MockedFunctionDeep<T[K]> : T[K] } &
  { [K in PropertyKeysOf<T>]: MaybeMockedDeep<T[K]> }

export declare type MaybeMockedDeep<T> = T extends MockableFunction
  ? MockedFunctionDeep<T>
  : T extends object
  ? MockedObjectDeep<T>
  : T
export declare type MaybeMocked<T> = T extends MockableFunction ? MockedFunction<T> : T extends object ? MockedObject<T> : T

export declare function mocked<T>(item: T, deep?: false): MaybeMocked<T>
export declare function mocked<T>(item: T, deep: true): MaybeMockedDeep<T>
export declare function mocked<T>(item: T, _deep?: false): MaybeMocked<T> | MaybeMockedDeep<T>;
export {};

EDIT: This won't work for CI builds, to have them pass you'll need to just cast your mock to any like so:

(mockedFn as any).mockImplementation(() => true);

@robcresswell
Copy link
Author

@superhawk610 Thanks, I'll test this out. Any idea when this might get merged?

@superhawk610
Copy link

I'm not sure, I'm relatively new to this project. Hopefully soon! @GeeWee approved the last couple approved PRs, maybe he can better answer that.

@G-Rath
Copy link
Contributor

G-Rath commented Mar 27, 2019

Hopefully this can get merged & released soon, as its a pretty big thing IMO.

In the meantime, I worked around this by creating a file to re-export mocked with the new typings:

https://gist.github.com/G-Rath/66246c74ee69d952fde71a1bc3f8687d

This is obviously a hack that forces TypeScript by casting to any, but it compiles & seems compatible with TS (I get autocompletion, type checking, etc).

I'd appreciate some input in trying to get it as hackless as possible - in particular, the deep parameter gave me a lot of grief.

@robcresswell
Copy link
Author

Hey @GeeWee,

Any chance you or one of the other maintainers can review this? It's been over a month, and your current release is broken / unusable.

If the library isn't being maintained any more, that's okay! Happy to fork, I don't expect free work, but a quick yes / no would be wonderful.

Thanks

@GeeWee
Copy link
Collaborator

GeeWee commented Mar 30, 2019

I'm in the process of merging 994 in.
Unfortunately ts-jest is in a bit of a twilight zone right now, as none of the core maintainers have very much time to dedicate to it. We're doing our best, but response times are probably going to be pretty slow until someone has more free time (or another contributor steps up to the plate)

Thanks for being polite about it.

@GeeWee
Copy link
Collaborator

GeeWee commented Mar 30, 2019

#994 is merged in. I'm not sure when @kulshekhar will release the next version, but I hope it'll fix this issue. I'm leaving it open until we figure it out. Please report back when you've tested it with the new release.

@grantlucas
Copy link

I've updated to 24.0.1 which appears to have #994 merged in at that point based on the current master but I'm not seeing the expected changes locally. If I manually copy what @superhawk610 pasted into /node_modules/ts-jest/dist/util/testing.d.ts the issues seem to resolve.

Can anyone else confirm if the changes from 994 are indeed in 24.0.1?

Thanks!

@kulshekhar
Copy link
Owner

Looks like this was merged after the last version was published. I'll publish a new one shortly

@robcresswell
Copy link
Author

@GeeWee Thanks for your help in merging this and thanks @kulshekhar for publishing!

@kulshekhar
Copy link
Owner

A new version has been published.

@robcresswell
Copy link
Author

Just realised this is still open; closing, as it has been resolved. Sorry for leaving it open!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants