Skip to content

Commit

Permalink
Fix zero total checkout use case. Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sirugh committed Feb 23, 2021
1 parent 6420448 commit b261791
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 11 deletions.
8 changes: 4 additions & 4 deletions packages/peregrine/lib/talons/CheckoutPage/useCheckoutPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ export const useCheckoutPage = (props = {}) => {

return {
activeContent,
availablePaymentMethods: checkoutData
? checkoutData.cart.available_payment_methods
: null,
cartItems,
checkoutStep,
customer,
Expand All @@ -241,9 +244,6 @@ export const useCheckoutPage = (props = {}) => {
handleReviewOrder,
reviewOrderButtonClicked,
toggleAddressBookContent,
toggleSignInContent,
availablePaymentMethods: checkoutData
? checkoutData.cart.available_payment_methods
: null
toggleSignInContent
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ exports[`CheckoutPage renders address book for customer 1`] = `
<div
className="checkoutContent_hidden"
>
<FormError
classes={
Object {
"root": "formErrors",
}
}
errors={Array []}
/>
<div
className="heading_container"
>
Expand Down Expand Up @@ -84,6 +92,143 @@ exports[`CheckoutPage renders address book for customer 1`] = `
</div>
`;

exports[`CheckoutPage renders an error and disables review order button if there is no payment method 1`] = `
<div
className="root"
>
Title
<div
className="checkoutContent"
>
<FormError
classes={
Object {
"root": "formErrors",
}
}
errors={
Array [
[Error: Payment is currently unavailable.],
]
}
/>
<div
className="heading_container"
>
<StockStatusMessage
cartItems={Array []}
message={
<React.Fragment>
<FormattedMessage
defaultMessage="An item in your cart is currently out-of-stock and must be removed in order to Checkout. Please return to your cart to remove the item."
id="checkoutPage.stockStatusMessage"
/>
<Link
className="cartLink"
to="/cart"
>
<FormattedMessage
defaultMessage="Return to Cart"
id="checkoutPage.returnToCart"
/>
</Link>
</React.Fragment>
}
/>
<h1
className="heading"
>
Guest Checkout
</h1>
</div>
<div
className="signInContainer"
>
<span
className="signInLabel"
>
<mock-FormattedMessage
defaultMessage="Sign in for Express Checkout"
id="checkoutPage.signInLabel"
/>
</span>
<button
className="signInButton"
disabled={false}
onClick={[MockFunction toggleSignInContent]}
type="button"
>
<span
className="content"
>
<mock-FormattedMessage
defaultMessage="Sign In"
id="checkoutPage.signInButton"
/>
</span>
</button>
</div>
<div
className="shipping_information_container"
>
<ShippingInformation
onSave={[MockFunction setShippingInformationDone]}
toggleActiveContent={[MockFunction toggleAddressBookContent]}
/>
</div>
<div
className="shipping_method_container"
>
<ShippingMethod
onSave={[MockFunction setShippingMethodDone]}
pageIsUpdating={true}
setPageIsUpdating={[MockFunction setIsUpdating]}
/>
</div>
<div
className="payment_information_container"
>
<PaymentInformation
checkoutError={false}
onSave={[MockFunction setPaymentInformationDone]}
/>
</div>
<div
className="price_adjustments_container"
>
<PriceAdjustments
setPageIsUpdating={[MockFunction setIsUpdating]}
/>
</div>
<button
className="review_order_button"
disabled={true}
type="button"
>
<span
className="content"
>
<mock-FormattedMessage
defaultMessage="Review Order"
id="checkoutPage.reviewOrder"
/>
</span>
</button>
<div
className="summaryContainer"
>
<OrderSummary
isUpdating={true}
/>
</div>
</div>
<GuestSignIn
isActive={false}
toggleActiveContent={[MockFunction toggleSignInContent]}
/>
</div>
`;

exports[`CheckoutPage renders checkout content for customer - default address 1`] = `
<div
className="root"
Expand All @@ -92,6 +237,14 @@ exports[`CheckoutPage renders checkout content for customer - default address 1`
<div
className="checkoutContent"
>
<FormError
classes={
Object {
"root": "formErrors",
}
}
errors={Array []}
/>
<div
className="heading_container"
>
Expand Down Expand Up @@ -176,6 +329,14 @@ exports[`CheckoutPage renders checkout content for customer - no default address
<div
className="checkoutContent"
>
<FormError
classes={
Object {
"root": "formErrors",
}
}
errors={Array []}
/>
<div
className="heading_container"
>
Expand Down Expand Up @@ -260,6 +421,14 @@ exports[`CheckoutPage renders checkout content for guest 1`] = `
<div
className="checkoutContent"
>
<FormError
classes={
Object {
"root": "formErrors",
}
}
errors={Array []}
/>
<div
className="heading_container"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@magento/peregrine/lib/talons/CheckoutPage/useCheckoutPage';
import CheckoutPage from '../checkoutPage';
import OrderConfirmationPage from '../OrderConfirmationPage';
import FormError from '../../FormError';

jest.mock('@magento/peregrine', () => {
const actual = jest.requireActual('@magento/peregrine');
Expand Down Expand Up @@ -36,6 +37,7 @@ jest.mock('@magento/peregrine/lib/talons/CheckoutPage/useCheckoutPage', () => {
jest.mock('../../../classify');

jest.mock('../../../components/Head', () => ({ Title: () => 'Title' }));
jest.mock('../../FormError', () => 'FormError');
jest.mock('../../StockStatusMessage', () => 'StockStatusMessage');
jest.mock('../ItemsReview', () => 'ItemsReview');
jest.mock('../GuestSignIn', () => 'GuestSignIn');
Expand All @@ -52,6 +54,7 @@ jest.mock('../AddressBook', () => 'AddressBook');

const defaultTalonProps = {
activeContent: 'checkout',
availablePaymentMethods: [{ code: 'braintree' }],
cartItems: [],
checkoutStep: 1,
customer: null,
Expand All @@ -74,9 +77,9 @@ const defaultTalonProps = {
setShippingMethodDone: jest.fn().mockName('setShippingMethodDone'),
setPaymentInformationDone: jest.fn().mockName('setPaymentInformationDone'),
toggleAddressBookContent: jest.fn().mockName('toggleAddressBookContent'),
toggleSignInContent: jest.fn().mockName('toggleSignInContent'),
availablePaymentMethods: [{ code: 'braintree' }]
toggleSignInContent: jest.fn().mockName('toggleSignInContent')
};

describe('CheckoutPage', () => {
test('throws a toast if there is an error', () => {
useCheckoutPage.mockReturnValueOnce({
Expand Down Expand Up @@ -215,4 +218,25 @@ describe('CheckoutPage', () => {
expect(priceAdjustmentsComponent.props).toMatchSnapshot();
expect(reviewOrderButtonComponent.props).toMatchSnapshot();
});

test('renders an error and disables review order button if there is no payment method', () => {
useCheckoutPage.mockReturnValueOnce({
...defaultTalonProps,
checkoutStep: CHECKOUT_STEP.PAYMENT,
isUpdating: true,
availablePaymentMethods: []
});

const tree = createTestInstance(<CheckoutPage />);
const formErrorComponent = tree.root.findByType(FormError);
const reviewOrderButtonComponent = tree.root.findByProps({
className: 'review_order_button'
});

expect(tree).toMatchSnapshot();
expect(formErrorComponent.props.errors[0]).toEqual(
new Error('Payment is currently unavailable.')
);
expect(reviewOrderButtonComponent.props.disabled).toBe(true);
});
});
11 changes: 6 additions & 5 deletions packages/venia-ui/lib/components/CheckoutPage/checkoutPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const CheckoutPage = props => {
* SHIPPING_ADDRESS, SHIPPING_METHOD, PAYMENT, REVIEW
*/
activeContent,
availablePaymentMethods,
cartItems,
checkoutStep,
customer,
Expand All @@ -65,8 +66,7 @@ const CheckoutPage = props => {
handleReviewOrder,
reviewOrderButtonClicked,
toggleAddressBookContent,
toggleSignInContent,
availablePaymentMethods
toggleSignInContent
} = talonProps;

const [, { addToast }] = useToasts();
Expand Down Expand Up @@ -176,9 +176,10 @@ const CheckoutPage = props => {
const formErrors = [];
const paymentMethods = Object.keys(payments);

// If we don't have an implementation for a method type, ignore it.
const isPaymentAvailable = !!availablePaymentMethods.find(({ code }) =>
paymentMethods.includes(code)
// If we have an implementation, or if this is a "zero" checkout,
// we can allow checkout to proceed.
const isPaymentAvailable = !!availablePaymentMethods.find(
({ code }) => code === 'free' || paymentMethods.includes(code)
);

if (!isPaymentAvailable) {
Expand Down

0 comments on commit b261791

Please sign in to comment.