Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WALL] Lubega / WALL-2955 / MT5 trade screen unit test #16807

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading