Skip to content

Commit

Permalink
Store: Update product categories fetching to use the data-layer (Auto…
Browse files Browse the repository at this point in the history
  • Loading branch information
justinshreve authored Nov 30, 2017
1 parent d57c5c0 commit c913b00
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ import { dispatchWithProps } from 'woocommerce/state/helpers';
import { post } from 'woocommerce/state/data-layer/request/actions';
import { setError } from 'woocommerce/state/sites/status/wc-api/actions';
import { productCategoryUpdated } from 'woocommerce/state/sites/product-categories/actions';
import { WOOCOMMERCE_PRODUCT_CATEGORY_CREATE } from 'woocommerce/state/action-types';
import {
WOOCOMMERCE_PRODUCT_CATEGORY_CREATE,
WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST,
WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST_SUCCESS,
} from 'woocommerce/state/action-types';
import { dispatchRequest } from 'state/data-layer/wpcom-http/utils';
import request from 'woocommerce/state/sites/http-request';

// @TODO Move these handlers to product-categories/handlers.js

export function handleProductCategoryCreate( store, action ) {
const { siteId, category, successAction, failureAction } = action;
Expand Down Expand Up @@ -38,6 +46,59 @@ export function handleProductCategoryCreate( store, action ) {
);
}

export function handleProductCategoriesRequest( { dispatch }, action ) {
const { siteId } = action;
dispatch( request( siteId, action ).get( 'products/categories' ) );
}

export function handleProductCategoriesSuccess( { dispatch }, action, { data } ) {
const { siteId } = action;

if ( ! isValidCategoriesArray( data ) ) {
dispatch( setError( siteId, action, { message: 'Invalid Categories Array', data } ) );
return;
}

dispatch( {
type: WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST_SUCCESS,
siteId,
data,
} );
}

export function handleProductCategoriesError( { dispatch }, action, error ) {
dispatch( setError( action.siteId, action, error ) );
}

function isValidCategoriesArray( categories ) {
for ( let i = 0; i < categories.length; i++ ) {
if ( ! isValidProductCategory( categories[ i ] ) ) {
// Short-circuit the loop and return now.
return false;
}
}
return true;
}

function isValidProductCategory( category ) {
return (
category &&
category.id &&
'number' === typeof category.id &&
category.name &&
'string' === typeof category.name &&
category.slug &&
'string' === typeof category.slug
);
}

export default {
[ WOOCOMMERCE_PRODUCT_CATEGORY_CREATE ]: [ handleProductCategoryCreate ],
[ WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST ]: [
dispatchRequest(
handleProductCategoriesRequest,
handleProductCategoriesSuccess,
handleProductCategoriesError
),
],
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,121 @@ import { spy, match } from 'sinon';
/**
* Internal dependencies
*/
import { handleProductCategoryCreate } from '../';
import { WOOCOMMERCE_API_REQUEST } from 'woocommerce/state/action-types';
import {
handleProductCategoryCreate,
handleProductCategoriesRequest,
handleProductCategoriesSuccess,
handleProductCategoriesError,
} from '../';
import {
WOOCOMMERCE_API_REQUEST,
WOOCOMMERCE_ERROR_SET,
WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST,
WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST_SUCCESS,
} from 'woocommerce/state/action-types';
import { createProductCategory } from 'woocommerce/state/sites/product-categories/actions';
import { WPCOM_HTTP_REQUEST } from 'state/action-types';

describe( 'handlers', () => {
describe( '#handleProductCategoriesRequest()', () => {
test( 'should dispatch a get action', () => {
const siteId = '123';
const dispatch = spy();
const action = {
type: WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST,
siteId,
};
handleProductCategoriesRequest( { dispatch }, action );
expect( dispatch ).to.have.been.calledWith(
match( {
type: WPCOM_HTTP_REQUEST,
method: 'GET',
path: `/jetpack-blogs/${ siteId }/rest-api/`,
query: {
path: '/wc/v3/products/categories&_method=GET',
json: true,
apiVersion: '1.1',
},
} )
);
} );
} );

describe( '#handleProductCategoriesSuccess()', () => {
test( 'should dispatch a success action with product category information when request completes', () => {
const siteId = '123';
const store = {
dispatch: spy(),
};

const response = [
{
id: 10,
name: 'Tops',
slug: 'tops',
description: '',
display: 'default',
},
];

const action = {
type: WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST,
siteId,
};
handleProductCategoriesSuccess( store, action, { data: response } );

expect( store.dispatch ).calledWith( {
type: WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST_SUCCESS,
siteId,
data: response,
} );
} );
test( 'should dispatch with an error if the response is not valid', () => {
const siteId = '123';
const store = {
dispatch: spy(),
};
const response = [ { bogus: 'test' } ];

const action = {
type: WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST,
siteId,
};
handleProductCategoriesSuccess( store, action, { data: response } );

expect( store.dispatch ).to.have.been.calledWith(
match( {
type: WOOCOMMERCE_ERROR_SET,
siteId,
originalAction: action,
} )
);
} );
} );

describe( '#handleProductCategoriesError()', () => {
test( 'should dispatch error', () => {
const siteId = '123';
const store = {
dispatch: spy(),
};

const action = {
type: WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST,
siteId,
};
handleProductCategoriesError( store, action, 'error' );

expect( store.dispatch ).to.have.been.calledWith(
match( {
type: WOOCOMMERCE_ERROR_SET,
siteId,
originalAction: action,
} )
);
} );
} );

describe( '#handleProductCategoryCreate', () => {
test( 'should dispatch a post action', () => {
const store = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@
/**
* Internal dependencies
*/

import wp from 'lib/wp';
import { setError } from '../status/wc-api/actions';
import {
WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST,
WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST_SUCCESS,
WOOCOMMERCE_PRODUCT_CATEGORY_CREATE,
WOOCOMMERCE_PRODUCT_CATEGORY_UPDATED,
} from 'woocommerce/state/action-types';
Expand All @@ -21,36 +17,6 @@ export function fetchProductCategories( siteId ) {
};

dispatch( getAction );

const jpPath = `/jetpack-blogs/${ siteId }/rest-api/`;
const apiPath = '/wc/v3/products/categories';

// TODO: Modify this to use the extensions data layer.
return wp.req
.get( { path: jpPath }, { path: apiPath } )
.then( ( { data } ) => {
dispatch( fetchProductCategoriesSuccess( siteId, data ) );
} )
.catch( err => {
dispatch( setError( siteId, getAction, err ) );
} );
};
}

export function fetchProductCategoriesSuccess( siteId, data ) {
if ( ! isValidCategoriesArray( data ) ) {
const originalAction = {
type: WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST,
siteId,
};

return setError( siteId, originalAction, { message: 'Invalid Categories Array', data } );
}

return {
type: WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST_SUCCESS,
siteId,
data,
};
}

Expand Down Expand Up @@ -93,25 +59,3 @@ export function productCategoryUpdated( siteId, data, originatingAction ) {
originatingAction,
};
}

function isValidCategoriesArray( categories ) {
for ( let i = 0; i < categories.length; i++ ) {
if ( ! isValidProductCategory( categories[ i ] ) ) {
// Short-circuit the loop and return now.
return false;
}
}
return true;
}

function isValidProductCategory( category ) {
return (
category &&
category.id &&
'number' === typeof category.id &&
category.name &&
'string' === typeof category.name &&
category.slug &&
'string' === typeof category.slug
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,11 @@ import { spy } from 'sinon';
* Internal dependencies
*/
import { fetchProductCategories } from '../actions';
import useNock from 'test/helpers/use-nock';
import {
WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST,
WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST_SUCCESS,
WOOCOMMERCE_ERROR_SET,
} from 'woocommerce/state/action-types';
import { WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST } from 'woocommerce/state/action-types';

describe( 'actions', () => {
describe( '#fetchProductCategories()', () => {
const siteId = '123';
const errorSiteId = '234';

useNock( nock => {
nock( 'https://public-api.wordpress.com:443' )
.persist()
.get( '/rest/v1.1/jetpack-blogs/123/rest-api/' )
.query( { path: '/wc/v3/products/categories' } )
.reply( 200, {
data: [
{
id: 10,
name: 'Tops',
slug: 'tops',
description: '',
display: 'default',
},
],
} )
.get( '/rest/v1.1/jetpack-blogs/234/rest-api/' )
.query( { path: '/wc/v2/products/categories' } )
.reply( 200, {
data: [
{
id: '1',
name: 'Error',
slug: false,
description: '',
display: 'default',
},
],
} );
} );

test( 'should dispatch an action', () => {
const getState = () => ( {} );
Expand All @@ -62,37 +25,5 @@ describe( 'actions', () => {
siteId,
} );
} );

test( 'should dispatch a success action with product category information when request completes', () => {
const getState = () => ( {} );
const dispatch = spy();
const response = fetchProductCategories( siteId )( dispatch, getState );

return response.then( () => {
expect( dispatch ).to.have.been.calledWith( {
type: WOOCOMMERCE_PRODUCT_CATEGORIES_REQUEST_SUCCESS,
siteId,
data: [
{
id: 10,
name: 'Tops',
slug: 'tops',
description: '',
display: 'default',
},
],
} );
} );
} );

test( 'should dispatch error action if the data is invalid', () => {
const getState = () => ( {} );
const dispatch = spy();
const response = fetchProductCategories( errorSiteId )( dispatch, getState );

return response.then( () => {
expect( dispatch ).to.have.been.calledWithMatch( { type: WOOCOMMERCE_ERROR_SET } );
} );
} );
} );
} );

0 comments on commit c913b00

Please sign in to comment.