@wordpress/core-data 7.27.1-next.46f643fa0.0 → 7.28.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 (64) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +2 -2
  3. package/build/actions.js +7 -0
  4. package/build/actions.js.map +1 -1
  5. package/build/entities.js +12 -1
  6. package/build/entities.js.map +1 -1
  7. package/build/hooks/use-resource-permissions.js +1 -1
  8. package/build/hooks/use-resource-permissions.js.map +1 -1
  9. package/build/index.js +50 -8
  10. package/build/index.js.map +1 -1
  11. package/build/private-actions.js +2 -2
  12. package/build/private-actions.js.map +1 -1
  13. package/build/private-selectors.js +3 -0
  14. package/build/private-selectors.js.map +1 -1
  15. package/build/resolvers.js +1 -1
  16. package/build/resolvers.js.map +1 -1
  17. package/build/selectors.js +26 -1
  18. package/build/selectors.js.map +1 -1
  19. package/build/utils/log-entity-deprecation.js +63 -0
  20. package/build/utils/log-entity-deprecation.js.map +1 -0
  21. package/build-module/actions.js +7 -0
  22. package/build-module/actions.js.map +1 -1
  23. package/build-module/entities.js +11 -0
  24. package/build-module/entities.js.map +1 -1
  25. package/build-module/hooks/use-resource-permissions.js +1 -1
  26. package/build-module/hooks/use-resource-permissions.js.map +1 -1
  27. package/build-module/index.js +50 -8
  28. package/build-module/index.js.map +1 -1
  29. package/build-module/private-actions.js +2 -2
  30. package/build-module/private-actions.js.map +1 -1
  31. package/build-module/private-selectors.js +2 -0
  32. package/build-module/private-selectors.js.map +1 -1
  33. package/build-module/resolvers.js +1 -1
  34. package/build-module/resolvers.js.map +1 -1
  35. package/build-module/selectors.js +26 -1
  36. package/build-module/selectors.js.map +1 -1
  37. package/build-module/utils/log-entity-deprecation.js +55 -0
  38. package/build-module/utils/log-entity-deprecation.js.map +1 -0
  39. package/build-types/actions.d.ts.map +1 -1
  40. package/build-types/entities.d.ts +11 -0
  41. package/build-types/entities.d.ts.map +1 -1
  42. package/build-types/index.d.ts.map +1 -1
  43. package/build-types/private-selectors.d.ts.map +1 -1
  44. package/build-types/selectors.d.ts +1 -1
  45. package/build-types/selectors.d.ts.map +1 -1
  46. package/build-types/utils/log-entity-deprecation.d.ts +15 -0
  47. package/build-types/utils/log-entity-deprecation.d.ts.map +1 -0
  48. package/package.json +18 -18
  49. package/src/actions.js +11 -0
  50. package/src/entities.js +12 -0
  51. package/src/hooks/test/use-resource-permissions.js +3 -3
  52. package/src/hooks/use-resource-permissions.ts +1 -1
  53. package/src/index.js +54 -14
  54. package/src/private-actions.js +2 -2
  55. package/src/private-selectors.ts +2 -0
  56. package/src/resolvers.js +1 -1
  57. package/src/selectors.ts +29 -1
  58. package/src/test/deprecated-entity-logging.js +291 -0
  59. package/src/test/private-actions.js +13 -13
  60. package/src/test/resolvers.js +7 -7
  61. package/src/test/selectors.js +18 -7
  62. package/src/utils/log-entity-deprecation.ts +67 -0
  63. package/src/utils/test/log-entity-deprecation.js +130 -0
  64. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,291 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import deprecated from '@wordpress/deprecated';
5
+ import { createRegistry } from '@wordpress/data';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import { store as coreDataStore } from '../index';
11
+
12
+ jest.mock( '@wordpress/deprecated' );
13
+ jest.mock( '@wordpress/api-fetch' );
14
+
15
+ // Use fake timers within this file.
16
+ // logEntityDeprecation() uses setTimeout() to avoid spurious logging, so fake timers are used to
17
+ // ensure that the deprecation warning is logged correctly.
18
+ jest.useFakeTimers();
19
+
20
+ /**
21
+ * Returns the expected arguments for the deprecated function call.
22
+ *
23
+ * @param {string} name - The name of the function.
24
+ * @param {Array} args - The arguments for the function.
25
+ * @param {boolean} isShorthandSelector - Whether the function is a shorthand selector.
26
+ * @param {string} alternativeFunction - The name of the alternative function.
27
+ * @return {Array} The expected arguments for the deprecated function call.
28
+ */
29
+ function getExpectedDeprecationArgs(
30
+ name,
31
+ args,
32
+ isShorthandSelector,
33
+ alternativeFunction
34
+ ) {
35
+ const expectedMessage = isShorthandSelector
36
+ ? `'${ name }'`
37
+ : `The 'root', 'media' entity (used via '${ name }')`;
38
+
39
+ let expectedAlternative = "the 'postType', 'attachment' entity";
40
+ if ( alternativeFunction ) {
41
+ expectedAlternative += ` via the '${ alternativeFunction }' function`;
42
+ }
43
+
44
+ return [
45
+ expectedMessage,
46
+ {
47
+ alternative: expectedAlternative,
48
+ since: '6.9',
49
+ },
50
+ ];
51
+ }
52
+
53
+ /**
54
+ * Creates a test registry with the core-data store and sets up the deprecated media entity.
55
+ *
56
+ * This approach enables testing generated selections/actions (like `getMedia`), and simplifies
57
+ * the tests by avoiding an endless amount of mocks.
58
+ *
59
+ * It means the tests in this file are integration rather than unit tests, so they're kept
60
+ * separate from the selector.js/reducer.js tests.
61
+ *
62
+ * @return {Object} Registry with core-data store registered.
63
+ */
64
+ function createTestRegistry() {
65
+ const registry = createRegistry();
66
+
67
+ // Register the core-data store
68
+ registry.register( coreDataStore );
69
+
70
+ // Set up the deprecated media entity configuration
71
+ const mediaEntityConfig = {
72
+ name: 'media',
73
+ kind: 'root',
74
+ baseURL: '/wp/v2/media',
75
+ baseURLParams: { context: 'edit' },
76
+ plural: 'mediaItems',
77
+ label: 'Media',
78
+ rawAttributes: [ 'caption', 'title', 'description' ],
79
+ supportsPagination: true,
80
+ };
81
+
82
+ // Add the media entity to the store
83
+ registry.dispatch( coreDataStore ).addEntities( [ mediaEntityConfig ] );
84
+
85
+ // Add a sample media record to the store for testing
86
+ const mediaRecord = {
87
+ id: '123',
88
+ title: 'Test Media',
89
+ content: 'Test content',
90
+ excerpt: 'Test excerpt',
91
+ };
92
+
93
+ registry
94
+ .dispatch( coreDataStore )
95
+ .receiveEntityRecords( 'root', 'media', mediaRecord );
96
+
97
+ jest.runAllTimers();
98
+
99
+ return registry;
100
+ }
101
+
102
+ describe( 'Deprecated entity logging', () => {
103
+ describe.each( [
104
+ {
105
+ type: 'selector',
106
+ name: 'getEntityConfig',
107
+ args: [ 'root', 'media' ],
108
+ },
109
+ {
110
+ type: 'selector',
111
+ name: 'getEntityRecord',
112
+ args: [ 'root', 'media', '123' ],
113
+ },
114
+ {
115
+ type: 'selector',
116
+ name: 'getRawEntityRecord',
117
+ args: [ 'root', 'media', '123' ],
118
+ },
119
+ {
120
+ type: 'selector',
121
+ name: 'hasEntityRecords',
122
+ args: [ 'root', 'media' ],
123
+ },
124
+ {
125
+ type: 'selector',
126
+ name: 'getEntityRecords',
127
+ args: [ 'root', 'media' ],
128
+ },
129
+ {
130
+ type: 'selector',
131
+ name: 'getEntityRecordsTotalItems',
132
+ args: [ 'root', 'media', { _fields: 'title' } ],
133
+ },
134
+ {
135
+ type: 'selector',
136
+ name: 'getEntityRecordsTotalPages',
137
+ args: [ 'root', 'media', { _fields: 'title' } ],
138
+ },
139
+ {
140
+ type: 'selector',
141
+ name: 'getEntityRecordEdits',
142
+ args: [ 'root', 'media', '123' ],
143
+ },
144
+ {
145
+ type: 'selector',
146
+ name: 'getEntityRecordNonTransientEdits',
147
+ args: [ 'root', 'media', '123' ],
148
+ },
149
+ {
150
+ type: 'selector',
151
+ name: 'hasEditsForEntityRecord',
152
+ args: [ 'root', 'media', '123' ],
153
+ },
154
+ {
155
+ type: 'selector',
156
+ name: 'getEditedEntityRecord',
157
+ args: [ 'root', 'media', '123' ],
158
+ },
159
+ {
160
+ type: 'selector',
161
+ name: 'isAutosavingEntityRecord',
162
+ args: [ 'root', 'media', '123' ],
163
+ },
164
+ {
165
+ type: 'selector',
166
+ name: 'isSavingEntityRecord',
167
+ args: [ 'root', 'media', '123' ],
168
+ },
169
+ {
170
+ type: 'selector',
171
+ name: 'isDeletingEntityRecord',
172
+ args: [ 'root', 'media', '123' ],
173
+ },
174
+ {
175
+ type: 'selector',
176
+ name: 'getLastEntitySaveError',
177
+ args: [ 'root', 'media', '123' ],
178
+ },
179
+ {
180
+ type: 'selector',
181
+ name: 'getLastEntityDeleteError',
182
+ args: [ 'root', 'media', '123' ],
183
+ },
184
+ {
185
+ type: 'selector',
186
+ name: 'canUser',
187
+ args: [ 'create', { kind: 'root', name: 'media' }, '123' ],
188
+ },
189
+ {
190
+ type: 'selector',
191
+ name: 'getRevisions',
192
+ args: [ 'root', 'media', '123' ],
193
+ },
194
+ {
195
+ type: 'selector',
196
+ name: 'getRevision',
197
+ args: [ 'root', 'media', '123', '10' ],
198
+ },
199
+ {
200
+ type: 'selector',
201
+ name: 'getMedia',
202
+ args: [ '123' ],
203
+ isShorthandSelector: true,
204
+ alternativeFunction: 'getEntityRecord',
205
+ },
206
+ {
207
+ type: 'selector',
208
+ name: 'getMediaItems',
209
+ args: [],
210
+ isShorthandSelector: true,
211
+ alternativeFunction: 'getEntityRecords',
212
+ },
213
+ {
214
+ type: 'action',
215
+ name: 'deleteEntityRecord',
216
+ args: [ 'root', 'media', '123' ],
217
+ },
218
+ {
219
+ type: 'action',
220
+ name: 'editEntityRecord',
221
+ args: [ 'root', 'media', '123', { title: 'Media' } ],
222
+ },
223
+ {
224
+ type: 'action',
225
+ name: 'saveEntityRecord',
226
+ args: [ 'root', 'media', { title: 'Media' } ],
227
+ },
228
+ {
229
+ type: 'action',
230
+ name: 'saveEditedEntityRecord',
231
+ args: [ 'root', 'media', '123' ],
232
+ },
233
+ {
234
+ type: 'action',
235
+ name: '__experimentalSaveSpecifiedEntityEdits',
236
+ args: [ 'root', 'media', '123', [ 'title' ] ],
237
+ },
238
+ {
239
+ type: 'action',
240
+ name: 'receiveRevisions',
241
+ args: [ 'root', 'media', '123', [ 'title' ] ],
242
+ },
243
+ {
244
+ type: 'action',
245
+ name: 'saveMedia',
246
+ args: [ { title: 'Media' } ],
247
+ alternativeFunction: 'saveEntityRecord',
248
+ isShorthandSelector: true,
249
+ },
250
+ {
251
+ type: 'action',
252
+ name: 'deleteMedia',
253
+ args: [ '123' ],
254
+ alternativeFunction: 'deleteEntityRecord',
255
+ isShorthandSelector: true,
256
+ },
257
+ ] )(
258
+ '$name $type',
259
+ ( { type, name, args, alternativeFunction, isShorthandSelector } ) => {
260
+ beforeEach( () => {
261
+ deprecated.mockReset();
262
+ } );
263
+
264
+ it( 'logs a deprecation warning when used with deprecated entities', () => {
265
+ // Create a test registry with the actual store
266
+ const registry = createTestRegistry();
267
+
268
+ if ( type === 'selector' ) {
269
+ // Dispatch the action.
270
+ registry.select( coreDataStore )[ name ]( ...args );
271
+ } else {
272
+ // Dispatch the action.
273
+ registry.dispatch( coreDataStore )[ name ]( ...args );
274
+ }
275
+
276
+ const [ expectedMessage, expectedOptions ] =
277
+ getExpectedDeprecationArgs(
278
+ name,
279
+ args,
280
+ isShorthandSelector,
281
+ alternativeFunction
282
+ );
283
+
284
+ expect( deprecated ).toHaveBeenCalledWith(
285
+ expectedMessage,
286
+ expectedOptions
287
+ );
288
+ } );
289
+ }
290
+ );
291
+ } );
@@ -24,8 +24,8 @@ describe( 'editMediaEntity', () => {
24
24
  resolveSelect = {
25
25
  getEntitiesConfig: jest.fn( () => [
26
26
  {
27
- kind: 'root',
28
- name: 'media',
27
+ kind: 'postType',
28
+ name: 'attachment',
29
29
  baseURL: '/wp/v2/media',
30
30
  },
31
31
  ] ),
@@ -82,14 +82,14 @@ describe( 'editMediaEntity', () => {
82
82
 
83
83
  expect( dispatch.__unstableAcquireStoreLock ).toHaveBeenCalledWith(
84
84
  'core',
85
- [ 'entities', 'records', 'root', 'media', recordId ],
85
+ [ 'entities', 'records', 'postType', 'attachment', recordId ],
86
86
  { exclusive: true }
87
87
  );
88
88
 
89
89
  expect( dispatch ).toHaveBeenCalledWith( {
90
90
  type: 'SAVE_ENTITY_RECORD_START',
91
- kind: 'root',
92
- name: 'media',
91
+ kind: 'postType',
92
+ name: 'attachment',
93
93
  recordId,
94
94
  } );
95
95
 
@@ -100,8 +100,8 @@ describe( 'editMediaEntity', () => {
100
100
  } );
101
101
 
102
102
  expect( dispatch.receiveEntityRecords ).toHaveBeenCalledWith(
103
- 'root',
104
- 'media',
103
+ 'postType',
104
+ 'attachment',
105
105
  [ updatedRecord ],
106
106
  undefined,
107
107
  true,
@@ -111,8 +111,8 @@ describe( 'editMediaEntity', () => {
111
111
 
112
112
  expect( dispatch ).toHaveBeenCalledWith( {
113
113
  type: 'SAVE_ENTITY_RECORD_FINISH',
114
- kind: 'root',
115
- name: 'media',
114
+ kind: 'postType',
115
+ name: 'attachment',
116
116
  recordId,
117
117
  error: undefined,
118
118
  } );
@@ -137,15 +137,15 @@ describe( 'editMediaEntity', () => {
137
137
 
138
138
  expect( dispatch ).toHaveBeenCalledWith( {
139
139
  type: 'SAVE_ENTITY_RECORD_START',
140
- kind: 'root',
141
- name: 'media',
140
+ kind: 'postType',
141
+ name: 'attachment',
142
142
  recordId,
143
143
  } );
144
144
 
145
145
  expect( dispatch ).toHaveBeenCalledWith( {
146
146
  type: 'SAVE_ENTITY_RECORD_FINISH',
147
- kind: 'root',
148
- name: 'media',
147
+ kind: 'postType',
148
+ name: 'attachment',
149
149
  recordId,
150
150
  error: apiError,
151
151
  } );
@@ -379,8 +379,8 @@ describe( 'getEmbedPreview', () => {
379
379
  describe( 'canUser', () => {
380
380
  const ENTITIES = [
381
381
  {
382
- name: 'media',
383
- kind: 'root',
382
+ name: 'attachment',
383
+ kind: 'postType',
384
384
  baseURL: '/wp/v2/media',
385
385
  baseURLParams: { context: 'edit' },
386
386
  },
@@ -417,7 +417,7 @@ describe( 'canUser', () => {
417
417
  'create',
418
418
  'media'
419
419
  )( { dispatch, registry, resolveSelect } );
420
- await canUser( 'create', { kind: 'root', name: 'media' } )( {
420
+ await canUser( 'create', { kind: 'postType', name: 'attachment' } )( {
421
421
  dispatch,
422
422
  registry,
423
423
  resolveSelect,
@@ -469,7 +469,7 @@ describe( 'canUser', () => {
469
469
  headers: new Map( [ [ 'allow', 'GET' ] ] ),
470
470
  } ) );
471
471
 
472
- await canUser( 'create', { kind: 'root', name: 'media' } )( {
472
+ await canUser( 'create', { kind: 'postType', name: 'attachment' } )( {
473
473
  dispatch,
474
474
  registry,
475
475
  resolveSelect,
@@ -482,7 +482,7 @@ describe( 'canUser', () => {
482
482
  } );
483
483
 
484
484
  expect( dispatch.receiveUserPermission ).toHaveBeenCalledWith(
485
- 'create/root/media',
485
+ 'create/postType/attachment',
486
486
  false
487
487
  );
488
488
  } );
@@ -514,7 +514,7 @@ describe( 'canUser', () => {
514
514
  headers: new Map( [ [ 'allow', 'POST, GET, PUT, DELETE' ] ] ),
515
515
  } ) );
516
516
 
517
- await canUser( 'create', { kind: 'root', name: 'media' } )( {
517
+ await canUser( 'create', { kind: 'postType', name: 'attachment' } )( {
518
518
  dispatch,
519
519
  registry,
520
520
  resolveSelect,
@@ -527,7 +527,7 @@ describe( 'canUser', () => {
527
527
  } );
528
528
 
529
529
  expect( dispatch.receiveUserPermission ).toHaveBeenCalledWith(
530
- 'create/root/media',
530
+ 'create/postType/attachment',
531
531
  true
532
532
  );
533
533
  } );
@@ -24,6 +24,7 @@ import {
24
24
  getRevisions,
25
25
  getRevision,
26
26
  } from '../selectors';
27
+
27
28
  // getEntityRecord and __experimentalGetEntityRecordNoResolver selectors share the same tests.
28
29
  describe.each( [
29
30
  [ getEntityRecord ],
@@ -52,6 +53,7 @@ describe.each( [
52
53
  ] );
53
54
  } );
54
55
  } );
56
+
55
57
  it( 'should return undefined for unknown entity kind, name', () => {
56
58
  const state = deepFreeze( {
57
59
  entities: {
@@ -290,6 +292,7 @@ describe( 'getRawEntityRecord', () => {
290
292
  },
291
293
  },
292
294
  };
295
+
293
296
  it( 'should preserve the structure of `raw` field by default', () => {
294
297
  const state = deepFreeze( {
295
298
  entities: {
@@ -732,7 +735,7 @@ describe( 'canUser', () => {
732
735
  } );
733
736
  expect( canUser( state, 'create', 'media' ) ).toBe( undefined );
734
737
  expect(
735
- canUser( state, 'create', { kind: 'root', name: 'media' } )
738
+ canUser( state, 'create', { kind: 'postType', name: 'attachment' } )
736
739
  ).toBe( undefined );
737
740
  } );
738
741
 
@@ -740,20 +743,24 @@ describe( 'canUser', () => {
740
743
  const state = deepFreeze( {
741
744
  userPermissions: {},
742
745
  } );
743
- expect( canUser( state, 'create', { name: 'media' } ) ).toBe( false );
744
- expect( canUser( state, 'create', { kind: 'root' } ) ).toBe( false );
746
+ expect( canUser( state, 'create', { name: 'attachment' } ) ).toBe(
747
+ false
748
+ );
749
+ expect( canUser( state, 'create', { kind: 'postType' } ) ).toBe(
750
+ false
751
+ );
745
752
  } );
746
753
 
747
754
  it( 'returns whether an action can be performed', () => {
748
755
  const state = deepFreeze( {
749
756
  userPermissions: {
750
757
  'create/media': false,
751
- 'create/root/media': false,
758
+ 'create/postType/attachment': false,
752
759
  },
753
760
  } );
754
761
  expect( canUser( state, 'create', 'media' ) ).toBe( false );
755
762
  expect(
756
- canUser( state, 'create', { kind: 'root', name: 'media' } )
763
+ canUser( state, 'create', { kind: 'postType', name: 'attachment' } )
757
764
  ).toBe( false );
758
765
  } );
759
766
 
@@ -761,12 +768,16 @@ describe( 'canUser', () => {
761
768
  const state = deepFreeze( {
762
769
  userPermissions: {
763
770
  'create/media/123': false,
764
- 'create/root/media/123': false,
771
+ 'create/postType/attachment/123': false,
765
772
  },
766
773
  } );
767
774
  expect( canUser( state, 'create', 'media', 123 ) ).toBe( false );
768
775
  expect(
769
- canUser( state, 'create', { kind: 'root', name: 'media', id: 123 } )
776
+ canUser( state, 'create', {
777
+ kind: 'postType',
778
+ name: 'attachment',
779
+ id: 123,
780
+ } )
770
781
  ).toBe( false );
771
782
  } );
772
783
  } );
@@ -0,0 +1,67 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import deprecated from '@wordpress/deprecated';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import { deprecatedEntities } from '../entities';
10
+
11
+ let loggedAlready = false;
12
+
13
+ /**
14
+ * Logs a deprecation warning for an entity, if it's deprecated.
15
+ *
16
+ * @param kind The kind of the entity.
17
+ * @param name The name of the entity.
18
+ * @param functionName The name of the function that was called with a deprecated entity.
19
+ * @param options The options for the deprecation warning.
20
+ * @param options.alternativeFunctionName The name of the alternative function that should be used instead.
21
+ * @param options.isShorthandSelector Whether the function is a shorthand selector.
22
+ */
23
+ export default function logEntityDeprecation(
24
+ kind: string,
25
+ name: string,
26
+ functionName: string,
27
+ {
28
+ alternativeFunctionName,
29
+ isShorthandSelector = false,
30
+ }: {
31
+ alternativeFunctionName?: string;
32
+ isShorthandSelector?: boolean;
33
+ } = {}
34
+ ) {
35
+ const deprecation = deprecatedEntities[ kind ]?.[ name ];
36
+ if ( ! deprecation ) {
37
+ return;
38
+ }
39
+
40
+ if ( ! loggedAlready ) {
41
+ const { alternative } = deprecation;
42
+
43
+ const message = isShorthandSelector
44
+ ? `'${ functionName }'`
45
+ : `The '${ kind }', '${ name }' entity (used via '${ functionName }')`;
46
+
47
+ let alternativeMessage = `the '${ alternative.kind }', '${ alternative.name }' entity`;
48
+ if ( alternativeFunctionName ) {
49
+ alternativeMessage += ` via the '${ alternativeFunctionName }' function`;
50
+ }
51
+
52
+ deprecated( message, {
53
+ ...deprecation,
54
+ alternative: alternativeMessage,
55
+ } );
56
+ }
57
+
58
+ // Only log an entity deprecation once per call stack,
59
+ // else there's spurious logging when selections or actions call through to other selectors or actions.
60
+ // Note: this won't prevent the deprecation warning being logged if a selector or action makes an async call
61
+ // to another selector or action, but this is probably the best we can do.
62
+ loggedAlready = true;
63
+ // At the end of the call stack, reset the flag.
64
+ setTimeout( () => {
65
+ loggedAlready = false;
66
+ }, 0 );
67
+ }
@@ -0,0 +1,130 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import deprecated from '@wordpress/deprecated';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import logEntityDeprecation from '../log-entity-deprecation';
10
+
11
+ jest.useFakeTimers();
12
+
13
+ // Mock the deprecatedEntities import
14
+ jest.mock( '../../entities', () => ( {
15
+ deprecatedEntities: {
16
+ root: {
17
+ media: {
18
+ since: '6.9',
19
+ alternative: {
20
+ kind: 'postType',
21
+ name: 'attachment',
22
+ },
23
+ },
24
+ },
25
+ },
26
+ } ) );
27
+
28
+ // Mock the deprecated function
29
+ jest.mock( '@wordpress/deprecated' );
30
+
31
+ describe( 'logEntityDeprecation', () => {
32
+ beforeEach( () => {
33
+ jest.clearAllMocks();
34
+
35
+ // Ensure the timeout that prevents spurious logging is cleared.
36
+ jest.runAllTimers();
37
+ } );
38
+
39
+ it( 'should call deprecated when entity is deprecated', () => {
40
+ logEntityDeprecation( 'root', 'media', 'getEntityRecord' );
41
+
42
+ expect( deprecated ).toHaveBeenCalledWith(
43
+ "The 'root', 'media' entity (used via 'getEntityRecord')",
44
+ {
45
+ since: '6.9',
46
+ alternative: "the 'postType', 'attachment' entity",
47
+ }
48
+ );
49
+ } );
50
+
51
+ it( 'should not call deprecated when entity is not deprecated', () => {
52
+ logEntityDeprecation( 'root', 'nonExistentEntity', 'getEntityRecord' );
53
+
54
+ expect( deprecated ).not.toHaveBeenCalled();
55
+ } );
56
+
57
+ it( 'should not call deprecated when kind is not deprecated', () => {
58
+ logEntityDeprecation( 'nonExistentKind', 'media', 'getEntityRecord' );
59
+
60
+ expect( deprecated ).not.toHaveBeenCalled();
61
+ } );
62
+
63
+ it( 'should handle different function names', () => {
64
+ logEntityDeprecation( 'root', 'media', 'saveEntityRecord' );
65
+
66
+ expect( deprecated ).toHaveBeenCalledWith(
67
+ "The 'root', 'media' entity (used via 'saveEntityRecord')",
68
+ {
69
+ since: '6.9',
70
+ alternative: "the 'postType', 'attachment' entity",
71
+ }
72
+ );
73
+ } );
74
+
75
+ it( 'should include alternative function name when provided', () => {
76
+ logEntityDeprecation( 'root', 'media', 'getEntityRecord', {
77
+ alternativeFunctionName: 'getPostTypeEntity',
78
+ } );
79
+
80
+ expect( deprecated ).toHaveBeenCalledWith(
81
+ "The 'root', 'media' entity (used via 'getEntityRecord')",
82
+ {
83
+ since: '6.9',
84
+ alternative:
85
+ "the 'postType', 'attachment' entity via the 'getPostTypeEntity' function",
86
+ }
87
+ );
88
+ } );
89
+
90
+ it( 'should handle isShorthandSelector', () => {
91
+ logEntityDeprecation( 'root', 'media', 'getMedia', {
92
+ isShorthandSelector: true,
93
+ } );
94
+
95
+ expect( deprecated ).toHaveBeenCalledWith( "'getMedia'", {
96
+ since: '6.9',
97
+ alternative: "the 'postType', 'attachment' entity",
98
+ } );
99
+ } );
100
+
101
+ it( 'should handle empty string parameters', () => {
102
+ logEntityDeprecation( '', '', '' );
103
+
104
+ expect( deprecated ).not.toHaveBeenCalled();
105
+ } );
106
+
107
+ it( 'should handle null parameters', () => {
108
+ logEntityDeprecation( null, null, null );
109
+
110
+ expect( deprecated ).not.toHaveBeenCalled();
111
+ } );
112
+
113
+ it( 'should handle undefined parameters', () => {
114
+ logEntityDeprecation( undefined, undefined, undefined );
115
+
116
+ expect( deprecated ).not.toHaveBeenCalled();
117
+ } );
118
+
119
+ it( 'should handle undefined options', () => {
120
+ logEntityDeprecation( 'root', 'media', 'getEntityRecord', undefined );
121
+
122
+ expect( deprecated ).toHaveBeenCalledWith(
123
+ "The 'root', 'media' entity (used via 'getEntityRecord')",
124
+ {
125
+ since: '6.9',
126
+ alternative: "the 'postType', 'attachment' entity",
127
+ }
128
+ );
129
+ } );
130
+ } );