From 5432049fcaacd4a626ea8ff981520515e29a5fae Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 30 Oct 2024 15:58:37 +0400 Subject: [PATCH] Core Data: Add the 'getEntitiesConfig' resolver (#65871) Co-authored-by: Mamaduka Co-authored-by: ellatrix Co-authored-by: youknowriad --- packages/core-data/src/actions.js | 20 +-- packages/core-data/src/entities.js | 64 --------- .../src/hooks/test/use-entity-record.js | 11 +- packages/core-data/src/resolvers.js | 86 ++++++++---- packages/core-data/src/test/actions.js | 63 ++++----- packages/core-data/src/test/entities.js | 80 ----------- packages/core-data/src/test/resolvers.js | 124 +++++++++++++----- 7 files changed, 189 insertions(+), 259 deletions(-) diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index e83ad02828cfe..13cbba39e1176 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -16,7 +16,7 @@ import deprecated from '@wordpress/deprecated'; */ import { getNestedValue, setNestedValue } from './utils'; import { receiveItems, removeItems, receiveQueriedItems } from './queried-data'; -import { getOrLoadEntitiesConfig, DEFAULT_ENTITY_KEY } from './entities'; +import { DEFAULT_ENTITY_KEY } from './entities'; import { createBatch } from './batch'; import { STORE_NAME } from './name'; import { getSyncProvider } from './sync'; @@ -285,8 +285,8 @@ export const deleteEntityRecord = query, { __unstableFetch = apiFetch, throwOnError = false } = {} ) => - async ( { dispatch } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); @@ -503,7 +503,7 @@ export const saveEntityRecord = } = {} ) => async ( { select, resolveSelect, dispatch } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); @@ -780,11 +780,11 @@ export const __experimentalBatch = */ export const saveEditedEntityRecord = ( kind, name, recordId, options ) => - async ( { select, dispatch } ) => { + async ( { select, dispatch, resolveSelect } ) => { if ( ! select.hasEditsForEntityRecord( kind, name, recordId ) ) { return; } - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); @@ -813,7 +813,7 @@ export const saveEditedEntityRecord = */ export const __experimentalSaveSpecifiedEntityEdits = ( kind, name, recordId, itemsToSave, options ) => - async ( { select, dispatch } ) => { + async ( { select, dispatch, resolveSelect } ) => { if ( ! select.hasEditsForEntityRecord( kind, name, recordId ) ) { return; } @@ -828,7 +828,7 @@ export const __experimentalSaveSpecifiedEntityEdits = setNestedValue( editsToSave, item, getNestedValue( edits, item ) ); } - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); @@ -973,8 +973,8 @@ export function receiveDefaultTemplateId( query, templateId ) { */ export const receiveRevisions = ( kind, name, recordKey, records, query, invalidateCache = false, meta ) => - async ( { dispatch } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.kind === kind && config.name === name ); diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index 8d09402087cf9..f73239e9afbbe 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -10,14 +10,7 @@ import apiFetch from '@wordpress/api-fetch'; import { __ } from '@wordpress/i18n'; import { RichTextData } from '@wordpress/rich-text'; -/** - * Internal dependencies - */ -import { addEntities } from './actions'; -import { getSyncProvider } from './sync'; - export const DEFAULT_ENTITY_KEY = 'id'; - const POST_RAW_ATTRIBUTES = [ 'title', 'excerpt', 'content' ]; export const rootEntitiesConfig = [ @@ -458,60 +451,3 @@ export const getMethodName = ( kind, name, prefix = 'get' ) => { const suffix = pascalCase( name ); return `${ prefix }${ kindPrefix }${ suffix }`; }; - -function registerSyncConfigs( configs ) { - configs.forEach( ( { syncObjectType, syncConfig } ) => { - getSyncProvider().register( syncObjectType, syncConfig ); - const editSyncConfig = { ...syncConfig }; - delete editSyncConfig.fetch; - getSyncProvider().register( syncObjectType + '--edit', editSyncConfig ); - } ); -} - -/** - * Loads the entities into the store. - * - * Note: The `name` argument is used for `root` entities requiring additional server data. - * - * @param {string} kind Kind - * @param {string} name Name - * @return {(thunkArgs: object) => Promise} Entities - */ -export const getOrLoadEntitiesConfig = - ( kind, name ) => - async ( { select, dispatch } ) => { - let configs = select.getEntitiesConfig( kind ); - const hasConfig = !! select.getEntityConfig( kind, name ); - - if ( configs?.length > 0 && hasConfig ) { - if ( window.__experimentalEnableSync ) { - if ( globalThis.IS_GUTENBERG_PLUGIN ) { - registerSyncConfigs( configs ); - } - } - - return configs; - } - - const loader = additionalEntityConfigLoaders.find( ( l ) => { - if ( ! name || ! l.name ) { - return l.kind === kind; - } - - return l.kind === kind && l.name === name; - } ); - if ( ! loader ) { - return []; - } - - configs = await loader.loadEntities(); - if ( window.__experimentalEnableSync ) { - if ( globalThis.IS_GUTENBERG_PLUGIN ) { - registerSyncConfigs( configs ); - } - } - - dispatch( addEntities( configs ) ); - - return configs; - }; diff --git a/packages/core-data/src/hooks/test/use-entity-record.js b/packages/core-data/src/hooks/test/use-entity-record.js index d83957abe06a1..ac2b547cd9c61 100644 --- a/packages/core-data/src/hooks/test/use-entity-record.js +++ b/packages/core-data/src/hooks/test/use-entity-record.js @@ -140,7 +140,14 @@ describe( 'useEntityRecord', () => { await act( () => new Promise( ( resolve ) => setTimeout( resolve, 0 ) ) ); - expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); + await waitFor( () => + expect( triggerFetch ).toHaveBeenCalledWith( { + path: '/wp/v2/widgets/1?context=edit', + parse: false, + } ) + ); + // Clear the fetch call history. + triggerFetch.mockReset(); rerender( ); @@ -157,6 +164,6 @@ describe( 'useEntityRecord', () => { await act( () => new Promise( ( resolve ) => setTimeout( resolve, 0 ) ) ); - expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); + expect( triggerFetch ).toHaveBeenCalledTimes( 0 ); } ); } ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index a5c33e18efbc6..d3980b89e8fc5 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -14,7 +14,7 @@ import apiFetch from '@wordpress/api-fetch'; * Internal dependencies */ import { STORE_NAME } from './name'; -import { getOrLoadEntitiesConfig, DEFAULT_ENTITY_KEY } from './entities'; +import { additionalEntityConfigLoaders, DEFAULT_ENTITY_KEY } from './entities'; import { forwardResolver, getNormalizedCommaSeparable, @@ -64,8 +64,8 @@ export const getCurrentUser = */ export const getEntityRecord = ( kind, name, key = '', query ) => - async ( { select, dispatch, registry } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { select, dispatch, registry, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind ); @@ -230,8 +230,8 @@ export const getEditedEntityRecord = forwardResolver( 'getEntityRecord' ); */ export const getEntityRecords = ( kind, name, query = {} ) => - async ( { dispatch, registry } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, registry, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind ); @@ -431,19 +431,36 @@ export const getEmbedPreview = */ export const canUser = ( requestedAction, resource, id ) => - async ( { dispatch, registry } ) => { + async ( { dispatch, registry, resolveSelect } ) => { if ( ! ALLOWED_RESOURCE_ACTIONS.includes( requestedAction ) ) { throw new Error( `'${ requestedAction }' is not a valid action.` ); } + const { hasStartedResolution } = registry.select( STORE_NAME ); + + // Prevent resolving the same resource twice. + for ( const relatedAction of ALLOWED_RESOURCE_ACTIONS ) { + if ( relatedAction === requestedAction ) { + continue; + } + const isAlreadyResolving = hasStartedResolution( 'canUser', [ + relatedAction, + resource, + id, + ] ); + if ( isAlreadyResolving ) { + return; + } + } + let resourcePath = null; if ( typeof resource === 'object' ) { if ( ! resource.kind || ! resource.name ) { throw new Error( 'The entity resource object is not valid.' ); } - const configs = await dispatch( - getOrLoadEntitiesConfig( resource.kind, resource.name ) + const configs = await resolveSelect.getEntitiesConfig( + resource.kind ); const entityConfig = configs.find( ( config ) => @@ -460,23 +477,6 @@ export const canUser = resourcePath = `/wp/v2/${ resource }` + ( id ? '/' + id : '' ); } - const { hasStartedResolution } = registry.select( STORE_NAME ); - - // Prevent resolving the same resource twice. - for ( const relatedAction of ALLOWED_RESOURCE_ACTIONS ) { - if ( relatedAction === requestedAction ) { - continue; - } - const isAlreadyResolving = hasStartedResolution( 'canUser', [ - relatedAction, - resource, - id, - ] ); - if ( isAlreadyResolving ) { - return; - } - } - let response; try { response = await apiFetch( { @@ -823,8 +823,8 @@ export const getDefaultTemplateId = */ export const getRevisions = ( kind, name, recordKey, query = {} ) => - async ( { dispatch, registry } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, registry, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind ); @@ -944,8 +944,8 @@ getRevisions.shouldInvalidate = ( action, kind, name, recordKey ) => */ export const getRevision = ( kind, name, recordKey, revisionKey, query ) => - async ( { dispatch } ) => { - const configs = await dispatch( getOrLoadEntitiesConfig( kind, name ) ); + async ( { dispatch, resolveSelect } ) => { + const configs = await resolveSelect.getEntitiesConfig( kind ); const entityConfig = configs.find( ( config ) => config.name === name && config.kind === kind ); @@ -1017,3 +1017,31 @@ export const getRegisteredPostMeta = ); } }; + +/** + * Requests entity configs for the given kind from the REST API. + * + * @param {string} kind Entity kind. + */ +export const getEntitiesConfig = + ( kind ) => + async ( { dispatch } ) => { + const loader = additionalEntityConfigLoaders.find( + ( l ) => l.kind === kind + ); + + if ( ! loader ) { + return; + } + + try { + const configs = await loader.loadEntities(); + if ( ! configs.length ) { + return; + } + + dispatch.addEntities( configs ); + } catch { + // Do nothing if the request comes back with an API error. + } + }; diff --git a/packages/core-data/src/test/actions.js b/packages/core-data/src/test/actions.js index c00c01fbb77a1..8438d03293c16 100644 --- a/packages/core-data/src/test/actions.js +++ b/packages/core-data/src/test/actions.js @@ -68,8 +68,7 @@ describe( 'deleteEntityRecord', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response apiFetch.mockImplementation( () => deletedRecord ); @@ -78,7 +77,7 @@ describe( 'deleteEntityRecord', () => { 'postType', 'post', deletedRecord.id - )( { dispatch } ); + )( { dispatch, resolveSelect } ); expect( apiFetch ).toHaveBeenCalledTimes( 1 ); expect( apiFetch ).toHaveBeenCalledWith( { @@ -86,7 +85,7 @@ describe( 'deleteEntityRecord', () => { method: 'DELETE', } ); - expect( dispatch ).toHaveBeenCalledTimes( 4 ); + expect( dispatch ).toHaveBeenCalledTimes( 3 ); expect( dispatch ).toHaveBeenCalledWith( { type: 'DELETE_ENTITY_RECORD_START', kind: 'postType', @@ -120,8 +119,7 @@ describe( 'deleteEntityRecord', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( entities ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) }; // Provide response apiFetch.mockImplementation( () => { @@ -137,7 +135,7 @@ describe( 'deleteEntityRecord', () => { { throwOnError: true, } - )( { dispatch } ) + )( { dispatch, resolveSelect } ) ).rejects.toEqual( new Error( 'API error' ) ); } ); @@ -151,8 +149,7 @@ describe( 'deleteEntityRecord', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( entities ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) }; // Provide response apiFetch.mockImplementation( () => { @@ -168,7 +165,7 @@ describe( 'deleteEntityRecord', () => { { throwOnError: false, } - )( { dispatch } ) + )( { dispatch, resolveSelect } ) ).resolves.toBe( false ); } ); } ); @@ -195,8 +192,7 @@ describe( 'saveEditedEntityRecord', () => { const dispatch = Object.assign( jest.fn(), { saveEntityRecord: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response const updatedRecord = { ...item, menu: 10 }; @@ -208,7 +204,7 @@ describe( 'saveEditedEntityRecord', () => { 'root', 'menuItem', 1 - )( { dispatch, select } ); + )( { dispatch, select, resolveSelect } ); expect( dispatch.saveEntityRecord ).toHaveBeenCalledWith( 'root', @@ -236,8 +232,7 @@ describe( 'saveEditedEntityRecord', () => { const dispatch = Object.assign( jest.fn(), { saveEntityRecord: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response const updatedRecord = { ...item, menu: 10 }; @@ -249,7 +244,7 @@ describe( 'saveEditedEntityRecord', () => { 'root', 'menuLocation', 'primary' - )( { dispatch, select } ); + )( { dispatch, select, resolveSelect } ); expect( dispatch.saveEntityRecord ).toHaveBeenCalledWith( 'root', @@ -280,9 +275,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => post, }; - - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response const updatedRecord = { ...post, id: 10 }; @@ -294,7 +287,7 @@ describe( 'saveEntityRecord', () => { 'postType', 'post', post - )( { select, dispatch } ); + )( { select, dispatch, resolveSelect } ); expect( apiFetch ).toHaveBeenCalledTimes( 1 ); expect( apiFetch ).toHaveBeenCalledWith( { @@ -303,7 +296,7 @@ describe( 'saveEntityRecord', () => { data: post, } ); - expect( dispatch ).toHaveBeenCalledTimes( 3 ); + expect( dispatch ).toHaveBeenCalledTimes( 2 ); expect( dispatch ).toHaveBeenCalledWith( { type: 'SAVE_ENTITY_RECORD_START', kind: 'postType', @@ -347,9 +340,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => post, }; - - // Provide entities - dispatch.mockReturnValueOnce( entities ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) }; // Provide response apiFetch.mockImplementation( () => { @@ -359,7 +350,7 @@ describe( 'saveEntityRecord', () => { await expect( saveEntityRecord( 'postType', 'post', post, { throwOnError: true, - } )( { select, dispatch } ) + } )( { select, dispatch, resolveSelect } ) ).rejects.toEqual( new Error( 'API error' ) ); } ); @@ -371,9 +362,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => post, }; - - // Provide entities - dispatch.mockReturnValueOnce( entities ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => entities ) }; // Provide response apiFetch.mockImplementation( () => { @@ -383,7 +372,7 @@ describe( 'saveEntityRecord', () => { await expect( saveEntityRecord( 'postType', 'post', post, { throwOnError: false, - } )( { select, dispatch } ) + } )( { select, dispatch, resolveSelect } ) ).resolves.toEqual( undefined ); } ); @@ -395,9 +384,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => post, }; - - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response const updatedRecord = { ...post, id: 10 }; @@ -409,7 +396,7 @@ describe( 'saveEntityRecord', () => { 'postType', 'post', post - )( { select, dispatch } ); + )( { select, dispatch, resolveSelect } ); expect( apiFetch ).toHaveBeenCalledTimes( 1 ); expect( apiFetch ).toHaveBeenCalledWith( { @@ -418,7 +405,7 @@ describe( 'saveEntityRecord', () => { data: post, } ); - expect( dispatch ).toHaveBeenCalledTimes( 3 ); + expect( dispatch ).toHaveBeenCalledTimes( 2 ); expect( dispatch ).toHaveBeenCalledWith( { type: 'SAVE_ENTITY_RECORD_START', kind: 'postType', @@ -467,9 +454,7 @@ describe( 'saveEntityRecord', () => { const select = { getRawEntityRecord: () => ( {} ), }; - - // Provide entities - dispatch.mockReturnValueOnce( configs ); + const resolveSelect = { getEntitiesConfig: jest.fn( () => configs ) }; // Provide response apiFetch.mockImplementation( () => postType ); @@ -478,7 +463,7 @@ describe( 'saveEntityRecord', () => { 'root', 'postType', postType - )( { select, dispatch } ); + )( { select, dispatch, resolveSelect } ); expect( apiFetch ).toHaveBeenCalledTimes( 1 ); expect( apiFetch ).toHaveBeenCalledWith( { @@ -487,7 +472,7 @@ describe( 'saveEntityRecord', () => { data: postType, } ); - expect( dispatch ).toHaveBeenCalledTimes( 3 ); + expect( dispatch ).toHaveBeenCalledTimes( 2 ); expect( dispatch ).toHaveBeenCalledWith( { type: 'SAVE_ENTITY_RECORD_START', kind: 'root', diff --git a/packages/core-data/src/test/entities.js b/packages/core-data/src/test/entities.js index 27b3d56e76865..294c843fae117 100644 --- a/packages/core-data/src/test/entities.js +++ b/packages/core-data/src/test/entities.js @@ -1,16 +1,9 @@ -/** - * WordPress dependencies - */ -import triggerFetch from '@wordpress/api-fetch'; -jest.mock( '@wordpress/api-fetch' ); - /** * Internal dependencies */ import { getMethodName, rootEntitiesConfig, - getOrLoadEntitiesConfig, prePersistPostType, } from '../entities'; @@ -43,79 +36,6 @@ describe( 'getMethodName', () => { } ); } ); -describe( 'getKindEntities', () => { - beforeEach( async () => { - triggerFetch.mockReset(); - } ); - - it( 'shouldn’t do anything if the entities have already been resolved', async () => { - const dispatch = jest.fn(); - const select = { - getEntitiesConfig: jest.fn( () => entities ), - getEntityConfig: jest.fn( () => ( { - kind: 'postType', - name: 'post', - } ) ), - }; - const entities = [ { kind: 'postType' } ]; - await getOrLoadEntitiesConfig( - 'postType', - 'post' - )( { dispatch, select } ); - expect( dispatch ).not.toHaveBeenCalled(); - } ); - - it( 'shouldn’t do anything if there no defined kind config', async () => { - const dispatch = jest.fn(); - const select = { - getEntitiesConfig: jest.fn( () => [] ), - getEntityConfig: jest.fn( () => undefined ), - }; - await getOrLoadEntitiesConfig( - 'unknownKind', - undefined - )( { dispatch, select } ); - expect( dispatch ).not.toHaveBeenCalled(); - } ); - - it( 'should fetch and add the entities', async () => { - const fetchedEntities = [ - { - rest_base: 'posts', - labels: { - singular_name: 'post', - }, - supports: { - revisions: true, - }, - }, - ]; - const dispatch = jest.fn(); - const select = { - getEntitiesConfig: jest.fn( () => [] ), - getEntityConfig: jest.fn( () => undefined ), - }; - triggerFetch.mockImplementation( () => fetchedEntities ); - - await getOrLoadEntitiesConfig( - 'postType', - 'post' - )( { dispatch, select } ); - expect( dispatch ).toHaveBeenCalledTimes( 1 ); - expect( dispatch.mock.calls[ 0 ][ 0 ].type ).toBe( 'ADD_ENTITIES' ); - expect( dispatch.mock.calls[ 0 ][ 0 ].entities.length ).toBe( 1 ); - expect( dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].baseURL ).toBe( - '/wp/v2/posts' - ); - expect( - dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].getRevisionsUrl( 1 ) - ).toBe( '/wp/v2/posts/1/revisions' ); - expect( - dispatch.mock.calls[ 0 ][ 0 ].entities[ 0 ].getRevisionsUrl( 1, 2 ) - ).toBe( '/wp/v2/posts/1/revisions/2' ); - } ); -} ); - describe( 'prePersistPostType', () => { it( 'set the status to draft and empty the title when saving auto-draft posts', () => { let record = { diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js index f15bee3b3c2b9..472056a4dfdc9 100644 --- a/packages/core-data/src/test/resolvers.js +++ b/packages/core-data/src/test/resolvers.js @@ -29,6 +29,7 @@ describe( 'getEntityRecord', () => { }, ]; const registry = { batch: ( callback ) => callback() }; + const resolveSelect = { getEntitiesConfig: jest.fn( () => ENTITIES ) }; let dispatch; beforeEach( async () => { @@ -43,9 +44,6 @@ describe( 'getEntityRecord', () => { } ); it( 'yields with requested post type', async () => { - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); - // Provide response triggerFetch.mockImplementation( () => POST_TYPE_RESPONSE ); @@ -53,7 +51,7 @@ describe( 'getEntityRecord', () => { 'root', 'postType', 'post' - )( { dispatch, registry } ); + )( { dispatch, registry, resolveSelect } ); // Fetch request should have been issued. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -84,8 +82,6 @@ describe( 'getEntityRecord', () => { const select = { hasEntityRecords: jest.fn( () => {} ), }; - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); // Provide response triggerFetch.mockImplementation( () => POST_TYPE_RESPONSE ); @@ -95,7 +91,7 @@ describe( 'getEntityRecord', () => { 'postType', 'post', query - )( { dispatch, select, registry } ); + )( { dispatch, select, registry, resolveSelect } ); // Trigger apiFetch, test that the query is present in the url. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -141,6 +137,7 @@ describe( 'getEntityRecords', () => { }, ]; const registry = { batch: ( callback ) => callback() }; + const resolveSelect = { getEntitiesConfig: jest.fn( () => ENTITIES ) }; beforeEach( async () => { triggerFetch.mockReset(); @@ -152,13 +149,14 @@ describe( 'getEntityRecords', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); // Provide response triggerFetch.mockImplementation( () => POST_TYPES ); - await getEntityRecords( 'root', 'postType' )( { dispatch, registry } ); + await getEntityRecords( + 'root', + 'postType' + )( { dispatch, registry, resolveSelect } ); // Fetch request should have been issued. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -183,13 +181,14 @@ describe( 'getEntityRecords', () => { __unstableAcquireStoreLock: jest.fn(), __unstableReleaseStoreLock: jest.fn(), } ); - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); // Provide response triggerFetch.mockImplementation( () => POST_TYPES ); - await getEntityRecords( 'root', 'postType' )( { dispatch, registry } ); + await getEntityRecords( + 'root', + 'postType' + )( { dispatch, registry, resolveSelect } ); // Fetch request should have been issued. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -216,13 +215,14 @@ describe( 'getEntityRecords', () => { __unstableReleaseStoreLock: jest.fn(), finishResolutions, } ); - // Provide entities - dispatch.mockReturnValueOnce( ENTITIES ); // Provide response triggerFetch.mockImplementation( () => POST_TYPES ); - await getEntityRecords( 'root', 'postType' )( { dispatch, registry } ); + await getEntityRecords( + 'root', + 'postType' + )( { dispatch, registry, resolveSelect } ); // Fetch request should have been issued. expect( triggerFetch ).toHaveBeenCalledWith( { @@ -290,6 +290,7 @@ describe( 'canUser', () => { baseURLParams: { context: 'edit' }, }, ]; + const resolveSelect = { getEntitiesConfig: jest.fn( () => ENTITIES ) }; let dispatch, registry; beforeEach( async () => { @@ -303,7 +304,6 @@ describe( 'canUser', () => { receiveUserPermission: jest.fn(), finishResolution: jest.fn(), } ); - dispatch.mockReturnValue( ENTITIES ); triggerFetch.mockReset(); } ); @@ -312,10 +312,14 @@ describe( 'canUser', () => { Promise.reject( { status: 404 } ) ); - await canUser( 'create', 'media' )( { dispatch, registry } ); + await canUser( + 'create', + 'media' + )( { dispatch, registry, resolveSelect } ); await canUser( 'create', { kind: 'root', name: 'media' } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledWith( { @@ -332,6 +336,7 @@ describe( 'canUser', () => { canUser( 'create', { name: 'wp_block' } )( { dispatch, registry, + resolveSelect, } ) ).rejects.toThrow( 'The entity resource object is not valid.' ); } ); @@ -341,7 +346,10 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'GET' ] ] ), } ) ); - await canUser( 'create', 'media' )( { dispatch, registry } ); + await canUser( + 'create', + 'media' + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledWith( { path: '/wp/v2/media', @@ -363,6 +371,7 @@ describe( 'canUser', () => { await canUser( 'create', { kind: 'root', name: 'media' } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledWith( { @@ -382,7 +391,10 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET, PUT, DELETE' ] ] ), } ) ); - await canUser( 'create', 'media' )( { dispatch, registry } ); + await canUser( + 'create', + 'media' + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledWith( { path: '/wp/v2/media', @@ -404,6 +416,7 @@ describe( 'canUser', () => { await canUser( 'create', { kind: 'root', name: 'media' } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledWith( { @@ -423,7 +436,11 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET, PUT, DELETE' ] ] ), } ) ); - await canUser( 'create', 'blocks', 123 )( { dispatch, registry } ); + await canUser( + 'create', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledWith( { path: '/wp/v2/blocks/123', @@ -449,6 +466,7 @@ describe( 'canUser', () => { } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledWith( { @@ -475,8 +493,14 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET' ] ] ), } ) ); - await canUser( 'create', 'blocks' )( { dispatch, registry } ); - await canUser( 'read', 'blocks' )( { dispatch, registry } ); + await canUser( + 'create', + 'blocks' + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'read', + 'blocks' + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); @@ -508,6 +532,7 @@ describe( 'canUser', () => { } )( { dispatch, registry, + resolveSelect, } ); await canUser( 'read', { kind: 'postType', @@ -515,6 +540,7 @@ describe( 'canUser', () => { } )( { dispatch, registry, + resolveSelect, } ); expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); @@ -541,10 +567,22 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET' ] ] ), } ) ); - await canUser( 'create', 'blocks' )( { dispatch, registry } ); - await canUser( 'read', 'blocks' )( { dispatch, registry } ); - await canUser( 'update', 'blocks' )( { dispatch, registry } ); - await canUser( 'delete', 'blocks' )( { dispatch, registry } ); + await canUser( + 'create', + 'blocks' + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'read', + 'blocks' + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'update', + 'blocks' + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'delete', + 'blocks' + )( { dispatch, registry, resolveSelect } ); expect( dispatch.receiveUserPermission ).toHaveBeenCalledWith( 'create/blocks', @@ -576,10 +614,26 @@ describe( 'canUser', () => { headers: new Map( [ [ 'allow', 'POST, GET, PUT, DELETE' ] ] ), } ) ); - await canUser( 'create', 'blocks', 123 )( { dispatch, registry } ); - await canUser( 'read', 'blocks', 123 )( { dispatch, registry } ); - await canUser( 'update', 'blocks', 123 )( { dispatch, registry } ); - await canUser( 'delete', 'blocks', 123 )( { dispatch, registry } ); + await canUser( + 'create', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'read', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'update', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); + await canUser( + 'delete', + 'blocks', + 123 + )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledTimes( 1 ); @@ -617,22 +671,22 @@ describe( 'canUser', () => { kind: 'postType', name: 'wp_block', id: 123, - } )( { dispatch, registry } ); + } )( { dispatch, registry, resolveSelect } ); await canUser( 'read', { kind: 'postType', name: 'wp_block', id: 123, - } )( { dispatch, registry } ); + } )( { dispatch, registry, resolveSelect } ); await canUser( 'update', { kind: 'postType', name: 'wp_block', id: 123, - } )( { dispatch, registry } ); + } )( { dispatch, registry, resolveSelect } ); await canUser( 'delete', { kind: 'postType', name: 'wp_block', id: 123, - } )( { dispatch, registry } ); + } )( { dispatch, registry, resolveSelect } ); expect( triggerFetch ).toHaveBeenCalledTimes( 1 );