Skip to content

Commit

Permalink
chore: Updating Payment State Polling to use a Custom Routine
Browse files Browse the repository at this point in the history
  • Loading branch information
grmartin committed Jul 5, 2023
1 parent d37cd30 commit 2a40aa0
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 8 deletions.
10 changes: 6 additions & 4 deletions src/payment/data/actions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createRoutine } from 'redux-saga-routines';
import { createCustomRoutine } from './utils';

// Routines are action + action creator pairs in a series.
// Actions adhere to the flux standard action format.
Expand All @@ -10,8 +11,11 @@ import { createRoutine } from 'redux-saga-routines';
// fetchBasket.SUCCESS | fetchBasket.success()
// fetchBasket.FAILURE | fetchBasket.failure()
// fetchBasket.FULFILL | fetchBasket.fulfill()
// fetchBasket.REQUEST | fetchBasket.request()
// fetchBasket.<CUSTOM> | fetchBasket.<custom>()
//
// Created with redux-saga-routines

export const fetchCaptureKey = createRoutine('FETCH_CAPTURE_KEY');
export const fetchClientSecret = createRoutine('FETCH_CLIENT_SECRET');
export const submitPayment = createRoutine('SUBMIT_PAYMENT');
Expand All @@ -20,7 +24,7 @@ export const fetchActiveOrder = createRoutine('FETCH_ACTIVE_ORDER');
export const addCoupon = createRoutine('ADD_COUPON');
export const removeCoupon = createRoutine('REMOVE_COUPON');
export const updateQuantity = createRoutine('UPDATE_QUANTITY');
export const pollPaymentState = createRoutine('UPDATE_PAYMENT_STATE');
export const pollPaymentState = createCustomRoutine('UPDATE_PAYMENT_STATE', ['RECEIVED']);

// Actions and their action creators
export const BASKET_DATA_RECEIVED = 'BASKET_DATA_RECEIVED';
Expand Down Expand Up @@ -77,9 +81,7 @@ export const clientSecretDataReceived = clientSecret => ({
payload: clientSecret,
});

export const PAYMENT_STATE_DATA_RECEIVED = 'PAYMENT_STATE_DATA_RECEIVED';

export const paymentStateDataReceived = paymentState => ({
type: PAYMENT_STATE_DATA_RECEIVED,
type: pollPaymentState.RECEIVED,
payload: paymentState,
});
3 changes: 1 addition & 2 deletions src/payment/data/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
CLIENT_SECRET_DATA_RECEIVED,
CLIENT_SECRET_PROCESSING,
MICROFORM_STATUS,
PAYMENT_STATE_DATA_RECEIVED,
fetchBasket,
submitPayment,
fetchCaptureKey,
Expand Down Expand Up @@ -197,7 +196,7 @@ const paymentState = (state = basketInitialState, action = null) => {
},
};

