Skip to content

Commit

Permalink
feat(redux): add packaging options redux
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagodicosta committed Feb 14, 2024
1 parent 1e22c37 commit 1fa1bc5
Show file tree
Hide file tree
Showing 18 changed files with 328 additions and 0 deletions.
9 changes: 9 additions & 0 deletions packages/redux/src/__tests__/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,9 @@ Object {
"FETCH_COLLECT_POINTS_FAILURE": "@farfetch/blackout-redux/FETCH_COLLECT_POINTS_FAILURE",
"FETCH_COLLECT_POINTS_REQUEST": "@farfetch/blackout-redux/FETCH_COLLECT_POINTS_REQUEST",
"FETCH_COLLECT_POINTS_SUCCESS": "@farfetch/blackout-redux/FETCH_COLLECT_POINTS_SUCCESS",
"FETCH_PACKAGING_OPTIONS_FAILURE": "@farfetch/blackout-redux/FETCH_PACKAGING_OPTIONS_FAILURE",
"FETCH_PACKAGING_OPTIONS_REQUEST": "@farfetch/blackout-redux/FETCH_PACKAGING_OPTIONS_REQUEST",
"FETCH_PACKAGING_OPTIONS_SUCCESS": "@farfetch/blackout-redux/FETCH_PACKAGING_OPTIONS_SUCCESS",
"REMOVE_CHECKOUT_ORDER_CONTEXT_FAILURE": "@farfetch/blackout-redux/REMOVE_CHECKOUT_ORDER_CONTEXT_FAILURE",
"REMOVE_CHECKOUT_ORDER_CONTEXT_REQUEST": "@farfetch/blackout-redux/REMOVE_CHECKOUT_ORDER_CONTEXT_REQUEST",
"REMOVE_CHECKOUT_ORDER_CONTEXT_SUCCESS": "@farfetch/blackout-redux/REMOVE_CHECKOUT_ORDER_CONTEXT_SUCCESS",
Expand Down Expand Up @@ -733,6 +736,8 @@ Object {
"fetchOrderItemAvailableActivitiesFactory": [Function],
"fetchOrderReturnOptions": [Function],
"fetchOrderReturnOptionsFactory": [Function],
"fetchPackagingOptions": [Function],
"fetchPackagingOptionsFactory": [Function],
"fetchPaymentIntent": [Function],
"fetchPaymentIntentCharge": [Function],
"fetchPaymentIntentChargeFactory": [Function],
Expand Down Expand Up @@ -1044,6 +1049,8 @@ Object {
"getOrderReturns": [Function],
"getOrderSummaries": [Function],
"getOrders": [Function],
"getPackagingOptionsError": [Function],
"getPackagingOptionsResult": [Function],
"getPaymentIntentChargeError": [Function],
"getPaymentIntentChargeResult": [Function],
"getPaymentIntentError": [Function],
Expand Down Expand Up @@ -1309,6 +1316,7 @@ Object {
"isLogoutLoading": [Function],
"isOrderFetched": [Function],
"isOrderLoading": [Function],
"isPackagingOptionsLoading": [Function],
"isPaymentIntentChargeLoading": [Function],
"isPaymentIntentFetched": [Function],
"isPaymentIntentLoading": [Function],
Expand Down Expand Up @@ -1477,6 +1485,7 @@ Object {
"@farfetch/blackout-redux/RESET_ORDER_RETURN_OPTIONS_ENTITIES": [Function],
},
"ordersReducer": [Function],
"packagingOptionsReducer": [Function],
"paymentsActionTypes": Object {
"CREATE_PAYMENT_INTENT_CHARGE_FAILURE": "@farfetch/blackout-redux/CREATE_PAYMENT_INTENT_CHARGE_FAILURE",
"CREATE_PAYMENT_INTENT_CHARGE_REQUEST": "@farfetch/blackout-redux/CREATE_PAYMENT_INTENT_CHARGE_REQUEST",
Expand Down
16 changes: 16 additions & 0 deletions packages/redux/src/checkout/actionTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,3 +514,19 @@ export const REMOVE_CHECKOUT_ORDER_CONTEXT_REQUEST =
*/
export const REMOVE_CHECKOUT_ORDER_CONTEXT_SUCCESS =
'@farfetch/blackout-redux/REMOVE_CHECKOUT_ORDER_CONTEXT_SUCCESS';

/**
* Action type dispatched when the packaging options request fails.
*/
export const FETCH_PACKAGING_OPTIONS_FAILURE =
'@farfetch/blackout-redux/FETCH_PACKAGING_OPTIONS_FAILURE';
/**
* Action type dispatched when the packaging options request starts.
*/
export const FETCH_PACKAGING_OPTIONS_REQUEST =
'@farfetch/blackout-redux/FETCH_PACKAGING_OPTIONS_REQUEST';
/**
* Action type dispatched when the fetch packaging options request succeeds.
*/
export const FETCH_PACKAGING_OPTIONS_SUCCESS =
'@farfetch/blackout-redux/FETCH_PACKAGING_OPTIONS_SUCCESS';
1 change: 1 addition & 0 deletions packages/redux/src/checkout/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * as checkoutActionTypes from './actionTypes.js';

export * from './actions/index.js';
export * from './actions/factories/index.js';
export * from './packaging/index.js';
export * from './selectors.js';

export {
Expand Down
59 changes: 59 additions & 0 deletions packages/redux/src/checkout/packaging/__tests__/reducer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as actionTypes from '../../actionTypes.js';
import reducer, * as fromReducer from '../reducer.js';
import type { PackagingOptionsState } from '../types/index.js';

let initialState: PackagingOptionsState;

describe('Packaging Options reducer', () => {
beforeEach(() => {
initialState = fromReducer.INITIAL_STATE;
});

it.each([actionTypes.FETCH_PACKAGING_OPTIONS_REQUEST])(
'should handle %s action type',
actionType => {
expect(reducer(undefined, { type: actionType })).toEqual({
error: initialState.error,
isLoading: true,
result: null,
});
},
);

it.each([actionTypes.FETCH_PACKAGING_OPTIONS_FAILURE])(
'should handle %s action type',
actionType => {
const error = 'foo';
const reducerResult = reducer(undefined, {
payload: { error },
type: actionType,
});
const expectedResult = {
error,
isLoading: false,
result: null,
};

expect(reducerResult).toEqual(expectedResult);
},
);

it.each([actionTypes.FETCH_PACKAGING_OPTIONS_SUCCESS])(
'should handle %s action type',
actionType => {
const result = 'foo';

const reducerResult = reducer(undefined, {
payload: { result },
type: actionType,
});
const expectedResult = {
error: initialState.error,
isLoading: false,
result,
};

expect(reducerResult).toEqual(expectedResult);
},
);
});
47 changes: 47 additions & 0 deletions packages/redux/src/checkout/packaging/__tests__/selectors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as packagingOptionsReducer from '../reducer.js';
import * as selectors from '../selectors.js';
import { mockPackagingOptionsState } from 'tests/__fixtures__/checkout/index.mjs';
import type { StoreState } from '../../../index.js';

describe('packaging options redux selectors', () => {
beforeEach(jest.clearAllMocks);

it('should get the packaging options result property from state', () => {
const spy = jest.spyOn(packagingOptionsReducer, 'getPackagingOptions');

expect(
selectors.getPackagingOptionsResult(
mockPackagingOptionsState as StoreState,
),
).toEqual(mockPackagingOptionsState.packagingOptions.result);
expect(spy).toHaveBeenCalledWith(
mockPackagingOptionsState.packagingOptions,
);
});

it('should get the packaging options error property from state', () => {
const spy = jest.spyOn(packagingOptionsReducer, 'getPackagingOptions');

expect(
selectors.getPackagingOptionsError(
mockPackagingOptionsState as StoreState,
),
).toEqual(mockPackagingOptionsState.packagingOptions.error);
expect(spy).toHaveBeenCalledWith(
mockPackagingOptionsState.packagingOptions,
);
});

it('should get the packaging options isLoading property from state', () => {
const spy = jest.spyOn(packagingOptionsReducer, 'getPackagingOptions');

expect(
selectors.isPackagingOptionsLoading(
mockPackagingOptionsState as StoreState,
),
).toEqual(mockPackagingOptionsState.packagingOptions.isLoading);
expect(spy).toHaveBeenCalledWith(
mockPackagingOptionsState.packagingOptions,
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as actionTypes from '../../../actionTypes.js';
import {
type Config,
type GetPackagingOptions,
type GetPackagingOptionsQuery,
type PackagingOption,
toBlackoutError,
} from '@farfetch/blackout-client';
import type { Dispatch } from 'redux';

/**
* Method responsible for get all packaging options.
*
* @param getPackagingOptions - Get all packaging options.
*
* @returns Thunk factory.
*/
const fetchPackagingOptionsFactory =
(getPackagingOptions: GetPackagingOptions) =>
(query: GetPackagingOptionsQuery, config?: Config) =>
async (dispatch: Dispatch): Promise<PackagingOption[]> => {
try {
dispatch({
type: actionTypes.FETCH_PACKAGING_OPTIONS_REQUEST,
});

const result = await getPackagingOptions(query, config);

dispatch({
payload: result,
type: actionTypes.FETCH_PACKAGING_OPTIONS_SUCCESS,
});

return result;
} catch (error) {
const errorAsBlackoutError = toBlackoutError(error);

dispatch({
payload: { error: errorAsBlackoutError },
type: actionTypes.FETCH_PACKAGING_OPTIONS_FAILURE,
});

throw errorAsBlackoutError;
}
};

export default fetchPackagingOptionsFactory;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Packaging options actions factories.
*/

export { default as fetchPackagingOptionsFactory } from './fetchPackagingOptionsFactory.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { fetchPackagingOptionsFactory } from './factories/index.js';
import { getPackagingOptions } from '@farfetch/blackout-client';

/**
* Fetch all packaging options.
*/
export default fetchPackagingOptionsFactory(getPackagingOptions);
5 changes: 5 additions & 0 deletions packages/redux/src/checkout/packaging/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Packaging actions.
*/

export { default as fetchPackagingOptions } from './fetchPackagingOptions.js';
5 changes: 5 additions & 0 deletions packages/redux/src/checkout/packaging/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './actions/index.js';
export * from './actions/factories/index.js';
export * from './types/index.js';
export { default as packagingOptionsReducer } from './reducer.js';
export * from './selectors.js';
69 changes: 69 additions & 0 deletions packages/redux/src/checkout/packaging/reducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as actionTypes from './../actionTypes.js';
import { type AnyAction, combineReducers } from 'redux';
import { createReducerWithResult } from '../../helpers/reducerFactory.js';
import type { PackagingOptionsState } from './index.js';

export const INITIAL_STATE: PackagingOptionsState = {
error: null,
result: null,
isLoading: false,
};

export const packagingOptions = createReducerWithResult(
'FETCH_PACKAGING_OPTIONS',
INITIAL_STATE,
actionTypes,
);

const error = (
state = INITIAL_STATE.error,
action: AnyAction,
): PackagingOptionsState['error'] => {
switch (action.type) {
case actionTypes.FETCH_PACKAGING_OPTIONS_FAILURE:
return action.payload.error;
case actionTypes.FETCH_PACKAGING_OPTIONS_REQUEST:
return INITIAL_STATE.error;
default:
return state;
}
};

const isLoading = (
state = INITIAL_STATE.isLoading,
action: AnyAction,
): PackagingOptionsState['isLoading'] => {
switch (action.type) {
case actionTypes.FETCH_PACKAGING_OPTIONS_REQUEST:
return true;
case actionTypes.FETCH_PACKAGING_OPTIONS_SUCCESS:
case actionTypes.FETCH_PACKAGING_OPTIONS_FAILURE:
return INITIAL_STATE.isLoading;
default:
return state;
}
};

const result = (
state = INITIAL_STATE.result,
action: AnyAction,
): PackagingOptionsState['result'] => {
switch (action.type) {
case actionTypes.FETCH_PACKAGING_OPTIONS_SUCCESS:
return action.payload.result;
default:
return state;
}
};

export const getPackagingOptions = (
state: PackagingOptionsState,
): PackagingOptionsState => state;

const packagingOptionsReducer = combineReducers({
result,
error,
isLoading,
});

export default packagingOptionsReducer;
33 changes: 33 additions & 0 deletions packages/redux/src/checkout/packaging/selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { getPackagingOptions } from './reducer.js';
import type { PackagingOptionsState, StoreState } from '../../index.js';

/**
* Returns the packaging options.
*
* @param state - Application state.
*
* @returns Packaging Options result.
*/
export const getPackagingOptionsResult = (state: StoreState) =>
getPackagingOptions(state.packagingOptions as PackagingOptionsState).result;

/**
* Returns the loading status for the packaging options operation.
*
* @param state - Application state.
*
* @returns Packaging Options operation Loading status.
*/
export const isPackagingOptionsLoading = (state: StoreState) =>
getPackagingOptions(state.packagingOptions as PackagingOptionsState)
.isLoading;

/**
* Returns the error status for the packaging options operation.
*
* @param state - Application state.
*
* @returns Packaging Options operation error.
*/
export const getPackagingOptionsError = (state: StoreState) =>
getPackagingOptions(state.packagingOptions as PackagingOptionsState).error;
7 changes: 7 additions & 0 deletions packages/redux/src/checkout/packaging/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { BlackoutError, PackagingOption } from '@farfetch/blackout-client';

export type PackagingOptionsState = {
result: PackagingOption[] | null;
isLoading: boolean;
error: BlackoutError | null;
};
3 changes: 3 additions & 0 deletions packages/redux/src/entities/schemas/packagingOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { schema } from 'normalizr';

export default new schema.Entity('packagingOptions');
1 change: 1 addition & 0 deletions packages/redux/src/entities/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ export * from './user.types.js';
export * from './raffle.types.js';
export * from './raffleParticipations.types.js';
export * from './raffleEstimation.types.js';
export * from './packagingOptions.types.js';
3 changes: 3 additions & 0 deletions packages/redux/src/entities/types/packagingOptions.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { PackagingOption } from '@farfetch/blackout-client';

export type PackagingOptionsEntity = PackagingOption[];
Loading

0 comments on commit 1fa1bc5

Please sign in to comment.