@wordpress/core-data 4.0.1-next.253d9b6e21.0 → 4.0.3

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 (106) hide show
  1. package/README.md +11 -3
  2. package/build/actions.js +124 -117
  3. package/build/actions.js.map +1 -1
  4. package/build/batch/default-processor.js +58 -27
  5. package/build/batch/default-processor.js.map +1 -1
  6. package/build/entities.js +24 -18
  7. package/build/entities.js.map +1 -1
  8. package/build/index.js +9 -17
  9. package/build/index.js.map +1 -1
  10. package/build/locks/actions.js +17 -77
  11. package/build/locks/actions.js.map +1 -1
  12. package/build/locks/engine.js +77 -0
  13. package/build/locks/engine.js.map +1 -0
  14. package/build/locks/reducer.js +1 -5
  15. package/build/locks/reducer.js.map +1 -1
  16. package/build/locks/selectors.js +6 -6
  17. package/build/locks/selectors.js.map +1 -1
  18. package/build/queried-data/get-query-parts.js +9 -4
  19. package/build/queried-data/get-query-parts.js.map +1 -1
  20. package/build/queried-data/selectors.js +3 -9
  21. package/build/queried-data/selectors.js.map +1 -1
  22. package/build/reducer.js +1 -4
  23. package/build/reducer.js.map +1 -1
  24. package/build/resolvers.js +120 -91
  25. package/build/resolvers.js.map +1 -1
  26. package/build/selectors.js +31 -11
  27. package/build/selectors.js.map +1 -1
  28. package/build/utils/if-not-resolved.js +6 -21
  29. package/build/utils/if-not-resolved.js.map +1 -1
  30. package/build/utils/index.js +8 -0
  31. package/build/utils/index.js.map +1 -1
  32. package/build/utils/is-raw-attribute.js +19 -0
  33. package/build/utils/is-raw-attribute.js.map +1 -0
  34. package/build-module/actions.js +106 -107
  35. package/build-module/actions.js.map +1 -1
  36. package/build-module/batch/default-processor.js +57 -27
  37. package/build-module/batch/default-processor.js.map +1 -1
  38. package/build-module/entities.js +19 -14
  39. package/build-module/entities.js.map +1 -1
  40. package/build-module/index.js +10 -14
  41. package/build-module/index.js.map +1 -1
  42. package/build-module/locks/actions.js +14 -68
  43. package/build-module/locks/actions.js.map +1 -1
  44. package/build-module/locks/engine.js +66 -0
  45. package/build-module/locks/engine.js.map +1 -0
  46. package/build-module/locks/reducer.js +1 -2
  47. package/build-module/locks/reducer.js.map +1 -1
  48. package/build-module/locks/selectors.js +4 -4
  49. package/build-module/locks/selectors.js.map +1 -1
  50. package/build-module/queried-data/get-query-parts.js +9 -4
  51. package/build-module/queried-data/get-query-parts.js.map +1 -1
  52. package/build-module/queried-data/selectors.js +3 -9
  53. package/build-module/queried-data/selectors.js.map +1 -1
  54. package/build-module/reducer.js +1 -3
  55. package/build-module/reducer.js.map +1 -1
  56. package/build-module/resolvers.js +94 -74
  57. package/build-module/resolvers.js.map +1 -1
  58. package/build-module/selectors.js +30 -10
  59. package/build-module/selectors.js.map +1 -1
  60. package/build-module/utils/if-not-resolved.js +6 -19
  61. package/build-module/utils/if-not-resolved.js.map +1 -1
  62. package/build-module/utils/index.js +1 -0
  63. package/build-module/utils/index.js.map +1 -1
  64. package/build-module/utils/is-raw-attribute.js +12 -0
  65. package/build-module/utils/is-raw-attribute.js.map +1 -0
  66. package/package.json +11 -12
  67. package/src/actions.js +112 -189
  68. package/src/batch/default-processor.js +57 -26
  69. package/src/batch/test/default-processor.js +53 -26
  70. package/src/entities.js +15 -16
  71. package/src/index.js +7 -10
  72. package/src/locks/actions.js +10 -61
  73. package/src/locks/engine.js +43 -0
  74. package/src/locks/reducer.js +1 -3
  75. package/src/locks/selectors.js +4 -4
  76. package/src/locks/test/engine.js +135 -0
  77. package/src/locks/test/reducer.js +1 -1
  78. package/src/locks/test/selectors.js +105 -124
  79. package/src/queried-data/get-query-parts.js +11 -6
  80. package/src/queried-data/selectors.js +2 -9
  81. package/src/queried-data/test/get-query-parts.js +1 -1
  82. package/src/queried-data/test/selectors.js +1 -0
  83. package/src/reducer.js +0 -2
  84. package/src/resolvers.js +86 -106
  85. package/src/selectors.js +113 -40
  86. package/src/test/actions.js +243 -172
  87. package/src/test/entities.js +40 -26
  88. package/src/test/resolvers.js +270 -223
  89. package/src/test/selectors.js +71 -0
  90. package/src/utils/if-not-resolved.js +8 -26
  91. package/src/utils/index.js +1 -0
  92. package/src/utils/is-raw-attribute.js +11 -0
  93. package/src/utils/test/if-not-resolved.js +28 -27
  94. package/src/utils/test/is-raw-attribute.js +22 -0
  95. package/build/controls.js +0 -44
  96. package/build/controls.js.map +0 -1
  97. package/build/locks/index.js +0 -47
  98. package/build/locks/index.js.map +0 -1
  99. package/build-module/controls.js +0 -31
  100. package/build-module/controls.js.map +0 -1
  101. package/build-module/locks/index.js +0 -4
  102. package/build-module/locks/index.js.map +0 -1
  103. package/src/controls.js +0 -31
  104. package/src/locks/index.js +0 -3
  105. package/src/locks/test/actions.js +0 -307
  106. package/src/test/integration.js +0 -264
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { controls } from '@wordpress/data';
4
+ import apiFetch from '@wordpress/api-fetch';
5
+
6
+ jest.mock( '@wordpress/api-fetch' );
5
7
 
