@wordpress/core-data 7.10.0 → 7.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/actions.js +13 -9
  3. package/build/actions.js.map +1 -1
  4. package/build/entities.js +3 -63
  5. package/build/entities.js.map +1 -1
  6. package/build/entity-types/attachment.js.map +1 -1
  7. package/build/entity-types/settings.js.map +1 -1
  8. package/build/hooks/use-entity-block-editor.js +4 -5
  9. package/build/hooks/use-entity-block-editor.js.map +1 -1
  10. package/build/lock-unlock.js.map +1 -1
  11. package/build/private-apis.js +3 -1
  12. package/build/private-apis.js.map +1 -1
  13. package/build/resolvers.js +98 -68
  14. package/build/resolvers.js.map +1 -1
  15. package/build/selectors.js +0 -19
  16. package/build/selectors.js.map +1 -1
  17. package/build/utils/index.js +7 -0
  18. package/build/utils/index.js.map +1 -1
  19. package/build/utils/receive-intermediate-results.js +8 -0
  20. package/build/utils/receive-intermediate-results.js.map +1 -0
  21. package/build-module/actions.js +14 -10
  22. package/build-module/actions.js.map +1 -1
  23. package/build-module/entities.js +2 -61
  24. package/build-module/entities.js.map +1 -1
  25. package/build-module/entity-types/attachment.js.map +1 -1
  26. package/build-module/entity-types/settings.js.map +1 -1
  27. package/build-module/hooks/use-entity-block-editor.js +4 -5
  28. package/build-module/hooks/use-entity-block-editor.js.map +1 -1
  29. package/build-module/lock-unlock.js.map +1 -1
  30. package/build-module/private-apis.js +3 -1
  31. package/build-module/private-apis.js.map +1 -1
  32. package/build-module/resolvers.js +98 -68
  33. package/build-module/resolvers.js.map +1 -1
  34. package/build-module/selectors.js +0 -18
  35. package/build-module/selectors.js.map +1 -1
  36. package/build-module/utils/index.js +1 -0
  37. package/build-module/utils/index.js.map +1 -1
  38. package/build-module/utils/receive-intermediate-results.js +2 -0
  39. package/build-module/utils/receive-intermediate-results.js.map +1 -0
  40. package/build-types/actions.d.ts +8 -4
  41. package/build-types/actions.d.ts.map +1 -1
  42. package/build-types/entities.d.ts +0 -1
  43. package/build-types/entities.d.ts.map +1 -1
  44. package/build-types/entity-types/attachment.d.ts +36 -1
  45. package/build-types/entity-types/attachment.d.ts.map +1 -1
  46. package/build-types/entity-types/settings.d.ts +4 -0
  47. package/build-types/entity-types/settings.d.ts.map +1 -1
  48. package/build-types/hooks/use-entity-block-editor.d.ts.map +1 -1
  49. package/build-types/index.d.ts +8 -5
  50. package/build-types/index.d.ts.map +1 -1
  51. package/build-types/lock-unlock.d.ts +1 -2
  52. package/build-types/lock-unlock.d.ts.map +1 -1
  53. package/build-types/private-apis.d.ts.map +1 -1
  54. package/build-types/queried-data/reducer.d.ts +10 -2
  55. package/build-types/reducer.d.ts +24 -2
  56. package/build-types/reducer.d.ts.map +1 -1
  57. package/build-types/resolvers.d.ts +16 -13
  58. package/build-types/resolvers.d.ts.map +1 -1
  59. package/build-types/selectors.d.ts +0 -9
  60. package/build-types/selectors.d.ts.map +1 -1
  61. package/build-types/utils/index.d.ts +1 -0
  62. package/build-types/utils/receive-intermediate-results.d.ts +2 -0
  63. package/build-types/utils/receive-intermediate-results.d.ts.map +1 -0
  64. package/package.json +19 -18
  65. package/src/actions.js +10 -10
  66. package/src/entities.js +2 -64
  67. package/src/entity-types/attachment.ts +35 -1
  68. package/src/entity-types/settings.ts +4 -0
  69. package/src/hooks/test/use-entity-record.js +9 -2
  70. package/src/hooks/use-entity-block-editor.js +4 -9
  71. package/src/private-apis.js +2 -0
  72. package/src/resolvers.js +125 -90
  73. package/src/selectors.ts +0 -32
  74. package/src/test/actions.js +24 -39
  75. package/src/test/entities.js +0 -80
  76. package/src/test/resolvers.js +89 -35
  77. package/src/utils/index.js +1 -0
  78. package/src/utils/receive-intermediate-results.js +3 -0
  79. package/tsconfig.tsbuildinfo +1 -1
  80. /package/src/{lock-unlock.js → lock-unlock.ts} +0 -0
