-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
assert: add partialDeepStrictEqual #54630
base: main
Are you sure you want to change the base?
Conversation
466c2f0
to
c0a58e2
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #54630 +/- ##
==========================================
+ Coverage 88.23% 88.41% +0.18%
==========================================
Files 652 654 +2
Lines 183920 187944 +4024
Branches 35863 36178 +315
==========================================
+ Hits 162286 166180 +3894
- Misses 14913 15000 +87
- Partials 6721 6764 +43
|
c0a58e2
to
04e92f0
Compare
The
notable-change
Please suggest a text for the release notes if you'd like to include a more detailed summary, then proceed to update the PR description with the text or a link to the notable change suggested text comment. Otherwise, the commit will be placed in the Other Notable Changes section. |
This PR adds new functionality, hence semver-minor This PR's new functionality (IMO) is notable-change |
04e92f0
to
0ee83d4
Compare
doc/api/assert.md
Outdated
// AssertionError | ||
``` | ||
|
||
## `assert.includes(actual, expected[, message])` |
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'm less convinced that this one is useful. Why not just simply use assert(actual.includes(expected))
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.
@jasnell I just followed the most "approved" comment in the original PR and implemented 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.
I agree with @jasnell and don't think this should be implemented. Let us concentrate on the partial inclusion. If anyone would ever ask for something else, we can still implement more.
is there any way we can push this forward? ar far as I know there is a little bit of people waiting for this and no clear consensus on the naming convention :) |
I still have concerns about whether we need everything in this PR but would very much like others to weigh in. @nodejs/test_runner @nodejs/assert ... anyone have thoughts? |
re naming, I definitely think the term "match" should be reserved for regexes. if the only difference between these new methods and deepEqual etc is that they allow extra properties, then perhaps it would make more sense as an option to the existing methods rather than entirely new ones? |
@ljharb the discussion where the "option" was discarded in favor of the new API started from this comment: #50399 (comment) |
other method names we could consider:
|
To clarify, the current proposal takes an "actual" and "expected", and it checks that every property on What about if I want to assert that a property is not present? is there a way to represent "never"? |
good questions! yes, this test will pass: {
description: 'compares two deeply nested objects with partial equality',
actual: { a: {nested: {property: true, some: 'other'}} },
expected: { a: {nested: {property: true}} },
}, and no, there is no way to check "not inclusion" , just if an object is a subset of another |
|
that would deviate from the already present implementations, like |
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.
implementation LGTM, I agree with the concerns on naming, lets change the name so this can land?
+1 for partialDeepEqual
Agreed. Also, should this have a |
ab7e68e
to
3d52d4b
Compare
lib/assert.js
Outdated
return false; | ||
} | ||
|
||
return ArrayPrototypeEvery(expected, (item) => ArrayPrototypeIncludes(actual, item)); |
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 actually incorrect. It will match identical parts multiple times. It is also going to have a bad performance.
I am not going to block this though, to get the general idea in and to improve afterwards. Can we just mark it experimental for now, due to these issues?
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.
@BridgeAR this was an actual issue, addressed it!
const key = keysExpected[i]; | ||
assert( | ||
ReflectHas(actual, key), | ||
new AssertionError({ message: `Expected key ${String(key)} not found in actual object` }), |
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 message won't be ideal. If it's a deeper array, it is completely unclear what this belongs to. It was actually my main issue with my first attempt. To highlight what parts are missing is tricky.
if (comparedObjects.has(actual)) { | ||
return true; | ||
} | ||
comparedObjects.add(actual); |
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 did not verify that but I believe the circular structure won't always work this way. AFAIC we have to handle both sides similar to the current implementation.
d58ffe7
to
c47e009
Compare
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 the documentation should precisely characterize the behavior of this function, including edge cases. Right now, it only mentions the "main difference", but that doesn't explain differences such as the following:
assert.deepStrictEqual(new Set([{ a: 1 }]), new Set([{ a: 1 }]))
// No error.
assert.partialDeepStrictEqual(new Set([{ a: 1 }]), new Set([{ a: 1 }]))
// Uncaught AssertionError.
On a side note, the commit message should use an imperative verb (e.g., add
) instead of adds
to comply with our guidelines.
@@ -2548,6 +2548,81 @@ assert.throws(throwingFirst, /Second$/); | |||
Due to the confusing error-prone notation, avoid a string as the second | |||
argument. | |||
|
|||
## `assert.partialDeepStrictEqual(actual, expected[, message])` |
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 should probably be marked as experimental.
doc/api/assert.md
Outdated
* `expected` {any} | ||
* `message` {string|Error} | ||
|
||
[`assert.partialDeepStrictEqual()`][] Assesses the equivalence between the `actual` and `expected` parameters through a |
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.
[`assert.partialDeepStrictEqual()`][] Assesses the equivalence between the `actual` and `expected` parameters through a | |
[`assert.partialDeepStrictEqual()`][] asserts the equivalence between the `actual` and `expected` parameters through a |
@tniessen I consider the mentioned difference a bug in the current implementation. I see a couple of cases not yet working as expected. We can either make sure it works fine up front or land this and continue on it later. |
c47e009
to
f0722f9
Compare
Fixed the issue with the comparison between objects in Sets, updated the commit message and the documentation |
I checked out f0722f9. Is this expected behavior? assert.partialDeepStrictEqual(new Set([{ a: 1 }]), new Set([{ a: 1 }, { b: 1 }]))
// No error. |
f0722f9
to
af0b9a0
Compare
you are right, I might have introduced that issue in the last commit. Fixed and added relevant 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.
LGTM
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 still think this function deserves a precise definition of its behavior. The two Set
-related bugs that I discovered today could have been expected behavior for all I know.
Looking at the implementation, objects in Set
s are apparently not tested for reference-equality, but objects in Array
s are. Again, I have no idea if that is expected behavior or not.
assert.deepStrictEqual([{ a: 5 }], [{ a: 5 }])
// No error.
assert.partialDeepStrictEqual([{ a: 5 }], [{ a: 5 }])
// AssertionError.
Also, the order of elements of Array
s is ignored for the purpose of this assertion, and holes in sparse arrays are ignored as well. I again have no idea if that is expected or not, but as a user, I certainly wouldn't expect it based on the documentation.
I would consider what you found an issue, I will fix the code soon, but I would like other people to chip in on how this case should work according to them |
af0b9a0
to
5af955e
Compare
I think this could land as experimental and we explicitly mention that this should always pass @puskin94 would you mind adding that? |
Fixes: nodejs#50399 Co-Authored-By: Cristian Barlutiu <[email protected]>
5af955e
to
561c191
Compare
I agree with the general strategy, but I think it'd be a good idea for the documentation to accurately define what superset of input pairs are permitted that are not allowed by |
I think it will still be refined during the development. And while doing that, we should define it. |
Would these different behaviours not be best expressed as boolean props of an optional object passed as the last argument to these functions? Something like: assert.deepStrictEqual([1, 2, 3], [3, 1, 2]) // pass
assert.deepStrictEqual([1, 2, 3], [3, 1, 2], { order: true }) // fail |
@danielbayley The problem with such options is that it's unclear whether or not they should apply to nested decision procedures. Neither option will cover all use cases. |
Fixes: #50399
Took heavy inspiration from #53415 , trying to push it to the finish line 🚀
On top of it, I took the liberty of:
Co-Authored-By: Cristian Barlutiu