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

DTRA / Kate / DTRA-1475 / Implement Take profit trade param functionality #16224

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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,150 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { mockStore } from '@deriv/stores';
import ModulesProvider from 'Stores/Providers/modules-providers';
import TraderProviders from '../../../../../trader-providers';
import TakeProfit from '../take-profit';

const take_profit_trade_param = 'Take profit';

const mediaQueryList = {
matches: true,
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
};

window.matchMedia = jest.fn().mockImplementation(() => mediaQueryList);

describe('TakeProfit', () => {
let default_mock_store: ReturnType<typeof mockStore>;

beforeEach(() => (default_mock_store = mockStore({})));

afterEach(() => jest.clearAllMocks());

const mockTakeProfit = () =>
render(
<TraderProviders store={default_mock_store}>
<ModulesProvider store={default_mock_store}>
<TakeProfit is_minimized />
</ModulesProvider>
</TraderProviders>
);

it('should render trade param with "Take profit" label', () => {
mockTakeProfit();

expect(screen.getByRole('textbox')).toBeInTheDocument();
expect(screen.getByText(take_profit_trade_param)).toBeInTheDocument();
});

it('should open ActionSheet with input, "Save" button and text content with definition if user clicks on trade param', () => {
mockTakeProfit();

expect(screen.queryByTestId('dt-actionsheet-overlay')).not.toBeInTheDocument();

userEvent.click(screen.getByText(take_profit_trade_param));

expect(screen.getByTestId('dt-actionsheet-overlay')).toBeInTheDocument();
const input = screen.getByRole('spinbutton');
expect(input).toBeInTheDocument();
expect(screen.getByText('Save')).toBeInTheDocument();
expect(
screen.getByText(
'When your profit reaches or exceeds the set amount, your trade will be closed automatically.'
)
).toBeInTheDocument();
});

it('should render alternative text content with definition for Accumulators', () => {
default_mock_store.modules.trade.is_accumulator = true;
mockTakeProfit();

userEvent.click(screen.getByText(take_profit_trade_param));

expect(
screen.getByText("Take profit can't be adjusted for ongoing accumulator contracts.")
).toBeInTheDocument();
});

it('should enable input, when user clicks on ToggleSwitch', () => {
mockTakeProfit();

userEvent.click(screen.getByText(take_profit_trade_param));

const toggle_switcher = screen.getAllByRole('button')[0];
const input = screen.getByRole('spinbutton');

expect(input).toBeDisabled();
userEvent.click(toggle_switcher);
expect(input).toBeEnabled();
});

it('should enable input, when user clicks on Take Profit overlay', () => {
mockTakeProfit();

userEvent.click(screen.getByText(take_profit_trade_param));

const take_profit_overlay = screen.getByTestId('dt_take_profit_overlay');
const input = screen.getByRole('spinbutton');

expect(input).toBeDisabled();
userEvent.click(take_profit_overlay);
expect(input).toBeEnabled();
});

it('should validate values, that user typed, and show error text if they are out of acceptable range. If values are wrong, when user clicks on "Save" button onChangeMultiple and onChange will not be called', () => {
default_mock_store.modules.trade.validation_params = {
take_profit: {
min: '0.01',
max: '100',
},
};
mockTakeProfit();

userEvent.click(screen.getByText(take_profit_trade_param));

const toggle_switcher = screen.getAllByRole('button')[0];
userEvent.click(toggle_switcher);

const input = screen.getByRole('spinbutton');
userEvent.type(input, ' ');
expect(screen.getByText('Please enter a take profit amount.'));

const save_button = screen.getByText('Save');
userEvent.click(save_button);
expect(default_mock_store.modules.trade.onChangeMultiple).not.toBeCalled();
expect(default_mock_store.modules.trade.onChange).not.toBeCalled();

userEvent.type(input, '0.0002');
expect(screen.getByText('Acceptable range: 0.01 to 100'));

userEvent.click(save_button);
expect(default_mock_store.modules.trade.onChangeMultiple).not.toBeCalled();
expect(default_mock_store.modules.trade.onChange).not.toBeCalled();
});

it('should validate values, that user typed. In case if values are correct, when user clicks on "Save" button onChangeMultiple and onChange will be called', () => {
default_mock_store.modules.trade.validation_params = {
take_profit: {
min: '0.01',
max: '100',
},
};
mockTakeProfit();

userEvent.click(screen.getByText(take_profit_trade_param));

const toggle_switcher = screen.getAllByRole('button')[0];
userEvent.click(toggle_switcher);

const input = screen.getByRole('spinbutton');
userEvent.type(input, '2');
expect(screen.getByText('Acceptable range: 0.01 to 100'));

userEvent.click(screen.getByText('Save'));
expect(default_mock_store.modules.trade.onChangeMultiple).toBeCalled();
expect(default_mock_store.modules.trade.onChange).toBeCalled();
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import './take-profit.scss';
import TakeProfit from './take-profit';

export default TakeProfit;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { ActionSheet } from '@deriv-com/quill-ui';
import { LabelPairedArrowLeftMdRegularIcon, LabelPairedCircleInfoMdRegularIcon } from '@deriv/quill-icons';
import { Localize } from '@deriv/translations';

type TAllowEqualsProps = {
current_index: number;
onNextClick: () => void;
onPrevClick: () => void;
};

const TakeProfitHeader = ({ current_index, onNextClick, onPrevClick }: TAllowEqualsProps) => (
kate-deriv marked this conversation as resolved.
Show resolved Hide resolved
<ActionSheet.Header
className='carousel-controls'
title={<Localize i18n_default_text='Take profit' />}
icon={
current_index ? (
<LabelPairedArrowLeftMdRegularIcon onClick={onPrevClick} />
) : (
<LabelPairedCircleInfoMdRegularIcon onClick={onNextClick} />
)
}
iconPosition={current_index ? 'left' : 'right'}
/>
);

export default TakeProfitHeader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
$HANDLEBAR_HEIGHT: var(--core-size-1000);
$HEADER_TITLE_HEIGHT: var(--core-size-3200);
$FOOTER_BUTTON_HEIGHT: var(--core-size-4000);

.take-profit {
&__wrapper {
position: relative;
height: calc(400px - $HANDLEBAR_HEIGHT - $HEADER_TITLE_HEIGHT - $FOOTER_BUTTON_HEIGHT);
padding-block-start: 0;

&--definition {
height: calc(400px - $HANDLEBAR_HEIGHT - $HEADER_TITLE_HEIGHT);
padding-block-start: 0;
}
}

&__warning {
margin-block-start: var(--core-spacing-800);
}

&__content {
display: flex;
justify-content: space-between;
align-items: center;
padding-block: var(--core-spacing-400);
}

&__overlay {
all: unset;
height: var(--core-size-2800);
width: calc(100vw - (2 * var(--core-spacing-800)));
kate-deriv marked this conversation as resolved.
Show resolved Hide resolved
position: absolute;
top: var(--core-spacing-2200);
left: var(--core-spacing-800);
}
}

.carousel-controls {
.quill-action-sheet--title--icon {
z-index: 2;
}
}
Loading
Loading