6
8
  /**
7
9
  * Internal dependencies
@@ -10,26 +12,12 @@ import {
10
12
  editEntityRecord,
11
13
  saveEntityRecord,
12
14
  deleteEntityRecord,
13
- receiveEntityRecords,
14
15
  receiveUserPermission,
15
16
  receiveAutosaves,
16
17
  receiveCurrentUser,
17
18
  __experimentalBatch,
18
19
  } from '../actions';
19
20
 
20
- jest.mock( '../locks/actions', () => ( {
21
- __unstableAcquireStoreLock: jest.fn( () => [
22
- {
23
- type: 'MOCKED_ACQUIRE_LOCK',
24
- },
25
- ] ),
26
- __unstableReleaseStoreLock: jest.fn( () => [
27
- {
28
- type: 'MOCKED_RELEASE_LOCK',
29
- },
30
- ] ),
31
- } ) );
32
-
33
21
  jest.mock( '../batch', () => {
34
22
  const { createBatch } = jest.requireActual( '../batch' );
35
23
  return {
@@ -40,120 +28,161 @@ jest.mock( '../batch', () => {
40
28
  } );
41
29
 
42
30
  describe( 'editEntityRecord', () => {
43
- it( 'throws when the edited entity does not have a loaded config.', () => {
31
+ it( 'throws when the edited entity does not have a loaded config.', async () => {
44
32
  const entity = { kind: 'someKind', name: 'someName', id: 'someId' };
45
- const fulfillment = editEntityRecord(
46
- entity.kind,
47
- entity.name,
48
- entity.id,
49
- {}
50
- );
51
- expect( fulfillment.next().value ).toEqual(
52
- controls.select( 'core', 'getEntity', entity.kind, entity.name )
53
- );
54
-
55
- // Don't pass back an entity config.
56
- expect( fulfillment.next.bind( fulfillment ) ).toThrow(
33
+ const select = {
34
+ getEntity: jest.fn(),
35
+ };
36
+ const fulfillment = () =>
37
+ editEntityRecord(
38
+ entity.kind,
39
+ entity.name,
40
+ entity.id,
41
+ {}
42
+ )( { select } );
43
+ expect( fulfillment ).toThrow(
57
44
  `The entity being edited (${ entity.kind }, ${ entity.name }) does not have a loaded config.`
58
45
  );
46
+ expect( select.getEntity ).toHaveBeenCalledTimes( 1 );
59
47
  } );
60
48
  } );
61
49
 
62
50
  describe( 'deleteEntityRecord', () => {
51
+ beforeEach( async () => {
52
+ apiFetch.mockReset();
53
+ jest.useFakeTimers();
54
+ } );
55
+
63
56
  it( 'triggers a DELETE request for an existing record', async () => {
64
- const post = 10;
57
+ const deletedRecord = { title: 'new post', id: 10 };
65
58
  const entities = [
66
59
  { name: 'post', kind: 'postType', baseURL: '/wp/v2/posts' },
67
60
  ];
68
- const fulfillment = deleteEntityRecord( 'postType', 'post', post );
69
61
 
70
- // Trigger generator
71
- fulfillment.next();
62
+ const dispatch = Object.assign( jest.fn(), {
63
+ receiveEntityRecords: jest.fn(),
64
+ __unstableAcquireStoreLock: jest.fn(),
65
+ __unstableReleaseStoreLock: jest.fn(),
66
+ } );
67
+ // Provide entities
68
+ dispatch.mockReturnValueOnce( entities );
72
69
 
73
- // Acquire lock
74
- expect( fulfillment.next( entities ).value.type ).toBe(
75
- 'MOCKED_ACQUIRE_LOCK'
76
- );
70
+ // Provide response
71
+ apiFetch.mockImplementation( () => deletedRecord );
77
72
 
78
- // Start
79
- expect( fulfillment.next().value.type ).toEqual(
80
- 'DELETE_ENTITY_RECORD_START'
81
- );
73
+ const result = await deleteEntityRecord(
74
+ 'postType',
75
+ 'post',
76
+ deletedRecord.id
77
+ )( { dispatch } );
82
78
 
83
- // delete api call
84
- const { value: apiFetchAction } = fulfillment.next();
85
- expect( apiFetchAction.request ).toEqual( {
79
+ expect( apiFetch ).toHaveBeenCalledTimes( 1 );
80
+ expect( apiFetch ).toHaveBeenCalledWith( {
86
81
  path: '/wp/v2/posts/10',
87
82
  method: 'DELETE',
88
83
  } );
89
84
 
90
- expect( fulfillment.next().value.type ).toBe( 'REMOVE_ITEMS' );
91
-
92
- expect( fulfillment.next().value.type ).toBe(
93
- 'DELETE_ENTITY_RECORD_FINISH'
85
+ expect( dispatch ).toHaveBeenCalledTimes( 4 );
86
+ expect( dispatch ).toHaveBeenCalledWith( {
87
+ type: 'DELETE_ENTITY_RECORD_START',
88
+ kind: 'postType',
89
+ name: 'post',
90
+ recordId: 10,
91
+ } );
92
+ expect( dispatch ).toHaveBeenCalledWith( {
93
+ type: 'DELETE_ENTITY_RECORD_FINISH',
94
+ kind: 'postType',
95
+ name: 'post',
96
+ recordId: 10,
97
+ error: undefined,
98
+ } );
99
+ expect( dispatch.__unstableAcquireStoreLock ).toHaveBeenCalledTimes(
100
+ 1
94
101
  );
95
-
96
- // Release lock
97
- expect( fulfillment.next().value.type ).toEqual(
98
- 'MOCKED_RELEASE_LOCK'
102
+ expect( dispatch.__unstableReleaseStoreLock ).toHaveBeenCalledTimes(
103
+ 1
99
104
  );
100
105
 
101
- expect( fulfillment.next() ).toMatchObject( {
102
- done: true,
103
- value: undefined,
104
- } );
106
+ expect( result ).toBe( deletedRecord );
105
107
  } );
106
108
  } );
107
109
 
108
110
  describe( 'saveEntityRecord', () => {
111
+ beforeEach( async () => {
112
+ apiFetch.mockReset();
113
+ jest.useFakeTimers();
114
+ } );
115
+
109
116
  it( 'triggers a POST request for a new record', async () => {
110
117
  const post = { title: 'new post' };
111
118
  const entities = [
112
119
  { name: 'post', kind: 'postType', baseURL: '/wp/v2/posts' },
113
120
  ];
114
- const fulfillment = saveEntityRecord( 'postType', 'post', post );
115
- // Trigger generator
116
- fulfillment.next();
121
+ const select = {
122
+ getRawEntityRecord: () => post,
123
+ };
117
124
 
118
- // Provide entities and acquire lock
119
- expect( fulfillment.next( entities ).value.type ).toBe(
120
- 'MOCKED_ACQUIRE_LOCK'
121
- );
125
+ const dispatch = Object.assign( jest.fn(), {
126
+ receiveEntityRecords: jest.fn(),
127
+ __unstableAcquireStoreLock: jest.fn(),
128
+ __unstableReleaseStoreLock: jest.fn(),
129
+ } );
130
+ // Provide entities
131
+ dispatch.mockReturnValueOnce( entities );
122
132
 
123
- // Trigger apiFetch
124
- expect( fulfillment.next().value.type ).toEqual(
125
- 'SAVE_ENTITY_RECORD_START'
126
- );
133
+ // Provide response
134
+ const updatedRecord = { ...post, id: 10 };
135
+ apiFetch.mockImplementation( () => {
136
+ return updatedRecord;
137
+ } );
127
138
 
128
- expect( fulfillment.next().value.type ).toBe( '@@data/SELECT' );
129
- const { value: apiFetchAction } = fulfillment.next( {} );
130
- expect( apiFetchAction.request ).toEqual( {
139
+ const result = await saveEntityRecord(
140
+ 'postType',
141
+ 'post',
142
+ post
143
+ )( { select, dispatch } );
144
+
145
+ expect( apiFetch ).toHaveBeenCalledTimes( 1 );
146
+ expect( apiFetch ).toHaveBeenCalledWith( {
131
147
  path: '/wp/v2/posts',
132
148
  method: 'POST',
133
149
  data: post,
134
150
  } );
135
- // Provide response and trigger action
136
- const updatedRecord = { ...post, id: 10 };
137
- const { value: received } = fulfillment.next( updatedRecord );
138
- expect( received ).toEqual(
139
- receiveEntityRecords(
140
- 'postType',
141
- 'post',
142
- updatedRecord,
143
- undefined,
144
- true,
145
- { title: 'new post' }
146
- )
151
+
152
+ expect( dispatch ).toHaveBeenCalledTimes( 3 );
153
+ expect( dispatch ).toHaveBeenCalledWith( {
154
+ type: 'SAVE_ENTITY_RECORD_START',
155
+ kind: 'postType',
156
+ name: 'post',
157
+ recordId: undefined,
158
+ isAutosave: false,
159
+ } );
160
+ expect( dispatch.__unstableAcquireStoreLock ).toHaveBeenCalledTimes(
161
+ 1
147
162
  );
148
- expect( fulfillment.next().value.type ).toBe(
149
- 'SAVE_ENTITY_RECORD_FINISH'
163
+ expect( dispatch ).toHaveBeenCalledWith( {
164
+ type: 'SAVE_ENTITY_RECORD_FINISH',
165
+ kind: 'postType',
166
+ name: 'post',
167
+ recordId: undefined,
168
+ error: undefined,
169
+ isAutosave: false,
170
+ } );
171
+ expect( dispatch.__unstableReleaseStoreLock ).toHaveBeenCalledTimes(
172
+ 1
150
173
  );
151
- // Release lock
152
- expect( fulfillment.next().value.type ).toEqual(
153
- 'MOCKED_RELEASE_LOCK'
174
+
175
+ expect( dispatch.receiveEntityRecords ).toHaveBeenCalledTimes( 1 );
176
+ expect( dispatch.receiveEntityRecords ).toHaveBeenCalledWith(
177
+ 'postType',
178
+ 'post',
179
+ updatedRecord,
180
+ undefined,
181
+ true,
182
+ post
154
183
  );
155
184
 
156
- expect( fulfillment.next().value ).toBe( updatedRecord );
185
+ expect( result ).toBe( updatedRecord );
157
186
  } );
158
187
 
159
188
  it( 'triggers a PUT request for an existing record', async () => {
@@ -161,41 +190,71 @@ describe( 'saveEntityRecord', () => {
161
190
  const entities = [
162
191
  { name: 'post', kind: 'postType', baseURL: '/wp/v2/posts' },
163
192
  ];
164
- const fulfillment = saveEntityRecord( 'postType', 'post', post );
165
- // Trigger generator
166
- fulfillment.next();
193
+ const select = {
194
+ getRawEntityRecord: () => post,
195
+ };
167
196
 
168
- // Provide entities and acquire lock
169
- expect( fulfillment.next( entities ).value.type ).toBe(
170
- 'MOCKED_ACQUIRE_LOCK'
171
- );
197
+ const dispatch = Object.assign( jest.fn(), {
198
+ receiveEntityRecords: jest.fn(),
199
+ __unstableAcquireStoreLock: jest.fn(),
200
+ __unstableReleaseStoreLock: jest.fn(),
201
+ } );
202
+ // Provide entities
203
+ dispatch.mockReturnValueOnce( entities );
172
204
 
173
- // Trigger apiFetch
174
- expect( fulfillment.next().value.type ).toEqual(
175
- 'SAVE_ENTITY_RECORD_START'
176
- );
177
- expect( fulfillment.next().value.type ).toBe( '@@data/SELECT' );
178
- const { value: apiFetchAction } = fulfillment.next( {} );
179
- expect( apiFetchAction.request ).toEqual( {
205
+ // Provide response
206
+ const updatedRecord = { ...post, id: 10 };
207
+ apiFetch.mockImplementation( () => {
208
+ return updatedRecord;
209
+ } );
210
+
211
+ const result = await saveEntityRecord(
212
+ 'postType',
213
+ 'post',
214
+ post
215
+ )( { select, dispatch } );
216
+
217
+ expect( apiFetch ).toHaveBeenCalledTimes( 1 );
218
+ expect( apiFetch ).toHaveBeenCalledWith( {
180
219
  path: '/wp/v2/posts/10',
181
220
  method: 'PUT',
182
221
  data: post,
183
222
  } );
184
- // Provide response and trigger action
185
- const { value: received } = fulfillment.next( post );
186
- expect( received ).toEqual(
187
- receiveEntityRecords( 'postType', 'post', post, undefined, true, {
188
- title: 'new post',
189
- id: 10,
190
- } )
223
+
224
+ expect( dispatch ).toHaveBeenCalledTimes( 3 );
225
+ expect( dispatch ).toHaveBeenCalledWith( {
226
+ type: 'SAVE_ENTITY_RECORD_START',
227
+ kind: 'postType',
228
+ name: 'post',
229
+ recordId: 10,
230
+ isAutosave: false,
231
+ } );
232
+ expect( dispatch.__unstableAcquireStoreLock ).toHaveBeenCalledTimes(
233
+ 1
191
234
  );
192
- expect( fulfillment.next().value.type ).toBe(
193
- 'SAVE_ENTITY_RECORD_FINISH'
235
+ expect( dispatch ).toHaveBeenCalledWith( {
236
+ type: 'SAVE_ENTITY_RECORD_FINISH',
237
+ kind: 'postType',
238
+ name: 'post',
239
+ recordId: 10,
240
+ error: undefined,
241
+ isAutosave: false,
242
+ } );
243
+ expect( dispatch.__unstableReleaseStoreLock ).toHaveBeenCalledTimes(
244
+ 1
194
245
  );
195
- // Release lock
196
- expect( fulfillment.next().value.type ).toEqual(
197
- 'MOCKED_RELEASE_LOCK'
246
+
247
+ expect( dispatch.receiveEntityRecords ).toHaveBeenCalledTimes( 1 );
248
+ expect( dispatch.receiveEntityRecords ).toHaveBeenCalledWith(
249
+ 'postType',
250
+ 'post',
251
+ updatedRecord,
252
+ undefined,
253
+ true,
254
+ post
198
255
  );
256
+
257
+ expect( result ).toBe( updatedRecord );
199
258
  } );
200
259
 
201
260
  it( 'triggers a PUT request for an existing record with a custom key', async () => {
@@ -208,45 +267,68 @@ describe( 'saveEntityRecord', () => {
208
267
  key: 'slug',
209
268
  },
210
269
  ];
211
- const fulfillment = saveEntityRecord( 'root', 'postType', postType );
212
- // Trigger generator
213
- fulfillment.next();
270
+ const select = {
271
+ getRawEntityRecord: () => ( {} ),
272
+ };
214
273
 
215
- // Provide entities and acquire lock
216
- expect( fulfillment.next( entities ).value.type ).toBe(
217
- 'MOCKED_ACQUIRE_LOCK'
218
- );
274
+ const dispatch = Object.assign( jest.fn(), {
275
+ receiveEntityRecords: jest.fn(),
276
+ __unstableAcquireStoreLock: jest.fn(),
277
+ __unstableReleaseStoreLock: jest.fn(),
278
+ } );
279
+ // Provide entities
280
+ dispatch.mockReturnValueOnce( entities );
219
281
 
220
- // Trigger apiFetch
221
- expect( fulfillment.next().value.type ).toEqual(
222
- 'SAVE_ENTITY_RECORD_START'
223
- );
224
- expect( fulfillment.next().value.type ).toBe( '@@data/SELECT' );
225
- const { value: apiFetchAction } = fulfillment.next( {} );
226
- expect( apiFetchAction.request ).toEqual( {
282
+ // Provide response
283
+ apiFetch.mockImplementation( () => postType );
284
+
285
+ const result = await saveEntityRecord(
286
+ 'root',
287
+ 'postType',
288
+ postType
289
+ )( { select, dispatch } );
290
+
291
+ expect( apiFetch ).toHaveBeenCalledTimes( 1 );
292
+ expect( apiFetch ).toHaveBeenCalledWith( {
227
293
  path: '/wp/v2/types/page',
228
294
  method: 'PUT',
229
295
  data: postType,
230
296
  } );
231
- // Provide response and trigger action
232
- const { value: received } = fulfillment.next( postType );
233
- expect( received ).toEqual(
234
- receiveEntityRecords(
235
- 'root',
236
- 'postType',
237
- postType,
238
- undefined,
239
- true,
240
- { slug: 'page', title: 'Pages' }
241
- )
297
+
298
+ expect( dispatch ).toHaveBeenCalledTimes( 3 );
299
+ expect( dispatch ).toHaveBeenCalledWith( {
300
+ type: 'SAVE_ENTITY_RECORD_START',
301
+ kind: 'root',
302
+ name: 'postType',
303
+ recordId: 'page',
304
+ isAutosave: false,
305
+ } );
306
+ expect( dispatch.__unstableAcquireStoreLock ).toHaveBeenCalledTimes(
307
+ 1
242
308
  );
243
- expect( fulfillment.next().value.type ).toBe(
244
- 'SAVE_ENTITY_RECORD_FINISH'
309
+ expect( dispatch ).toHaveBeenCalledWith( {
310
+ type: 'SAVE_ENTITY_RECORD_FINISH',
311
+ kind: 'root',
312
+ name: 'postType',
313
+ recordId: 'page',
314
+ error: undefined,
315
+ isAutosave: false,
316
+ } );
317
+ expect( dispatch.__unstableReleaseStoreLock ).toHaveBeenCalledTimes(
318
+ 1
245
319
  );
246
- // Release lock
247
- expect( fulfillment.next().value.type ).toEqual(
248
- 'MOCKED_RELEASE_LOCK'
320
+
321
+ expect( dispatch.receiveEntityRecords ).toHaveBeenCalledTimes( 1 );
322
+ expect( dispatch.receiveEntityRecords ).toHaveBeenCalledWith(
323
+ 'root',
324
+ 'postType',
325
+ postType,
326
+ undefined,
327
+ true,
328
+ { slug: 'page', title: 'Pages' }
249
329
  );
330
+
331
+ expect( result ).toBe( postType );
250
332
  } );
251
333
  } );
252
334
 
@@ -305,21 +387,7 @@ describe( 'receiveCurrentUser', () => {
305
387
 
306
388
  describe( '__experimentalBatch', () => {
307
389
  it( 'batches multiple actions together', async () => {
308
- const generator = __experimentalBatch(
309
- [
310
- ( { saveEntityRecord: _saveEntityRecord } ) =>
311
- _saveEntityRecord( 'root', 'widget', {} ),
312
- ( { saveEditedEntityRecord: _saveEditedEntityRecord } ) =>
313
- _saveEditedEntityRecord( 'root', 'widget', 123 ),
314
- ( { deleteEntityRecord: _deleteEntityRecord } ) =>
315
- _deleteEntityRecord( 'root', 'widget', 123, {} ),
316
- ],
317
- { __unstableProcessor: ( inputs ) => Promise.resolve( inputs ) }
318
- );
319
- // Run generator up to `yield getDispatch()`.
320
- const { value: getDispatchControl } = generator.next();
321
- expect( getDispatchControl ).toEqual( { type: 'GET_DISPATCH' } );
322
- const actions = {
390
+ const dispatch = {
323
391
  saveEntityRecord: jest.fn(
324
392
  ( kind, name, record, { __unstableFetch } ) => {
325
393
  __unstableFetch( {} );
@@ -339,36 +407,39 @@ describe( '__experimentalBatch', () => {
339
407
  }
340
408
  ),
341
409
  };
342
- const dispatch = () => actions;
343
- // Run generator up to `yield __unstableAwaitPromise( ... )`.
344
- const { value: awaitPromiseControl } = generator.next( dispatch );
345
- expect( actions.saveEntityRecord ).toHaveBeenCalledWith(
410
+
411
+ const results = await __experimentalBatch(
412
+ [
413
+ ( { saveEntityRecord: _saveEntityRecord } ) =>
414
+ _saveEntityRecord( 'root', 'widget', {} ),
415
+ ( { saveEditedEntityRecord: _saveEditedEntityRecord } ) =>
416
+ _saveEditedEntityRecord( 'root', 'widget', 123 ),
417
+ ( { deleteEntityRecord: _deleteEntityRecord } ) =>
418
+ _deleteEntityRecord( 'root', 'widget', 123, {} ),
419
+ ],
420
+ { __unstableProcessor: ( inputs ) => Promise.resolve( inputs ) }
421
+ )( { dispatch } );
422
+
423
+ expect( dispatch.saveEntityRecord ).toHaveBeenCalledWith(
346
424
  'root',
347
425
  'widget',
348
426
  {},
349
427
  { __unstableFetch: expect.any( Function ) }
350
428
  );
351
- expect( actions.saveEditedEntityRecord ).toHaveBeenCalledWith(
429
+ expect( dispatch.saveEditedEntityRecord ).toHaveBeenCalledWith(
352
430
  'root',
353
431
  'widget',
354
432
  123,
355
433
  { __unstableFetch: expect.any( Function ) }
356
434
  );
357
- expect( actions.deleteEntityRecord ).toHaveBeenCalledWith(
435
+ expect( dispatch.deleteEntityRecord ).toHaveBeenCalledWith(
358
436
  'root',
359
437
  'widget',
360
438
  123,
361
439
  {},
362
440
  { __unstableFetch: expect.any( Function ) }
363
441
  );
364
- expect( awaitPromiseControl ).toEqual( {
365
- type: 'AWAIT_PROMISE',
366
- promise: expect.any( Promise ),
367
- } );
368
- // Run generator to the end.
369
- const { value: results } = generator.next(
370
- await awaitPromiseControl.promise
371
- );
442
+
372
443
  expect( results ).toEqual( [
373
444
  { id: 123, created: true },
374
445
  { id: 123, updated: true },
@@ -1,3 +1,9 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import triggerFetch from '@wordpress/api-fetch';
5
+ jest.mock( '@wordpress/api-fetch' );
6
+
1
7
  /**
2
8
  * Internal dependencies
3
9
  */
