Skip to content

Commit

Permalink
Click to Pay - Adding unit tests (#2502)
Browse files Browse the repository at this point in the history
* feat: mc test

* feat: more tests

* logout tests

* test for ctplogin
  • Loading branch information
ribeiroguilherme authored Jan 10, 2024
1 parent a701162 commit 9acef96
Show file tree
Hide file tree
Showing 10 changed files with 859 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { ComponentChildren, h } from 'preact';
import { ClickToPayContext, IClickToPayContext } from '../../context/ClickToPayContext';
import { render, screen } from '@testing-library/preact';
import CoreProvider from '../../../../../core/Context/CoreProvider';
import { mock } from 'jest-mock-extended';
import CtPLogin from './CtPLogin';
import userEvent from '@testing-library/user-event';
import SrciError from '../../services/sdks/SrciError';

const customRender = (children: ComponentChildren, providerProps: IClickToPayContext) => {
return render(
// @ts-ignore TODO: Fix this weird complain
<CoreProvider i18n={global.i18n} loadingContext="test" resources={global.resources}>
{/* eslint-disable-next-line react/no-children-prop */}
<ClickToPayContext.Provider value={{ ...providerProps }} children={children} />
</CoreProvider>
);
};

test('should set CTP to primary payment method if shopper interacts with the login input', async () => {
const user = userEvent.setup();

const contextProps = mock<IClickToPayContext>();
contextProps.isCtpPrimaryPaymentMethod = false;
contextProps.schemes = ['mc', 'visa'];
contextProps.setIsCtpPrimaryPaymentMethod.mockImplementation(isPrimary => {
contextProps.isCtpPrimaryPaymentMethod = isPrimary;
});

const { rerender } = customRender(<CtPLogin />, contextProps);

let button = await screen.findByRole('button', { name: 'Continue' });
expect(button).toHaveClass('adyen-checkout__button--secondary');

const input = await screen.findByLabelText('Email');

await user.click(input);
await user.keyboard('shopper@example.com');

rerender(customRender(<CtPLogin />, contextProps));

expect(contextProps.setIsCtpPrimaryPaymentMethod).toHaveBeenCalledWith(true);

button = await screen.findByRole('button', { name: 'Continue' });
expect(button).not.toHaveClass('adyen-checkout__button--secondary');
});

test('should not start the user login if the email is invalid', async () => {
const user = userEvent.setup();

const contextProps = mock<IClickToPayContext>();
contextProps.isCtpPrimaryPaymentMethod = true;
contextProps.setIsCtpPrimaryPaymentMethod.mockImplementation(() => {});
contextProps.verifyIfShopperIsEnrolled.mockRejectedValue(
new SrciError({ reason: 'ID_FORMAT_UNSUPPORTED', message: '' }, 'verifyIfShopperIsEnrolled', 'visa')
);
contextProps.schemes = ['mc', 'visa'];

customRender(<CtPLogin />, contextProps);

const input = await screen.findByLabelText('Email');
await user.click(input);
await user.keyboard('my.invalid.email@example');

const button = await screen.findByRole('button', { name: 'Continue' });
await user.click(button);

expect(contextProps.startIdentityValidation).toHaveBeenCalledTimes(0);
expect(input).toBeInvalid();
expect(await screen.findByText('Format not supported')).toBeInTheDocument();
expect(button).not.toHaveClass('adyen-checkout__button--loading');
});

test('should display not found if the email is not registered', async () => {
const user = userEvent.setup();

const contextProps = mock<IClickToPayContext>();
contextProps.isCtpPrimaryPaymentMethod = true;
contextProps.setIsCtpPrimaryPaymentMethod.mockImplementation(() => {});
contextProps.verifyIfShopperIsEnrolled.mockResolvedValue({ isEnrolled: false });
contextProps.startIdentityValidation.mockImplementation();
contextProps.schemes = ['mc', 'visa'];

customRender(<CtPLogin />, contextProps);

const input = await screen.findByLabelText('Email');
await user.click(input);
await user.keyboard('my.invalid.email@example');

const button = await screen.findByRole('button', { name: 'Continue' });
await user.click(button);

expect(contextProps.startIdentityValidation).toHaveBeenCalledTimes(0);
expect(input).toBeInvalid();
expect(await screen.findByText('No account found, enter a valid email or continue using manual card entry')).toBeInTheDocument();
expect(button).not.toHaveClass('adyen-checkout__button--loading');
});

test('should start the identity validation if the user is enrolled', async () => {
const user = userEvent.setup();

const contextProps = mock<IClickToPayContext>();
contextProps.isCtpPrimaryPaymentMethod = true;
contextProps.setIsCtpPrimaryPaymentMethod.mockImplementation(() => {});
contextProps.verifyIfShopperIsEnrolled.mockResolvedValue({ isEnrolled: true });
contextProps.startIdentityValidation.mockImplementation();
contextProps.schemes = ['mc', 'visa'];

customRender(<CtPLogin />, contextProps);

const input = await screen.findByLabelText('Email');
await user.click(input);
await user.keyboard('shopper@email.com');

const button = await screen.findByRole('button', { name: 'Continue' });
await user.click(button);

expect(contextProps.startIdentityValidation).toHaveBeenCalledTimes(1);
expect(button).toHaveClass('adyen-checkout__button--loading');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { ComponentChildren, h } from 'preact';
import { mock } from 'jest-mock-extended';
import { render, screen } from '@testing-library/preact';
import userEvent from '@testing-library/user-event';
import { ClickToPayContext, IClickToPayContext } from '../../context/ClickToPayContext';
import CtPLogoutLink from './CtPLogoutLink';
import { CtpState } from '../../services/ClickToPayService';
import ShopperCard from '../../models/ShopperCard';
import CoreProvider from '../../../../../core/Context/CoreProvider';

const customRender = (children: ComponentChildren, providerProps: IClickToPayContext) => {
return render(
// @ts-ignore TODO: Fix this weird complain
<CoreProvider i18n={global.i18n} loadingContext="test" resources={global.resources}>
{/* eslint-disable-next-line react/no-children-prop */}
<ClickToPayContext.Provider value={{ ...providerProps }} children={children} />
</CoreProvider>
);
};

test('should not render if shopper is not recognized', async () => {
const contextProps = mock<IClickToPayContext>();
contextProps.ctpState = CtpState.Login;

const { container } = customRender(<CtPLogoutLink />, contextProps);

// @ts-ignore FIX TYPES
expect(container).toBeEmptyDOMElement();
});

test('should render i18n message of ctp.logout.notYourCards if there are multiple cards available', async () => {
const user = userEvent.setup();

const contextProps = mock<IClickToPayContext>();
contextProps.ctpState = CtpState.Ready;
contextProps.cards = [mock<ShopperCard>(), mock<ShopperCard>(), mock<ShopperCard>()];
contextProps.logoutShopper.mockImplementation();

customRender(<CtPLogoutLink />, contextProps);
expect(await screen.findByRole('button', { name: 'Not your cards?' })).toBeTruthy();

await user.click(screen.getByRole('button', { name: 'Not your cards?' }));
expect(contextProps.logoutShopper).toHaveBeenCalledTimes(1);
});

test('should render i18n message of ctp.logout.notYourCard if there is only one card available', async () => {
const user = userEvent.setup();

const contextProps = mock<IClickToPayContext>();
contextProps.ctpState = CtpState.Ready;
contextProps.cards = [mock<ShopperCard>()];
contextProps.logoutShopper.mockImplementation();

customRender(<CtPLogoutLink />, contextProps);
expect(await screen.findByRole('button', { name: 'Not your card?' })).toBeTruthy();

await user.click(screen.getByRole('button', { name: 'Not your card?' }));
expect(contextProps.logoutShopper).toHaveBeenCalledTimes(1);
});

test('should render i18n message of ctp.logout.notYourProfile if there is no card available', async () => {
const user = userEvent.setup();

const contextProps = mock<IClickToPayContext>();
contextProps.ctpState = CtpState.Ready;
contextProps.cards = [];
contextProps.logoutShopper.mockImplementation();

customRender(<CtPLogoutLink />, contextProps);
expect(await screen.findByRole('button', { name: 'Not your profile?' })).toBeTruthy();

await user.click(screen.getByRole('button', { name: 'Not your profile?' }));
expect(contextProps.logoutShopper).toHaveBeenCalledTimes(1);
});

test('should render i18n message of ctp.logout.notYou if the shopper is going through OTP ', async () => {
const user = userEvent.setup();

const contextProps = mock<IClickToPayContext>();
contextProps.ctpState = CtpState.OneTimePassword;
contextProps.logoutShopper.mockImplementation();

customRender(<CtPLogoutLink />, contextProps);
expect(await screen.findByRole('button', { name: 'Not you?' })).toBeTruthy();

await user.click(screen.getByRole('button', { name: 'Not you?' }));
expect(contextProps.logoutShopper).toHaveBeenCalledTimes(1);
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import useClickToPayContext from '../../context/useClickToPayContext';
import { CtpState } from '../../services/ClickToPayService';
import classnames from 'classnames';
import { useMemo } from 'preact/hooks';
import './CtPLogoutLink.scss';
import useCoreContext from '../../../../../core/Context/useCoreContext';
import './CtPLogoutLink.scss';

const CtPLogoutLink = (): h.JSX.Element => {
const CtPLogoutLink = () => {
const { ctpState, logoutShopper, status, cards } = useClickToPayContext();
const { i18n } = useCoreContext();

Expand Down
Loading

0 comments on commit 9acef96

Please sign in to comment.