-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Core Data: Don't return partial data when selecting a complete item #71474
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
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
| const context = query?.context ?? 'default'; | ||
|
|
||
| if ( query === undefined ) { | ||
| if ( ! query || ! query._fields ) { |
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.
The new condition is the same as that used in the reducer.
gutenberg/packages/core-data/src/queried-data/reducer.js
Lines 153 to 161 in 2e69c4a
| // An item is considered complete if it is received without an associated | |
| // fields query. Ideally, this would be implemented in such a way where the | |
| // complete aggregate of all fields would satisfy completeness. Since the | |
| // fields are not consistent across all entities, this would require | |
| // introspection on the REST schema for each entity to know which fields | |
| // compose a complete item for that entity. | |
| const queryParts = query ? getQueryParts( query ) : {}; | |
| const isCompleteQuery = | |
| ! query || ! Array.isArray( queryParts.fields ); |
|
Size Change: +13 B (0%) Total Size: 1.93 MB
ℹ️ View Unchanged
|
packages/core-data/src/test/store.js
Outdated
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.
The filename is just a placeholder, unless we have better ideas 😅
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.
Curious why we wouldn't want this in packages/core-data/src/test/selectors.js ?
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.
These are more like integration tests. I guess we can also convert those tests to be integration, but that's outside of the scope for this PR, IMO.
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.
Turns out we already had unfinished unit tests for precisely this case. I've added the missing unit tests and removed the integration one.
P.S. I think I was too eager to introduce integration tests; we've been discussing them for a while. But I'm working on a different bug, where I think they'll be more suitable.
| it( 'should return null if incomplete item received, complete item requested', () => {} ); |
aduth
left a comment
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.
My memory is a bit fuzzy on the details of the original implementation in #19498, but this change seems sensible to me 👍
| const context = query?.context ?? 'default'; | ||
|
|
||
| if ( query === undefined ) { | ||
| if ( ! query || ! query._fields ) { |
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.
Does this now make the && query._fields on the condition below redundant?
gutenberg/packages/core-data/src/selectors.ts
Line 378 in 0e2eb9f
| if ( item && query._fields ) { |
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.
Why would it?
It's good practice to check argument existence before iterating on them. I think we should leave the linked condition.
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.
What I mean is that line 378 can now never be reached if query._fields is falsey, so there's no need in checking that it's truthy.
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.
You're right. I don't have a strong opinion here, but it seems like a good check to keep in place "just in case" 😄
Updated in d1b7dca.
packages/core-data/src/test/store.js
Outdated
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.
Curious why we wouldn't want this in packages/core-data/src/test/selectors.js ?
| const queriedState = | ||
| state.entities.records?.[ kind ]?.[ name ]?.queriedData; |
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 just extracted it into a reusable variable.
|
Flaky tests detected in f0c164d. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/17540850163
|
| // getEntityRecord and __experimentalGetEntityRecordNoResolver selectors share the same tests. | ||
| describe.each( [ | ||
| [ getEntityRecord ], | ||
| [ __experimentalGetEntityRecordNoResolver ], | ||
| ] )( '%p', ( selector ) => { |
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've removed coverage for __experimentalGetEntityRecordNoResolver. It's a leftover from when the data package was introduced and hasn't been used in the core.
I think we should just remove or deprecate it.
aduth
left a comment
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.
Makes sense and LGTM 👍
| setNestedValue( filteredItem, field, value ); | ||
| } | ||
| return filteredItem as EntityRecord; | ||
| if ( ! 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.
I like the flattening with early return 👍
|
Thanks for the review, @aduth 🙇 |
…ordPress#71474) Co-authored-by: Mamaduka <[email protected]> Co-authored-by: aduth <[email protected]> Co-authored-by: albanyacademy <[email protected]>
What?
Closes #71375.
PR fixes a bug in the data store that would return subset record properties (as an intermediate response) when the consumer was requesting and expecting the whole record.
Note: This regressed sometime after initial
_fieldssupport was implemented. The lack of integration tests made it harder to catch similar regressions.I've added coverage for the current case, plus some basic uses as integration tests. Hopefully, we can expand on those in the future.
Why?
When a component requests a full entity record, it expects to receive
undefinedor the whole record. Returning partial data can lead to unexpected failures as described in the issue.How?
Fixes the complete item check for the
getEntityRecordselector to match a similar condition in the resolver.Testing Instructions
Integration tests
npm run test:unit -- packages/core-data/src/test/store.jsManual
Testing Instructions for Keyboard
Same.