Skip to content

Commit

Permalink
test(checkout): CHECKOUT-8926 add RTL tests for guest customer step u…
Browse files Browse the repository at this point in the history
…se cases
  • Loading branch information
richapatel1510 committed Jan 22, 2025
1 parent cf153bb commit d34cae6
Show file tree
Hide file tree
Showing 3 changed files with 342 additions and 0 deletions.
125 changes: 125 additions & 0 deletions packages/core/src/app/customer/Customer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { CheckoutService, createCheckoutService, createEmbeddedCheckoutMessenger, EmbeddedCheckoutMessenger } from "@bigcommerce/checkout-sdk";
import userEvent from "@testing-library/user-event";
import { noop } from "lodash";
import React, { FunctionComponent } from 'react';

import { AnalyticsContextProps, AnalyticsEvents, AnalyticsProviderMock } from "@bigcommerce/checkout/analytics";
import { ExtensionProvider } from "@bigcommerce/checkout/checkout-extension";
import { getLanguageService, LocaleProvider } from "@bigcommerce/checkout/locale";
import { CHECKOUT_ROOT_NODE_ID, CheckoutProvider } from "@bigcommerce/checkout/payment-integration-api";
import { cartWithBillingEmail, CheckoutPageNodeObject } from "@bigcommerce/checkout/test-framework";
import { render, screen } from "@bigcommerce/checkout/test-utils";

import Checkout, { CheckoutProps } from "../checkout/Checkout";
import { createErrorLogger } from "../common/error";
import { createEmbeddedCheckoutStylesheet, createEmbeddedCheckoutSupport } from "../embeddedCheckout";

describe('Customer Component', () => {
let checkout: CheckoutPageNodeObject;
let CheckoutTest: FunctionComponent<CheckoutProps>;
let checkoutService: CheckoutService;
let defaultProps: CheckoutProps & AnalyticsContextProps;
let embeddedMessengerMock: EmbeddedCheckoutMessenger;
let analyticsTracker: AnalyticsEvents;

beforeAll(() => {
checkout = new CheckoutPageNodeObject();
checkout.goto();
});

afterEach(() => {
checkout.resetHandlers();
});

afterAll(() => {
checkout.close();
});

beforeEach(() => {
window.scrollTo = jest.fn();

checkoutService = createCheckoutService();
embeddedMessengerMock = createEmbeddedCheckoutMessenger({
parentOrigin: 'https://store.url',
});
analyticsTracker = {
checkoutBegin: jest.fn(),
trackStepCompleted: jest.fn(),
trackStepViewed: jest.fn(),
orderPurchased: jest.fn(),
customerEmailEntry: jest.fn(),
customerSuggestionInit: jest.fn(),
customerSuggestionExecute: jest.fn(),
customerPaymentMethodExecuted: jest.fn(),
showShippingMethods: jest.fn(),
selectedPaymentMethod: jest.fn(),
clickPayButton: jest.fn(),
paymentRejected: jest.fn(),
paymentComplete: jest.fn(),
exitCheckout: jest.fn(),
walletButtonClick: jest.fn(),
};
defaultProps = {
checkoutId: 'x',
containerId: CHECKOUT_ROOT_NODE_ID,
createEmbeddedMessenger: () => embeddedMessengerMock,
embeddedStylesheet: createEmbeddedCheckoutStylesheet(),
embeddedSupport: createEmbeddedCheckoutSupport(getLanguageService()),
errorLogger: createErrorLogger(),
analyticsTracker,
};

jest.spyOn(defaultProps.errorLogger, 'log').mockImplementation(noop);

CheckoutTest = (props) => (
<CheckoutProvider checkoutService={checkoutService}>
<LocaleProvider checkoutService={checkoutService}>
<AnalyticsProviderMock>
<ExtensionProvider
checkoutService={checkoutService}
errorLogger={{
log: jest.fn(),
}}
>
<Checkout {...props} />
</ExtensionProvider>
</AnalyticsProviderMock>
</LocaleProvider>
</CheckoutProvider>
);
});

it('edit guest customer email', async () => {
checkout.use('CartWithBillingEmail');

render(<CheckoutTest {...defaultProps} />);

await checkout.waitForShippingStep();

expect(screen.getByText('[email protected]')).toBeInTheDocument();

await userEvent.click(screen.getByRole('button', {
name: 'Edit'
}))

await checkout.waitForCustomerStep();
await userEvent.clear(await screen.findByLabelText('Email'));
await userEvent.type(await screen.findByLabelText('Email'), '[email protected]');

checkout.updateCheckout(
'put',
'/checkouts/xxxxxxxxxx-xxxx-xxax-xxxx-xxxxxx/billing-address/undefined',
{
...cartWithBillingEmail,
billingAddress: {
...cartWithBillingEmail.billingAddress,
email: '[email protected]',
}
}
);

await userEvent.click(await screen.findByText('Continue'));

expect(screen.getByText('[email protected]')).toBeInTheDocument();
});
});
216 changes: 216 additions & 0 deletions packages/core/src/app/customer/CustomerGuest.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import '@testing-library/jest-dom';
import {
Cart,
Checkout,
CheckoutSelectors,
CheckoutService,
createCheckoutService,
Customer as CustomerData,
StoreConfig,
} from '@bigcommerce/checkout-sdk';
import faker from '@faker-js/faker';
import userEvent from '@testing-library/user-event';
import { c } from 'msw/lib/glossary-2792c6da';
import React, { FunctionComponent } from 'react';

