-
-
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
expect: Fix non-object received value in toHaveProperty #7986
Conversation
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.
Can't say I completely understand what is going on in this matcher, but the added tests all seem correct to me. Just unfortunate that the snapshot names are getting a bit confusing because for many of them, the reason for the assertion result is not visible in the stringified obj
😐
@jeysal Yeah, although concise parallel arrays of test cases seem super at first glance:
After enough time to be confident that the change in behavior is solid, when we collaborate to improve the report, let’s pay special attention to clear feedback when received is an instance. |
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.
As I was on the review, I just did it ;)
Looks good to me
packages/expect/src/utils.ts
Outdated
// Beware: 'length' in string throws, but property does exist. | ||
// However, string['length'] is number, not undefined. | ||
result.hasEndProp = false; | ||
} |
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.
In case the try/catch is only about primitives, I would prefer ... && typeof object === "object" && prop in object
over try/catch.
In case of other situations, where in
would throw where we really have no alternative to try/catch, then I would prefer extending the comment in the catch-clause to make it clear for the next code reader (and prevent her/him refactoring to a typeof x === "object"
check).
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.
Thank you for constructive critique from viewpoint of reader. Yes, I agree that the comment is incomplete and unclear.
Here is some data. What do you suggest to improve either code or comment, or both?
- While preparing to rewrite with
typeof
I found either object or function (which was reason to add memoized test case) - While writing this comment, I noticed yet another possibility of Host object (provided by the JS environment) while rereading https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof#Description
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.
In this case, I would prefer to avoid try/catch and instead typeof-check for object/function (or maybe negative check for number/string/boolean/symbol).
Reasoning: Here have to swallow/mask a thrown error completely (it wouldn't be possible to e.g. log it). In such situations it's more safe to just state all the expected exemptions than possibly hide non-in
operator related (i.e. really unexpected) errors. If we later need some additional exemptions (e.g. for your mentioned Host object or whatever) just add them later (+ fixate them with test cases).
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.
Yes, I agree. Thank you for clear and convincing reasoning.
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.
Okay, great! And thanks for fixing this issue!
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 needs #7708...
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.
Merged that, could we use import {isPrimitive} from 'jest-get-type';
? And if that's insufficient, fix it so it is?
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.
Thank you. I just pushed another refactoring commit :)
This is, BTW, a breaking change. Multiple tests are failing due to:
I thought the standard way of behaving for Jest was to consider |
Yeah mostly, but we want to move away from it (why |
Makes sense, I agree with the change. Should we back-out for the minor? Or is it good to go as-is? |
I think we should make sure it works like it does in 24.1.0 (it is a breaking change), and create an issue for reinstating the current behavior for Jest 25. Agreed? We still want to fix #7942, though |
@mjesun The purpose of the pull request was to fix a regression. I might have gone too far. To help me figure out if we can keep the unbreaking part and defer the breaking part, can you give a minimal example of assertion that fails? |
Aha, the bug in assignment to expect({a: {}}).toHaveProperty('a.b', undefined); // 23.6
expect({a: {}}).not.toHaveProperty('a.b'); // 23.6 Yeah, I will open pull request to change it back and comment out the test until Jest 25 |
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
Fixes #7942
getPath
function, EDITmoveguardin
operatorintowith conditional and for primitive types boolean-number-string-symbol and use it only if value istry
blockundefined
hasOwnProperty
method that calledequals
for valueundefined
even when property does not exist in received objectResidue for future pull requests:
'pass must be initialized'
error with meaningful matcher error if expected array path is emptygetPath
from recursive to iterativeTest plan
Added 14 test cases. Here is the key to notes in cells:
TypeError: Cannot use 'in' operator to search for 'key' in …
Expected the function to throw an error. But it didn't throw anything.
TypeError: Cannot read property 'prototype' of undefined
false
as received valueThe other tests confirm that
toHaveProperty
matcher is compatible within
operator.For example, the first row that passes for a setter without a getter. It is what it is :(
new Foo()
'setter'
undefined
foo2
'a'
undefined
foo2
'c'
'c'
foo2
'val'
true
new E()
'nodeType'
1
''
'length'
0
memoized
'memo'
[]
{a: {}}
'a.b'
undefined
false
key
0
key
''
key
Symbol()
key
Object.create
'not'
{}
[]