package/src/resolvers.js CHANGED
@@ -14,13 +14,14 @@ import apiFetch from '@wordpress/api-fetch';
14
14
  * Internal dependencies
15
15
  */
16
16
  import { STORE_NAME } from './name';
17
- import { getOrLoadEntitiesConfig, DEFAULT_ENTITY_KEY } from './entities';
17
+ import { additionalEntityConfigLoaders, DEFAULT_ENTITY_KEY } from './entities';
18
18
  import {
19
19
  forwardResolver,
20
20
  getNormalizedCommaSeparable,
21
21
  getUserPermissionCacheKey,
22
22
  getUserPermissionsFromAllowHeader,
23
23
  ALLOWED_RESOURCE_ACTIONS,
24
+ RECEIVE_INTERMEDIATE_RESULTS,
24
25
  } from './utils';
25
26
  import { getSyncProvider } from './sync';
26
27
  import { fetchBlockPatterns } from './fetch';
@@ -64,8 +65,8 @@ export const getCurrentUser =
64
65
  */
65
66
  export const getEntityRecord =
66
67
  ( kind, name, key = '', query ) =>
67
- async ( { select, dispatch, registry } ) => {
68
- const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
68
+ async ( { select, dispatch, registry, resolveSelect } ) => {
69
+ const configs = await resolveSelect.getEntitiesConfig( kind );
69
70
  const entityConfig = configs.find(
70
71
  ( config ) => config.name === name && config.kind === kind
71
72
  );
@@ -230,8 +231,8 @@ export const getEditedEntityRecord = forwardResolver( 'getEntityRecord' );
230
231
  */
231
232
  export const getEntityRecords =
232
233
  ( kind, name, query = {} ) =>
233
- async ( { dispatch, registry } ) => {
234
- const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
234
+ async ( { dispatch, registry, resolveSelect } ) => {
235
+ const configs = await resolveSelect.getEntitiesConfig( kind );
235
236
  const entityConfig = configs.find(
236
237
  ( config ) => config.name === name && config.kind === kind
237
238
  );
@@ -245,6 +246,14 @@ export const getEntityRecords =
245
246
  { exclusive: false }
246
247
  );
247
248
 
249
+ const key = entityConfig.key || DEFAULT_ENTITY_KEY;
250
+
251
+ function getResolutionsArgs( records ) {
252
+ return records
253
+ .filter( ( record ) => record?.[ key ] )
254
+ .map( ( record ) => [ kind, name, record[ key ] ] );
255
+ }
256
+
248
257
  try {
249
258
  if ( query._fields ) {
250
259
  // If requesting specific fields, items and query association to said
@@ -267,7 +276,8 @@ export const getEntityRecords =
267
276
  ...query,
268
277
  } );
269
278
 
270
- let records, meta;
279
+ let records = [],
280
+ meta;
271
281
  if ( entityConfig.supportsPagination && query.per_page !== -1 ) {
272
282
  const response = await apiFetch( { path, parse: false } );
273
283
  records = Object.values( await response.json() );
@@ -279,6 +289,44 @@ export const getEntityRecords =
279
289
  response.headers.get( 'X-WP-TotalPages' )
280
290
  ),
281
291
  };
292
+ } else if (
293
+ query.per_page === -1 &&
294
+ query[ RECEIVE_INTERMEDIATE_RESULTS ] === true
295
+ ) {
296
+ let page = 1;
297
+ let totalPages;
298
+
299
+ do {
300
+ const response = await apiFetch( {
301
+ path: addQueryArgs( path, { page, per_page: 100 } ),
302
+ parse: false,
303
+ } );
304
+ const pageRecords = Object.values( await response.json() );
305
+
306
+ totalPages = parseInt(
307
+ response.headers.get( 'X-WP-TotalPages' )
308
+ );
309
+
310
+ records.push( ...pageRecords );
311
+ registry.batch( () => {
312
+ dispatch.receiveEntityRecords(
313
+ kind,
314
+ name,
315
+ records,
316
+ query
317
+ );
318
+ dispatch.finishResolutions(
319
+ 'getEntityRecord',
320
+ getResolutionsArgs( pageRecords )
321
+ );
322
+ } );
323
+ page++;
324
+ } while ( page <= totalPages );
325
+
326
+ meta = {
327
+ totalItems: records.length,
328
+ totalPages: 1,
329
+ };
282
330
  } else {
283
331
  records = Object.values( await apiFetch( { path } ) );
284
332
  meta = {
@@ -318,11 +366,6 @@ export const getEntityRecords =
318
366
  // See https://github.com/WordPress/gutenberg/pull/26575
319
367
  // See https://github.com/WordPress/gutenberg/pull/64504
320
368
  if ( ! query?._fields && ! query.context ) {
321
- const key = entityConfig.key || DEFAULT_ENTITY_KEY;
322
- const resolutionsArgs = records
323
- .filter( ( record ) => record?.[ key ] )
324
- .map( ( record ) => [ kind, name, record[ key ] ] );
325
-
326
369
  const targetHints = records
327
370
  .filter( ( record ) => record?.[ key ] )
328
371
  .map( ( record ) => ( {
@@ -356,7 +399,7 @@ export const getEntityRecords =
356
399
  );
357
400
  dispatch.finishResolutions(
358
401
  'getEntityRecord',
359
- resolutionsArgs
402
+ getResolutionsArgs( records )
360
403
  );
361
404
  dispatch.finishResolutions(
362
405
  'canUser',
@@ -431,19 +474,36 @@ export const getEmbedPreview =
431
474
  */
432
475
  export const canUser =
433
476
  ( requestedAction, resource, id ) =>
434
- async ( { dispatch, registry } ) => {
477
+ async ( { dispatch, registry, resolveSelect } ) => {
435
478
  if ( ! ALLOWED_RESOURCE_ACTIONS.includes( requestedAction ) ) {
436
479
  throw new Error( `'${ requestedAction }' is not a valid action.` );
437
480
  }
438
481
 
482
+ const { hasStartedResolution } = registry.select( STORE_NAME );
483
+
484
+ // Prevent resolving the same resource twice.
485
+ for ( const relatedAction of ALLOWED_RESOURCE_ACTIONS ) {
486
+ if ( relatedAction === requestedAction ) {
487
+ continue;
488
+ }
489
+ const isAlreadyResolving = hasStartedResolution( 'canUser', [
490
+ relatedAction,
491
+ resource,
492
+ id,
493
+ ] );
494
+ if ( isAlreadyResolving ) {
495
+ return;
496
+ }
497
+ }
498
+
439
499
  let resourcePath = null;
440
500
  if ( typeof resource === 'object' ) {
441
501
  if ( ! resource.kind || ! resource.name ) {
442
502
  throw new Error( 'The entity resource object is not valid.' );
443
503
  }
444
504
 
445
- const configs = await dispatch(
446
- getOrLoadEntitiesConfig( resource.kind, resource.name )
505
+ const configs = await resolveSelect.getEntitiesConfig(
506
+ resource.kind
447
507
  );
448
508
  const entityConfig = configs.find(
449
509
  ( config ) =>
@@ -460,23 +520,6 @@ export const canUser =
460
520
  resourcePath = `/wp/v2/${ resource }` + ( id ? '/' + id : '' );
461
521
  }
462
522
 
463
- const { hasStartedResolution } = registry.select( STORE_NAME );
464
-
465
- // Prevent resolving the same resource twice.
466
- for ( const relatedAction of ALLOWED_RESOURCE_ACTIONS ) {
467
- if ( relatedAction === requestedAction ) {
468
- continue;
469
- }
470
- const isAlreadyResolving = hasStartedResolution( 'canUser', [
471
- relatedAction,
472
- resource,
473
- id,
474
- ] );
475
- if ( isAlreadyResolving ) {
476
- return;
477
- }
478
- }
479
-
480
523
  let response;
481
524
  try {
482
525
  response = await apiFetch( {
@@ -563,58 +606,6 @@ export const getAutosave =
563
606
  await resolveSelect.getAutosaves( postType, postId );
564
607
  };
565
608
 
566
- /**
567
- * Retrieve the frontend template used for a given link.
568
- *
569
- * @param {string} link Link.
570
- */
571
- export const __experimentalGetTemplateForLink =
572
- ( link ) =>
573
- async ( { dispatch, resolveSelect } ) => {
574
- let template;
575
- try {
576
- // This is NOT calling a REST endpoint but rather ends up with a response from
577
- // an Ajax function which has a different shape from a WP_REST_Response.
578
- template = await apiFetch( {
579
- url: addQueryArgs( link, {
580
- '_wp-find-template': true,
581
- } ),
582
- } ).then( ( { data } ) => data );
583
- } catch ( e ) {
584
- // For non-FSE themes, it is possible that this request returns an error.
585
- }
586
-
587
- if ( ! template ) {
588
- return;
589
- }
590
-
591
- const record = await resolveSelect.getEntityRecord(
592
- 'postType',
593
- 'wp_template',
594
- template.id
595
- );
596
-
597
- if ( record ) {
598
- dispatch.receiveEntityRecords(
599
- 'postType',
600
- 'wp_template',
601
- [ record ],
602
- {
603
- 'find-template': link,
604
- }
605
- );
606
- }
607
- };
608
-
609
- __experimentalGetTemplateForLink.shouldInvalidate = ( action ) => {
610
- return (
611
- ( action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS' ) &&
612
- action.invalidateCache &&
613
- action.kind === 'postType' &&
614
- action.name === 'wp_template'
615
- );
616
- };
617
-
618
609
  export const __experimentalGetCurrentGlobalStylesId =
619
610
  () =>
620
611
  async ( { dispatch, resolveSelect } ) => {
@@ -644,6 +635,7 @@ export const __experimentalGetCurrentThemeBaseGlobalStyles =
644
635
  () =>
645
636
  async ( { resolveSelect, dispatch } ) => {
646
637
  const currentTheme = await resolveSelect.getCurrentTheme();
638
+ // Please adjust the preloaded requests if this changes!
647
639
  const themeGlobalStyles = await apiFetch( {
648
640
  path: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }?context=view`,
649
641
  } );
@@ -657,6 +649,7 @@ export const __experimentalGetCurrentThemeGlobalStylesVariations =
657
649
  () =>
658
650
  async ( { resolveSelect, dispatch } ) => {
659
651
  const currentTheme = await resolveSelect.getCurrentTheme();
652
+ // Please adjust the preloaded requests if this changes!
660
653
  const variations = await apiFetch( {
661
654
  path: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }/variations?context=view`,
662
655
  } );
@@ -799,13 +792,27 @@ export const getNavigationFallbackId =
799
792
 
800
793
  export const getDefaultTemplateId =
801
794
  ( query ) =>
802
- async ( { dispatch } ) => {
795
+ async ( { dispatch, registry, resolveSelect } ) => {
803
796
  const template = await apiFetch( {
804
797
  path: addQueryArgs( '/wp/v2/templates/lookup', query ),
805
798
  } );
799
+ // Wait for the the entities config to be loaded, otherwise receiving
800
+ // the template as an entity will not work.
801
+ await resolveSelect.getEntitiesConfig( 'postType' );
806
802
  // Endpoint may return an empty object if no template is found.
807
803
  if ( template?.id ) {
808
- dispatch.receiveDefaultTemplateId( query, template.id );
804
+ registry.batch( () => {
805
+ dispatch.receiveDefaultTemplateId( query, template.id );
806
+ dispatch.receiveEntityRecords( 'postType', 'wp_template', [
807
+ template,
808
+ ] );
809
+ // Avoid further network requests.
810
+ dispatch.finishResolution( 'getEntityRecord', [
811
+ 'postType',
812
+ 'wp_template',
813
+ template.id,
814
+ ] );
815
+ } );
809
816
  }
810
817
  };
811
818
 
@@ -821,8 +828,8 @@ export const getDefaultTemplateId =
821
828
  */
822
829
  export const getRevisions =
823
830
  ( kind, name, recordKey, query = {} ) =>
824
- async ( { dispatch, registry } ) => {
825
- const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
831
+ async ( { dispatch, registry, resolveSelect } ) => {
832
+ const configs = await resolveSelect.getEntitiesConfig( kind );
826
833
  const entityConfig = configs.find(
827
834
  ( config ) => config.name === name && config.kind === kind
828
835
  );
@@ -942,8 +949,8 @@ getRevisions.shouldInvalidate = ( action, kind, name, recordKey ) =>
942
949
  */
943
950
  export const getRevision =
944
951
  ( kind, name, recordKey, revisionKey, query ) =>
945
- async ( { dispatch } ) => {
946
- const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) );
952
+ async ( { dispatch, resolveSelect } ) => {
953
+ const configs = await resolveSelect.getEntitiesConfig( kind );
947
954
  const entityConfig = configs.find(
948
955
  ( config ) => config.name === name && config.kind === kind
949
956
  );
@@ -1015,3 +1022,31 @@ export const getRegisteredPostMeta =
1015
1022
  );
1016
1023
  }
1017
1024
  };
1025
+
1026
+ /**
1027
+ * Requests entity configs for the given kind from the REST API.
1028
+ *
1029
+ * @param {string} kind Entity kind.
1030
+ */
1031
+ export const getEntitiesConfig =
1032
+ ( kind ) =>
1033
+ async ( { dispatch } ) => {
1034
+ const loader = additionalEntityConfigLoaders.find(
1035
+ ( l ) => l.kind === kind
1036
+ );
1037
+
1038
+ if ( ! loader ) {
1039
+ return;
1040
+ }
1041
+
1042
+ try {
1043
+ const configs = await loader.loadEntities();
1044
+ if ( ! configs.length ) {
1045
+ return;
1046
+ }
1047
+
1048
+ dispatch.addEntities( configs );
1049
+ } catch {
1050
+ // Do nothing if the request comes back with an API error.
1051
+ }
1052
+ };
package/src/selectors.ts CHANGED
@@ -1284,38 +1284,6 @@ export function getReferenceByDistinctEdits( state ) {
1284
1284
  return state.editsReference;
1285
1285
  }
1286
1286
 
1287
- /**
1288
- * Retrieve the frontend template used for a given link.
1289
- *
1290
- * @param state Editor state.
1291
- * @param link Link.
1292
- *
1293
- * @return The template record.
1294
- */
1295
- export function __experimentalGetTemplateForLink(
1296
- state: State,
1297
- link: string
1298
- ): Optional< ET.Updatable< ET.WpTemplate > > | null | false {
1299
- const records = getEntityRecords< ET.WpTemplate >(
1300
- state,
1301
- 'postType',
1302
- 'wp_template',
1303
- {
1304
- 'find-template': link,
1305
- }
1306
- );
1307
-
1308
- if ( records?.length ) {
1309
- return getEditedEntityRecord< ET.WpTemplate >(
1310
- state,
1311
- 'postType',
1312
- 'wp_template',
1313
- records[ 0 ].id
1314
- );
1315
- }
1316
- return null;
1317
- }
1318
-
1319
1287
  /**
1320
1288
  * Retrieve the current theme's base global styles
1321
1289
  *
@@ -68,8 +68,7 @@ describe( 'deleteEntityRecord', () => {
68
68
  __unstableAcquireStoreLock: jest.fn(),
69
69
  __unstableReleaseStoreLock: jest.fn(),
70
70
  } );
71
- // Provide entities
72
- dispatch.mockReturnValueOnce( configs );
71
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) };
73
72
 
74
73
  // Provide response
75
74
  apiFetch.mockImplementation( () => deletedRecord );
@@ -78,7 +77,7 @@ describe( 'deleteEntityRecord', () => {
78
77
  'postType',
79
78
  'post',
80
79
  deletedRecord.id
81
- )( { dispatch } );
80
+ )( { dispatch, resolveSelect } );
82
81
 
83
82
  expect( apiFetch ).toHaveBeenCalledTimes( 1 );
84
83
  expect( apiFetch ).toHaveBeenCalledWith( {
@@ -86,7 +85,7 @@ describe( 'deleteEntityRecord', () => {
86
85
  method: 'DELETE',
87
86
  } );
88
87
 
89
- expect( dispatch ).toHaveBeenCalledTimes( 4 );
88
+ expect( dispatch ).toHaveBeenCalledTimes( 3 );
90
89
  expect( dispatch ).toHaveBeenCalledWith( {
91
90
  type: 'DELETE_ENTITY_RECORD_START',
92
91
  kind: 'postType',
@@ -120,8 +119,7 @@ describe( 'deleteEntityRecord', () => {
120
119
  __unstableAcquireStoreLock: jest.fn(),
121
120
  __unstableReleaseStoreLock: jest.fn(),
122
121
  } );
123
- // Provide entities
124
- dispatch.mockReturnValueOnce( entities );
122
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) };
125
123
 
126
124
  // Provide response
127
125
  apiFetch.mockImplementation( () => {
@@ -137,7 +135,7 @@ describe( 'deleteEntityRecord', () => {
137
135
  {
138
136
  throwOnError: true,
139
137
  }
140
- )( { dispatch } )
138
+ )( { dispatch, resolveSelect } )
141
139
  ).rejects.toEqual( new Error( 'API error' ) );
142
140
  } );
143
141
 
@@ -151,8 +149,7 @@ describe( 'deleteEntityRecord', () => {
151
149
  __unstableAcquireStoreLock: jest.fn(),
152
150
  __unstableReleaseStoreLock: jest.fn(),
153
151
  } );
154
- // Provide entities
155
- dispatch.mockReturnValueOnce( entities );
152
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) };
156
153
 
157
154
  // Provide response
158
155
  apiFetch.mockImplementation( () => {
@@ -168,7 +165,7 @@ describe( 'deleteEntityRecord', () => {
168
165
  {
169
166
  throwOnError: false,
170
167
  }
171
- )( { dispatch } )
168
+ )( { dispatch, resolveSelect } )
172
169
  ).resolves.toBe( false );
173
170
  } );
174
171
  } );
@@ -195,8 +192,7 @@ describe( 'saveEditedEntityRecord', () => {
195
192
  const dispatch = Object.assign( jest.fn(), {
196
193
  saveEntityRecord: jest.fn(),
197
194
  } );
198
- // Provide entities
199
- dispatch.mockReturnValueOnce( configs );
195
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) };
200
196
 
201
197
  // Provide response
202
198
  const updatedRecord = { ...item, menu: 10 };
@@ -208,7 +204,7 @@ describe( 'saveEditedEntityRecord', () => {
208
204
  'root',
209
205
  'menuItem',
210
206
  1
211
- )( { dispatch, select } );
207
+ )( { dispatch, select, resolveSelect } );
212
208
 
213
209
  expect( dispatch.saveEntityRecord ).toHaveBeenCalledWith(
214
210
  'root',
@@ -236,8 +232,7 @@ describe( 'saveEditedEntityRecord', () => {
236
232
  const dispatch = Object.assign( jest.fn(), {
237
233
  saveEntityRecord: jest.fn(),
238
234
  } );
239
- // Provide entities
240
- dispatch.mockReturnValueOnce( configs );
235
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) };
241
236
 
242
237
  // Provide response
243
238
  const updatedRecord = { ...item, menu: 10 };
@@ -249,7 +244,7 @@ describe( 'saveEditedEntityRecord', () => {
249
244
  'root',
250
245
  'menuLocation',
251
246
  'primary'
252
- )( { dispatch, select } );
247
+ )( { dispatch, select, resolveSelect } );
253
248
 
254
249
  expect( dispatch.saveEntityRecord ).toHaveBeenCalledWith(
255
250
  'root',
@@ -280,9 +275,7 @@ describe( 'saveEntityRecord', () => {
280
275
  const select = {
281
276
  getRawEntityRecord: () => post,
282
277
  };
283
-
284
- // Provide entities
285
- dispatch.mockReturnValueOnce( configs );
278
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) };
286
279
 
287
280
  // Provide response
288
281
  const updatedRecord = { ...post, id: 10 };
@@ -294,7 +287,7 @@ describe( 'saveEntityRecord', () => {
294
287
  'postType',
295
288
  'post',
296
289
  post
297
- )( { select, dispatch } );
290
+ )( { select, dispatch, resolveSelect } );
298
291
 
299
292
  expect( apiFetch ).toHaveBeenCalledTimes( 1 );
300
293
  expect( apiFetch ).toHaveBeenCalledWith( {
@@ -303,7 +296,7 @@ describe( 'saveEntityRecord', () => {
303
296
  data: post,
304
297
  } );
305
298
 
306
- expect( dispatch ).toHaveBeenCalledTimes( 3 );
299
+ expect( dispatch ).toHaveBeenCalledTimes( 2 );
307
300
  expect( dispatch ).toHaveBeenCalledWith( {
308
301
  type: 'SAVE_ENTITY_RECORD_START',
309
302
  kind: 'postType',
@@ -347,9 +340,7 @@ describe( 'saveEntityRecord', () => {
347
340
  const select = {
348
341
  getRawEntityRecord: () => post,
349
342
  };
350
-
351
- // Provide entities
352
- dispatch.mockReturnValueOnce( entities );
343
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) };
353
344
 
354
345
  // Provide response
355
346
  apiFetch.mockImplementation( () => {
@@ -359,7 +350,7 @@ describe( 'saveEntityRecord', () => {
359
350
  await expect(
360
351
  saveEntityRecord( 'postType', 'post', post, {
361
352
  throwOnError: true,
362
- } )( { select, dispatch } )
353
+ } )( { select, dispatch, resolveSelect } )
363
354
  ).rejects.toEqual( new Error( 'API error' ) );
364
355
  } );
365
356
 
@@ -371,9 +362,7 @@ describe( 'saveEntityRecord', () => {
371
362
  const select = {
372
363
  getRawEntityRecord: () => post,
373
364
  };
374
-
375
- // Provide entities
376
- dispatch.mockReturnValueOnce( entities );
365
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) };
377
366
 
378
367
  // Provide response
379
368
  apiFetch.mockImplementation( () => {
@@ -383,7 +372,7 @@ describe( 'saveEntityRecord', () => {
383
372
  await expect(
384
373
  saveEntityRecord( 'postType', 'post', post, {
385
374
  throwOnError: false,
386
- } )( { select, dispatch } )
375
+ } )( { select, dispatch, resolveSelect } )
387
376
  ).resolves.toEqual( undefined );
388
377
  } );
389
378
 
@@ -395,9 +384,7 @@ describe( 'saveEntityRecord', () => {
395
384
  const select = {
396
385
  getRawEntityRecord: () => post,
397
386
  };
398
-
399
- // Provide entities
400
- dispatch.mockReturnValueOnce( configs );
387
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) };
401
388
 
402
389
  // Provide response
403
390
  const updatedRecord = { ...post, id: 10 };
@@ -409,7 +396,7 @@ describe( 'saveEntityRecord', () => {
409
396
  'postType',
410
397
  'post',
411
398
  post
412
- )( { select, dispatch } );
399
+ )( { select, dispatch, resolveSelect } );
413
400
 
414
401
  expect( apiFetch ).toHaveBeenCalledTimes( 1 );
415
402
  expect( apiFetch ).toHaveBeenCalledWith( {
@@ -418,7 +405,7 @@ describe( 'saveEntityRecord', () => {
418
405
  data: post,
419
406
  } );
420
407
 
421
- expect( dispatch ).toHaveBeenCalledTimes( 3 );
408
+ expect( dispatch ).toHaveBeenCalledTimes( 2 );
422
409
  expect( dispatch ).toHaveBeenCalledWith( {
423
410
  type: 'SAVE_ENTITY_RECORD_START',
424
411
  kind: 'postType',
@@ -467,9 +454,7 @@ describe( 'saveEntityRecord', () => {
467
454
  const select = {
468
455
  getRawEntityRecord: () => ( {} ),
469
456
  };
470
-
471
- // Provide entities
472
- dispatch.mockReturnValueOnce( configs );
457
+ const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) };
473
458
 
474
459
  // Provide response
475
460
  apiFetch.mockImplementation( () => postType );
@@ -478,7 +463,7 @@ describe( 'saveEntityRecord', () => {
478
463
  'root',
479
464
  'postType',
480
465
  postType
481
- )( { select, dispatch } );
466
+ )( { select, dispatch, resolveSelect } );
482
467
 
483
468
  expect( apiFetch ).toHaveBeenCalledTimes( 1 );
484
469
  expect( apiFetch ).toHaveBeenCalledWith( {
@@ -487,7 +472,7 @@ describe( 'saveEntityRecord', () => {
487
472
  data: postType,
488
473
  } );
489
474
 
490
- expect( dispatch ).toHaveBeenCalledTimes( 3 );
475
+ expect( dispatch ).toHaveBeenCalledTimes( 2 );
491
476
  expect( dispatch ).toHaveBeenCalledWith( {
492
477
  type: 'SAVE_ENTITY_RECORD_START',
493
478
  kind: 'root',
@@ -1,16 +1,9 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import triggerFetch from '@wordpress/api-fetch';
5
- jest.mock( '@wordpress/api-fetch' );
6
-
7
1
  /**
8
2
  * Internal dependencies
9
3
  */
10
4
  import {
11
5
  getMethodName,
12
6
  rootEntitiesConfig,
13
- getOrLoadEntitiesConfig,
14
7
  prePersistPostType,
15
8
  } from '../entities';
16
9
 
@@ -43,79 +36,6 @@ describe( 'getMethodName', () => {
43
36
  } );
44
37
  } );
45
38
 
46
- describe( 'getKindEntities', () => {
47
- beforeEach( async () => {
48
- triggerFetch.mockReset();
49
- } );
50
-
51
- it( 'shouldn’t do anything if the entities have already been resolved', async () => {
52
- const dispatch = jest.fn();
53
- const select = {
54
- getEntitiesConfig: jest.fn( () => entities ),
55
- getEntityConfig: jest.fn( () => ( {
56
- kind: 'postType',
57
- name: 'post',
58
- } ) ),
59
- };
60
- const entities = [ { kind: 'postType' } ];
61
- await getOrLoadEntitiesConfig(
62
- 'postType',
63
- 'post'
64
- )( { dispatch, select } );
65
- expect( dispatch ).not.toHaveBeenCalled();
66
- } );
67
-
68
- it( 'shouldn’t do anything if there no defined kind config', async () => {
69
- const dispatch = jest.fn();
70
- const select = {
71
- getEntitiesConfig: jest.fn( () => [] ),
72
- getEntityConfig: jest.fn( () => undefined ),
73
- };
74
- await getOrLoadEntitiesConfig(
75
- 'unknownKind',
76
- undefined
77
- )( { dispatch, select } );
78
- expect( dispatch ).not.toHaveBeenCalled();
79
- } );
80
-
81
- it( 'should fetch and add the entities', async () => {
82
- const fetchedEntities = [
83
- {
84
- rest_base: 'posts',
85
- labels: {
86
- singular_name: 'post',
87
- },
88
- supports: {
89
- revisions: true,
90
- },
91
- },
92
- ];
93
- const dispatch = jest.fn();
94
- const select = {
95
- getEntitiesConfig: jest.fn( () => [] ),
96
- getEntityConfig: jest.fn( () => undefined ),
97
- };
98
- triggerFetch.mockImplementation( () => fetchedEntities );
99
-
100
- await getOrLoadEntitiesConfig(
101
- 'postType',
102
- 'post'
103
- )( { dispatch, select } );
104
- expect( dispatch ).toHaveBeenCalledTimes( 1 );
105
- expect( dispatch.mock.calls[ 0 ][ 0 ].type ).toBe( 'ADD_ENTITIES' );
106
- expect( dispatch.mock.calls[ 0 ][ 0 ].entities.length ).toBe( 1 );
107
- expect( dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].baseURL ).toBe(
108
- '/wp/v2/posts'
109
- );
110
- expect(
111
- dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].getRevisionsUrl( 1 )
112
- ).toBe( '/wp/v2/posts/1/revisions' );
113
- expect(
114
- dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].getRevisionsUrl( 1, 2 )
115
- ).toBe( '/wp/v2/posts/1/revisions/2' );
116
- } );
117
- } );
118
-
119
39
  describe( 'prePersistPostType', () => {
120
40
  it( 'set the status to draft and empty the title when saving auto-draft posts', () => {
121
41
  let record = {