Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new @wordpress/api-request package #7018

Merged
merged 9 commits into from
Jun 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ module.exports = {
selector: 'ImportDeclaration[source.value=/^@wordpress\\u002F.+\\u002F/]',
message: 'Path access on WordPress dependencies is not allowed.',
},
{
selector: 'ImportDeclaration[source.value=/^api-request$/]',
message: 'Use @wordpress/api-request as import path instead.',
},
{
selector: 'ImportDeclaration[source.value=/^blob$/]',
message: 'Use @wordpress/blob as import path instead.',
Expand Down
7 changes: 6 additions & 1 deletion components/higher-order/with-api-data/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
import memoize from 'memize';
import { mapKeys } from 'lodash';

/**
* WordPress dependencies
*/
import apiRequest from '@wordpress/api-request';

export const getStablePath = memoize( ( path ) => {
const [ base, query ] = path.split( '?' );
if ( ! query ) {
Expand Down Expand Up @@ -75,7 +80,7 @@ export function getCachedResponse( request ) {
}

export function getResponseFromNetwork( request ) {
const promise = wp.apiRequest( request )
const promise = apiRequest( request )
.then( ( body, status, xhr ) => {
return {
body,
Expand Down
27 changes: 15 additions & 12 deletions components/higher-order/with-api-data/test/request.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* WordPress dependencies
*/
import apiRequest from '@wordpress/api-request';

/**
* Internal dependencies
*/
Expand Down Expand Up @@ -25,15 +30,13 @@ describe( 'request', () => {
),
};

let wpApiRequest;
beforeEach( () => {
getStablePath.clear();
for ( const key in cache ) {
delete cache[ key ];
}

wpApiRequest = wp.apiRequest;
wp.apiRequest = jest.fn( () => ( {
apiRequest.mockReturnValue = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part becomes a bit magic since this module is being mocked in the setup file. Have you tried to use Manual Mocks using __mocks__ folder? If you do so you need to explicitly call jest.mock('./moduleName') in your test file which is easier to follow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried jest.mock('./moduleName', () => {}) but It didn't work. I'll take a look at the manual mocks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What seems to work for me is I put a __mocks__/moduleName within the same path as the test (so test/__mocks__/moduleName/index.js) and the mock is in the file then anything importing that module being tested will use the mock instead. Seems to work well for me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that important at the moment, to be honest. Just wanted to make sure you are aware of other options. We can refactor later.

// jQuery.Deferred aren't true promises, particularly in their
// treatment of resolved arguments. $.ajax will spread resolved
// arguments, but this is not valid for Promise (only single).
Expand All @@ -43,11 +46,7 @@ describe( 'request', () => {
'success',
xhr
) ),
} ) );
} );

afterEach( () => {
wp.apiRequest = wpApiRequest;
};
} );

describe( 'getResponseHeaders()', () => {
Expand Down Expand Up @@ -97,7 +96,7 @@ describe( 'request', () => {
} );

return awaitResponse.then( ( data ) => {
expect( wp.apiRequest ).toHaveBeenCalled();
expect( apiRequest ).toHaveBeenCalled();
expect( data ).toEqual( actualResponse );
} );
} );
Expand Down Expand Up @@ -129,6 +128,10 @@ describe( 'request', () => {
} );

describe( 'request()', () => {
beforeEach( () => {
apiRequest.mockClear();
} );

it( 'should try from cache for GET', () => {
cache[ getStablePath( '/wp?c=5&a=5&b=5' ) ] = actualResponse;
const awaitResponse = request( {
Expand All @@ -137,7 +140,7 @@ describe( 'request', () => {
} );

return awaitResponse.then( ( data ) => {
expect( wp.apiRequest ).not.toHaveBeenCalled();
expect( apiRequest ).not.toHaveBeenCalled();
expect( data ).toEqual( actualResponse );
} );
} );
Expand All @@ -150,7 +153,7 @@ describe( 'request', () => {
} );

return awaitResponse.then( ( data ) => {
expect( wp.apiRequest ).toHaveBeenCalled();
expect( apiRequest ).toHaveBeenCalled();
expect( data ).toEqual( actualResponse );
} );
} );
Expand All @@ -162,7 +165,7 @@ describe( 'request', () => {
} );

return awaitResponse.then( ( data ) => {
expect( wp.apiRequest ).toHaveBeenCalled();
expect( apiRequest ).toHaveBeenCalled();
expect( data ).toEqual( actualResponse );
} );
} );
Expand Down
3 changes: 2 additions & 1 deletion core-blocks/embed/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
BlockAlignmentToolbar,
RichText,
} from '@wordpress/editor';
import apiRequest from '@wordpress/api-request';

/**
* Internal dependencies
Expand All @@ -30,7 +31,7 @@ import './editor.scss';
const HOSTS_NO_PREVIEWS = [ 'facebook.com' ];

// Caches the embed API calls, so if blocks get transformed, or deleted and added again, we don't spam the API.
const wpEmbedAPI = memoize( ( url ) => wp.apiRequest( { path: `/oembed/1.0/proxy?${ stringify( { url } ) }` } ) );
const wpEmbedAPI = memoize( ( url ) => apiRequest( { path: `/oembed/1.0/proxy?${ stringify( { url } ) }` } ) );

const matchesPatterns = ( url, patterns = [] ) => {
return patterns.some( ( pattern ) => {
Expand Down
10 changes: 0 additions & 10 deletions edit-post/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ import store from './store';
import { initializeMetaBoxState } from './store/actions';
import Editor from './editor';

/**
* Configure heartbeat to refresh the wp-api nonce, keeping the editor
* authorization intact.
*/
window.jQuery( document ).on( 'heartbeat-tick', ( event, response ) => {
if ( response[ 'rest-nonce' ] ) {
window.wpApiSettings.nonce = response[ 'rest-nonce' ];
}
} );

/**
* Reinitializes the editor after the user chooses to reboot the editor after
* an unhandled error occurs, replacing previously mounted editor element using
Expand Down
3 changes: 2 additions & 1 deletion edit-post/store/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { reduce, some } from 'lodash';
import { select, subscribe } from '@wordpress/data';
import { speak } from '@wordpress/a11y';
import { __ } from '@wordpress/i18n';
import apiRequest from '@wordpress/api-request';

/**
* Internal dependencies
Expand Down Expand Up @@ -98,7 +99,7 @@ const effects = {
additionalData.forEach( ( [ key, value ] ) => formData.append( key, value ) );

// Save the metaboxes
wp.apiRequest( {
apiRequest( {
url: window._wpMetaBoxUrl,
method: 'POST',
processData: false,
Expand Down
7 changes: 6 additions & 1 deletion editor/components/autocompleters/user.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* WordPress dependencies
*/
import apiRequest from '@wordpress/api-request';

/**
* A user mentions completer.
*
Expand All @@ -12,7 +17,7 @@ export default {
if ( search ) {
payload = '?search=' + encodeURIComponent( search );
}
return wp.apiRequest( { path: '/wp/v2/users' + payload } );
return apiRequest( { path: '/wp/v2/users' + payload } );
},
isDebounced: true,
getOptionKeywords( user ) {
Expand Down
7 changes: 4 additions & 3 deletions editor/components/post-taxonomies/flat-term-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { __, _x, sprintf } from '@wordpress/i18n';
import { Component, compose } from '@wordpress/element';
import { FormTokenField, withAPIData } from '@wordpress/components';
import { withSelect, withDispatch } from '@wordpress/data';
import apiRequest from '@wordpress/api-request';

/**
* Module constants
Expand Down Expand Up @@ -75,7 +76,7 @@ class FlatTermSelector extends Component {
fetchTerms( params = {} ) {
const query = { ...DEFAULT_QUERY, ...params };
const basePath = wp.api.getTaxonomyRoute( this.props.slug );
const request = wp.apiRequest( { path: `/wp/v2/${ basePath }?${ stringify( query ) }` } );
const request = apiRequest( { path: `/wp/v2/${ basePath }?${ stringify( query ) }` } );
request.then( ( terms ) => {
this.setState( ( state ) => ( {
availableTerms: state.availableTerms.concat(
Expand Down Expand Up @@ -106,15 +107,15 @@ class FlatTermSelector extends Component {
return new Promise( ( resolve, reject ) => {
// Tries to create a term or fetch it if it already exists
const basePath = wp.api.getTaxonomyRoute( this.props.slug );
wp.apiRequest( {
apiRequest( {
path: `/wp/v2/${ basePath }`,
method: 'POST',
data: { name: termName },
} ).then( resolve, ( xhr ) => {
const errorCode = xhr.responseJSON && xhr.responseJSON.code;
if ( errorCode === 'term_exists' ) {
// search the new category created since last fetch
this.addRequest = wp.apiRequest( {
this.addRequest = apiRequest( {
path: `/wp/v2/${ basePath }?${ stringify( { ...DEFAULT_QUERY, search: termName } ) }`,
} );
return this.addRequest.then( ( searchResult ) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Component, compose } from '@wordpress/element';
import { TreeSelect, withAPIData, withInstanceId, withSpokenMessages, Button } from '@wordpress/components';
import { buildTermsTree } from '@wordpress/utils';
import { withSelect, withDispatch } from '@wordpress/data';
import apiRequest from '@wordpress/api-request';

/**
* Module Constants
Expand Down Expand Up @@ -103,7 +104,7 @@ class HierarchicalTermSelector extends Component {
} );
// Tries to create a term or fetch it if it already exists
const basePath = wp.api.getTaxonomyRoute( this.props.slug );
this.addRequest = wp.apiRequest( {
this.addRequest = apiRequest( {
path: `/wp/v2/${ basePath }`,
method: 'POST',
data: {
Expand All @@ -116,7 +117,7 @@ class HierarchicalTermSelector extends Component {
const errorCode = xhr.responseJSON && xhr.responseJSON.code;
if ( errorCode === 'term_exists' ) {
// search the new category created since last fetch
this.addRequest = wp.apiRequest( {
this.addRequest = apiRequest( {
path: `/wp/v2/${ basePath }?${ stringify( { ...DEFAULT_QUERY, parent: formParent || 0, search: formName } ) }`,
} );
return this.addRequest.then( ( searchResult ) => {
Expand Down Expand Up @@ -161,7 +162,7 @@ class HierarchicalTermSelector extends Component {

componentDidMount() {
const basePath = wp.api.getTaxonomyRoute( this.props.slug );
this.fetchRequest = wp.apiRequest( { path: `/wp/v2/${ basePath }?${ stringify( DEFAULT_QUERY ) }` } );
this.fetchRequest = apiRequest( { path: `/wp/v2/${ basePath }?${ stringify( DEFAULT_QUERY ) }` } );
this.fetchRequest.then(
( terms ) => { // resolve
const availableTermsTree = buildTermsTree( terms );
Expand Down
3 changes: 2 additions & 1 deletion editor/components/url-input/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { __, sprintf, _n } from '@wordpress/i18n';
import { Component, Fragment } from '@wordpress/element';
import { keycodes, decodeEntities } from '@wordpress/utils';
import { Spinner, withInstanceId, withSpokenMessages, Popover } from '@wordpress/components';
import apiRequest from '@wordpress/api-request';

const { UP, DOWN, ENTER } = keycodes;

Expand Down Expand Up @@ -68,7 +69,7 @@ class UrlInput extends Component {
selectedSuggestion: null,
loading: true,
} );
this.suggestionsRequest = wp.apiRequest( {
this.suggestionsRequest = apiRequest( {
path: `/wp/v2/posts?${ stringify( {
search: value,
per_page: 20,
Expand Down
17 changes: 9 additions & 8 deletions editor/store/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { speak } from '@wordpress/a11y';
import apiRequest from '@wordpress/api-request';

/**
* Internal dependencies
Expand Down Expand Up @@ -130,7 +131,7 @@ export default {
parent: post.id,
};

request = wp.apiRequest( {
request = apiRequest( {
path: `/wp/v2/${ basePath }/${ post.id }/autosaves`,
method: 'POST',
data: toSend,
Expand All @@ -145,7 +146,7 @@ export default {
dispatch( removeNotice( SAVE_POST_NOTICE_ID ) );
dispatch( removeNotice( AUTOSAVE_POST_NOTICE_ID ) );

request = wp.apiRequest( {
request = apiRequest( {
path: `/wp/v2/${ basePath }/${ post.id }`,
method: 'PUT',
data: toSend,
Expand Down Expand Up @@ -251,7 +252,7 @@ export default {
const { postId } = action;
const basePath = wp.api.getPostTypeRoute( getCurrentPostType( getState() ) );
dispatch( removeNotice( TRASH_POST_NOTICE_ID ) );
wp.apiRequest( { path: `/wp/v2/${ basePath }/${ postId }`, method: 'DELETE' } ).then(
apiRequest( { path: `/wp/v2/${ basePath }/${ postId }`, method: 'DELETE' } ).then(
() => {
dispatch( {
...action,
Expand Down Expand Up @@ -294,7 +295,7 @@ export default {
context: 'edit',
};

wp.apiRequest( { path: `/wp/v2/${ basePath }/${ post.id }`, data } ).then(
apiRequest( { path: `/wp/v2/${ basePath }/${ post.id }`, data } ).then(
( newPost ) => {
dispatch( resetPost( newPost ) );
}
Expand Down Expand Up @@ -439,9 +440,9 @@ export default {

let result;
if ( id ) {
result = wp.apiRequest( { path: `/wp/v2/${ basePath }/${ id }` } );
result = apiRequest( { path: `/wp/v2/${ basePath }/${ id }` } );
} else {
result = wp.apiRequest( { path: `/wp/v2/${ basePath }?per_page=-1` } );
result = apiRequest( { path: `/wp/v2/${ basePath }?per_page=-1` } );
}

result.then(
Expand Down Expand Up @@ -494,7 +495,7 @@ export default {
const path = isTemporary ? `/wp/v2/${ basePath }` : `/wp/v2/${ basePath }/${ id }`;
const method = isTemporary ? 'POST' : 'PUT';

wp.apiRequest( { path, data, method } ).then(
apiRequest( { path, data, method } ).then(
( updatedSharedBlock ) => {
dispatch( {
type: 'SAVE_SHARED_BLOCK_SUCCESS',
Expand Down Expand Up @@ -550,7 +551,7 @@ export default {
sharedBlock.uid,
] ) );

wp.apiRequest( { path: `/wp/v2/${ basePath }/${ id }`, method: 'DELETE' } ).then(
apiRequest( { path: `/wp/v2/${ basePath }/${ id }`, method: 'DELETE' } ).then(
() => {
dispatch( {
type: 'DELETE_SHARED_BLOCK_SUCCESS',
Expand Down
Loading