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:
parent
7592dae4bb
commit
833345dfee
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 ] );
|
|
@ -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 );
|
||||
};
|
|
@ -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 || {},
|
||||
};
|
||||
},
|
||||
};
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
},
|
||||
};
|
|
@ -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 );
|
||||
},
|
||||
};
|
|
@ -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 );
|
||||
} );
|
||||
} );
|
|
@ -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 } );
|
||||
} );
|
||||
} );
|
|
@ -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 );
|
||||
} );
|
||||
} );
|
|
@ -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 || {},
|
||||
};
|
||||
},
|
||||
};
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
},
|
||||
};
|
|
@ -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 );
|
||||
},
|
||||
};
|
|
@ -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 );
|
||||
} );
|
||||
} );
|
|
@ -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' } );
|
||||
} );
|
||||
} );
|
|
@ -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 );
|
||||
} );
|
||||
} );
|
|
@ -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,
|
||||
},
|
||||
};
|
|
@ -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 || {},
|
||||
};
|
||||
},
|
||||
};
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
},
|
||||
};
|
|
@ -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 );
|
||||
},
|
||||
};
|
|
@ -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 );
|
||||
} );
|
||||
} );
|
|
@ -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
|
||||
);
|
||||
} );
|
||||
} );
|
|
@ -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 );
|
||||
} );
|
||||
} );
|
|
@ -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 || {},
|
||||
};
|
||||
},
|
||||
};
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
},
|
||||
};
|
|
@ -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 );
|
||||
},
|
||||
};
|
|
@ -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 );
|
||||
} );
|
||||
} );
|
|
@ -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' ]
|
||||
);
|
||||
} );
|
||||
} );
|
|
@ -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 );
|
||||
} );
|
||||
} );
|
|
@ -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' );
|
||||
} );
|
||||
} );
|
Loading…
Reference in New Issue