From 12cb5e10b682d2d1e131e9d7592e38319600007e Mon Sep 17 00:00:00 2001 From: "m.ray" <16125548+MadalinaRaicu@users.noreply.github.com> Date: Tue, 28 Nov 2023 01:49:26 +0200 Subject: [PATCH] chore(trading): merge main in develop (#5352) Co-authored-by: Matthew Russell --- .../components/settings/settings.spec.tsx | 12 ++ apps/trading/components/settings/settings.tsx | 57 +++++++++- .../transfer/test_transfer_key_to_key.py | 32 +++--- libs/accounts/src/lib/accounts-table.spec.tsx | 68 +++++------- libs/accounts/src/lib/transfer-form.spec.tsx | 104 ++++++++++++++++-- libs/accounts/src/lib/transfer-form.tsx | 14 +-- 6 files changed, 209 insertions(+), 78 deletions(-) create mode 100644 apps/trading/components/settings/settings.spec.tsx diff --git a/apps/trading/components/settings/settings.spec.tsx b/apps/trading/components/settings/settings.spec.tsx new file mode 100644 index 000000000..363c32ce9 --- /dev/null +++ b/apps/trading/components/settings/settings.spec.tsx @@ -0,0 +1,12 @@ +import { Settings } from './settings'; +import { render, screen } from '@testing-library/react'; + +describe('Settings', () => { + it('should the settings component with all the options', () => { + render(); + expect(screen.getByText('Dark mode')).toBeInTheDocument(); + expect(screen.getByText('Share usage data')).toBeInTheDocument(); + expect(screen.getByText('Toast location')).toBeInTheDocument(); + expect(screen.getByText('Reset to default')).toBeInTheDocument(); + }); +}); diff --git a/apps/trading/components/settings/settings.tsx b/apps/trading/components/settings/settings.tsx index 5688eb575..30d00c1c1 100644 --- a/apps/trading/components/settings/settings.tsx +++ b/apps/trading/components/settings/settings.tsx @@ -1,7 +1,13 @@ -import { Switch, ToastPositionSetter } from '@vegaprotocol/ui-toolkit'; +import { + Dialog, + Intent, + Switch, + ToastPositionSetter, + TradingButton, +} from '@vegaprotocol/ui-toolkit'; import { useThemeSwitcher } from '@vegaprotocol/react-helpers'; import { useTelemetryApproval } from '../../lib/hooks/use-telemetry-approval'; -import type { ReactNode } from 'react'; +import { useState, type ReactNode } from 'react'; import classNames from 'classnames'; import { useT } from '../../lib/use-t'; @@ -9,6 +15,7 @@ export const Settings = () => { const t = useT(); const { theme, setTheme } = useThemeSwitcher(); const [isApproved, setIsApproved] = useTelemetryApproval(); + const [open, setOpen] = useState(false); return (
@@ -33,6 +40,52 @@ export const Settings = () => { + + { + setOpen(true); + }} + > + {t('Reset')} + + +
+

+ {t( + 'You will lose all persisted settings and you will be logged out.' + )} +

+

+ {t('Are you sure you want to reset all settings to default?')} +

+
+ +
+ { + localStorage.clear(); + window.location.reload(); + }} + > + {t('Yes, clear cache and refresh')} + + { + setOpen(false); + }} + > + {t('No, keep settings')} + +
+
+
{process.env.GIT_TAG && ( diff --git a/apps/trading/e2e/tests/transfer/test_transfer_key_to_key.py b/apps/trading/e2e/tests/transfer/test_transfer_key_to_key.py index 606a460b6..48c495a3b 100644 --- a/apps/trading/e2e/tests/transfer/test_transfer_key_to_key.py +++ b/apps/trading/e2e/tests/transfer/test_transfer_key_to_key.py @@ -1,4 +1,4 @@ -import pytest +import pytest import re from playwright.sync_api import Page, expect from vega_sim.service import VegaService @@ -20,40 +20,40 @@ def test_transfer_submit(continuous_market, vega: VegaService, page: Page): # 1003-TRAN-010 # 1003-TRAN-023 page.goto('/#/portfolio') - + expect(page.get_by_test_id('transfer-form')).to_be_visible page.get_by_test_id('select-asset').click() expect(page.get_by_test_id('rich-select-option')).to_have_count(1) - + page.get_by_test_id('rich-select-option').click() page.select_option('[data-testid=transfer-form] [name="toVegaKey"]', index=2) page.select_option('[data-testid=transfer-form] [name="fromAccount"]', index=1) - + expected_asset_text = re.compile(r"tDAI tDAI999,991.49731 tDAI.{6}….{4}") actual_asset_text = page.get_by_test_id('select-asset').text_content().strip() - + assert expected_asset_text.search(actual_asset_text), f"Expected pattern not found in {actual_asset_text}" - + page.locator('[data-testid=transfer-form] input[name="amount"]').fill('1') expect(page.locator('[data-testid=transfer-form] input[name="amount"]')).not_to_be_empty() - + page.locator('[data-testid=transfer-form] [type="submit"]').click() wait_for_toast_confirmation(page) vega.forward("10s") vega.wait_fn(1) vega.wait_for_total_catchup() - expected_confirmation_text = re.compile(r"Transfer completeYour transaction has been confirmedView in block explorerTransferTo .{6}….{6}1\.00 tDAI") + expected_confirmation_text = re.compile(r"Transfer completeYour transaction has been confirmed View in block explorerTransferTo .{6}….{6}1\.00 tDAI") actual_confirmation_text = page.get_by_test_id('toast-content').text_content() assert expected_confirmation_text.search(actual_confirmation_text), f"Expected pattern not found in {actual_confirmation_text}" - + @pytest.mark.usefixtures("page", "auth", "risk_accepted") def test_transfer_vesting_below_minimum(continuous_market, vega: VegaService, page: Page): vega.update_network_parameter( - "market_maker", parameter="transfer.minTransferQuantumMultiple", new_value="100000" + "market_maker", parameter="transfer.minTransferQuantumMultiple", new_value="100000" ) vega.wait_for_total_catchup() - + create_and_faucet_wallet(vega=vega, wallet=PARTY_A, amount=1e3) create_and_faucet_wallet(vega=vega, wallet=PARTY_B, amount=1e5) create_and_faucet_wallet(vega=vega, wallet=PARTY_C, amount=1e5) @@ -96,11 +96,11 @@ def test_transfer_vesting_below_minimum(continuous_market, vega: VegaService, pa next_epoch(vega=vega) page.goto('/#/portfolio') expect(page.get_by_test_id('transfer-form')).to_be_visible - + change_keys(page, vega, "party_b") page.get_by_test_id('select-asset').click() page.get_by_test_id('rich-select-option').click() - + option_value = page.locator('[data-testid="transfer-form"] [name="fromAccount"] option[value^="ACCOUNT_TYPE_VESTED_REWARDS"]').first.get_attribute("value") page.select_option('[data-testid="transfer-form"] [name="fromAccount"]', option_value) @@ -120,13 +120,13 @@ def test_transfer_vesting_below_minimum(continuous_market, vega: VegaService, pa vega.forward("10s") vega.wait_fn(10) vega.wait_for_total_catchup() - + page.get_by_text("Use max").first.click() page.locator('[data-testid=transfer-form] [type="submit"]').click() wait_for_toast_confirmation(page) vega.forward("10s") vega.wait_fn(1) vega.wait_for_total_catchup() - expected_confirmation_text = re.compile(r"Transfer completeYour transaction has been confirmedView in block explorerTransferTo .{6}….{6}0\.00001 tDAI") + expected_confirmation_text = re.compile(r"Transfer completeYour transaction has been confirmed View in block explorerTransferTo .{6}….{6}0\.00001 tDAI") actual_confirmation_text = page.get_by_test_id('toast-content').text_content() - assert expected_confirmation_text.search(actual_confirmation_text), f"Expected pattern not found in {actual_confirmation_text}" \ No newline at end of file + assert expected_confirmation_text.search(actual_confirmation_text), f"Expected pattern not found in {actual_confirmation_text}" diff --git a/libs/accounts/src/lib/accounts-table.spec.tsx b/libs/accounts/src/lib/accounts-table.spec.tsx index 3b4155c74..e3da431f1 100644 --- a/libs/accounts/src/lib/accounts-table.spec.tsx +++ b/libs/accounts/src/lib/accounts-table.spec.tsx @@ -1,10 +1,23 @@ -import { act, render, screen } from '@testing-library/react'; +import { act, render, screen, within } from '@testing-library/react'; import * as Types from '@vegaprotocol/types'; import type { AccountFields } from './accounts-data-provider'; import { getAccountData } from './accounts-data-provider'; import { AccountTable } from './accounts-table'; import userEvent from '@testing-library/user-event'; - +const asset1 = { + __typename: 'Asset', + id: 'asset-1', + symbol: 'tBTC', + decimals: 5, + name: 'T BTC', +}; +const asset2 = { + __typename: 'Asset', + id: 'asset-2', + symbol: 'aBTC', + decimals: 5, + name: 'A BTC', +}; const singleRow = { __typename: 'AccountBalance', type: Types.AccountType.ACCOUNT_TYPE_MARGIN, @@ -13,12 +26,7 @@ const singleRow = { __typename: 'Market', id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35', }, - asset: { - __typename: 'Asset', - id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c', - symbol: 'tBTC', - decimals: 5, - }, + asset: asset1, available: '125600000', used: '125600000', total: '251200000', @@ -33,12 +41,7 @@ const secondRow = { __typename: 'Market', id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35', }, - asset: { - __typename: 'Asset', - id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c', - symbol: 'aBTC', - decimals: 5, - }, + asset: asset2, available: '125600001', used: '125600001', total: '251200002', @@ -134,7 +137,7 @@ describe('AccountsTable', () => { it('should sort assets', async () => { // 7001-COLL-010 - const { container } = render( + render( null} @@ -142,13 +145,13 @@ describe('AccountsTable', () => { /> ); - const headerCell = screen.getByText('Asset'); - await userEvent.click(headerCell); - const rows = container.querySelectorAll( - '.ag-center-cols-container .ag-row' - ); - expect(rows[0].textContent).toContain('aBTC'); - expect(rows[1].textContent).toContain('tBTC'); + const headerCell = screen + .getAllByRole('columnheader') + .find((h) => h?.getAttribute('col-id') === 'asset.symbol') as HTMLElement; + + await userEvent.click(within(headerCell).getByText(/asset/i)); + + expect(headerCell).toHaveAttribute('aria-sort', 'ascending'); }); it('should apply correct formatting in view as user mode', async () => { @@ -176,12 +179,7 @@ describe('AccountsTable', () => { rowData={singleRowData} onClickAsset={() => null} isReadOnly={false} - pinnedAsset={{ - decimals: 5, - id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c', - symbol: 'tBTC', - name: 'tBTC', - }} + pinnedAsset={asset1} /> ); await screen.findAllByRole('rowgroup'); @@ -213,23 +211,13 @@ describe('AccountsTable', () => { const result = getAccountData([singleRow]); const expected = [ { - asset: { - __typename: 'Asset', - decimals: 5, - id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c', - symbol: 'tBTC', - }, + asset: asset1, available: '0', balance: '0', breakdown: [ { __typename: 'AccountBalance', - asset: { - __typename: 'Asset', - decimals: 5, - id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c', - symbol: 'tBTC', - }, + asset: asset1, available: '0', balance: '125600000', total: '125600000', diff --git a/libs/accounts/src/lib/transfer-form.spec.tsx b/libs/accounts/src/lib/transfer-form.spec.tsx index b7403e16a..e7ff67084 100644 --- a/libs/accounts/src/lib/transfer-form.spec.tsx +++ b/libs/accounts/src/lib/transfer-form.spec.tsx @@ -1,4 +1,10 @@ -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { + fireEvent, + render, + screen, + waitFor, + within, +} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import BigNumber from 'bignumber.js'; import { @@ -7,7 +13,7 @@ import { TransferForm, type TransferFormProps, } from './transfer-form'; -import { AccountType } from '@vegaprotocol/types'; +import { AccountType, AccountTypeMapping } from '@vegaprotocol/types'; import { removeDecimal } from '@vegaprotocol/utils'; describe('TransferForm', () => { @@ -39,8 +45,7 @@ describe('TransferForm', () => { }; const amount = '100'; - const pubKey = - '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680'; + const pubKey = '1'.repeat(64); const asset = { id: 'eur', symbol: '€', @@ -50,10 +55,7 @@ describe('TransferForm', () => { }; const props = { pubKey, - pubKeys: [ - pubKey, - 'a4b6e3de5d7ef4e31ae1b090be49d1a2ef7bcefff60cccf7658a0d4922651cce', - ], + pubKeys: [pubKey, '2'.repeat(64)], feeFactor: '0.001', submitTransfer: jest.fn(), accounts: [ @@ -177,7 +179,7 @@ describe('TransferForm', () => { // Test use max button await userEvent.click(screen.getByRole('button', { name: 'Use max' })); - expect(amountInput).toHaveValue('1000'); + expect(amountInput).toHaveValue('1000.00'); // Test amount validation await userEvent.clear(amountInput); @@ -262,7 +264,7 @@ describe('TransferForm', () => { // Test use max button await userEvent.click(screen.getByRole('button', { name: 'Use max' })); - expect(amountInput).toHaveValue('100'); + expect(amountInput).toHaveValue('100.00'); // If transfering from a vested account 'include fees' checkbox should // be disabled and fees should be 0 @@ -291,6 +293,88 @@ describe('TransferForm', () => { }); }); + it('handles lots of decimal places', async () => { + const balance = '904195168829277777'; + const expectedBalance = '0.904195168829277777'; + + const longDecimalAsset = { + id: 'assetId', + symbol: 'VEGA', + name: 'VEGA', + decimals: 18, + quantum: '1', + }; + + const account = { + type: AccountType.ACCOUNT_TYPE_VESTED_REWARDS, + asset: longDecimalAsset, + balance, + }; + + const mockSubmit = jest.fn(); + + renderComponent({ + ...props, + accounts: [account], + submitTransfer: mockSubmit, + minQuantumMultiple: '100000', + }); + + // Select a pubkey + await userEvent.selectOptions( + screen.getByLabelText('To Vega key'), + props.pubKeys[1] // Use not current pubkey so we can check it switches to current pubkey later + ); + + // Select asset + await selectAsset(longDecimalAsset); + + const accountSelect = screen.getByLabelText('From account'); + const option = within(accountSelect) + .getAllByRole('option') + .find( + (o) => o.getAttribute('value') === `${account.type}-${account.asset.id}` + ); + // plus one for disabled 'please select' option + + expect(option).toHaveTextContent( + `${AccountTypeMapping[account.type]} (${expectedBalance} ${ + account.asset.symbol + })` + ); + + await userEvent.selectOptions( + accountSelect, + `${AccountType.ACCOUNT_TYPE_VESTED_REWARDS}-${longDecimalAsset.id}` + ); + + expect(accountSelect).toHaveValue( + `${AccountType.ACCOUNT_TYPE_VESTED_REWARDS}-${longDecimalAsset.id}` + ); + + // Check switch back to connected key + const amountInput = screen.getByLabelText('Amount'); + + // Test use max button + await userEvent.click(screen.getByRole('button', { name: 'Use max' })); + expect(amountInput).toHaveValue(expectedBalance); + + await submit(); + + await waitFor(() => { + // 1003-TRAN-023 + expect(mockSubmit).toHaveBeenCalledTimes(1); + expect(mockSubmit).toHaveBeenCalledWith({ + fromAccountType: AccountType.ACCOUNT_TYPE_VESTED_REWARDS, + toAccountType: AccountType.ACCOUNT_TYPE_GENERAL, + to: props.pubKey, + asset: longDecimalAsset.id, + amount: balance, + oneOff: {}, + }); + }); + }); + describe('IncludeFeesCheckbox', () => { it('validates fields and submits when checkbox is checked', async () => { const mockSubmit = jest.fn(); diff --git a/libs/accounts/src/lib/transfer-form.tsx b/libs/accounts/src/lib/transfer-form.tsx index 4ceff1ab2..861364c1b 100644 --- a/libs/accounts/src/lib/transfer-form.tsx +++ b/libs/accounts/src/lib/transfer-form.tsx @@ -5,7 +5,6 @@ import { useVegaPublicKey, addDecimal, formatNumber, - addDecimalsFormatNumber, toBigNum, } from '@vegaprotocol/utils'; import { useT } from './use-t'; @@ -218,12 +217,7 @@ export const TransferForm = ({ - } + balance={} /> ))} @@ -290,8 +284,8 @@ export const TransferForm = ({ return ( ); })} @@ -420,7 +414,7 @@ export const TransferForm = ({ type="button" className="absolute right-0 top-0 ml-auto text-xs underline" onClick={() => - setValue('amount', parseFloat(accountBalance).toString(), { + setValue('amount', accountBalance, { shouldValidate: true, }) }