Skip to content

Commit

Permalink
Move checkout state code into thunks and rename CheckoutState conte…
Browse files Browse the repository at this point in the history
…xt to `CheckoutEvents` (woocommerce#6455)

* Add checkout data store

* wip on checkout data store

* CheckoutContext now uses the checkout store

* Investigated and removed setting the redirectUrl on the default state

* update extension and address hooks to use checkout data store

* use checkout data store in checkout-processor and use-checkout-button

* trim useCheckoutContext from use-payment-method-interface && use-store-cart-item-quantity

* Remove useCheckoutContext from shipping provider

* Remove isCalculating from state

* Removed useCheckoutContext from lots of places

* Remove useCheckoutContext from checkout-payment-block

* Remove useCheckoutContext in checkout-shipping-methods-block and checkout-shipping-address-block

* add isCart selector and action and update the checkoutstate context

* Fixed redirectUrl bug by using thunks

* Remove dispatchActions from checkout-state

* Change SET_HAS_ERROR action to be neater

* Thomas' feedback

* Tidy up

* Oops, deleted things I shouldn't have

* Typescript

* Fix types

* Fix tests

* Remove isCart

* Update docs and remove unecessary getRedirectUrl() selector

* validate event emitter button

* Added thunks in a separate file

* Call thunks from checkout-state

* Checkout logic tested and working

* Remove dependency injection as much as poss, tidy up and fix some TS errors

* Fix types in thunks.ts

* Fixed some ts errors

* WIP

* Fixed bug

* Shift side effects from checkout-state to checkout-processor

* Revert "Shift side effects from checkout-state to checkout-processor"

This reverts commit 059533d.

* Rename CheckoutState to CheckoutEvents

* Move status check outside the thunk

* remove duplicate EVENTS constant

* remove temp buttons

* Remove console logs

* Augment @wordpress/data package with our new store types

* Add correct type for CheckoutAction

* Remove createErrorNotice arg from runCheckoutAfterProcessingWithErrorObservers

* Remove createErrorNotice from emit event types

* Use type keyword when importing types

* Add correct types for dispatch and select in thunks

* Update wordpress/data types

* Replace store creation with new preferred method

* Set correct action type on reducer

* Remove unnecessary async from thunk

* add CHECKOUT_ prefix to checkout events again

* export EVENTS with eveything else in checkout0-events/event-emit

* Remove duplicate SelectFromMap and TailParameters

* Updated type for paymentStatus

* TODO remove wp/data experimental thunks

* Remove `setCustomerId` from events and `processCheckoutResponseHeaders` (woocommerce#6586)

* Prevent passing dispatch, instead get actions direct from store

* Get setCustomerId from the store instead of passing it to processCheckoutResponseHeaders

* Revert "Prevent passing dispatch, instead get actions direct from store"

This reverts commit 4479a2e.

* Auto stash before revert of "Prevent passing dispatch, instead get actions direct from store"

* Remove duplicate dispatch

* Fix unit tests

Co-authored-by: Thomas Roberts <[email protected]>
Co-authored-by: Thomas Roberts <[email protected]>
  • Loading branch information
3 people authored and senadir committed Nov 12, 2022
1 parent 3fa05de commit ab10fa4
Show file tree
Hide file tree
Showing 25 changed files with 16,864 additions and 4,328 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ import { ValidationInputError } from '@woocommerce/blocks-checkout';
*/
import { useStoreCart } from '../cart/use-store-cart';
import { useStoreCartCoupons } from '../cart/use-store-cart-coupons';
<<<<<<< HEAD
import { noticeContexts, responseTypes } from '../../event-emit';
import { useCheckoutEventsContext } from '../../providers/cart-checkout/checkout-events';
import { usePaymentEventsContext } from '../../providers/cart-checkout/payment-events';
=======
import { useEmitResponse } from '../use-emit-response';
import { useCheckoutEventsContext } from '../../providers/cart-checkout/checkout-events';
import { usePaymentMethodDataContext } from '../../providers/cart-checkout/payment-methods';
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
import { useShippingDataContext } from '../../providers/cart-checkout/shipping';
import { useCustomerDataContext } from '../../providers/cart-checkout/customer';
import { prepareTotalItems } from './utils';
Expand All @@ -38,6 +44,25 @@ export const usePaymentMethodInterface = (): PaymentMethodInterface => {
onCheckoutAfterProcessingWithError,
onSubmit,
} = useCheckoutEventsContext();
<<<<<<< HEAD
=======
const {
isCalculating,
isComplete,
isIdle,
isProcessing,
customerId,
} = useSelect( ( select ) => {
const store = select( CHECKOUT_STORE_KEY );
return {
isComplete: store.isComplete(),
isIdle: store.isIdle(),
isProcessing: store.isProcessing(),
customerId: store.getCustomerId(),
isCalculating: store.isCalculating(),
};
} );
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))

