From 6fdac2419c7593d63bffe1b91add2feae8c06e5c Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 22 Nov 2023 15:10:19 +0000 Subject: [PATCH] chore(trading): move python stop order tests to jest (#5329) --- .../tests/deal_ticket/test_stop_order_oco.py | 98 +-------- .../deal-ticket-stop-order.spec.tsx | 195 +++++++++++++----- 2 files changed, 140 insertions(+), 153 deletions(-) diff --git a/apps/trading/e2e/tests/deal_ticket/test_stop_order_oco.py b/apps/trading/e2e/tests/deal_ticket/test_stop_order_oco.py index 4685613a6..f31d4c3f2 100644 --- a/apps/trading/e2e/tests/deal_ticket/test_stop_order_oco.py +++ b/apps/trading/e2e/tests/deal_ticket/test_stop_order_oco.py @@ -2,10 +2,8 @@ import pytest from playwright.sync_api import Page, expect from vega_sim.service import VegaService from actions.vega import submit_order -from conftest import init_vega -from fixtures.market import setup_continuous_market from actions.utils import wait_for_toast_confirmation -from wallet_config import MM_WALLET, MM_WALLET2, TERMINATE_WALLET, wallets + stop_order_btn = "order-type-Stop" stop_limit_order_btn = "order-type-StopLimit" @@ -328,98 +326,4 @@ def test_submit_stop_oco_limit_order_cancel( page.locator(".ag-center-cols-container").locator('[col-id="status"]').last ).to_have_text("CancelledOCO") -class TestStopOcoValidation: - @pytest.fixture(scope="class") - def vega(self, request): - with init_vega(request) as vega: - yield vega - @pytest.fixture(scope="class") - def continuous_market(self, vega): - return setup_continuous_market(vega) - - @pytest.mark.usefixtures("page", "auth", "risk_accepted") - def test_stop_market_order_oco_form_validation(self, continuous_market, page: Page): - page.goto(f"/#/markets/{continuous_market}") - page.get_by_test_id(stop_order_btn).click() - page.get_by_test_id(stop_market_order_btn).is_visible() - page.get_by_test_id(stop_market_order_btn).click() - page.get_by_test_id(oco).click() - expect( - page.get_by_test_id("sidebar-content").get_by_text("Trigger").last - ).to_be_visible() - # 7002-SORD-084 - expect(page.locator('[for="triggerDirection-risesAbove-oco"]')).to_have_text( - "Rises above" - ) - # 7002-SORD-085 - expect(page.locator('[for="triggerDirection-fallsBelow-oco"]')).to_have_text( - "Falls below" - ) - # 7002-SORD-087 - expect(page.locator('[for="triggerType-price-oco"]')).to_have_text("Price") - expect(page.locator('[for="triggerType-price"]')).to_be_checked - # 7002-SORD-088 - expect( - page.locator('[for="triggerType-trailingPercentOffset-oco"]') - ).to_have_text("Trailing Percent Offset") - expect(page.locator('[for="order-size-oco"]')).to_have_text("Size") - - @pytest.mark.usefixtures("page", "auth", "risk_accepted") - def test_stop_limit_order_oco_form_validation(self, continuous_market, page: Page): - page.goto(f"/#/markets/{continuous_market}") - page.get_by_test_id(stop_order_btn).click() - page.get_by_test_id(stop_market_order_btn).is_visible() - page.get_by_test_id(stop_limit_order_btn).click() - page.get_by_test_id(oco).click() - expect( - page.get_by_test_id("sidebar-content").get_by_text("Trigger").last - ).to_be_visible() - # 7002-SORD-099 - expect(page.locator('[for="triggerDirection-risesAbove-oco"]')).to_have_text( - "Rises above" - ) - # 7002-SORD-091 - expect(page.locator('[for="triggerDirection-fallsBelow-oco"]')).to_have_text( - "Falls below" - ) - # 7002-SORD-095 - expect(page.locator('[for="triggerType-price-oco"]')).to_have_text("Price") - expect(page.locator('[for="triggerType-price"]')).to_be_checked - # 7002-SORD-095 - expect( - page.locator('[for="triggerType-trailingPercentOffset-oco"]') - ).to_have_text("Trailing Percent Offset") - - expect(page.locator('[for="order-size-oco"]')).to_have_text("Size") - expect(page.locator('[for="order-price-oco"]')).to_have_text("Price") - - @pytest.mark.usefixtures("page", "auth", "risk_accepted") - def test_maximum_number_of_active_stop_orders_oco( - self, continuous_market, vega: VegaService, page: Page - ): - page.goto(f"/#/markets/{continuous_market}") - page.get_by_test_id(stop_order_btn).click() - page.get_by_test_id(stop_limit_order_btn).is_visible() - page.get_by_test_id(stop_limit_order_btn).click() - page.get_by_test_id(order_side_sell).click() - page.locator("label").filter(has_text="Falls below").click() - page.get_by_test_id(trigger_price).fill("102") - page.get_by_test_id(order_size).fill("3") - page.get_by_test_id(order_price).fill("103") - page.get_by_test_id(oco).click() - page.get_by_test_id(trigger_price_oco).fill("120") - page.get_by_test_id(order_size_oco).fill("2") - page.get_by_test_id(order_limit_price_oco).fill("99") - for i in range(2): - page.get_by_test_id(submit_stop_order).click() - wait_for_toast_confirmation(page) - vega.wait_fn(1) - vega.forward("20s") - vega.wait_for_total_catchup() - if page.get_by_test_id(close_toast).is_visible(): - page.get_by_test_id(close_toast).click() - # 7002-SORD-011 - expect(page.get_by_test_id("stop-order-warning-limit")).to_have_text( - "There is a limit of 4 active stop orders per market. Orders submitted above the limit will be immediately rejected." - ) diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-stop-order.spec.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-stop-order.spec.tsx index a4c7d1054..78a7761f8 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-stop-order.spec.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-stop-order.spec.tsx @@ -101,7 +101,7 @@ describe('StopOrder', () => { jest.clearAllMocks(); }); - it('should display ticket defaults', async () => { + it('should display ticket defaults limit order', async () => { render(generateJsx()); // place order button should always be enabled expect(screen.getByTestId(submitButton)).toBeEnabled(); @@ -131,6 +131,47 @@ describe('StopOrder', () => { }); }); + it('should display ticket defaults market order', async () => { + render(generateJsx()); + // place order button should always be enabled + expect(screen.getByTestId(submitButton)).toBeEnabled(); + // Assert defaults are used + await userEvent.click(screen.getByTestId(orderTypeTrigger)); + await userEvent.click(screen.getByTestId(orderTypeMarket)); + await userEvent.click(screen.getByTestId(orderTypeTrigger)); + expect(screen.getByTestId(orderTypeLimit).dataset.state).toEqual( + 'unchecked' + ); + expect(screen.getByTestId(orderTypeMarket).dataset.state).toEqual( + 'checked' + ); + await userEvent.click(screen.getByTestId(orderTypeMarket)); + expect(screen.getByTestId(orderSideBuy).dataset.state).toEqual('checked'); + expect(screen.getByTestId(sizeInput)).toHaveDisplayValue('0'); + expect(screen.getByTestId(timeInForce)).toHaveValue( + Schema.OrderTimeInForce.TIME_IN_FORCE_FOK + ); + // 7002-SORD-084 + expect( + screen.getByTestId(triggerDirectionRisesAbove).dataset.state + ).toEqual('checked'); + // 7002-SORD-085 + expect( + screen.getByTestId(triggerDirectionFallsBelow).dataset.state + ).toEqual('unchecked'); + expect(screen.getByTestId(triggerTypePrice).dataset.state).toEqual( + 'checked' + ); + expect(screen.getByTestId(expire).dataset.state).toEqual('unchecked'); + expect(screen.getByTestId(oco).dataset.state).toEqual('unchecked'); + await userEvent.click(screen.getByTestId(expire)); + await waitFor(() => { + expect(screen.getByTestId(expiryStrategySubmit).dataset.state).toEqual( + 'checked' + ); + }); + }); + it('calculate notional for market limit', async () => { render(generateJsx()); await userEvent.type(screen.getByTestId(sizeInput), '10'); @@ -239,33 +280,43 @@ describe('StopOrder', () => { it.each([ { fieldName: 'size', ocoValue: false }, { fieldName: 'ocoSize', ocoValue: true }, - ])('validates $fieldName field', async ({ ocoValue }) => { - render(generateJsx()); - if (ocoValue) { - await userEvent.click(screen.getByTestId(oco)); - } - await userEvent.click(screen.getByTestId(submitButton)); - const getByTestId = (id: string) => - screen.getByTestId(ocoPostfix(id, ocoValue)); - const queryByTestId = (id: string) => - screen.queryByTestId(ocoPostfix(id, ocoValue)); - // default value should be invalid - expect(getByTestId(sizeErrorMessage)).toBeInTheDocument(); - // to small value should be invalid - await userEvent.type(getByTestId(sizeInput), '0.01'); - expect(getByTestId(sizeErrorMessage)).toBeInTheDocument(); + { fieldName: 'size', ocoValue: false, orderTypeMarketValue: true }, + { fieldName: 'ocoSize', ocoValue: true, orderTypeMarketValue: true }, + ])( + 'validates $fieldName field', + async ({ ocoValue, orderTypeMarketValue }) => { + render(generateJsx()); + if (orderTypeMarketValue) { + await userEvent.click(screen.getByTestId(orderTypeTrigger)); + await userEvent.click(screen.getByTestId(orderTypeMarket)); + } + if (ocoValue) { + await userEvent.click(screen.getByTestId(oco)); + } + await userEvent.click(screen.getByTestId(submitButton)); + const getByTestId = (id: string) => + screen.getByTestId(ocoPostfix(id, ocoValue)); + const queryByTestId = (id: string) => + screen.queryByTestId(ocoPostfix(id, ocoValue)); + // default value should be invalid + expect(getByTestId(sizeErrorMessage)).toBeInTheDocument(); + // to small value should be invalid + await userEvent.type(getByTestId(sizeInput), '0.01'); + expect(getByTestId(sizeErrorMessage)).toBeInTheDocument(); - // clear and fill using valid value - await userEvent.clear(getByTestId(sizeInput)); - await userEvent.type(getByTestId(sizeInput), '0.1'); - expect(queryByTestId(sizeErrorMessage)).toBeNull(); - }); + // clear and fill using valid value + await userEvent.clear(getByTestId(sizeInput)); + await userEvent.type(getByTestId(sizeInput), '0.1'); + expect(queryByTestId(sizeErrorMessage)).toBeNull(); + } + ); it.each([ { fieldName: 'price', ocoValue: false }, { fieldName: 'ocoPrice', ocoValue: true }, ])('validates $fieldName field', async ({ ocoValue }) => { render(generateJsx()); + if (ocoValue) { await userEvent.click(screen.getByTestId(oco)); } @@ -275,7 +326,7 @@ describe('StopOrder', () => { screen.getByTestId(ocoPostfix(id, ocoValue)); const queryByTestId = (id: string) => screen.queryByTestId(ocoPostfix(id, ocoValue)); - + // 7002-SORD-095 expect(getByTestId(priceErrorMessage)).toBeInTheDocument(); await userEvent.type(getByTestId(priceInput), '0.001'); expect(getByTestId(priceErrorMessage)).toBeInTheDocument(); @@ -305,48 +356,77 @@ describe('StopOrder', () => { it.each([ { fieldName: 'triggerPrice', ocoValue: false }, { fieldName: 'ocoTriggerPrice', ocoValue: true }, - ])('validates $fieldName field', async ({ ocoValue }) => { - render(generateJsx()); + { fieldName: 'triggerPrice', ocoValue: false, orderTypeMarketValue: true }, + { + fieldName: 'ocoTriggerPrice', + ocoValue: true, + orderTypeMarketValue: true, + }, + ])( + 'validates $fieldName field', + async ({ ocoValue, orderTypeMarketValue }) => { + render(generateJsx()); + if (orderTypeMarketValue) { + await userEvent.click(screen.getByTestId(orderTypeTrigger)); + await userEvent.click(screen.getByTestId(orderTypeMarket)); + } + if (ocoValue) { + await userEvent.click(screen.getByTestId(oco)); + await userEvent.click(screen.getByTestId(triggerDirectionFallsBelow)); + } + await userEvent.click(screen.getByTestId(submitButton)); + const getByTestId = (id: string) => + screen.getByTestId(ocoPostfix(id, ocoValue)); + const queryByTestId = (id: string) => + screen.queryByTestId(ocoPostfix(id, ocoValue)); + // 7002-SORD-095 + // 7002-SORD-087 - if (ocoValue) { - await userEvent.click(screen.getByTestId(oco)); - await userEvent.click(screen.getByTestId(triggerDirectionFallsBelow)); + expect(getByTestId(triggerPriceErrorMessage)).toBeInTheDocument(); + + // switch to trailing percentage offset trigger type + await userEvent.click(getByTestId(triggerTypeTrailingPercentOffset)); + expect(queryByTestId(triggerPriceErrorMessage)).toBeNull(); + + // switch back to price trigger type + await userEvent.click(getByTestId(triggerTypePrice)); + expect(getByTestId(triggerPriceErrorMessage)).toBeInTheDocument(); + + // to small value should be invalid + await userEvent.type(getByTestId(triggerPriceInput), '0.001'); + expect(getByTestId(triggerPriceErrorMessage)).toBeInTheDocument(); + + // clear and fill using value causing immediate trigger + await userEvent.clear(getByTestId(triggerPriceInput)); + await userEvent.type(getByTestId(triggerPriceInput), '0.01'); + expect(queryByTestId(triggerPriceErrorMessage)).toBeNull(); + expect(queryByTestId(triggerPriceWarningMessage)).toBeInTheDocument(); + + // change to correct value + await userEvent.type(getByTestId(triggerPriceInput), '2'); + expect(queryByTestId(triggerPriceWarningMessage)).toBeNull(); } - await userEvent.click(screen.getByTestId(submitButton)); - const getByTestId = (id: string) => - screen.getByTestId(ocoPostfix(id, ocoValue)); - const queryByTestId = (id: string) => - screen.queryByTestId(ocoPostfix(id, ocoValue)); - expect(getByTestId(triggerPriceErrorMessage)).toBeInTheDocument(); - - // switch to trailing percentage offset trigger type - await userEvent.click(getByTestId(triggerTypeTrailingPercentOffset)); - expect(queryByTestId(triggerPriceErrorMessage)).toBeNull(); - - // switch back to price trigger type - await userEvent.click(getByTestId(triggerTypePrice)); - expect(getByTestId(triggerPriceErrorMessage)).toBeInTheDocument(); - - // to small value should be invalid - await userEvent.type(getByTestId(triggerPriceInput), '0.001'); - expect(getByTestId(triggerPriceErrorMessage)).toBeInTheDocument(); - - // clear and fill using value causing immediate trigger - await userEvent.clear(getByTestId(triggerPriceInput)); - await userEvent.type(getByTestId(triggerPriceInput), '0.01'); - expect(queryByTestId(triggerPriceErrorMessage)).toBeNull(); - expect(queryByTestId(triggerPriceWarningMessage)).toBeInTheDocument(); - - // change to correct value - await userEvent.type(getByTestId(triggerPriceInput), '2'); - expect(queryByTestId(triggerPriceWarningMessage)).toBeNull(); - }); + ); it.each([ { fieldName: 'trailingPercentageOffset', ocoValue: false }, { fieldName: 'ocoTrailingPercentageOffset', ocoValue: true }, + { + fieldName: 'trailingPercentageOffset', + ocoValue: false, + orderTypeMarket: true, + }, + { + fieldName: 'ocoTrailingPercentageOffset', + ocoValue: true, + orderTypeMarket: true, + }, ])('validates $fieldName field', async ({ ocoValue }) => { render(generateJsx()); + if (orderTypeMarket) { + await userEvent.click(screen.getByTestId(orderTypeTrigger)); + await userEvent.click(screen.getByTestId(orderTypeMarket)); + } if (ocoValue) { await userEvent.click(screen.getByTestId(oco)); } @@ -401,9 +481,11 @@ describe('StopOrder', () => { it('sync oco trigger', async () => { render(generateJsx()); await userEvent.click(screen.getByTestId(oco)); + // 7002-SORD-099 expect( screen.getByTestId(triggerDirectionRisesAbove).dataset.state ).toEqual('checked'); + // 7002-SORD-091 expect( screen.getByTestId(ocoPostfix(triggerDirectionFallsBelow)).dataset.state ).toEqual('checked'); @@ -481,6 +563,7 @@ describe('StopOrder', () => { expect(mockDataProvider.mock.lastCall?.[0].skip).toBe(true); await userEvent.type(screen.getByTestId(sizeInput), '0.01'); expect(mockDataProvider.mock.lastCall?.[0].skip).toBe(false); + // 7002-SORD-011 expect(screen.getByTestId(numberOfActiveOrdersLimit)).toBeInTheDocument(); });