@@ -7,7 +13,6 @@ import {
7
13
  getKindEntities,
8
14
  prePersistPostType,
9
15
  } from '../entities';
10
- import { addEntities } from '../actions';
11
16
 
12
17
  describe( 'getMethodName', () => {
13
18
  it( 'should return the right method name for an entity with the root kind', () => {
@@ -45,43 +50,52 @@ describe( 'getMethodName', () => {
45
50
  } );
46
51
 
47
52
  describe( 'getKindEntities', () => {
53
+ beforeEach( async () => {
54
+ triggerFetch.mockReset();
55
+ jest.useFakeTimers();
56
+ } );
57
+
48
58
  it( 'shouldn’t do anything if the entities have already been resolved', async () => {
59
+ const dispatch = jest.fn();
60
+ const select = {
61
+ getEntitiesByKind: jest.fn( () => entities ),
62
+ };
49
63
  const entities = [ { kind: 'postType' } ];
50
- const fulfillment = getKindEntities( 'postType' );
51
- // Start the generator
52
- fulfillment.next();
53
- // Provide the entities
54
- const end = fulfillment.next( entities );
55
- expect( end.done ).toBe( true );
64
+ await getKindEntities( 'postType' )( { dispatch, select } );
65
+ expect( dispatch ).not.toHaveBeenCalled();
56
66
  } );
57
67
 
58
68
  it( 'shouldn’t do anything if there no defined kind config', async () => {
59
- const fulfillment = getKindEntities( 'unknownKind' );
60
- // Start the generator
61
- fulfillment.next();
62
- // Provide no entities to continue
63
- const end = fulfillment.next( [] );
64
- expect( end.done ).toBe( true );
69
+ const dispatch = jest.fn();
70
+ const select = {
71
+ getEntitiesByKind: jest.fn( () => [] ),
72
+ };
73
+ await getKindEntities( 'unknownKind' )( { dispatch, select } );
74
+ expect( dispatch ).not.toHaveBeenCalled();
65
75
  } );
66
76
 
67
77
  it( 'should fetch and add the entities', async () => {
68
78
  const fetchedEntities = [
69
79
  {
70
- baseURL: '/wp/v2/posts',
71
- kind: 'postType',
72
- name: 'post',
80
+ rest_base: 'posts',
81
+ labels: {
82
+ singular_name: 'post',
83
+ },
73
84
  },
74
85
  ];
75
- const fulfillment = getKindEntities( 'postType' );
76
- // Start the generator
77
- fulfillment.next();
78
- // Provide no entities to continue
79
- fulfillment.next( [] );
80
- // Fetch entities and trigger action
81
- const { value: action } = fulfillment.next( fetchedEntities );
82
- expect( action ).toEqual( addEntities( fetchedEntities ) );
83
- const end = fulfillment.next();
84
- expect( end ).toEqual( { done: true, value: fetchedEntities } );
86
+ const dispatch = jest.fn();
87
+ const select = {
88
+ getEntitiesByKind: jest.fn( () => [] ),
89
+ };
90
+ triggerFetch.mockImplementation( () => fetchedEntities );
91
+
92
+ await getKindEntities( 'postType' )( { dispatch, select } );
93
+ expect( dispatch ).toHaveBeenCalledTimes( 1 );
94
+ expect( dispatch.mock.calls[ 0 ][ 0 ].type ).toBe( 'ADD_ENTITIES' );
95
+ expect( dispatch.mock.calls[ 0 ][ 0 ].entities.length ).toBe( 1 );
96
+ expect( dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].baseURL ).toBe(
97
+ '/wp/v2/posts'
98
+ );
85
99
  } );
86
100
  } );
87
101