From 40459057a0de958dcf36c4af31b192a0f73ff9e0 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Fri, 20 Jul 2018 17:16:50 -0400 Subject: [PATCH] Core Data: Partially reimplement resolvers as controls --- packages/core-data/src/actions.js | 16 ++++++++++++++++ packages/core-data/src/controls.js | 16 ++++++++++++++++ packages/core-data/src/index.js | 2 ++ packages/core-data/src/resolvers.js | 13 +++++++------ packages/core-data/src/test/resolvers.js | 22 +++++++++++----------- 5 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 packages/core-data/src/controls.js diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 31107d8daef10..3f550becca66e 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -3,6 +3,22 @@ */ import { castArray } from 'lodash'; +/** + * Given an apiFetch payload, returns an action object used in signalling that + * an API request should be issued. This can be used in tandem with the data + * module's `controls` option for asynchronous API request logic flows. + * + * @param {Object} options apiFetch options payload. + * + * @return {Object} Action object. + */ +export function fetchFromAPI( options ) { + return { + type: 'FETCH_FROM_API', + ...options, + }; +} + /** * Returns an action object used in signalling that terms have been received * for a given taxonomy. diff --git a/packages/core-data/src/controls.js b/packages/core-data/src/controls.js new file mode 100644 index 0000000000000..981533d5b101e --- /dev/null +++ b/packages/core-data/src/controls.js @@ -0,0 +1,16 @@ +/** + * WordPress dependencies + */ +import apiFetch from '@wordpress/api-fetch'; + +/** + * Given an action object, triggers an API request to retrieve the result from + * the given action path. + * + * @param {Object} action Fetch action object. + * + * @return {Promise} Fetch promise. + */ +export function FETCH_FROM_API( action ) { + return apiFetch( { path: action.path } ); +} diff --git a/packages/core-data/src/index.js b/packages/core-data/src/index.js index 31fe114746930..ae1d4a2adece5 100644 --- a/packages/core-data/src/index.js +++ b/packages/core-data/src/index.js @@ -10,6 +10,7 @@ import reducer from './reducer'; import * as selectors from './selectors'; import * as actions from './actions'; import * as resolvers from './resolvers'; +import * as controls from './controls'; import { defaultEntities, getMethodName } from './entities'; import { REDUCER_KEY } from './name'; @@ -26,6 +27,7 @@ const entitySelectors = createEntityRecordGetter( selectors ); const store = registerStore( REDUCER_KEY, { reducer, actions, + controls, selectors: { ...selectors, ...entitySelectors }, resolvers: { ...resolvers, ...entityResolvers }, } ); diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index a105997bfedd6..a267257012eaf 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -12,6 +12,7 @@ import apiFetch from '@wordpress/api-fetch'; * Internal dependencies */ import { + fetchFromAPI, receiveTerms, receiveUserQuery, receiveEntityRecords, @@ -23,16 +24,16 @@ import { getKindEntities } from './entities'; * Requests categories from the REST API, yielding action objects on request * progress. */ -export async function* getCategories() { - const categories = await apiFetch( { path: '/wp/v2/categories?per_page=-1' } ); +export function* getCategories() { + const categories = yield fetchFromAPI( { path: '/wp/v2/categories?per_page=-1' } ); yield receiveTerms( 'categories', categories ); } /** * Requests authors from the REST API. */ -export async function* getAuthors() { - const users = await apiFetch( { path: '/wp/v2/users/?who=authors&per_page=-1' } ); +export function* getAuthors() { + const users = yield fetchFromAPI( { path: '/wp/v2/users/?who=authors&per_page=-1' } ); yield receiveUserQuery( 'authors', users ); } @@ -74,7 +75,7 @@ export async function* getEntityRecords( state, kind, name ) { /** * Requests theme supports data from the index. */ -export async function* getThemeSupports() { - const index = await apiFetch( { path: '/' } ); +export function* getThemeSupports() { + const index = yield fetchFromAPI( { path: '/' } ); yield receiveThemeSupportsFromIndex( index ); } diff --git a/packages/core-data/src/test/resolvers.js b/packages/core-data/src/test/resolvers.js index 29f0cf68bf271..5d31a137355e4 100644 --- a/packages/core-data/src/test/resolvers.js +++ b/packages/core-data/src/test/resolvers.js @@ -7,25 +7,25 @@ import apiFetch from '@wordpress/api-fetch'; * Internal dependencies */ import { getCategories, getEntityRecord, getEntityRecords } from '../resolvers'; -import { receiveTerms, receiveEntityRecords, addEntities } from '../actions'; +import { + fetchFromAPI, + receiveTerms, + receiveEntityRecords, + addEntities, +} from '../actions'; jest.mock( '@wordpress/api-fetch' ); describe( 'getCategories', () => { const CATEGORIES = [ { id: 1 } ]; - beforeAll( () => { - apiFetch.mockImplementation( ( options ) => { - if ( options.path === '/wp/v2/categories?per_page=-1' ) { - return Promise.resolve( CATEGORIES ); - } - } ); - } ); - it( 'yields with requested terms', async () => { const fulfillment = getCategories(); - const received = ( await fulfillment.next() ).value; - expect( received ).toEqual( receiveTerms( 'categories', CATEGORIES ) ); + let yielded; + yielded = fulfillment.next().value; + expect( yielded.type ).toBe( fetchFromAPI().type ); + yielded = fulfillment.next( CATEGORIES ).value; + expect( yielded ).toEqual( receiveTerms( 'categories', CATEGORIES ) ); } ); } );