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

fix: spyOn should not rely on hasOwnProperty from the spied object #11721

Merged
merged 3 commits into from Aug 16, 2021

Conversation

cexbrayat
Copy link
Contributor

Summary

The spyOn function uses hasOwnProperty from the spied object, but this method can be unavailable,
for example if the object has the null prototype, or if it is a proxy that filters some keys.

This arises in Vue 3 projects where the proxies returned by the framework do not expose all methods,
and forces the testing library to manually patch the proxies with hasOwnProperty to let Jest do its work
https://github.com/vuejs/vue-test-utils-next/blob/23d3d3e1f4178a87de5023f5255e0623653affdc/src/mount.ts#L493-L495

Test plan

This commit changes the code to use Object.prototype.hasOwnProperty and fixes this issue.
A unit test has been added to reproduce the issue.

@facebook-github-bot
Copy link
Contributor

Hi @cexbrayat!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@fb.com. Thanks!

@codecov-commenter
Copy link

codecov-commenter commented Aug 3, 2021

Codecov Report

Merging #11721 (d614bb1) into master (fdc74af) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master   #11721   +/-   ##
=======================================
  Coverage   69.01%   69.01%           
=======================================
  Files         312      312           
  Lines       16335    16335           
  Branches     4734     4734           
=======================================
  Hits        11273    11273           
  Misses       5034     5034           
  Partials       28       28           
Impacted Files Coverage Δ
packages/jest-mock/src/index.ts 84.98% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update fdc74af...d614bb1. Read the comment docs.

@facebook-github-bot
Copy link
Contributor

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!

Copy link
Contributor

@sigveio sigveio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test case demonstrates the problem well, and borrowing hasOwnProperty from the Object prototype is good practise in this kind of context. 👍 Especially since hasOwnProperty is not protected, meaning objects could even have their own implementation that produces unpredictable results.

Only thing I see missing is a changelog entry for the fix

@cexbrayat
Copy link
Contributor Author

@sigveio Thanks for the feedback.
I added an entry to the changelog. Let me know if anything else is needed.

@Smrtnyk
Copy link

Smrtnyk commented Aug 3, 2021

This is definitely a good improvement

@@ -1216,6 +1216,18 @@ describe('moduleMocker', () => {
expect(originalCallArguments[1]).toBe(secondArg);
expect(spy).not.toHaveBeenCalled();
});

it('should not rely on hasOwnProperty', () => {
Copy link

@Smrtnyk Smrtnyk Aug 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description of the test I find not the best.
It still relies on hasOwnProperty as it is calling it from the Object.prototype
I would name it as should not throw an error if spying on object without prototype or something like that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it could be simplified to 'should work with object of null prototype'?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 👍

The `spyOn` function uses `hasOwnProperty` from the spied object, but this method can be unavailable,
for example if the object has the `null` prototype, or if it is a proxy that filters some keys.

This arises in Vue 3 projects where the proxies returned by the framework do not expose all methods,
and forces the testing library to manually patch the proxies with `hasOwnProperty` to let Jest do its work
https://github.com/vuejs/vue-test-utils-next/blob/23d3d3e1f4178a87de5023f5255e0623653affdc/src/mount.ts#L493-L495

This commit changes the code to use `Object.prototype.hasOwnProperty` and fixes this issue.
Copy link
Member

@SimenB SimenB left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@SimenB SimenB merged commit f3ae13c into jestjs:master Aug 16, 2021
cexbrayat added a commit to cexbrayat/vue-next that referenced this pull request Aug 30, 2021
Updates jest and ts-jest to v27, as jest v27.1.0 includes a necessary fix to unblock further work on spying issues.

See jestjs/jest#11721
cexbrayat added a commit to cexbrayat/vue-test-utils-next that referenced this pull request Aug 30, 2021
vue-test-utils-next now uses jest v27.1+, which includes a fix for hasOwnPropery (see jestjs/jest#11721).
This allows to remove the dirty workaround we had in our codebase, but users will have to update to Jest v27.1+.
cexbrayat added a commit to cexbrayat/vue-test-utils-next that referenced this pull request Aug 30, 2021
vue-test-utils-next now uses jest v27.1+, which includes a fix for hasOwnPropery (see jestjs/jest#11721).
This allows to remove the dirty workaround we had in our codebase, but users will have to update to Jest v27.1+.
yyx990803 pushed a commit to vuejs/core that referenced this pull request Sep 1, 2021
Updates jest and ts-jest to v27, as jest v27.1.0 includes a necessary fix to unblock further work on spying issues.

See jestjs/jest#11721
docschina-bot pushed a commit to docschina/vue-compat-docs-cn that referenced this pull request Sep 1, 2021
Updates jest and ts-jest to v27, as jest v27.1.0 includes a necessary fix to unblock further work on spying issues.

See jestjs/jest#11721
@github-actions
Copy link

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.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants