Skip to content

Commit

Permalink
chore: mt5 trade screen components unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
lubega-deriv committed Sep 11, 2024
1 parent 3a12b9e commit 8af20ac
Show file tree
Hide file tree
Showing 7 changed files with 547 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import { useDevice } from '@deriv-com/ui';
import { fireEvent, render, screen } from '@testing-library/react';
import { useModal } from '../../../../../../components/ModalProvider';
import { MT5TradeDetailsItem } from '..';

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

jest.mock('../../../../../../components/Base', () => ({
WalletClipboard: ({ textCopy }: { textCopy: string }) => (
<div data-testid='dt_wallet_clipboard'>Mock Clipboard {textCopy}</div>
),
}));

jest.mock('../../../../../../components/ModalProvider', () => ({
useModal: jest.fn(),
}));

describe('MT5TradeDetailsItem', () => {
beforeEach(() => {
(useDevice as jest.Mock).mockReturnValue({ isDesktop: true });
(useModal as jest.Mock).mockReturnValue({ show: jest.fn() });
});

it('renders clipboard variant correctly', () => {
render(<MT5TradeDetailsItem label='Test Label' value='Test Value' />);

expect(screen.getByText('Test Label')).toBeInTheDocument();
expect(screen.getByText('Test Value')).toBeInTheDocument();
expect(screen.getByTestId('dt_wallet_clipboard')).toBeInTheDocument();
expect(screen.getByTestId('dt_wallet_clipboard')).toHaveTextContent('Mock Clipboard Test Value');
});

it('renders password variant correctly', () => {
render(<MT5TradeDetailsItem label='Password' variant='password' />);

expect(screen.getByText('Password')).toBeInTheDocument();
expect(screen.getByText('Forgot Password?')).toBeInTheDocument();
});

it('renders info variant correctly', () => {
render(<MT5TradeDetailsItem value='Info message' variant='info' />);

expect(screen.getByText('Info message')).toBeInTheDocument();
});

it('shows ChangePassword component when "Forgot Password?" is clicked', () => {
const mockShow = jest.fn();
(useModal as jest.Mock).mockReturnValue({ show: mockShow });
(useDevice as jest.Mock).mockReturnValue({ isDesktop: false });

render(<MT5TradeDetailsItem label='Password' variant='password' />);

fireEvent.click(screen.getByText('Forgot Password?'));
expect(mockShow).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import MT5DesktopRedirectOption from '../MT5DesktopRedirectOption';

jest.mock('../MT5TradeLink', () => ({
__esModule: true,
default: ({ app, platform }: { app: string; platform: string }) => (
<div data-platform={platform} data-testid={`dt_mt5_trade_link_${app}`}>
{app}
</div>
),
}));

describe('MT5DesktopRedirectOption', () => {
it('renders MT5TradeLink components for all desktop apps', () => {
render(<MT5DesktopRedirectOption />);

const expectedApps = ['web', 'windows', 'macos', 'linux'];
expectedApps.forEach(app => {
const linkElement = screen.getByTestId(`dt_mt5_trade_link_${app}`);
expect(linkElement).toBeInTheDocument();
expect(linkElement).toHaveTextContent(app);
expect(linkElement).toHaveAttribute('data-platform', 'mt5');
});

expect(screen.getAllByTestId(/dt_mt5_trade_link_/)).toHaveLength(expectedApps.length);
});

it('renders MT5TradeLink components in the correct order', () => {
render(<MT5DesktopRedirectOption />);

const linkElements = screen.getAllByTestId(/dt_mt5_trade_link_/);
const renderedOrder = linkElements.map(el => el.textContent);

expect(renderedOrder).toEqual(['web', 'windows', 'macos', 'linux']);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React from 'react';
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
import { THooks } from '../../../../../../types';
import { getDeeplinkUrl, getMobileAppInstallerUrl, getWebtraderUrl } from '../constants';
import MT5MobileRedirectOption from '../MT5MobileRedirectOption';

jest.mock('../constants', () => ({
getDeeplinkUrl: jest.fn(),
getMobileAppInstallerUrl: jest.fn(),
getWebtraderUrl: jest.fn(),
}));

describe('MT5MobileRedirectOption', () => {
const mockMT5TradeAccount = {} as THooks.MT5AccountsList;
let originalLocation: Location;

beforeEach(() => {
jest.useFakeTimers();
(getDeeplinkUrl as jest.Mock).mockReturnValue('mock-deeplink-url');
(getMobileAppInstallerUrl as jest.Mock).mockResolvedValue('mock-installer-url');
(getWebtraderUrl as jest.Mock).mockReturnValue('mock-webtrader-url');

originalLocation = window.location;
// @ts-expect-error - this is required to mock the replacement of the read-only window.location
delete window.location;
window.location = {
...originalLocation,
replace: jest.fn(),
} as Location;
});

afterEach(() => {
jest.clearAllMocks();
jest.useRealTimers();
window.location = originalLocation;
});

it('renders the content of mt5 mobile redirect option', () => {
render(<MT5MobileRedirectOption mt5TradeAccount={mockMT5TradeAccount} />);

expect(screen.getByText('MetaTrader5 web terminal')).toBeInTheDocument();
expect(screen.getAllByText(/Trade with MT5 mobile app/)[0]).toBeInTheDocument();
expect(screen.getByText(/Note: Don't have the MT5 app?/)).toBeInTheDocument();
});

it('navigates to webtrader URL when web terminal button is clicked', () => {
render(<MT5MobileRedirectOption mt5TradeAccount={mockMT5TradeAccount} />);

const webTerminalLink = screen.getByRole('link', { name: /MetaTrader5 web terminal/ });
expect(webTerminalLink).toHaveAttribute('target', '_blank');
expect(webTerminalLink).toHaveAttribute('rel', 'noopener noreferrer');
expect(webTerminalLink).toHaveAttribute('href', 'mock-webtrader-url');
});

it('initiates mobile app redirection when mobile app button is clicked', async () => {
render(<MT5MobileRedirectOption mt5TradeAccount={mockMT5TradeAccount} />);

fireEvent.click(screen.getAllByText(/Trade with MT5 mobile app/)[0]);
expect(window.location.replace).toHaveBeenCalledWith('mock-deeplink-url');
(window.location.replace as jest.Mock).mockClear();

await act(async () => {
jest.runAllTimers();
});

await waitFor(
() => {
expect(window.location.replace).toHaveBeenCalledWith('mock-installer-url');
},
{ timeout: 3001 }
);
});

it('clears timeout when document becomes hidden', () => {
render(<MT5MobileRedirectOption mt5TradeAccount={mockMT5TradeAccount} />);

fireEvent.click(screen.getAllByText(/Trade with MT5 mobile app/)[0]);
Object.defineProperty(document, 'hidden', { configurable: true, value: true });
act(() => {
document.dispatchEvent(new Event('visibilitychange'));
});
act(() => {
jest.advanceTimersByTime(3000);
});

expect(window.location.replace).toHaveBeenCalledTimes(1);
expect(window.location.replace).toHaveBeenCalledWith('mock-deeplink-url');
});

it('clears timeout and opens installer when window.onblur is true and document is not hidden', () => {
render(<MT5MobileRedirectOption mt5TradeAccount={mockMT5TradeAccount} />);

fireEvent.click(screen.getAllByText(/Trade with MT5 mobile app/)[0]);
Object.defineProperty(document, 'hidden', { configurable: false, value: false });
Object.defineProperty(window, 'onblur', {
value: jest.fn(),
writable: true,
});
act(() => {
document.dispatchEvent(new Event('visibilitychange'));
});
act(() => {
jest.advanceTimersByTime(3000);
});

expect(window.location.replace).toHaveBeenCalledTimes(3);
expect(window.location.replace).toHaveBeenCalledWith('mock-deeplink-url');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React from 'react';
import { useCtraderServiceToken } from '@deriv/api-v2';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { getPlatformFromUrl } from '../../../../../../helpers/urls';
import { TPlatforms } from '../../../../../../types';
import MT5TradeLink from '../MT5TradeLink';

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

jest.mock('../../../../../../helpers/urls', () => ({
getPlatformFromUrl: jest.fn(),
}));

describe('MT5TradeLink', () => {
beforeEach(() => {
(useCtraderServiceToken as jest.Mock).mockReturnValue({
mutateAsync: jest.fn().mockResolvedValue({ service_token: { ctrader: { token: 'mock-token' } } }),
});
(getPlatformFromUrl as jest.Mock).mockReturnValue({ isStaging: false, isTestLink: false });

window.open = jest.fn();
});

it('renders MT5 download link correctly', () => {
render(<MT5TradeLink platform='mt5' />);

expect(screen.getByText('MetaTrader 5 Linux app')).toBeInTheDocument();
expect(screen.getByText('Learn more')).toBeInTheDocument();
});

it('renders DTrader web terminal link correctly', () => {
render(<MT5TradeLink platform='dxtrade' />);

expect(screen.getByText('Run Deriv X on your browser')).toBeInTheDocument();
expect(screen.getByText('Web terminal')).toBeInTheDocument();
});

it('opens MT5 download link when clicked', () => {
render(<MT5TradeLink platform='mt5' />);

fireEvent.click(screen.getByText('Learn more'));
expect(window.open).toHaveBeenCalledWith(expect.stringContaining('metatrader5'));
});

it('opens DTrader web terminal when clicked', async () => {
render(<MT5TradeLink platform='dxtrade' />);

fireEvent.click(screen.getByText('Web terminal'));
await waitFor(() => {
expect(window.open).toHaveBeenCalledWith('https://dx.deriv.com');
});
});

it('opens cTrader web terminal with token when clicked', async () => {
render(<MT5TradeLink platform='ctrader' />);

fireEvent.click(screen.getByText('Web terminal'));
await waitFor(() => {
expect(window.open).toHaveBeenCalledWith('https://ct.deriv.com/?token=mock-token');
});
});

it('handles demo mode for DTrader', async () => {
render(<MT5TradeLink isDemo={true} platform='dxtrade' />);

fireEvent.click(screen.getByText('Web terminal'));
await waitFor(() => {
expect(window.open).toHaveBeenCalledWith('https://dx-demo.deriv.com');
});
});

it('renders cTrader app download link correctly', () => {
render(<MT5TradeLink app='ctrader' />);

expect(screen.getByText('CTrader Windows App')).toBeInTheDocument();
expect(screen.getByText('Download')).toBeInTheDocument();
});
it('handles cTrader token failure', async () => {
(useCtraderServiceToken as jest.Mock).mockReturnValue({
mutateAsync: jest.fn().mockResolvedValue({ service_token: { ctrader: { token: null } } }),
});

render(<MT5TradeLink platform='ctrader' />);

fireEvent.click(screen.getByText('Web terminal'));
await waitFor(() => {
expect(window.open).toHaveBeenCalledWith('https://ct.deriv.com');
});
});

it('handles staging environment for cTrader', async () => {
(getPlatformFromUrl as jest.Mock).mockReturnValue({ isStaging: true, isTestLink: false });

render(<MT5TradeLink platform='ctrader' />);

fireEvent.click(screen.getByText('Web terminal'));
await waitFor(() => {
expect(window.open).toHaveBeenCalledWith('https://ct-uat.deriv.com/?token=mock-token');
});
});

it('handles test link for cTrader', async () => {
(getPlatformFromUrl as jest.Mock).mockReturnValue({ isStaging: false, isTestLink: true });

render(<MT5TradeLink platform='ctrader' />);

fireEvent.click(screen.getByText('Web terminal'));
await waitFor(() => {
expect(window.open).toHaveBeenCalledWith('https://ct-uat.deriv.com/?token=mock-token');
});
});

it('handles other platforms', async () => {
render(<MT5TradeLink platform={'mt5Investor' as TPlatforms.All} />);

fireEvent.click(screen.getByText('Web terminal'));
await waitFor(() => {
expect(window.open).toHaveBeenCalledWith('');
});
});
});
Loading

0 comments on commit 8af20ac

Please sign in to comment.