import { AnalyticsProviderMock } from '@bigcommerce/checkout/analytics';
import { createLocaleContext, LocaleContext, LocaleContextType } from '@bigcommerce/checkout/locale';
import { CheckoutProvider } from '@bigcommerce/checkout/payment-integration-api';
import { render, screen, waitFor, within } from '@bigcommerce/checkout/test-utils';

import { getBillingAddress } from '../billing/billingAddresses.mock';
import { getCart } from '../cart/carts.mock';
import { getCheckout } from '../checkout/checkouts.mock';
import { getStoreConfig } from '../config/config.mock';

import Customer, { CustomerProps, WithCheckoutCustomerProps } from './Customer';
import { getGuestCustomer } from './customers.mock';
import CustomerViewType from './CustomerViewType';

describe('Customer Guest', () => {
let CustomerTest: FunctionComponent<CustomerProps & Partial<WithCheckoutCustomerProps>>;
let checkoutService: CheckoutService;
let localeContext: LocaleContextType;
let checkout: Checkout;
let cart: Cart;
let config: StoreConfig;
let customer: CustomerData;
const defaultProps = {
isSubscribed: false,
isWalletButtonsOnTop: false,
onSubscribeToNewsletter: jest.fn(),
step: {} as CheckoutStepStatus,
};

beforeEach(() => {
checkoutService = createCheckoutService();
localeContext = createLocaleContext(getStoreConfig());
checkout = getCheckout();
cart = getCart();
customer = getGuestCustomer();
config = getStoreConfig();

jest.spyOn(checkoutService.getState().data, 'getCheckout').mockReturnValue(checkout);

jest.spyOn(checkoutService.getState().data, 'getCart').mockReturnValue(cart);

jest.spyOn(checkoutService.getState().data, 'getConfig').mockReturnValue(config);

jest.spyOn(checkoutService, 'loadPaymentMethods').mockResolvedValue(
checkoutService.getState(),
);

jest.spyOn(checkoutService, 'initializeCustomer').mockResolvedValue(
checkoutService.getState(),
);

jest.spyOn(checkoutService.getState().data, 'getPaymentMethods').mockReturnValue([]);

CustomerTest = (props) => (
<CheckoutProvider checkoutService={checkoutService}>
<LocaleContext.Provider value={localeContext}>
<AnalyticsProviderMock>
<Customer {...props} />
</AnalyticsProviderMock>
</LocaleContext.Provider>
</CheckoutProvider>
);
});

it('renders guest form and continue as guest', async () => {
const email = faker.internet.email();

jest.spyOn(checkoutService, 'continueAsGuest').mockResolvedValue({} as CheckoutSelectors);

render(<CustomerTest viewType={CustomerViewType.Guest} {...defaultProps} />);

expect(screen.getByTestId('checkout-customer-guest')).toBeInTheDocument();
expect(screen.getByLabelText(
localeContext.language.translate('customer.email_label'),
)).toBeInTheDocument();

await userEvent.type(screen.getByLabelText(
localeContext.language.translate('customer.email_label'),
), email);

await userEvent.click(screen.getByRole('button', {
name: localeContext.language.translate('customer.continue')
}));

expect(checkoutService.continueAsGuest).toHaveBeenCalledWith({
email,
});
});

it('displays error message if email is not valid', async () => {
jest.spyOn(checkoutService, 'continueAsGuest').mockResolvedValue({} as CheckoutSelectors);

render(<CustomerTest viewType={CustomerViewType.Guest} {...defaultProps} />);

expect(screen.getByTestId('checkout-customer-guest')).toBeInTheDocument();

const invalidEmail = 'test@test.';
const emailField = screen.getByLabelText(localeContext.language.translate('customer.email_label'));

expect(emailField).toBeInTheDocument();
await userEvent.type(emailField, invalidEmail);

await userEvent.click(screen.getByRole('button', {
name: localeContext.language.translate('customer.continue')
}));

expect(screen.getByLabelText(localeContext.language.translate('customer.email_invalid_error'))).toBeInTheDocument();

expect(checkoutService.continueAsGuest).not.toHaveBeenCalled();

const email = faker.internet.email();

await userEvent.clear(emailField);
await userEvent.type(emailField, email);

await userEvent.click(screen.getByRole('button', {
name: localeContext.language.translate('customer.continue')
}));

expect(checkoutService.continueAsGuest).toHaveBeenCalledWith({
email,
});
});

it('displays error message if privacy policy is required and not checked', async () => {
const email = faker.internet.email();

jest.spyOn(checkoutService.getState().data, 'getConfig').mockReturnValue({
...config,
checkoutSettings: {
...config.checkoutSettings,
privacyPolicyUrl: 'foo',
},
});
jest.spyOn(checkoutService, 'continueAsGuest').mockResolvedValue({} as CheckoutSelectors);

render(<CustomerTest viewType={CustomerViewType.Guest} {...defaultProps} />);

expect(screen.getByTestId('checkout-customer-guest')).toBeInTheDocument();
expect(screen.getByLabelText(
localeContext.language.translate('customer.email_label'),
)).toBeInTheDocument();

await userEvent.type(screen.getByLabelText(
localeContext.language.translate('customer.email_label'),
), email);

await userEvent.click(screen.getByRole('button', {
name: localeContext.language.translate('customer.continue')
}));

expect(screen.getByLabelText(localeContext.language.translate('privacy_policy.required_error'))).toBeInTheDocument();

expect(checkoutService.continueAsGuest).not.toHaveBeenCalled();

const link = screen.getByText('privacy policy');

expect(link).toBeInTheDocument();
expect(link).toHaveAttribute('href', 'foo');

expect(screen.getByTestId('privacy-policy-checkbox')).toBeInTheDocument();
await userEvent.click(screen.getByTestId('privacy-policy-checkbox'));

await userEvent.click(screen.getByRole('button', {
name: localeContext.language.translate('customer.continue')
}));

expect(checkoutService.continueAsGuest).toHaveBeenCalledWith({
email,
});

});

it('checks subscribe to news letter and continue as guest', async () => {
const email = faker.internet.email();

jest.spyOn(checkoutService, 'continueAsGuest').mockResolvedValue({} as CheckoutSelectors);

render(<CustomerTest viewType={CustomerViewType.Guest} {...defaultProps} />);

const emailField = screen.getByLabelText(localeContext.language.translate('customer.email_label'));

await userEvent.type(emailField, email);

const subscribeCheckbox = screen.getByLabelText(
localeContext.language.translate('customer.guest_subscribe_to_newsletter_text'),
);

await userEvent.click(subscribeCheckbox);

await userEvent.click(screen.getByRole('button', {
name: localeContext.language.translate('customer.continue')
}));

expect(checkoutService.continueAsGuest).toHaveBeenCalledWith({
email,
acceptsAbandonedCartEmails: true,
acceptsMarketingNewsletter: true,
});
});
});
1 change: 1 addition & 0 deletions packages/test-framework/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './fixture/pagePreset';
export {
CheckoutPageNodeObject,
cartReadyForMultiShipping,
cartWithBillingEmail,
consignment,
shippingAddress2,
shippingAddress3,
Expand Down

0 comments on commit d34cae6

Please sign in to comment.