Skip to content

Commit

Permalink
[Cashier-V2] george / FEQ-1998 / Add tests for Payment Agent Withdraw…
Browse files Browse the repository at this point in the history
…al module (#14436)

* feat(cashier-v2): ⚡ add payment agent withdrawal module

* test(cashier-v2): 🧪 add tests for payment agent withdrawal module components

* perf(cashier-v2): 🎨 replace successfull state with status

* test: 🧪 improve tests

* fix: 🚑 fix conflict

* fix: tests
  • Loading branch information
heorhi-deriv authored Apr 2, 2024
1 parent 2ebda39 commit d5db594
Show file tree
Hide file tree
Showing 10 changed files with 605 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { PageContainer } from '../../components';
import { PaymentAgentWithdrawalModule, WithdrawalVerificationModule } from '../../lib';

const PaymentAgent = () => {
const [verificationCode, setVerificationCode] = useState('1');
const [verificationCode, setVerificationCode] = useState('');

useEffect(() => {
const queryParams = new URLSearchParams(location.search);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import PaymentAgent from '../PaymentAgent';

jest.mock('../../../lib', () => ({
...jest.requireActual('../../../lib'),
PaymentAgentWithdrawalModule: jest.fn(() => <div>PaymentAgentWithdrawalModule</div>),
WithdrawalVerificationModule: jest.fn(() => <div>WithdrawalVerificationModule</div>),
}));

jest.mock('../../../components', () => ({
...jest.requireActual('../../../components'),
PageContainer: jest.fn(({ children }) => <>{children}</>),
}));

describe('<PaymentAgent />', () => {
const originalWindowLocation = window.location;

beforeEach(() => {
Object.defineProperty(window, 'location', {
value: new URL('http://localhost/redirect?verification=1234'),
writable: true,
});
});

afterEach(() => {
Object.defineProperty(window, 'location', {
configurable: true,
value: originalWindowLocation,
});
});

it('should remove the `verification` param from the window url', () => {
const replaceStateSpy = jest.spyOn(window.history, 'replaceState');

render(<PaymentAgent />);

expect(replaceStateSpy).toBeCalledWith({}, '', 'http://localhost/redirect');
});

it('should render withdrawal email verification page if no verification code found', () => {
Object.defineProperty(window, 'location', {
value: new URL('http://localhost/redirect'),
writable: true,
});

render(<PaymentAgent />);
expect(screen.getByText('WithdrawalVerificationModule')).toBeInTheDocument();
});

it('should render payment agent withdrawal module', () => {
render(<PaymentAgent />);
expect(screen.getByText('PaymentAgentWithdrawalModule')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ const PaymentAgentWithdrawal = () => {
Choose your preferred payment agent and enter your withdrawal amount. If your payment agent is not
listed,{' '}
<Text className={styles['unlisted-withdrawal-link']} color='red' size='sm' weight='bold'>
<span onClick={showUnlistedWithdrawalForm} onKeyDown={showUnlistedWithdrawalForm}>
<span
data-testid='dt_unlisted_withdrawal_link'
onClick={showUnlistedWithdrawalForm}
onKeyDown={showUnlistedWithdrawalForm}
>
search for them using their account number
</span>
</Text>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React from 'react';
import userEvent from '@testing-library/user-event';
import { render, screen } from '@testing-library/react';
import PaymentAgentWithdrawal from '../PaymentAgentWithdrawal';
import { usePaymentAgentContext } from '../../provider';
import { usePaymentAgentWithdrawalContext } from '../provider';

const mockedUsePaymentAgentContext = usePaymentAgentContext as jest.MockedFunction<typeof usePaymentAgentContext>;
const mockedUsePaymentAgentWithdrawalContext = usePaymentAgentWithdrawalContext as jest.MockedFunction<
typeof usePaymentAgentWithdrawalContext
>;

jest.mock('@deriv-com/ui', () => ({
...jest.requireActual('@deriv-com/ui'),
Loader: jest.fn(() => <div>Loader</div>),
}));
jest.mock('../../provider', () => ({
PaymentAgentProvider: jest.fn(({ children }) => <div>{children}</div>),
usePaymentAgentContext: jest.fn(() => ({ isPaymentAgentListLoading: false })),
}));

let mockedSetIsUnlistedWithdrawal: jest.MockedFunction<typeof jest.fn>;

jest.mock('../provider', () => ({
PaymentAgentWithdrawalProvider: jest.fn(({ children }) => <div>{children}</div>),
usePaymentAgentWithdrawalContext: jest.fn(() => ({
isTryWithdrawalSuccessful: false,
isUnlistedWithdrawal: false,
isWithdrawalSuccessful: false,
setIsUnlistedWithdrawal: mockedSetIsUnlistedWithdrawal,
})),
}));

jest.mock('../../components', () => ({
PaymentAgentList: jest.fn(() => <div>PaymentAgentList</div>),
PaymentAgentSearchContainer: jest.fn(() => <div>PaymentAgentSearchContainer</div>),
}));

jest.mock('../components', () => ({
PaymentAgentUnlistedWithdrawalForm: jest.fn(() => <div>PaymentAgentUnlistedWithdrawalForm</div>),
PaymentAgentWithdrawalConfirm: jest.fn(() => <div>PaymentAgentWithdrawalConfirm</div>),
PaymentAgentWithdrawalReceipt: jest.fn(() => <div>PaymentAgentWithdrawalReceipt</div>),
}));

describe('PaymentAgentWithdrawal', () => {
let mockedProps: React.ComponentProps<typeof PaymentAgentWithdrawal>;

beforeEach(() => {
mockedProps = {
setVerificationCode: jest.fn(),
verificationCode: 'code',
};
mockedSetIsUnlistedWithdrawal = jest.fn();
});

it('should render proper title and PaymentAgentSearchContainer by default', () => {
render(<PaymentAgentWithdrawal {...mockedProps} />);

expect(
screen.getByText(
/Choose your preferred payment agent and enter your withdrawal amount. If your payment agent is not listed,/
)
).toBeInTheDocument();
expect(screen.getByText(/search for them using their account number/)).toBeInTheDocument();
expect(screen.getByText('PaymentAgentSearchContainer')).toBeInTheDocument();
});

it('should trigger setIsUnlistedWithdrawal callback when the suer is clicking on "search for them using their account number" text', () => {
render(<PaymentAgentWithdrawal {...mockedProps} />);

const unlistedWithdrawalLink = screen.getByTestId('dt_unlisted_withdrawal_link');
userEvent.click(unlistedWithdrawalLink);

expect(mockedSetIsUnlistedWithdrawal).toHaveBeenCalledWith(true);
});

it('should show loader when isPaymentAgentListLoading equals to true', () => {
//@ts-expect-error since this is a mock, we only need partial properties of data
mockedUsePaymentAgentContext.mockReturnValueOnce({ isPaymentAgentListLoading: true });

render(<PaymentAgentWithdrawal {...mockedProps} />);

expect(screen.getByText('Loader')).toBeInTheDocument();
});

it('should show PaymentAgentWithdrawalConfirm when withdrawalStatus equals to `try_successful`', () => {
//@ts-expect-error since this is a mock, we only need partial properties of data
mockedUsePaymentAgentWithdrawalContext.mockReturnValueOnce({ withdrawalStatus: 'try_successful' });

render(<PaymentAgentWithdrawal {...mockedProps} />);

expect(screen.getByText('PaymentAgentWithdrawalConfirm')).toBeInTheDocument();
});

it('should show PaymentAgentWithdrawalReceipt when withdrawalStatus equals to `successful`', () => {
//@ts-expect-error since this is a mock, we only need partial properties of data
mockedUsePaymentAgentWithdrawalContext.mockReturnValueOnce({ withdrawalStatus: 'successful' });

render(<PaymentAgentWithdrawal {...mockedProps} />);

expect(screen.getByText('PaymentAgentWithdrawalReceipt')).toBeInTheDocument();
});

it('should show PaymentAgentUnlistedWithdrawalForm when isUnlistedWithdrawal equals to true', () => {
//@ts-expect-error since this is a mock, we only need partial properties of data
mockedUsePaymentAgentWithdrawalContext.mockReturnValueOnce({ isUnlistedWithdrawal: true });

render(<PaymentAgentWithdrawal {...mockedProps} />);

expect(screen.getByText('PaymentAgentUnlistedWithdrawalForm')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import userEvent from '@testing-library/user-event';
import { render, screen, waitFor } from '@testing-library/react';
import PaymentAgentUnlistedWithdrawalForm from '../PaymentAgentUnlistedWithdrawalForm';

const mockedRequestTryPaymentAgentWithdrawal = jest.fn();

jest.mock('@deriv/api-v2', () => ({
...jest.requireActual('@deriv/api-v2'),
useActiveAccount: jest.fn(() => ({ data: { currency_config: { display_code: 'USD' } } })),
}));

jest.mock('../../../../PaymentAgentWithdrawal/provider', () => ({
usePaymentAgentWithdrawalContext: jest.fn(() => ({
requestTryPaymentAgentWithdrawal: mockedRequestTryPaymentAgentWithdrawal,
getPaymentAgentWithdrawalValidationSchema: jest.fn(),
setIsUnlistedWithdrawal: jest.fn(),
})),
}));

describe('PaymentAgentUnlistedWithdrawalForm', () => {
it('should show Back to list title and icon', () => {
render(<PaymentAgentUnlistedWithdrawalForm />);

const title = screen.getByText('Back to list');
const backArrowIcon = screen.getByTestId('dt-back-arrow-icon');

expect(title).toBeInTheDocument();
expect(backArrowIcon).toBeInTheDocument();
});

it('continue button should be disabled by default', () => {
render(<PaymentAgentUnlistedWithdrawalForm />);

const continueBtn = screen.getByRole('button', {
name: 'Continue',
});

expect(continueBtn).toBeDisabled();
});

it('should trigger requestTryPaymentAgentWithdrawal callback when submitting the form', async () => {
render(<PaymentAgentUnlistedWithdrawalForm />);

const accountNumberInput = screen.getAllByRole('textbox')[0];
const amountInput = screen.getAllByRole('textbox')[1];
const continueBtn = screen.getByRole('button', {
name: 'Continue',
});

userEvent.type(accountNumberInput, 'CR1234567');
userEvent.type(amountInput, '100');
userEvent.click(continueBtn);

await waitFor(() => {
expect(mockedRequestTryPaymentAgentWithdrawal).toHaveBeenCalledWith({
paymentagent_loginid: 'CR1234567',
amount: 100,
});
});
});

it('should show proper note', () => {
render(<PaymentAgentUnlistedWithdrawalForm />);

const note = screen.getByText('Note: Deriv does not charge any transfer fees.');

expect(note).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import Icon from '../../../../../../../assets/images/ic-cashier-add.svg';
import PaymentAgentReceiptDetail from '../PaymentAgentReceiptDetail';

jest.mock('@deriv-com/ui', () => ({
...jest.requireActual('@deriv-com/ui'),
useDevice: jest.fn(() => ({ isMobile: false })),
}));

describe('PaymentAgentCardDetail', () => {
let mockedProps: React.ComponentProps<typeof PaymentAgentReceiptDetail>;

beforeEach(() => {
mockedProps = {
children: ['+375291234567', '+375297654321'],
icon: Icon,
action: 'tel',
};
});

it('should render detail icon', () => {
render(<PaymentAgentReceiptDetail {...mockedProps} />);

const icon = screen.getByTestId('dt_detail_icon');

expect(icon).toBeInTheDocument();
});

it('should render one detail', () => {
render(<PaymentAgentReceiptDetail {...mockedProps} action={undefined} children='Payment agent detail' />);

expect(screen.getByText('Payment agent detail')).toBeInTheDocument();
});

it('should render details array', () => {
render(<PaymentAgentReceiptDetail {...mockedProps} />);

expect(screen.getByText(/375291234567/)).toBeInTheDocument();
expect(screen.getByText(/375297654321/)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const PaymentAgentWithdrawalReceipt = () => {
</div>
</div>
{paymentAgentName && (
<div className={styles['details-wrapper']}>
<div className={styles['details-wrapper']} data-testid='dt_details_section'>
<Text align='center' as='p' size='xs' weight='bold'>{`${paymentAgentName}'s contact details`}</Text>
<div className={styles.details}>
{paymentAgentPhoneNumbers.length > 0 && (
Expand Down
Loading

0 comments on commit d5db594

Please sign in to comment.