-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
add support for Explicit Resource Management to mocked functions #14895
Conversation
✅ Deploy Preview for jestjs ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
if (!Symbol.dispose) { | ||
Object.defineProperty(Symbol, 'dispose', { | ||
get() { | ||
return Symbol.for('nodejs.dispose'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit weird, and the result of #14888 - usually, it should be possible to polyfill Symbol.dispose
in any possible way, e.g. by doing Symbol.dispose ??= Symbol.for('dispose')
, but because of #14888 it needs to explicitly be polyfilled with Symbol.for('nodejs.dispose')
.
I'm not sure if that change over there was a good idea, especially because that polyfill doesn't seem to be available in all scopes (that's why we need to polyfill here in the first place).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that also explains the failing node16 tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's what the symbol is in a nodejs app, tho. so why would it be an issue?
But if we instead move the test to an e2e test as mentioned elsewhere, then we could just skip that tests on node versions which don't support it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was a bit irritating to me first because jest picks up Symbol.dispose
as Symbol.for('nodejs.dispose')
, while in the test itself was undefined
, so it needed to be polyfilled to the same value (while in a normal application, you can polyfill it as pretty much anything and don't need to match the "outside runtime").
But I guess it makes sense that jest
itself might see something different than the JestEnvironment itself.
using mockedLog = jest.spyOn(console, 'log'); | ||
expect(jest.isMockFunction(console.log)).toBeTruthy(); | ||
|
||
console.log('test'); | ||
expect(mockedLog).toHaveBeenCalled(); | ||
} | ||
expect(jest.isMockFunction(console.log)).toBeFalsy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a common usage:
using mockedLog = jest.spyOn(console, 'log');
is only mocked inside of the current scope, and as soon as the block is left, the mock is restored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is awesome!
Generally, I don't really know what to make of these node16 failures, so I'd be happy for any feedback. As this feature is not available there, is it sensible to skip the tests there? |
Yes. Usually tests are skipped, if some feature is not supported. The jest/packages/test-utils/src/ConditionalTest.ts Lines 33 to 35 in 8bbe2a3
It would be good to mention the feature in documentation. That is a good place to clear out the requirements like Node.js or TypeScript versions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super exciting stuff!
can you add a changelog entry as well?
tsconfig.json
Outdated
@@ -8,6 +8,7 @@ | |||
"declaration": true, | |||
"emitDeclarationOnly": true, | |||
"stripInternal": true, | |||
"lib": ["es2021", "ESNext.Disposable"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need this with the inline <reference lib="ESNext.Disposable" />
?
using mockedLog = jest.spyOn(console, 'log'); | ||
expect(jest.isMockFunction(console.log)).toBeTruthy(); | ||
|
||
console.log('test'); | ||
expect(mockedLog).toHaveBeenCalled(); | ||
} | ||
expect(jest.isMockFunction(console.log)).toBeFalsy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is awesome!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the tests into an integration test - I think code-wise it's as clean as I can get it at this point.
I'll take another look at the docs.
I've also added some docs. I hope the place works, and if you have any suggestions for better examples, I'm very open to feedback. Good docs examples are not my biggest strength :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
we're missing a file to actually run the new E2E test - but I'll fix that up myself 🙂
@@ -155,9 +155,9 @@ export default class NodeEnvironment implements JestEnvironment<Timer> { | |||
if ('asyncDispose' in Symbol && !('asyncDispose' in global.Symbol)) { | |||
const globalSymbol = global.Symbol as unknown as SymbolConstructor; | |||
// @ts-expect-error - it's readonly - but we have checked above that it's not there | |||
globalSymbol.asyncDispose = globalSymbol('nodejs.asyncDispose'); | |||
globalSymbol.asyncDispose = globalSymbol.for('nodejs.asyncDispose'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oopsie 😅
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Summary
This fixes #14294
Spied-on functions can now be instantiated with
using
instead ofconst
and they will be restored once the current scope is left.Test plan
I added a
test toan integration test.jest-mock