Skip to content

Commit

Permalink
[cashier-v2] aum/FEQ-1676/cashier-v2-withdrawal-fiat-module (deriv-co…
Browse files Browse the repository at this point in the history
…m#13550)

* chore: initial setup for WithdrawalFiat

* chore: replace temporary ActionScreen with deriv-com/ui instance

* feat: ✨ added the WithdrawalFiat module

* fix: fix unit tests

* refactor: migrate scss files to scss modules

* fix: fix styling for iframe

* chore: some cleanups and applied suggestions
  • Loading branch information
aum-deriv authored Feb 15, 2024
1 parent 6783d2c commit db4e225
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/cashier-v2/src/assets/images/error-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions packages/cashier-v2/src/components/ErrorScreen/ErrorScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { ActionScreen, Button } from '@deriv-com/ui';
import ErrorIcon from '../../assets/images/error-icon.svg';

type TProps = {
message?: string;
};

const ErrorState: React.FC<TProps> = ({
message = 'Sorry an error occurred. Please try accessing our cashier page again.',
}) => {
return (
<ActionScreen
actionButtons={
<Button onClick={() => window.location.reload()} size='lg' variant='ghost'>
Try again
</Button>
}
description={message}
icon={<ErrorIcon data-testid='dt_error_icon' />}
title='Oops, something went wrong!'
/>
);
};

export default ErrorState;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import ErrorScreen from '../ErrorScreen';

describe('ErrorScreen', () => {
afterAll(() => {
jest.clearAllMocks();
});

it('should show the correct title and icon with default message', () => {
render(<ErrorScreen />);
expect(screen.getByTestId('dt_error_icon')).toBeInTheDocument();
expect(screen.getByText('Oops, something went wrong!')).toBeInTheDocument();
expect(
screen.getByText('Sorry an error occurred. Please try accessing our cashier page again.')
).toBeInTheDocument();
});

it('should show the message passed as prop', () => {
render(<ErrorScreen message='Error message from props' />);
expect(screen.getByText('Error message from props')).toBeInTheDocument();
});

it('should reload the page when Try again button is clicked', () => {
const reloadMock = jest.fn();
Object.defineProperty(window, 'location', {
value: { reload: reloadMock },
writable: true,
});
render(<ErrorScreen />);
screen.getByRole('button', { name: 'Try again' }).click();
expect(reloadMock).toHaveBeenCalled();
});
});
1 change: 1 addition & 0 deletions packages/cashier-v2/src/components/ErrorScreen/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as ErrorScreen } from './ErrorScreen';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.iframe {
height: 100%;
max-width: 58.8rem;
border: none;

@include mobile-cashier-v2 {
width: 100%;
}
}
44 changes: 44 additions & 0 deletions packages/cashier-v2/src/lib/WithdrawalFiat/WithdrawalFiat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { useEffect } from 'react';
import { useCashierFiatAddress } from '@deriv/api';
import { Loader } from '@deriv-com/ui';
import { ErrorScreen } from '../../components/ErrorScreen';
import { isServerError } from '../../utils';
import styles from './WithdrawalFiat.module.scss';

type WithdrawalFiatProps = {
verificationCode?: string;
};

const WithdrawalFiat: React.FC<WithdrawalFiatProps> = ({ verificationCode }) => {
const { data: iframeUrl, error: withdrawalFiatError, isError, isLoading, mutate } = useCashierFiatAddress();

useEffect(() => {
if (verificationCode) {
mutate('withdraw', {
verification_code: verificationCode,
});
}
}, [mutate, verificationCode]);

if (isError && isServerError(withdrawalFiatError.error)) {
return <ErrorScreen message={withdrawalFiatError.error.message} />;
}

return (
<React.Fragment>
{isLoading && <Loader />}
{iframeUrl && (
<iframe
className={styles.iframe}
data-testid='dt_withdrawal_fiat_iframe'
key={iframeUrl}
src={iframeUrl}
style={{ display: isLoading ? 'none' : 'block' }}
title='withdrawal_fiat_iframe'
/>
)}
</React.Fragment>
);
};

export default WithdrawalFiat;
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react';
import { useCashierFiatAddress } from '@deriv/api';
import { act, render, screen, waitFor } from '@testing-library/react';
import WithdrawalFiat from '../WithdrawalFiat';

jest.mock('@deriv/api', () => ({
useCashierFiatAddress: jest.fn(),
}));

describe('<WithdrawalFiat />', () => {
it('should render the iframe with the withdrawal url from API response', async () => {
const verificationCode = 'abcd1234';
(useCashierFiatAddress as jest.Mock).mockReturnValue({
data: 'https://example.com',
error: null,
isError: false,

isLoading: false,
mutate: jest.fn(),
});

await act(async () => {
render(<WithdrawalFiat verificationCode={verificationCode} />);
await waitFor(() => {
expect(screen.queryByTestId('dt_derivs-loader')).not.toBeInTheDocument();
});
const iframe = screen.getByTestId('dt_withdrawal_fiat_iframe');
expect(iframe).toHaveAttribute('src', 'https://example.com');
});
});

it('should render the loader while the iframe is loading', () => {
const verificationCode = 'abcd1234';

(useCashierFiatAddress as jest.Mock).mockReturnValue({
isLoading: true,
mutate: jest.fn(),
});

render(<WithdrawalFiat verificationCode={verificationCode} />);
expect(screen.getByTestId('dt_derivs-loader')).toBeInTheDocument();
});

it('should render the error screen when server responds with error', () => {
(useCashierFiatAddress as jest.Mock).mockReturnValue({
error: {
error: {
code: '500',
message: 'Server Error',
},
},
isError: true,
mutate: jest.fn(),
});

render(<WithdrawalFiat />);
expect(screen.getByText('Server Error')).toBeInTheDocument();
});
});
1 change: 1 addition & 0 deletions packages/cashier-v2/src/lib/WithdrawalFiat/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as WithdrawalFiatModule } from './WithdrawalFiat';
2 changes: 2 additions & 0 deletions packages/cashier-v2/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './loader';
export * from './utils';
9 changes: 9 additions & 0 deletions packages/cashier-v2/src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
type TServerError = {
code: string;
details?: { [key: string]: string };
fields?: string[];
message: string;
};

export const isServerError = (error: unknown): error is TServerError =>
typeof error === 'object' && error !== null && 'code' in error;

0 comments on commit db4e225

Please sign in to comment.