const { isCalculating, isComplete, isIdle, isProcessing, customerId } =
useSelect( ( select ) => {
Expand Down
26 changes: 26 additions & 0 deletions assets/js/base/context/hooks/test/use-checkout-submit.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
config as paymentDataStoreConfig,
} from '../../../../data/payment';

<<<<<<< HEAD
jest.mock( '../../providers/cart-checkout/checkout-events', () => {
const original = jest.requireActual(
'../../providers/cart-checkout/checkout-events'
Expand All @@ -28,6 +29,25 @@ jest.mock( '../../providers/cart-checkout/checkout-events', () => {
},
};
} );
=======
const mockUseCheckoutEventsContext = {
onSubmit: jest.fn(),
};
const mockUsePaymentMethodDataContext = {
activePaymentMethod: '',
currentStatus: {
isDoingExpressPayment: false,
},
};

jest.mock( '../../providers/cart-checkout/checkout-events', () => ( {
useCheckoutEventsContext: () => mockUseCheckoutEventsContext,
} ) );

jest.mock( '../../providers/cart-checkout/payment-methods', () => ( {
usePaymentMethodDataContext: () => mockUsePaymentMethodDataContext,
} ) );
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))

describe( 'useCheckoutSubmit', () => {
let registry, renderer;
Expand Down Expand Up @@ -65,6 +85,12 @@ describe( 'useCheckoutSubmit', () => {

onSubmit();

<<<<<<< HEAD
expect( onSubmit ).toHaveBeenCalledTimes( 1 );
=======
expect( mockUseCheckoutEventsContext.onSubmit ).toHaveBeenCalledTimes(
1
);
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
} );
} );
7 changes: 7 additions & 0 deletions assets/js/base/context/hooks/use-checkout-submit.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { __experimentalApplyCheckoutFilter } from '@woocommerce/blocks-checkout'
* Internal dependencies
*/
import { useCheckoutEventsContext } from '../providers';
<<<<<<< HEAD
=======
import { usePaymentMethodDataContext } from '../providers/cart-checkout/payment-methods';
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
import { usePaymentMethods } from './payment-methods/use-payment-methods';

/**
Expand Down Expand Up @@ -39,6 +43,7 @@ export const useCheckoutSubmit = () => {
( select ) => {
const store = select( PAYMENT_STORE_KEY );

<<<<<<< HEAD
return {
activePaymentMethod: store.getActivePaymentMethod(),
isExpressPaymentMethodActive:
Expand All @@ -47,6 +52,8 @@ export const useCheckoutSubmit = () => {
}
);

=======
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
const { onSubmit } = useCheckoutEventsContext();

const { paymentMethods = {} } = usePaymentMethods();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@ import {
import { usePrevious } from '@woocommerce/base-hooks';
import deprecated from '@wordpress/deprecated';
import { useDispatch, useSelect } from '@wordpress/data';
<<<<<<< HEAD
import {
CHECKOUT_STORE_KEY,
PAYMENT_STORE_KEY,
VALIDATION_STORE_KEY,
} from '@woocommerce/block-data';
=======
import { CHECKOUT_STORE_KEY } from '@woocommerce/block-data';
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))

/**
* Internal dependencies
*/
<<<<<<< HEAD
import { useEventEmitters, reducer as emitReducer } from './event-emit';
import type { emitterCallback } from '../../../event-emit';
import { STATUS } from '../../../../../data/checkout/constants';
Expand All @@ -49,6 +54,18 @@ type CheckoutEventsContextType = {
};

const CheckoutEventsContext = createContext< CheckoutEventsContextType >( {
=======
import type { CheckoutEventsContextType } from './types';
import { useEventEmitters, reducer as emitReducer } from './event-emit';
import { STATUS } from '../../../../../data/checkout/constants';
import { useValidationContext } from '../../validation';
import { useStoreEvents } from '../../../hooks/use-store-events';
import { useCheckoutNotices } from '../../../hooks/use-checkout-notices';
import { useEmitResponse } from '../../../hooks/use-emit-response';
import { CheckoutState } from '../../../../../data/checkout/default-state';

const CheckoutEventsContext = createContext( {
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
onSubmit: () => void null,
onCheckoutAfterProcessingWithSuccess: () => () => void null,
onCheckoutAfterProcessingWithError: () => () => void null,
Expand All @@ -75,6 +92,7 @@ export const CheckoutEventsProvider = ( {
children: React.ReactChildren;
redirectUrl: string;
} ): JSX.Element => {
<<<<<<< HEAD
const paymentMethods = getPaymentMethods();
const expressPaymentMethods = getExpressPaymentMethods();
const { isEditor } = useEditorContext();
Expand All @@ -101,12 +119,15 @@ export const CheckoutEventsProvider = ( {
__internalUpdateAvailablePaymentMethods,
] );

=======
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
const checkoutActions = useDispatch( CHECKOUT_STORE_KEY );
const checkoutState: CheckoutState = useSelect( ( select ) =>
select( CHECKOUT_STORE_KEY ).getCheckoutState()
);

if ( redirectUrl && redirectUrl !== checkoutState.redirectUrl ) {
<<<<<<< HEAD
checkoutActions.__internalSetRedirectUrl( redirectUrl );
}

Expand All @@ -116,6 +137,26 @@ export const CheckoutEventsProvider = ( {
const { dispatchCheckoutEvent } = useStoreEvents();
const { checkoutNotices, paymentNotices, expressPaymentNotices } =
useCheckoutNotices();
=======
checkoutActions.setRedirectUrl( redirectUrl );
}

const { setValidationErrors } = useValidationContext();
const { createErrorNotice } = useDispatch( 'core/notices' );

const { dispatchCheckoutEvent } = useStoreEvents();
const {
isSuccessResponse,
isErrorResponse,
isFailResponse,
shouldRetry,
} = useEmitResponse();
const {
checkoutNotices,
paymentNotices,
expressPaymentNotices,
} = useCheckoutNotices();
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))

const [ observers, observerDispatch ] = useReducer( emitReducer, {} );
const currentObservers = useRef( observers );
Expand Down Expand Up @@ -155,7 +196,11 @@ export const CheckoutEventsProvider = ( {
// the registered callbacks
useEffect( () => {
if ( checkoutState.status === STATUS.BEFORE_PROCESSING ) {
<<<<<<< HEAD
checkoutActions.__internalEmitValidateEvent( {
=======
checkoutActions.emitValidateEvent( {
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
observers: currentObservers.current,
setValidationErrors,
} );
Expand All @@ -181,7 +226,11 @@ export const CheckoutEventsProvider = ( {
}

if ( checkoutState.status === STATUS.AFTER_PROCESSING ) {
<<<<<<< HEAD
checkoutActions.__internalEmitAfterProcessingEvents( {
=======
checkoutActions.emitAfterProcessingEvents( {
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
observers: currentObservers.current,
notices: {
checkoutNotices,
Expand All @@ -197,10 +246,21 @@ export const CheckoutEventsProvider = ( {
checkoutState.orderId,
checkoutState.customerId,
checkoutState.orderNotes,
<<<<<<< HEAD
checkoutState.paymentResult,
previousStatus,
previousHasError,
createErrorNotice,
=======
checkoutState.processingResponse,
previousStatus,
previousHasError,
createErrorNotice,
isErrorResponse,
isFailResponse,
isSuccessResponse,
shouldRetry,
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
checkoutNotices,
expressPaymentNotices,
paymentNotices,
Expand All @@ -209,10 +269,17 @@ export const CheckoutEventsProvider = ( {

const onSubmit = useCallback( () => {
dispatchCheckoutEvent( 'submit' );
<<<<<<< HEAD
checkoutActions.__internalSetBeforeProcessing();
}, [ dispatchCheckoutEvent, checkoutActions ] );

const checkoutEventHandlers = {
=======
checkoutActions.setBeforeProcessing();
}, [ dispatchCheckoutEvent, checkoutActions ] );

const checkoutEventHandlers: CheckoutEventsContextType = {
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
onSubmit,
onCheckoutBeforeProcessing,
onCheckoutValidationBeforeProcessing,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Internal dependencies
*/
import type { emitterCallback } from '../../../event-emit';

export type CheckoutEventsContextType = {
// Submits the checkout and begins processing.
onSubmit: () => void;
// Used to register a callback that will fire after checkout has been processed and there are no errors.
onCheckoutAfterProcessingWithSuccess: ReturnType< typeof emitterCallback >;
// Used to register a callback that will fire when the checkout has been processed and has an error.
onCheckoutAfterProcessingWithError: ReturnType< typeof emitterCallback >;
// Deprecated in favour of onCheckoutValidationBeforeProcessing.
onCheckoutBeforeProcessing: ReturnType< typeof emitterCallback >;
// Used to register a callback that will fire when the checkout has been submitted before being sent off to the server.
onCheckoutValidationBeforeProcessing: ReturnType< typeof emitterCallback >;
};
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ const CheckoutProcessor = () => {
};
} );

<<<<<<< HEAD
const { __internalSetHasError, __internalProcessCheckoutResponse } =
=======
const { setHasError, processCheckoutResponse } =
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
useDispatch( CHECKOUT_STORE_KEY );

const hasValidationErrors = useSelect(
Expand Down Expand Up @@ -317,8 +321,13 @@ const CheckoutProcessor = () => {
cartNeedsShipping,
createErrorNotice,
receiveCart,
<<<<<<< HEAD
__internalSetHasError,
__internalProcessCheckoutResponse,
=======
setHasError,
processCheckoutResponse,
>>>>>>> 7e0f79e5a (Move checkout state code into thunks and rename `CheckoutState` context to `CheckoutEvents` (#6455))
] );

// Process order if conditions are good.
Expand Down
Loading

0 comments on commit ab10fa4

Please sign in to comment.