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

Getting from MockedFunction to Mock #9

Closed
yakirn opened this issue Jan 19, 2021 · 6 comments
Closed

Getting from MockedFunction to Mock #9

yakirn opened this issue Jan 19, 2021 · 6 comments

Comments

@yakirn
Copy link

yakirn commented Jan 19, 2021

Hey,
First of all, thank you for an awesome extension!
Second, please see this unanswered question.
It's more of a quality of life thing than an actual issue (I hate to use any in TS).
Figured since the code works just fine there must be a less risky way to tell TS it's fine.
The assertion is from jest-extended

TL;DR
I'm trying to make TS to accept the following line but without casting to any:
expect(chrome.tabs.update).toHaveBeenCalledAfter(chrome.cookies.set as any);
Thanks!

jacksteamdev added a commit to jacksteamdev/DefinitelyTyped that referenced this issue Jan 19, 2021
This change allows `MockedFunction` to be used where `Mock` can be used. I don't think this fundamentally changes `MockedFunction`, just makes it more robust. This would resolve issues where an extended expect method takes a `Mock` type, but the mocking library uses `MockedFunction`.

Related issues:
extend-chrome/jest-chrome#9
jest-community/jest-extended#292
@jacksteamdev
Copy link
Contributor

jacksteamdev commented Jan 19, 2021

Great question! It looks like there's an open PR in jest-extended that fixes this issue.

The root of the problem is that Mock and MockedFunction are both based on MockInstance, but are different types.

This could be solved two ways:

  1. toHaveBeenCalledAfter could take a MockInstance, not a Mock. This is what the PR for jest-extended does.
  2. MockedFunction could be based on Mock. This is probably the best solution.

Both probably need to happen.

I've made a draft PR in @types/jest, but I don't have time to finish it before my next meeting. I'll try to get back to it soon. Feel free to run with it if you want!

@jacksteamdev jacksteamdev added the help wanted Extra attention is needed label Jan 27, 2021
@jacksteamdev
Copy link
Contributor

jacksteamdev commented Jan 27, 2021

@yakirn Maybe you could cast to MockInstance in the meantime? At least it's better than any.

expect(chrome.tabs.update).toHaveBeenCalledAfter(chrome.cookies.set as jest.MockInstance);

@yakirn
Copy link
Author

yakirn commented Jan 28, 2021

@jacksteamdev casting to jest.Mock did the trick!
expect(chrome.tabs.update).toHaveBeenCalledAfter(chrome.cookies.set as jest.Mock);

jest.MockInstance is a generic that requires two arguments, but also jest.MockInstance<any, any> failed with:

interface jest.MockInstance<T, Y extends any[]>
Argument of type 'MockInstance<any, any>' is not assignable to parameter of type 'Mock<any, any>'.
Type 'MockInstance<any, any>' is missing the following properties from type 'Mock<any, any>': apply, call, bind, prototype, and 5 more.ts(2345)

Anything left to do with the PR do DefinitelyTyped? If you can fill me in I can try and continue over the weekend.

@jacksteamdev
Copy link
Contributor

jacksteamdev commented Feb 2, 2021

@yakirn I finished the DefinitelyTyped PR. I wanted to add some tests. We'll see how it goes 🤞

We should upvote the PR in jest-extended, which needs to get merged.

jest-community/jest-extended#292

@yakirn
Copy link
Author

yakirn commented Feb 2, 2021

Thank you so much @jacksteamdev ! I upvoted and I’ll ask my coworkers to do the same :)

@jacksteamdev jacksteamdev removed the help wanted Extra attention is needed label Feb 2, 2021
@jacksteamdev
Copy link
Contributor

@yakirn It looks like these PRs probably won't go anywhere fast. 😞

But, we can use module augmentation to fix it locally. Create a declaration file, (ie, jest-mocked-function.d.ts), and put this in it:

/// <reference types="jest" />

declare namespace jest {
  interface Matchers {
    /**
     * Use `.toHaveBeenCalledBefore` when checking if a `MockInstance` was called before another `MockInstance`.
     *
     * Note: Required Jest version >=23
     *
     * @param {MockInstance} mock
     */
    toHaveBeenCalledBefore(mock: jest.MockInstance): R

    /**
     * Use `.toHaveBeenCalledAfter` when checking if a `MockInstance` was called after another `MockInstance`.
     *
     * Note: Required Jest version >=23
     *
     * @param {MockInstance} mock
     */
    toHaveBeenCalledAfter(mock: jest.MockInstance): R
  }

  interface Expect {
    /**
     * Use `.toHaveBeenCalledBefore` when checking if a `MockInstance` was called before another `MockInstance`.
     *
     * Note: Required Jest version >=23
     *
     * @param {MockInstance} mock
     */
    toHaveBeenCalledBefore(mock: jest.MockInstance): R

    /**
     * Use `.toHaveBeenCalledAfter` when checking if a `MockInstance` was called after another `MockInstance`.
     *
     * Note: Required Jest version >=23
     *
     * @param {MockInstance} mock
     */
    toHaveBeenCalledAfter(mock: jest.MockInstance): R
  }
}

I've tried it out like this, and it works for me!

import { chrome } from "jest-chrome";

import "jest-extended";

test('toBeCalledAfter allows MockedFunction', () => {
  expect(chrome.alarms.clear).toHaveBeenCalledAfter(chrome.alarms.create)
})

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

2 participants