Remove 'wc-admin' client/store implementation (https://github.com/woocommerce/woocommerce-admin/pull/1344)

This has been replaced by the `wc-api` store, under client/wc-api
This commit is contained in:
Kevin Killingsworth 2019-01-28 13:18:21 -06:00 committed by Justin Shreve
parent 7592dae4bb
commit 833345dfee
38 changed files with 0 additions and 2437 deletions

View File

@ -10,7 +10,6 @@ import { Provider as SlotFillProvider } from 'react-slot-fill';
*/
import './stylesheets/_embedded.scss';
import { EmbedLayout } from './layout';
import 'store';
import 'wc-api/wp-data-store';
render(

View File

@ -10,7 +10,6 @@ import { Provider as SlotFillProvider } from 'react-slot-fill';
*/
import './stylesheets/_index.scss';
import { PageLayout } from './layout';
import 'store';
import 'wc-api/wp-data-store';
render(

View File

@ -1,41 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { combineReducers, registerStore } from '@wordpress/data';
/**
* Internal dependencies
*/
import { applyMiddleware, addThunks } from './middleware';
import orders from 'store/orders';
import reports from 'store/reports';
import notes from 'store/notes';
const store = registerStore( 'wc-admin', {
reducer: combineReducers( {
orders: orders.reducer,
reports: reports.reducer,
notes: notes.reducer,
} ),
actions: {
...orders.actions,
...reports.actions,
...notes.actions,
},
selectors: {
...orders.selectors,
...reports.selectors,
...notes.selectors,
},
resolvers: {
...orders.resolvers,
...reports.resolvers,
...notes.resolvers,
},
} );
applyMiddleware( store, [ addThunks ] );

View File

@ -1,16 +0,0 @@
/** @format */
export function applyMiddleware( store, middlewares ) {
middlewares = middlewares.slice();
middlewares.reverse();
let dispatch = store.dispatch;
middlewares.forEach( middleware => ( dispatch = middleware( store )( dispatch ) ) );
return Object.assign( store, { dispatch } );
}
export const addThunks = ( { getState } ) => next => action => {
if ( 'function' === typeof action ) {
return action( getState );
}
return next( action );
};

View File

@ -1,17 +0,0 @@
/** @format */
export default {
setNotes( notes, query ) {
return {
type: 'SET_NOTES',
notes,
query: query || {},
};
},
setNotesError( query ) {
return {
type: 'SET_NOTES_ERROR',
query: query || {},
};
},
};

View File

@ -1,15 +0,0 @@
/** @format */
/**
* Internal dependencies
*/
import actions from './actions';
import reducer from './reducer';
import resolvers from './resolvers';
import selectors from './selectors';
export default {
actions,
reducer,
resolvers,
selectors,
};

View File

@ -1,31 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { merge } from 'lodash';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import { getJsonString } from 'store/utils';
const DEFAULT_STATE = {};
export default function notesReducer( state = DEFAULT_STATE, action ) {
const queryKey = getJsonString( action.query );
switch ( action.type ) {
case 'SET_NOTES':
return merge( {}, state, {
[ queryKey ]: action.notes,
} );
case 'SET_NOTES_ERROR':
return merge( {}, state, {
[ queryKey ]: ERROR,
} );
}
return state;
}

View File

@ -1,32 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { dispatch } from '@wordpress/data';
import apiFetch from '@wordpress/api-fetch';
/**
* WooCommerce dependencies
*/
import { stringifyQuery } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
import { NAMESPACE } from 'store/constants';
export default {
// TODO: Use controls data plugin or fresh-data instead of async
async getNotes( ...args ) {
// This is interim code to work with either 2.x or 3.x version of @wordpress/data
// TODO: Change to just `getNotes( query )` after Gutenberg plugin uses @wordpress/data 3+
const query = args.length === 1 ? args[ 0 ] : args[ 1 ];
try {
const notes = await apiFetch( { path: NAMESPACE + 'admin/notes' + stringifyQuery( query ) } );
dispatch( 'wc-admin' ).setNotes( notes, query );
} catch ( error ) {
dispatch( 'wc-admin' ).setNotesError( query );
}
},
};

View File

@ -1,49 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { get } from 'lodash';
import { select } from '@wordpress/data';
/**
* Internal dependencies
*/
import { getJsonString } from 'store/utils';
import { ERROR } from 'store/constants';
/**
* Returns notes for a specific query.
*
* @param {Object} state Current state
* @param {Object} query Note query parameters
* @return {Array} Notes
*/
function getNotes( state, query = {} ) {
return get( state, [ 'notes', getJsonString( query ) ], [] );
}
export default {
getNotes,
/**
* Returns true if a query is pending.
*
* @param {Object} state Current state
* @return {Boolean} True if the `getNotes` request is pending, false otherwise
*/
isGetNotesRequesting( state, ...args ) {
return select( 'core/data' ).isResolving( 'wc-admin', 'getNotes', args );
},
/**
* Returns true if a get notes request has returned an error.
*
* @param {Object} state Current state
* @param {Object} query Query parameters
* @return {Boolean} True if the `getNotes` request has failed, false otherwise
*/
isGetNotesError( state, query ) {
return ERROR === getNotes( state, query );
},
};

View File

@ -1,80 +0,0 @@
/**
* @format
*/
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import notesReducer from '../reducer';
import { getJsonString } from 'store/utils';
describe( 'notesReducer()', () => {
it( 'returns an empty data object by default', () => {
const state = notesReducer( undefined, {} );
expect( state ).toEqual( {} );
} );
it( 'returns with received notes data', () => {
const originalState = deepFreeze( {} );
const query = {
page: 2,
};
const notes = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const state = notesReducer( originalState, {
type: 'SET_NOTES',
query,
notes,
} );
const queryKey = getJsonString( query );
expect( state[ queryKey ] ).toEqual( notes );
} );
it( 'tracks multiple queries in notes data', () => {
const otherQuery = {
page: 3,
};
const otherQueryKey = getJsonString( otherQuery );
const otherNotes = [ { id: 1 }, { id: 2 }, { id: 3 } ];
const otherQueryState = {
[ otherQueryKey ]: otherNotes,
};
const originalState = deepFreeze( otherQueryState );
const query = {
page: 2,
};
const notes = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const state = notesReducer( originalState, {
type: 'SET_NOTES',
query,
notes,
} );
const queryKey = getJsonString( query );
expect( state[ queryKey ] ).toEqual( notes );
expect( state[ otherQueryKey ] ).toEqual( otherNotes );
} );
it( 'returns with received error data', () => {
const originalState = deepFreeze( {} );
const query = {
page: 2,
};
const state = notesReducer( originalState, {
type: 'SET_NOTES_ERROR',
query,
} );
const queryKey = getJsonString( query );
expect( state[ queryKey ] ).toEqual( ERROR );
} );
} );

View File

@ -1,53 +0,0 @@
/*
* @format
*/
/**
* External dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { dispatch } from '@wordpress/data';
/**
* Internal dependencies
*/
import { NAMESPACE } from 'store/constants';
import resolvers from '../resolvers';
const { getNotes } = resolvers;
jest.mock( '@wordpress/data', () => ( {
dispatch: jest.fn().mockReturnValue( {
setNotes: jest.fn(),
} ),
} ) );
jest.mock( '@wordpress/api-fetch', () => jest.fn() );
describe( 'getNotes', () => {
const NOTES_1 = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const NOTES_2 = [ { id: 1 }, { id: 2 }, { id: 3 } ];
beforeAll( () => {
apiFetch.mockImplementation( options => {
if ( options.path === NAMESPACE + 'admin/notes' ) {
return Promise.resolve( NOTES_1 );
}
if ( options.path === NAMESPACE + 'admin/notes?page=2' ) {
return Promise.resolve( NOTES_2 );
}
} );
} );
it( 'returns requested data', async () => {
expect.assertions( 1 );
await getNotes();
expect( dispatch().setNotes ).toHaveBeenCalledWith( NOTES_1, undefined );
} );
it( 'returns requested data for a specific query', async () => {
expect.assertions( 1 );
await getNotes( { page: 2 } );
expect( dispatch().setNotes ).toHaveBeenCalledWith( NOTES_2, { page: 2 } );
} );
} );

View File

@ -1,92 +0,0 @@
/*
* @format
*/
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import selectors from '../selectors';
import { select } from '@wordpress/data';
import { getJsonString } from 'store/utils';
const { getNotes, isGetNotesRequesting, isGetNotesError } = selectors;
jest.mock( '@wordpress/data', () => ( {
...require.requireActual( '@wordpress/data' ),
select: jest.fn().mockReturnValue( {} ),
} ) );
const query = { page: 1 };
const queryKey = getJsonString( query );
describe( 'getNotes()', () => {
it( 'returns an empty array when no notes are available', () => {
const state = deepFreeze( {} );
expect( getNotes( state, query ) ).toEqual( [] );
} );
it( 'returns stored notes for current query', () => {
const notes = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const state = deepFreeze( {
notes: {
[ queryKey ]: notes,
},
} );
expect( getNotes( state, query ) ).toEqual( notes );
} );
} );
describe( 'isGetNotesRequesting()', () => {
beforeAll( () => {
select( 'core/data' ).isResolving = jest.fn().mockReturnValue( false );
} );
afterAll( () => {
select( 'core/data' ).isResolving.mockRestore();
} );
function setIsResolving( isResolving ) {
select( 'core/data' ).isResolving.mockImplementation(
( reducerKey, selectorName ) =>
isResolving && reducerKey === 'wc-admin' && selectorName === 'getNotes'
);
}
it( 'returns false if never requested', () => {
const result = isGetNotesRequesting( query );
expect( result ).toBe( false );
} );
it( 'returns false if request finished', () => {
setIsResolving( false );
const result = isGetNotesRequesting( query );
expect( result ).toBe( false );
} );
it( 'returns true if requesting', () => {
setIsResolving( true );
const result = isGetNotesRequesting( query );
expect( result ).toBe( true );
} );
} );
describe( 'isGetNotesError()', () => {
it( 'returns false by default', () => {
const state = deepFreeze( {} );
expect( isGetNotesError( state, query ) ).toEqual( false );
} );
it( 'returns true if ERROR constant is found', () => {
const state = deepFreeze( {
notes: {
[ queryKey ]: ERROR,
},
} );
expect( isGetNotesError( state, query ) ).toEqual( true );
} );
} );

View File

@ -1,17 +0,0 @@
/** @format */
export default {
setOrders( orders, query ) {
return {
type: 'SET_ORDERS',
orders,
query: query || {},
};
},
setOrdersError( query ) {
return {
type: 'SET_ORDERS_ERROR',
query: query || {},
};
},
};

View File

@ -1,15 +0,0 @@
/** @format */
/**
* Internal dependencies
*/
import actions from './actions';
import reducer from './reducer';
import resolvers from './resolvers';
import selectors from './selectors';
export default {
actions,
reducer,
resolvers,
selectors,
};

View File

@ -1,32 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { merge } from 'lodash';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import { getJsonString } from 'store/utils';
const DEFAULT_STATE = {};
export default function ordersReducer( state = DEFAULT_STATE, action ) {
const queryKey = getJsonString( action.query );
switch ( action.type ) {
case 'SET_ORDERS':
return merge( {}, state, {
[ queryKey ]: action.orders,
} );
case 'SET_ORDERS_ERROR':
return merge( {}, state, {
[ queryKey ]: ERROR,
} );
}
return state;
}

View File

@ -1,32 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { dispatch } from '@wordpress/data';
import apiFetch from '@wordpress/api-fetch';
/**
* WooCommerce dependencies
*/
import { stringifyQuery } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
import { NAMESPACE } from 'store/constants';
export default {
// TODO: Use controls data plugin or fresh-data instead of async
async getOrders( ...args ) {
// This is interim code to work with either 2.x or 3.x version of @wordpress/data
// TODO: Change to just `getNotes( query )` after Gutenberg plugin uses @wordpress/data 3+
const query = args.length === 1 ? args[ 0 ] : args[ 1 ];
try {
const orders = await apiFetch( { path: NAMESPACE + 'orders' + stringifyQuery( query ) } );
dispatch( 'wc-admin' ).setOrders( orders, query );
} catch ( error ) {
dispatch( 'wc-admin' ).setOrdersError( query );
}
},
};

View File

@ -1,49 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { get } from 'lodash';
import { select } from '@wordpress/data';
/**
* Internal dependencies
*/
import { getJsonString } from 'store/utils';
import { ERROR } from 'store/constants';
/**
* Returns orders for a specific query.
*
* @param {Object} state Current state
* @param {Object} query Report query parameters
* @return {Array} Report details
*/
function getOrders( state, query = {} ) {
return get( state, [ 'orders', getJsonString( query ) ], [] );
}
export default {
getOrders,
/**
* Returns true if a getOrders request is pending.
*
* @param {Object} state Current state
* @return {Boolean} True if the `getOrders` request is pending, false otherwise
*/
isGetOrdersRequesting( state, ...args ) {
return select( 'core/data' ).isResolving( 'wc-admin', 'getOrders', args );
},
/**
* Returns true if a getOrders request has returned an error.
*
* @param {Object} state Current state
* @param {Object} query Query parameters
* @return {Boolean} True if the `getOrders` request has failed, false otherwise
*/
isGetOrdersError( state, query ) {
return ERROR === getOrders( state, query );
},
};

View File

@ -1,80 +0,0 @@
/**
* @format
*/
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import ordersReducer from '../reducer';
import { getJsonString } from 'store/utils';
describe( 'ordersReducer()', () => {
it( 'returns an empty data object by default', () => {
const state = ordersReducer( undefined, {} );
expect( state ).toEqual( {} );
} );
it( 'returns with received orders data', () => {
const originalState = deepFreeze( {} );
const query = {
orderby: 'date',
};
const orders = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const state = ordersReducer( originalState, {
type: 'SET_ORDERS',
query,
orders,
} );
const queryKey = getJsonString( query );
expect( state[ queryKey ] ).toEqual( orders );
} );
it( 'tracks multiple queries in orders data', () => {
const otherQuery = {
orderby: 'id',
};
const otherQueryKey = getJsonString( otherQuery );
const otherOrders = [ { id: 1 }, { id: 2 }, { id: 3 } ];
const otherQueryState = {
[ otherQueryKey ]: otherOrders,
};
const originalState = deepFreeze( otherQueryState );
const query = {
orderby: 'date',
};
const orders = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const state = ordersReducer( originalState, {
type: 'SET_ORDERS',
query,
orders,
} );
const queryKey = getJsonString( query );
expect( state[ queryKey ] ).toEqual( orders );
expect( state[ otherQueryKey ] ).toEqual( otherOrders );
} );
it( 'returns with received error data', () => {
const originalState = deepFreeze( {} );
const query = {
orderby: 'date',
};
const state = ordersReducer( originalState, {
type: 'SET_ORDERS_ERROR',
query,
} );
const queryKey = getJsonString( query );
expect( state[ queryKey ] ).toEqual( ERROR );
} );
} );

View File

@ -1,53 +0,0 @@
/*
* @format
*/
/**
* External dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { dispatch } from '@wordpress/data';
/**
* Internal dependencies
*/
import { NAMESPACE } from 'store/constants';
import resolvers from '../resolvers';
const { getOrders } = resolvers;
jest.mock( '@wordpress/data', () => ( {
dispatch: jest.fn().mockReturnValue( {
setOrders: jest.fn(),
} ),
} ) );
jest.mock( '@wordpress/api-fetch', () => jest.fn() );
describe( 'getOrders', () => {
const ORDERS_1 = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const ORDERS_2 = [ { id: 1 }, { id: 2 }, { id: 3 } ];
beforeAll( () => {
apiFetch.mockImplementation( options => {
if ( options.path === NAMESPACE + 'orders' ) {
return Promise.resolve( ORDERS_1 );
}
if ( options.path === NAMESPACE + 'orders?orderby=id' ) {
return Promise.resolve( ORDERS_2 );
}
} );
} );
it( 'returns requested report data', async () => {
expect.assertions( 1 );
await getOrders();
expect( dispatch().setOrders ).toHaveBeenCalledWith( ORDERS_1, undefined );
} );
it( 'returns requested report data for a specific query', async () => {
expect.assertions( 1 );
await getOrders( { orderby: 'id' } );
expect( dispatch().setOrders ).toHaveBeenCalledWith( ORDERS_2, { orderby: 'id' } );
} );
} );

View File

@ -1,92 +0,0 @@
/*
* @format
*/
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';
import { select } from '@wordpress/data';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import selectors from '../selectors';
import { getJsonString } from 'store/utils';
const { getOrders, isGetOrdersRequesting, isGetOrdersError } = selectors;
jest.mock( '@wordpress/data', () => ( {
...require.requireActual( '@wordpress/data' ),
select: jest.fn().mockReturnValue( {} ),
} ) );
const query = { orderby: 'date' };
const queryKey = getJsonString( query );
describe( 'getOrders()', () => {
it( 'returns an empty array when no orders are available', () => {
const state = deepFreeze( {} );
expect( getOrders( state, query ) ).toEqual( [] );
} );
it( 'returns stored orders for current query', () => {
const orders = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const state = deepFreeze( {
orders: {
[ queryKey ]: orders,
},
} );
expect( getOrders( state, query ) ).toEqual( orders );
} );
} );
describe( 'isGetOrdersRequesting()', () => {
beforeAll( () => {
select( 'core/data' ).isResolving = jest.fn().mockReturnValue( false );
} );
afterAll( () => {
select( 'core/data' ).isResolving.mockRestore();
} );
function setIsResolving( isResolving ) {
select( 'core/data' ).isResolving.mockImplementation(
( reducerKey, selectorName ) =>
isResolving && reducerKey === 'wc-admin' && selectorName === 'getOrders'
);
}
it( 'returns false if never requested', () => {
const result = isGetOrdersRequesting( query );
expect( result ).toBe( false );
} );
it( 'returns false if request finished', () => {
setIsResolving( false );
const result = isGetOrdersRequesting( query );
expect( result ).toBe( false );
} );
it( 'returns true if requesting', () => {
setIsResolving( true );
const result = isGetOrdersRequesting( query );
expect( result ).toBe( true );
} );
} );
describe( 'isGetOrdersError()', () => {
it( 'returns false by default', () => {
const state = deepFreeze( {} );
expect( isGetOrdersError( state, query ) ).toEqual( false );
} );
it( 'returns true if ERROR constant is found', () => {
const state = deepFreeze( {
orders: {
[ queryKey ]: ERROR,
},
} );
expect( isGetOrdersError( state, query ) ).toEqual( true );
} );
} );

View File

@ -1,31 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { combineReducers } from '@wordpress/data';
/**
* Internal dependencies
*/
import items from './items';
import stats from './stats';
export default {
reducer: combineReducers( {
items: items.reducer,
stats: stats.reducer,
} ),
actions: {
...items.actions,
...stats.actions,
},
selectors: {
...items.selectors,
...stats.selectors,
},
resolvers: {
...items.resolvers,
...stats.resolvers,
},
};

View File

@ -1,20 +0,0 @@
/** @format */
export default {
setReportItems( endpoint, query, data, totalCount ) {
return {
type: 'SET_REPORT_ITEMS',
endpoint,
query: query || {},
data,
totalCount,
};
},
setReportItemsError( endpoint, query ) {
return {
type: 'SET_REPORT_ITEMS_ERROR',
endpoint,
query: query || {},
};
},
};

View File

@ -1,15 +0,0 @@
/** @format */
/**
* Internal dependencies
*/
import actions from './actions';
import reducer from './reducer';
import resolvers from './resolvers';
import selectors from './selectors';
export default {
actions,
reducer,
resolvers,
selectors,
};

View File

@ -1,39 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { merge } from 'lodash';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import { getJsonString } from 'store/utils';
const DEFAULT_STATE = {};
export default function reportItemsReducer( state = DEFAULT_STATE, action ) {
const queryKey = getJsonString( action.query );
switch ( action.type ) {
case 'SET_REPORT_ITEMS':
return merge( {}, state, {
[ action.endpoint ]: {
[ queryKey ]: {
data: action.data,
totalCount: action.totalCount,
},
},
} );
case 'SET_REPORT_ITEMS_ERROR':
return merge( {}, state, {
[ action.endpoint ]: {
[ queryKey ]: ERROR,
},
} );
}
return state;
}

View File

@ -1,36 +0,0 @@
/** @format */
/**
* External dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { dispatch } from '@wordpress/data';
/**
* WooCommerce dependencies
*/
import { stringifyQuery } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
import { NAMESPACE } from 'store/constants';
export default {
async getReportItems( ...args ) {
const [ endpoint, query ] = args.slice( -2 );
try {
const response = await apiFetch( {
parse: false,
path: NAMESPACE + 'reports/' + endpoint + stringifyQuery( query ),
} );
const itemsData = await response.json();
const totalCount = parseInt( response.headers.get( 'x-wp-total' ) );
dispatch( 'wc-admin' ).setReportItems( endpoint, query, itemsData, totalCount );
} catch ( error ) {
dispatch( 'wc-admin' ).setReportItemsError( endpoint, query );
}
},
};

View File

@ -1,51 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { get } from 'lodash';
import { select } from '@wordpress/data';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import { getJsonString } from 'store/utils';
/**
* Returns report items for a specific endpoint query.
*
* @param {Object} state Current state
* @param {String} endpoint Stats endpoint
* @param {Object} query Report query parameters
* @return {Object} Report details
*/
function getReportItems( state, endpoint, query = {} ) {
return get( state, [ 'reports', 'items', endpoint, getJsonString( query ) ], { data: [] } );
}
export default {
getReportItems,
/**
* Returns true if a getReportItems request is pending.
*
* @param {Object} state Current state
* @return {Boolean} True if the `getReportItems` request is pending, false otherwise
*/
isGetReportItemsRequesting( state, ...args ) {
return select( 'core/data' ).isResolving( 'wc-admin', 'getReportItems', args );
},
/**
* Returns true if a getReportItems request has returned an error.
*
* @param {Object} state Current state
* @param {String} endpoint Items endpoint
* @param {Object} query Report query parameters
* @return {Boolean} True if the `getReportItems` request has failed, false otherwise
*/
isGetReportItemsError( state, endpoint, query ) {
return ERROR === getReportItems( state, endpoint, query );
},
};

View File

@ -1,104 +0,0 @@
/**
* @format
*/
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import reportItemsReducer from '../reducer';
import { getJsonString } from 'store/utils';
describe( 'reportItemsReducer()', () => {
const endpoint = 'coupons';
it( 'returns an empty object by default', () => {
const state = reportItemsReducer( undefined, {} );
expect( state ).toEqual( {} );
} );
it( 'returns with received items data', () => {
const originalState = deepFreeze( {} );
const query = {
orderby: 'orders_count',
};
const itemsData = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const itemsTotalCount = 50;
const state = reportItemsReducer( originalState, {
type: 'SET_REPORT_ITEMS',
endpoint,
query,
data: itemsData,
totalCount: itemsTotalCount,
} );
const queryKey = getJsonString( query );
expect( state[ endpoint ][ queryKey ] ).toEqual( {
data: itemsData,
totalCount: itemsTotalCount,
} );
} );
it( 'tracks multiple queries in items data', () => {
const otherQuery = {
orderby: 'id',
};
const otherQueryKey = getJsonString( otherQuery );
const otherItemsData = [ { id: 1 }, { id: 2 }, { id: 3 } ];
const otherItemsTotalCount = 70;
const otherQueryState = {
[ endpoint ]: {
[ otherQueryKey ]: {
data: otherItemsData,
totalCount: otherItemsTotalCount,
},
},
};
const originalState = deepFreeze( otherQueryState );
const query = {
orderby: 'orders_count',
};
const itemsData = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const itemsTotalCount = 50;
const state = reportItemsReducer( originalState, {
type: 'SET_REPORT_ITEMS',
endpoint,
query,
data: itemsData,
totalCount: itemsTotalCount,
} );
const queryKey = getJsonString( query );
expect( state[ endpoint ][ queryKey ] ).toEqual( {
data: itemsData,
totalCount: itemsTotalCount,
} );
expect( state[ endpoint ][ otherQueryKey ] ).toEqual( {
data: otherItemsData,
totalCount: otherItemsTotalCount,
} );
} );
it( 'returns with received error data', () => {
const originalState = deepFreeze( {} );
const query = {
orderby: 'orders_count',
};
const state = reportItemsReducer( originalState, {
type: 'SET_REPORT_ITEMS_ERROR',
endpoint,
query,
} );
const queryKey = getJsonString( query );
expect( state[ endpoint ][ queryKey ] ).toEqual( ERROR );
} );
} );

View File

@ -1,74 +0,0 @@
/*
* @format
*/
/**
* External dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { dispatch } from '@wordpress/data';
/**
* Internal dependencies
*/
import resolvers from '../resolvers';
const { getReportItems } = resolvers;
jest.mock( '@wordpress/data', () => ( {
dispatch: jest.fn().mockReturnValue( {
setReportItems: jest.fn(),
} ),
} ) );
jest.mock( '@wordpress/api-fetch', () => jest.fn() );
describe( 'getReportItems', () => {
const ITEMS_1 = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const ITEMS_1_COUNT = 50;
const ITEMS_2 = [ { id: 1 }, { id: 2 }, { id: 3 } ];
const ITEMS_2_COUNT = 75;
const endpoint = 'products';
beforeAll( () => {
apiFetch.mockImplementation( options => {
if ( options.path === `/wc/v4/reports/${ endpoint }` ) {
return Promise.resolve( {
headers: {
get: () => ITEMS_1_COUNT,
},
json: () => Promise.resolve( ITEMS_1 ),
} );
}
if ( options.path === `/wc/v4/reports/${ endpoint }?orderby=id` ) {
return Promise.resolve( {
headers: {
get: () => ITEMS_2_COUNT,
},
json: () => Promise.resolve( ITEMS_2 ),
} );
}
} );
} );
it( 'returns requested report data', async () => {
expect.assertions( 1 );
await getReportItems( endpoint );
expect( dispatch().setReportItems ).toHaveBeenCalledWith(
endpoint,
undefined,
ITEMS_1,
ITEMS_1_COUNT
);
} );
it( 'returns requested report data for a specific query', async () => {
expect.assertions( 1 );
await getReportItems( endpoint, { orderby: 'id' } );
expect( dispatch().setReportItems ).toHaveBeenCalledWith(
endpoint,
{ orderby: 'id' },
ITEMS_2,
ITEMS_2_COUNT
);
} );
} );

View File

@ -1,106 +0,0 @@
/*
* @format
*/
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';
import { select } from '@wordpress/data';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import { getJsonString } from 'store/utils';
import selectors from '../selectors';
const { getReportItems, isGetReportItemsRequesting, isGetReportItemsError } = selectors;
jest.mock( '@wordpress/data', () => ( {
...require.requireActual( '@wordpress/data' ),
select: jest.fn().mockReturnValue( {} ),
} ) );
const query = { orderby: 'date' };
const queryKey = getJsonString( query );
const endpoint = 'coupons';
describe( 'getReportItems()', () => {
it( 'returns an empty object when no items are available', () => {
const state = deepFreeze( {} );
expect( getReportItems( state, endpoint, query ) ).toEqual( { data: [] } );
} );
it( 'returns stored items for current query', () => {
const itemsData = [ { id: 1214 }, { id: 1215 }, { id: 1216 } ];
const itemsTotalCount = 50;
const queryState = {
data: itemsData,
totalCount: itemsTotalCount,
};
const state = deepFreeze( {
reports: {
items: {
[ endpoint ]: {
[ queryKey ]: queryState,
},
},
},
} );
expect( getReportItems( state, endpoint, query ) ).toEqual( queryState );
} );
} );
describe( 'isGetReportItemsRequesting()', () => {
beforeAll( () => {
select( 'core/data' ).isResolving = jest.fn().mockReturnValue( false );
} );
afterAll( () => {
select( 'core/data' ).isResolving.mockRestore();
} );
function setIsResolving( isResolving ) {
select( 'core/data' ).isResolving.mockImplementation(
( reducerKey, selectorName ) =>
isResolving && reducerKey === 'wc-admin' && selectorName === 'getReportItems'
);
}
it( 'returns false if never requested', () => {
const result = isGetReportItemsRequesting( endpoint );
expect( result ).toBe( false );
} );
it( 'returns false if request finished', () => {
setIsResolving( false );
const result = isGetReportItemsRequesting( endpoint );
expect( result ).toBe( false );
} );
it( 'returns true if requesting', () => {
setIsResolving( true );
const result = isGetReportItemsRequesting( endpoint );
expect( result ).toBe( true );
} );
} );
describe( 'isGetReportItemsError()', () => {
it( 'returns false by default', () => {
const state = deepFreeze( {} );
expect( isGetReportItemsError( state, endpoint, query ) ).toEqual( false );
} );
it( 'returns true if ERROR constant is found', () => {
const state = deepFreeze( {
reports: {
items: {
[ endpoint ]: {
[ queryKey ]: ERROR,
},
},
},
} );
expect( isGetReportItemsError( state, endpoint, query ) ).toEqual( true );
} );
} );

View File

@ -1,21 +0,0 @@
/** @format */
export default {
setReportStats( endpoint, report, query, totalResults, totalPages ) {
return {
type: 'SET_REPORT_STATS',
endpoint,
report,
totalResults,
totalPages,
query: query || {},
};
},
setReportStatsError( endpoint, query ) {
return {
type: 'SET_REPORT_STATS_ERROR',
endpoint,
query: query || {},
};
},
};

View File

@ -1,16 +0,0 @@
/** @format */
/**
* Internal dependencies
*/
import actions from './actions';
import reducer from './reducer';
import resolvers from './resolvers';
import selectors from './selectors';
export default {
actions,
reducer,
resolvers,
selectors,
};

View File

@ -1,40 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { merge } from 'lodash';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import { getJsonString } from 'store/utils';
const DEFAULT_STATE = {};
export default function reportStatsReducer( state = DEFAULT_STATE, action ) {
if ( 'SET_REPORT_STATS' === action.type ) {
const queryKey = getJsonString( action.query );
return merge( {}, state, {
[ action.endpoint ]: {
[ queryKey ]: {
data: action.report,
totalResults: action.totalResults,
totalPages: action.totalPages,
},
},
} );
}
if ( 'SET_REPORT_STATS_ERROR' === action.type ) {
const queryKey = getJsonString( action.query );
return merge( {}, state, {
[ action.endpoint ]: {
[ queryKey ]: ERROR,
},
} );
}
return state;
}

View File

@ -1,63 +0,0 @@
/** @format */
/**
* External dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { dispatch } from '@wordpress/data';
/**
* WooCommerce dependencies
*/
import { stringifyQuery } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
import { NAMESPACE, SWAGGERNAMESPACE } from 'store/constants';
export default {
// TODO: Use controls data plugin or fresh-data instead of async
async getReportStats( ...args ) {
// This is interim code to work with either 2.x or 3.x version of @wordpress/data
// TODO: Change to just `getNotes( endpoint, query )`
// after Gutenberg plugin uses @wordpress/data 3+
const [ endpoint, query ] = args.length === 2 ? args : args.slice( 1, 3 );
const statEndpoints = [ 'orders', 'revenue', 'products', 'taxes' ];
let apiPath = endpoint + stringifyQuery( query );
// TODO: Remove once swagger endpoints are phased out.
const swaggerEndpoints = [ 'categories' ];
if ( swaggerEndpoints.indexOf( endpoint ) >= 0 ) {
apiPath = SWAGGERNAMESPACE + 'reports/' + endpoint + '/stats' + stringifyQuery( query );
try {
const response = await fetch( apiPath );
const report = await response.json();
dispatch( 'wc-admin' ).setReportStats( endpoint, report, query );
} catch ( error ) {
dispatch( 'wc-admin' ).setReportStatsError( endpoint, query );
}
return;
}
if ( statEndpoints.indexOf( endpoint ) >= 0 ) {
apiPath = NAMESPACE + 'reports/' + endpoint + '/stats' + stringifyQuery( query );
}
try {
const response = await apiFetch( {
path: apiPath,
parse: false,
} );
const report = await response.json();
const totalResults = parseInt( response.headers.get( 'x-wp-total' ) );
const totalPages = parseInt( response.headers.get( 'x-wp-totalpages' ) );
dispatch( 'wc-admin' ).setReportStats( endpoint, report, query, totalResults, totalPages );
} catch ( error ) {
dispatch( 'wc-admin' ).setReportStatsError( endpoint, query );
}
},
};

View File

@ -1,52 +0,0 @@
/** @format */
/**
* External dependencies
*/
import { get } from 'lodash';
import { select } from '@wordpress/data';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import { getJsonString } from 'store/utils';
/**
* Returns report stats details for a specific endpoint query.
*
* @param {Object} state Current state
* @param {String} endpoint Stats endpoint
* @param {Object} query Report query parameters
* @return {Object} Report details
*/
function getReportStats( state, endpoint, query = {} ) {
const queries = get( state, [ 'reports', 'stats', endpoint ], {} );
return queries[ getJsonString( query ) ] || null;
}
export default {
getReportStats,
/**
* Returns true if a stats query is pending.
*
* @param {Object} state Current state
* @return {Boolean} True if the `getReportStats` request is pending, false otherwise
*/
isReportStatsRequesting( state, ...args ) {
return select( 'core/data' ).isResolving( 'wc-admin', 'getReportStats', args );
},
/**
* Returns true if a report stat request has returned an error.
*
* @param {Object} state Current state
* @param {String} endpoint Stats endpoint
* @param {Object} query Report query parameters
* @return {Boolean} True if the `getReportStats` request has failed, false otherwise
*/
isReportStatsError( state, endpoint, query ) {
return ERROR === getReportStats( state, endpoint, query );
},
};

View File

@ -1,164 +0,0 @@
/**
* @format
*/
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import reportStatsReducer from '../reducer';
import { getJsonString } from 'store/utils';
describe( 'reportStatsReducer()', () => {
it( 'returns an empty data object by default', () => {
const state = reportStatsReducer( undefined, {} );
expect( state ).toEqual( {} );
} );
it( 'returns with received report data', () => {
const originalState = deepFreeze( {} );
const query = {
after: '2018-01-04T00:00:00+00:00',
before: '2018-07-14T00:00:00+00:00',
interval: 'day',
};
const report = {
totals: {
orders_count: 10,
num_items_sold: 9,
},
interval: [ 0, 1, 2 ],
};
const endpoint = 'revenue';
const state = reportStatsReducer( originalState, {
type: 'SET_REPORT_STATS',
endpoint,
query,
report,
totalResults: 3,
totalPages: 1,
} );
const queryKey = getJsonString( query );
expect( state[ endpoint ][ queryKey ] ).toEqual( {
data: { ...report },
totalResults: 3,
totalPages: 1,
} );
} );
it( 'tracks multiple queries per endpoint in report data', () => {
const otherQuery = {
after: '2018-01-04T00:00:00+00:00',
before: '2018-07-14T00:00:00+00:00',
interval: 'week',
};
const otherQueryKey = getJsonString( otherQuery );
const otherQueryState = {
revenue: {
[ otherQueryKey ]: { data: { totals: 1000 } },
},
};
const originalState = deepFreeze( otherQueryState );
const query = {
after: '2018-01-04T00:00:00+00:00',
before: '2018-07-14T00:00:00+00:00',
interval: 'day',
};
const report = {
totals: {
orders_count: 10,
num_items_sold: 9,
},
interval: [ 0, 1, 2 ],
};
const endpoint = 'revenue';
const state = reportStatsReducer( originalState, {
type: 'SET_REPORT_STATS',
endpoint,
query,
report,
totalResults: 3,
totalPages: 1,
} );
const queryKey = getJsonString( query );
expect( state[ endpoint ][ queryKey ] ).toEqual( {
data: { ...report },
totalResults: 3,
totalPages: 1,
} );
expect( state[ endpoint ][ otherQueryKey ].data.totals ).toEqual( 1000 );
} );
it( 'tracks multiple endpoints in report data', () => {
const productsQuery = {
after: '2018-01-04T00:00:00+00:00',
before: '2018-07-14T00:00:00+00:00',
interval: 'week',
};
const productsQueryKey = getJsonString( productsQuery );
const productsQueryState = {
products: {
[ productsQueryKey ]: { data: { totals: 1999 } },
},
};
const originalState = deepFreeze( productsQueryState );
const query = {
after: '2018-01-04T00:00:00+00:00',
before: '2018-07-14T00:00:00+00:00',
interval: 'day',
};
const report = {
totals: {
orders_count: 10,
num_items_sold: 9,
},
interval: [ 0, 1, 2 ],
};
const endpoint = 'revenue';
const state = reportStatsReducer( originalState, {
type: 'SET_REPORT_STATS',
endpoint,
query,
report,
totalResults: 3,
totalPages: 1,
} );
const queryKey = getJsonString( query );
expect( state[ endpoint ][ queryKey ] ).toEqual( {
data: { ...report },
totalResults: 3,
totalPages: 1,
} );
expect( state.products[ productsQueryKey ].data.totals ).toEqual( 1999 );
} );
it( 'returns with received error data', () => {
const originalState = deepFreeze( {} );
const query = {
after: '2018-01-04T00:00:00+00:00',
before: '2018-07-14T00:00:00+00:00',
interval: 'day',
};
const endpoint = 'revenue';
const state = reportStatsReducer( originalState, {
type: 'SET_REPORT_STATS_ERROR',
endpoint,
query,
} );
const queryKey = getJsonString( query );
expect( state[ endpoint ][ queryKey ] ).toEqual( ERROR );
} );
} );

View File

@ -1,107 +0,0 @@
/*
* @format
*/
/**
* External dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { dispatch } from '@wordpress/data';
/**
* Internal dependencies
*/
import resolvers from '../resolvers';
const { getReportStats } = resolvers;
jest.mock( '@wordpress/data', () => ( {
dispatch: jest.fn().mockReturnValue( {
setReportStats: jest.fn(),
} ),
} ) );
jest.mock( '@wordpress/api-fetch', () => jest.fn() );
describe( 'getReportStats', () => {
const REPORT_1 = {
totals: {
orders_count: 10,
num_items_sold: 9,
},
interval: [ 0, 1, 2 ],
};
const REPORT_1_TOTALS = {
'x-wp-total': 10,
'x-wp-totalpages': 2,
};
const REPORT_2 = {
totals: {
orders_count: 5,
items_sold: 5,
gross_revenue: 999.99,
},
intervals: [
{
interval: 'week',
subtotals: {},
},
],
};
const REPORT_2_TOTALS = {
'x-wp-total': 20,
'x-wp-totalpages': 4,
};
beforeAll( () => {
apiFetch.mockImplementation( options => {
if ( options.path === '/wc/v4/reports/revenue/stats' ) {
return Promise.resolve( {
headers: {
get: header => REPORT_1_TOTALS[ header ],
},
json: () => Promise.resolve( REPORT_1 ),
} );
}
if ( options.path === '/wc/v4/reports/products/stats?interval=week' ) {
return Promise.resolve( {
headers: {
get: header => REPORT_2_TOTALS[ header ],
},
json: () => Promise.resolve( REPORT_2 ),
} );
}
} );
} );
it( 'returns requested report data', async () => {
expect.assertions( 1 );
const endpoint = 'revenue';
await getReportStats( endpoint, undefined );
expect( dispatch().setReportStats ).toHaveBeenCalledWith(
endpoint,
REPORT_1,
undefined,
REPORT_1_TOTALS[ 'x-wp-total' ],
REPORT_1_TOTALS[ 'x-wp-totalpages' ]
);
} );
it( 'returns requested report data for a specific query', async () => {
expect.assertions( 1 );
const endpoint = 'products';
const query = { interval: 'week' };
await getReportStats( endpoint, query );
expect( dispatch().setReportStats ).toHaveBeenCalledWith(
endpoint,
REPORT_2,
query,
REPORT_2_TOTALS[ 'x-wp-total' ],
REPORT_2_TOTALS[ 'x-wp-totalpages' ]
);
} );
} );

View File

@ -1,102 +0,0 @@
/*
* @format
*/
/**
* External dependencies
*/
import deepFreeze from 'deep-freeze';
import { select } from '@wordpress/data';
/**
* Internal dependencies
*/
import { ERROR } from 'store/constants';
import selectors from '../selectors';
const { getReportStats, isReportStatsRequesting, isReportStatsError } = selectors;
jest.mock( '@wordpress/data', () => ( {
...require.requireActual( '@wordpress/data' ),
select: jest.fn().mockReturnValue( {} ),
} ) );
const endpointName = 'revenue';
describe( 'getReportStats()', () => {
it( 'returns null when no report data is available', () => {
const state = deepFreeze( {} );
expect( getReportStats( state, endpointName ) ).toEqual( null );
} );
it( 'returns stored report information by endpoint and query combination', () => {
const report = {
totals: {
orders_count: 10,
num_items_sold: 9,
},
interval: [ 0, 1, 2 ],
};
const state = deepFreeze( {
reports: {
stats: {
revenue: {
'{}': { ...report },
},
},
},
} );
expect( getReportStats( state, endpointName ) ).toEqual( report );
} );
} );
describe( 'isReportStatsRequesting()', () => {
beforeAll( () => {
select( 'core/data' ).isResolving = jest.fn().mockReturnValue( false );
} );
afterAll( () => {
select( 'core/data' ).isResolving.mockRestore();
} );
function setIsResolving( isResolving ) {
select( 'core/data' ).isResolving.mockImplementation(
( reducerKey, selectorName ) =>
isResolving && reducerKey === 'wc-admin' && selectorName === 'getReportStats'
);
}
it( 'returns false if never requested', () => {
const result = isReportStatsRequesting( endpointName );
expect( result ).toBe( false );
} );
it( 'returns false if request finished', () => {
setIsResolving( false );
const result = isReportStatsRequesting( endpointName );
expect( result ).toBe( false );
} );
it( 'returns true if requesting', () => {
setIsResolving( true );
const result = isReportStatsRequesting( endpointName );
expect( result ).toBe( true );
} );
} );
describe( 'isReportStatsError()', () => {
it( 'returns false by default', () => {
const state = deepFreeze( {} );
expect( isReportStatsError( state, endpointName ) ).toEqual( false );
} );
it( 'returns true if ERROR constant is found', () => {
const state = deepFreeze( {
reports: {
stats: {
revenue: {
'{}': ERROR,
},
},
},
} );
expect( isReportStatsError( state, endpointName ) ).toEqual( true );
} );
} );

View File

@ -1,598 +0,0 @@
/*
* @format
*/
/**
* Internal dependencies
*/
import {
isReportDataEmpty,
getReportChartData,
getSummaryNumbers,
getFilterQuery,
getReportTableData,
timeStampFilterDates,
} from '../utils';
import * as ordersConfig from 'analytics/report/orders/config';
jest.mock( '../utils', () => ( {
...require.requireActual( '../utils' ),
getReportTableQuery: () => ( {
after: '2018-10-10',
before: '2018-10-10',
} ),
} ) );
describe( 'isReportDataEmpty()', () => {
it( 'returns false if report is valid', () => {
const report = {
data: {
totals: {
orders_count: 10,
num_items_sold: 9,
},
intervals: [ 0, 1, 2 ],
},
};
expect( isReportDataEmpty( report ) ).toEqual( false );
} );
it( 'returns true if report object is undefined', () => {
expect( isReportDataEmpty( undefined ) ).toEqual( true );
} );
it( 'returns true if data response object is missing', () => {
expect( isReportDataEmpty( {} ) ).toEqual( true );
} );
it( 'returns true if totals response object is missing', () => {
expect( isReportDataEmpty( { data: {} } ) ).toEqual( true );
} );
it( 'returns true if intervals response object is empty', () => {
expect( isReportDataEmpty( { data: { intervals: [], totals: 2 } } ) ).toEqual( true );
} );
} );
describe( 'getReportChartData()', () => {
const select = jest.fn().mockReturnValue( {} );
const response = {
isEmpty: false,
isError: false,
isRequesting: false,
data: {
totals: null,
intervals: [],
},
};
beforeAll( () => {
select( 'wc-api' ).getReportStats = jest.fn().mockReturnValue( {} );
select( 'wc-api' ).isReportStatsRequesting = jest.fn().mockReturnValue( false );
select( 'wc-api' ).getReportStatsError = jest.fn().mockReturnValue( false );
} );
afterAll( () => {
select( 'wc-api' ).getReportStats.mockRestore();
select( 'wc-api' ).isReportStatsRequesting.mockRestore();
select( 'wc-api' ).getReportStatsError.mockRestore();
} );
function setGetReportStats( func ) {
select( 'wc-api' ).getReportStats.mockImplementation( ( ...args ) => func( ...args ) );
}
function setIsReportStatsRequesting( func ) {
select( 'wc-api' ).isReportStatsRequesting.mockImplementation( ( ...args ) => func( ...args ) );
}
function setGetReportStatsError( func ) {
select( 'wc-api' ).getReportStatsError.mockImplementation( ( ...args ) => func( ...args ) );
}
it( 'returns isRequesting if first request is in progress', () => {
setIsReportStatsRequesting( () => {
return true;
} );
const result = getReportChartData( 'revenue', 'primary', {}, select );
expect( result ).toEqual( { ...response, isRequesting: true } );
} );
it( 'returns isError if first request errors', () => {
setIsReportStatsRequesting( () => {
return false;
} );
setGetReportStatsError( () => {
return { error: 'Error' };
} );
const result = getReportChartData( 'revenue', 'primary', {}, select );
expect( result ).toEqual( { ...response, isError: true } );
} );
it( 'returns results after single page of data', () => {
const data = {
totals: {
orders_count: 115,
gross_revenue: 13966.92,
},
intervals: [
{
interval: 'day',
date_start: '2018-07-01 00:00:00',
subtotals: {
orders_count: 115,
gross_revenue: 13966.92,
},
},
],
};
setIsReportStatsRequesting( () => {
return false;
} );
setGetReportStatsError( () => {
return undefined;
} );
setGetReportStats( () => {
return {
totalResults: 1,
data,
};
} );
const result = getReportChartData( 'revenue', 'primary', {}, select );
expect( result ).toEqual( { ...response, data: { ...data } } );
} );
it( 'returns combined results for multiple pages of data', () => {
const totalResults = 110;
const orders_count = 115;
const gross_revenue = 13966.92;
const intervals = [];
for ( let i = 0; i < totalResults; i++ ) {
intervals.push( {
interval: 'day',
date_start: '2018-07-01 00:00:00',
subtotals: { orders_count, gross_revenue },
} );
}
const totals = {
orders_count: orders_count * totalResults,
gross_revenue: gross_revenue * totalResults,
};
setIsReportStatsRequesting( () => {
return false;
} );
setGetReportStatsError( () => {
return undefined;
} );
setGetReportStats( ( endpoint, query ) => {
if ( 2 === query.page ) {
return {
totalResults,
data: {
totals,
intervals: intervals.slice( 100, 110 ),
},
};
}
return {
totalResults,
data: {
totals,
intervals: intervals.slice( 0, 100 ),
},
};
} );
const actualResponse = getReportChartData( 'revenue', 'primary', {}, select );
const expectedResponse = {
...response,
data: {
totals,
intervals,
},
};
expect( actualResponse ).toEqual( expectedResponse );
} );
it( 'returns isRequesting if additional requests are in progress', () => {
setIsReportStatsRequesting( ( endpoint, query ) => {
if ( 2 === query.page ) {
return true;
}
return false;
} );
setGetReportStatsError( () => {
return undefined;
} );
const result = getReportChartData( 'revenue', 'primary', {}, select );
expect( result ).toEqual( { ...response, isRequesting: true } );
} );
it( 'returns isError if additional requests return an error', () => {
setIsReportStatsRequesting( () => {
return false;
} );
setGetReportStatsError( ( endpoint, query ) => {
if ( 2 === query.page ) {
return { error: 'Error' };
}
return undefined;
} );
const result = getReportChartData( 'revenue', 'primary', {}, select );
expect( result ).toEqual( { ...response, isError: true } );
} );
it( 'returns empty state if a query returns no data', () => {
setIsReportStatsRequesting( () => {
return false;
} );
setGetReportStatsError( () => {
return undefined;
} );
setGetReportStats( () => {
return {
totalResults: undefined,
data: {},
};
} );
const result = getReportChartData( 'revenue', 'primary', {}, select );
expect( result ).toEqual( { ...response, isEmpty: true } );
} );
} );
describe( 'getSummaryNumbers()', () => {
const select = jest.fn().mockReturnValue( {} );
const response = {
isError: false,
isRequesting: false,
totals: {
primary: null,
secondary: null,
},
};
const query = {
after: '2018-10-10',
before: '2018-10-10',
period: 'custom',
compare: 'previous_period',
};
beforeAll( () => {
select( 'wc-api' ).getReportStats = jest.fn().mockReturnValue( {} );
select( 'wc-api' ).isReportStatsRequesting = jest.fn().mockReturnValue( false );
select( 'wc-api' ).getReportStatsError = jest.fn().mockReturnValue( false );
} );
afterAll( () => {
select( 'wc-api' ).getReportStats.mockRestore();
select( 'wc-api' ).isReportStatsRequesting.mockRestore();
select( 'wc-api' ).getReportStatsError.mockRestore();
} );
function setGetReportStats( func ) {
select( 'wc-api' ).getReportStats.mockImplementation( ( ...args ) => func( ...args ) );
}
function setIsReportStatsRequesting( func ) {
select( 'wc-api' ).isReportStatsRequesting.mockImplementation( ( ...args ) => func( ...args ) );
}
function setGetReportStatsError( func ) {
select( 'wc-api' ).getReportStatsError.mockImplementation( ( ...args ) => func( ...args ) );
}
it( 'returns isRequesting if a request is in progress', () => {
setIsReportStatsRequesting( () => {
return true;
} );
const result = getSummaryNumbers( 'revenue', query, select );
expect( result ).toEqual( { ...response, isRequesting: true } );
} );
it( 'returns isError if request errors', () => {
setIsReportStatsRequesting( () => {
return false;
} );
setGetReportStatsError( () => {
return { error: 'Error' };
} );
const result = getSummaryNumbers( 'revenue', query, select );
expect( result ).toEqual( { ...response, isError: true } );
} );
it( 'returns results after queries finish', () => {
const totals = {
primary: {
orders_count: 115,
gross_revenue: 13966.92,
},
secondary: {
orders_count: 85,
gross_revenue: 10406.1,
},
};
setIsReportStatsRequesting( () => {
return false;
} );
setGetReportStatsError( () => {
return undefined;
} );
setGetReportStats( () => {
return {
totals,
};
} );
setGetReportStats( ( endpoint, _query ) => {
if ( '2018-10-10T00:00:00+00:00' === _query.after ) {
return {
data: {
totals: totals.primary,
intervals: [],
},
};
}
return {
data: {
totals: totals.secondary,
intervals: [],
},
};
} );
const result = getSummaryNumbers( 'revenue', query, select );
expect( result ).toEqual( { ...response, totals } );
} );
} );
describe( 'getFilterQuery', () => {
/**
* Mock the orders config
*/
const filters = [
{
param: 'filter',
filters: [
{ value: 'top_meal', query: { lunch: 'burritos' } },
{ value: 'top_dessert', query: { dinner: 'ice_cream' } },
{ value: 'compare-cuisines', settings: { param: 'region' } },
{
value: 'food_destination',
subFilters: [
{ value: 'choose_a_european_city', settings: { param: 'european_cities' } },
],
},
],
},
];
const advancedFilters = {
filters: {
mexican: {
rules: [ { value: 'is' }, { value: 'is_not' } ],
},
french: {
rules: [ { value: 'includes' }, { value: 'excludes' } ],
},
},
};
ordersConfig.filters = filters;
ordersConfig.advancedFilters = advancedFilters;
it( 'should return an empty object if no filter param is given', () => {
const query = {};
const filterQuery = getFilterQuery( 'orders', query );
expect( filterQuery ).toEqual( {} );
} );
it( 'should return an empty object if filter parameter is not in configs', () => {
const query = { filter: 'canned_meat' };
const filterQuery = getFilterQuery( 'orders', query );
expect( filterQuery ).toEqual( {} );
} );
it( 'should return the query for an advanced filter', () => {
const query = { filter: 'advanced', mexican_is: 'delicious' };
const filterQuery = getFilterQuery( 'orders', query );
expect( filterQuery ).toEqual( { mexican_is: 'delicious', match: 'all' } );
} );
it( 'should ignore other queries not defined by filter configs', () => {
const query = {
filter: 'advanced',
mexican_is_not: 'healthy',
orderby: 'calories',
topping: 'salsa-verde',
};
const filterQuery = getFilterQuery( 'orders', query );
expect( filterQuery ).toEqual( { mexican_is_not: 'healthy', match: 'all' } );
} );
it( 'should apply the match parameter advanced filters', () => {
const query = {
filter: 'advanced',
french_includes: 'le-fromage',
match: 'any',
};
const filterQuery = getFilterQuery( 'orders', query );
expect( filterQuery ).toEqual( { french_includes: 'le-fromage', match: 'any' } );
} );
it( 'should return the query for compare filters', () => {
const query = { filter: 'compare-cuisines', region: 'vietnam,malaysia,thailand' };
const filterQuery = getFilterQuery( 'orders', query );
expect( filterQuery ).toEqual( { region: 'vietnam,malaysia,thailand' } );
} );
it( 'should return the query for subFilters', () => {
const query = { filter: 'choose_a_european_city', european_cities: 'paris,rome,barcelona' };
const filterQuery = getFilterQuery( 'orders', query );
expect( filterQuery ).toEqual( { european_cities: 'paris,rome,barcelona' } );
} );
} );
describe( 'getReportTableData()', () => {
const select = jest.fn().mockReturnValue( {} );
const response = {
isError: false,
isRequesting: false,
items: {
data: [],
},
};
const query = {
after: '2018-10-10',
before: '2018-10-10',
};
beforeAll( () => {
select( 'wc-api' ).getReportItems = jest.fn().mockReturnValue( {} );
select( 'wc-api' ).isReportItemsRequesting = jest.fn().mockReturnValue( false );
select( 'wc-api' ).getReportItemsError = jest.fn().mockReturnValue( undefined );
} );
afterAll( () => {
select( 'wc-api' ).getReportItems.mockRestore();
select( 'wc-api' ).isReportItemsRequesting.mockRestore();
select( 'wc-api' ).getReportItemsError.mockRestore();
} );
function setGetReportItems( func ) {
select( 'wc-api' ).getReportItems.mockImplementation( ( ...args ) => func( ...args ) );
}
function setIsReportItemsRequesting( func ) {
select( 'wc-api' ).isReportItemsRequesting.mockImplementation( ( ...args ) => func( ...args ) );
}
function setGetReportItemsError( func ) {
select( 'wc-api' ).getReportItemsError.mockImplementation( ( ...args ) => func( ...args ) );
}
it( 'returns isRequesting if a request is in progress', () => {
setIsReportItemsRequesting( () => true );
const result = getReportTableData( 'coupons', query, select );
expect( result ).toEqual( { ...response, query, isRequesting: true } );
expect( select( 'wc-api' ).getReportItems ).toHaveBeenLastCalledWith( 'coupons', query );
expect( select( 'wc-api' ).isReportItemsRequesting ).toHaveBeenLastCalledWith(
'coupons',
query
);
expect( select( 'wc-api' ).getReportItemsError ).toHaveBeenCalledTimes( 0 );
} );
it( 'returns isError if request errors', () => {
setIsReportItemsRequesting( () => false );
setGetReportItemsError( () => ( { error: 'Error' } ) );
const result = getReportTableData( 'coupons', query, select );
expect( result ).toEqual( { ...response, query, isError: true } );
expect( select( 'wc-api' ).getReportItems ).toHaveBeenLastCalledWith( 'coupons', query );
expect( select( 'wc-api' ).isReportItemsRequesting ).toHaveBeenLastCalledWith(
'coupons',
query
);
expect( select( 'wc-api' ).getReportItemsError ).toHaveBeenLastCalledWith( 'coupons', query );
} );
it( 'returns results after queries finish', () => {
const items = [ { id: 1 }, { id: 2 }, { id: 3 } ];
setIsReportItemsRequesting( () => false );
setGetReportItemsError( () => undefined );
setGetReportItems( () => items );
const result = getReportTableData( 'coupons', query, select );
expect( result ).toEqual( { ...response, query, items } );
expect( select( 'wc-api' ).getReportItems ).toHaveBeenLastCalledWith( 'coupons', query );
expect( select( 'wc-api' ).isReportItemsRequesting ).toHaveBeenLastCalledWith(
'coupons',
query
);
expect( select( 'wc-api' ).getReportItemsError ).toHaveBeenLastCalledWith( 'coupons', query );
} );
} );
describe( 'timeStampFilterDates', () => {
const advancedFilters = {
filters: {
city: {
input: { component: 'Search' },
},
my_date: {
input: { component: 'Date' },
},
},
};
it( 'should not change activeFilters not using the Date component', () => {
const activeFilter = {
key: 'name',
rule: 'is',
value: 'New York',
};
const timeStampedActiveFilter = timeStampFilterDates( advancedFilters, activeFilter );
expect( timeStampedActiveFilter ).toMatchObject( activeFilter );
} );
it( 'should append timestamps to activeFilters using the Date component', () => {
const activeFilter = {
key: 'my_date',
rule: 'after',
value: '2018-04-04',
};
const timeStampedActiveFilter = timeStampFilterDates( advancedFilters, activeFilter );
expect( timeStampedActiveFilter.value ).toBe( '2018-04-04T00:00:00+00:00' );
} );
it( 'should append start of day for "after" rule', () => {
const activeFilter = {
key: 'my_date',
rule: 'after',
value: '2018-04-04',
};
const timeStampedActiveFilter = timeStampFilterDates( advancedFilters, activeFilter );
expect( timeStampedActiveFilter.value ).toBe( '2018-04-04T00:00:00+00:00' );
} );
it( 'should append end of day for "before" rule', () => {
const activeFilter = {
key: 'my_date',
rule: 'before',
value: '2018-04-04',
};
const timeStampedActiveFilter = timeStampFilterDates( advancedFilters, activeFilter );
expect( timeStampedActiveFilter.value ).toBe( '2018-04-04T23:59:59+00:00' );
} );
it( 'should handle "between" values', () => {
const activeFilter = {
key: 'my_date',
rule: 'before',
value: [ '2018-04-04', '2018-04-10' ],
};
const timeStampedActiveFilter = timeStampFilterDates( advancedFilters, activeFilter );
expect( Array.isArray( timeStampedActiveFilter.value ) ).toBe( true );
expect( timeStampedActiveFilter.value ).toHaveLength( 2 );
expect( timeStampedActiveFilter.value[ 0 ] ).toContain( 'T00:00:00+00:00' );
expect( timeStampedActiveFilter.value[ 1 ] ).toContain( 'T23:59:59+00:00' );
} );
} );