case PAYMENT_STATE_DATA_RECEIVED:
case pollPaymentState.RECEIVED:
return {
...state,
paymentState: action.payload.state,
Expand Down
3 changes: 1 addition & 2 deletions src/payment/data/redux.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
fetchBasket,
fetchActiveOrder,
pollPaymentState,
PAYMENT_STATE_DATA_RECEIVED,
} from './actions';
import { currencyDisclaimerSelector, paymentSelector } from './selectors';
import { localizedCurrencySelector } from './utils';
Expand Down Expand Up @@ -258,7 +257,7 @@ describe('redux tests', () => {
expect(triggerStore.getState().payment.basket.paymentStatePolling.keepPolling).toBe(true);
expect(triggerStore.getState().payment.basket.paymentState).toBe(PAYMENT_STATE.PENDING);

triggerStore.dispatch({ type: PAYMENT_STATE_DATA_RECEIVED, payload: { state: PAYMENT_STATE.COMPLETED } });
triggerStore.dispatch({ type: pollPaymentState.RECEIVED, payload: { state: PAYMENT_STATE.COMPLETED } });
expect(triggerStore.getState().payment.basket.paymentStatePolling.keepPolling).toBe(false);
expect(triggerStore.getState().payment.basket.paymentState).toBe(PAYMENT_STATE.COMPLETED);

Expand Down
15 changes: 15 additions & 0 deletions src/payment/data/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import camelCase from 'lodash.camelcase';
import snakeCase from 'lodash.snakecase';
import { getConfig } from '@edx/frontend-platform';
import Cookies from 'universal-cookie';
import { createRoutineCreator, defaultRoutineStages } from 'redux-saga-routines';
import { ORDER_TYPES } from './constants';

export function modifyObjectKeys(object, modify) {
Expand Down Expand Up @@ -273,3 +274,17 @@ export const chainReducers = (reducers) => {
);
};
};

/**
* Create a Routine with Custom Steps
* @param {string} name Name of the Routine
* @param {string[]} addtlStages An Array of Additional Steps (these will be uppercased)
* @param {boolean=} keepDefaults If we should include the normal Routine Steps
* @returns {*} A Redux Saga Routine
*/
export function createCustomRoutine(name, addtlStages, keepDefaults = true) {
return createRoutineCreator([
...(keepDefaults ? defaultRoutineStages : []),
...addtlStages.map(x => x.toUpperCase()),
])(name);
}
49 changes: 49 additions & 0 deletions src/payment/data/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Factory } from 'rosie';
import '../__factories__/basket.factory';

import { defaultRoutineStages } from 'redux-saga-routines';
import { ORDER_TYPES } from './constants';
import {
AsyncActionType,
Expand All @@ -17,6 +18,7 @@ import {
SECS_AS_MS,
MINS_AS_MS,
chainReducers,
createCustomRoutine,
} from './utils';

describe('modifyObjectKeys', () => {
Expand Down Expand Up @@ -370,3 +372,50 @@ describe('chainReducers([reducers])', () => {
expect(firstStateResult.second_reducer_value).toEqual(undefined);
});
});

describe('createCustomRoutine', () => {
const tests = [
{
name: 'Additional Stage (UC) + Inherts Default Stages',
params: { name: 'TEST_ROUTINE_1', addtlStages: ['MEOW'], inheritDefaults: true },
},
{
name: 'Additional Stage (LC) + Inherts Default Stages',
params: { name: 'TEST_ROUTINE_2', addtlStages: ['meow'], inheritDefaults: true },
},
{
name: 'Additional Stage (LC) + Doesnt Inherit Default Stages',
params: { name: 'TEST_ROUTINE_3', addtlStages: ['woof'], inheritDefaults: false },
},
];

for (let i = 0, testPlan = tests[i]; i < tests.length; i++, testPlan = tests[i]) {
it(testPlan.name, () => {
/* eslint-disable no-underscore-dangle */ // We don't control the fact that we have to access _ props here.
const routineUnderTest = createCustomRoutine(
testPlan.params.name,
testPlan.params.addtlStages,
testPlan.params.inheritDefaults,
);

expect(routineUnderTest._PREFIX).toEqual(testPlan.params.name);

for (let si = 0, stageName = defaultRoutineStages[si];
si < defaultRoutineStages.length;
si++, stageName = defaultRoutineStages[si]) {
if (testPlan.params.inheritDefaults) {
expect(routineUnderTest._STAGES).toContain(stageName);
} else {
expect(routineUnderTest._STAGES).not.toContain(stageName);
}
}

for (let si = 0, stageName = testPlan.params.addtlStages[si];
si < testPlan.params.addtlStages.length;
si++, stageName = testPlan.params.addtlStages[si]) {
expect(routineUnderTest._STAGES).toContain(stageName.toUpperCase());
}
/* eslint-enable no-underscore-dangle */
});
}
});

0 comments on commit 2a40aa0

Please sign in to comment.