Skip to content

Commit

Permalink
Core Data: Add checks to actions and selectors to avoid throwing erro…
Browse files Browse the repository at this point in the history
…rs when the relevant config is not loaded. (#18559)

* Core Data: Add checks to selectors to avoid throwing errors when the relevant config is not loaded.

* Core Data: Throw when `editEntityRecord` targets an entity without a config.

* Core Data: Fix default value typo in `getEntityRecordNonTransientEdits`.

* Core Data: Test the behavior of `editEntityRecord` and `getEntityRecordNonTransientEdits` on entities without configs.
  • Loading branch information
epiqueras authored Nov 20, 2019
1 parent 6c4b5e5 commit d3e7c6b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 8 deletions.
10 changes: 5 additions & 5 deletions packages/core-data/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ export function receiveEmbedPreview( url, preview ) {
* @return {Object} Action object.
*/
export function* editEntityRecord( kind, name, recordId, edits, options = {} ) {
const { transientEdits = {}, mergedEdits = {} } = yield select(
'getEntity',
kind,
name
);
const entity = yield select( 'getEntity', kind, name );
if ( ! entity ) {
throw new Error( `The entity being edited (${ kind }, ${ name }) does not have a loaded config.` );
}
const { transientEdits = {}, mergedEdits = {} } = entity;
const record = yield select( 'getRawEntityRecord', kind, name, recordId );
const editedRecord = yield select(
'getEditedEntityRecord',
Expand Down
7 changes: 5 additions & 2 deletions packages/core-data/src/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,11 @@ export function getEntityRecordEdits( state, kind, name, recordId ) {
*/
export const getEntityRecordNonTransientEdits = createSelector(
( state, kind, name, recordId ) => {
const { transientEdits = {} } = getEntity( state, kind, name );
const edits = getEntityRecordEdits( state, kind, name, recordId ) || [];
const { transientEdits } = getEntity( state, kind, name ) || {};
const edits = getEntityRecordEdits( state, kind, name, recordId ) || {};
if ( ! transientEdits ) {
return edits;
}
return Object.keys( edits ).reduce( ( acc, key ) => {
if ( ! transientEdits[ key ] ) {
acc[ key ] = edits[ key ];
Expand Down
29 changes: 28 additions & 1 deletion packages/core-data/src/test/actions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
/**
* Internal dependencies
*/
import { saveEntityRecord, receiveEntityRecords, receiveUserPermission, receiveAutosaves, receiveCurrentUser } from '../actions';
import {
editEntityRecord,
saveEntityRecord,
receiveEntityRecords,
receiveUserPermission,
receiveAutosaves,
receiveCurrentUser,
} from '../actions';
import { select } from '../controls';

describe( 'editEntityRecord', () => {
it( 'throws when the edited entity does not have a loaded config.', () => {
const entity = { kind: 'someKind', name: 'someName', id: 'someId' };
const fulfillment = editEntityRecord(
entity.kind,
entity.name,
entity.id,
{}
);
expect( fulfillment.next().value ).toEqual(
select( 'getEntity', entity.kind, entity.name )
);
// Don't pass back an entity config.
expect( fulfillment.next.bind( fulfillment ) ).toThrow(
`The entity being edited (${ entity.kind }, ${ entity.name }) does not have a loaded config.`
);
} );
} );

describe( 'saveEntityRecord', () => {
it( 'triggers a POST request for a new record', async () => {
Expand Down
12 changes: 12 additions & 0 deletions packages/core-data/src/test/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import deepFreeze from 'deep-freeze';
import {
getEntityRecord,
getEntityRecords,
getEntityRecordNonTransientEdits,
getEmbedPreview,
isPreviewEmbedFallback,
canUser,
Expand Down Expand Up @@ -104,6 +105,17 @@ describe( 'getEntityRecords', () => {
} );
} );

describe( 'getEntityRecordNonTransientEdits', () => {
it( 'should return an empty object when the entity does not have a loaded config.', () => {
const state = deepFreeze( {
entities: { config: {}, data: {} },
} );
expect(
getEntityRecordNonTransientEdits( state, 'someKind', 'someName', 'someId' )
).toEqual( {} );
} );
} );

describe( 'getEmbedPreview()', () => {
it( 'returns preview stored for url', () => {
let state = deepFreeze( {
Expand Down

0 comments on commit d3e7c6b

Please sign in to comment.