chore: upgrade to React 18 (#952)

* chore: upgrade react only

* chore: import renderHook from testing-library/react

* chore: add @babel/runtime to fix tests

* fix: fix some of the tests

* fix: fix some of the tests

* fix: fix tests failing on not being wrapped in act

* fix: fix tests in use-environment

* fix:  fix @types/react issue

* fix: fix formatting

* fix: remove unsued method

* fix: callout not accepting react node and root element null check

* fix: main.tsx stats null check

* fix: implicit any type fixes

* Update libs/environment/src/hooks/use-nodes.spec.tsx

* fix:  import act from testing-lib

* fix:  add strict mode back

* fix:  fix formatting issues

* fix: add babel deps for storybook

* Update tsconfig.json (#970)

* Update tsconfig.json

* feat: [console-lite] - add missing types in few places

Co-authored-by: maciek <maciek@vegaprotocol.io>

* chore(#952): remove any from useDataProvider hook

Co-authored-by: macqbat <kubat.maciek@gmail.com>
Co-authored-by: maciek <maciek@vegaprotocol.io>
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
This commit is contained in:
m.ray 2022-08-09 11:43:11 +02:00 committed by GitHub
parent 80f6725a9a
commit 71ede25339
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 4704 additions and 5266 deletions

View File

@ -1,12 +1,12 @@
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';
import { StrictMode } from 'react';
import * as ReactDOM from 'react-dom';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import './styles.css';
import App from './app/app';
import { ENV } from './app/config/env';
import { StrictMode } from 'react';
const { dsn } = ENV;
@ -19,12 +19,13 @@ if (dsn) {
environment: ENV.envName,
});
}
const rootElement = document.getElementById('root');
const root = rootElement && createRoot(rootElement);
ReactDOM.render(
root?.render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>,
document.getElementById('root')
</StrictMode>
);

View File

@ -36,7 +36,7 @@ export const DealTicketSteps = ({
}: DealTicketMarketProps) => {
const navigate = useNavigate();
const setMarket = useCallback(
(marketId) => {
(marketId: string) => {
navigate(`/trading/${marketId}`);
},
[navigate]

View File

@ -25,6 +25,14 @@ import SimpleMarketToolbar from './simple-market-toolbar';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
import type { SimpleMarketDataSub_marketData } from './__generated__/SimpleMarketDataSub';
import { IS_MARKET_TRADABLE } from '../../constants';
import type {
CellKeyDownEvent,
FullWidthCellKeyDownEvent,
} from 'ag-grid-community/dist/lib/events';
import type {
GetRowIdParams,
TabToNextCellParams,
} from 'ag-grid-community/dist/lib/entities/iCallbackParams';
export type SimpleMarketsType = SimpleMarkets_markets & {
percentChange?: number | '-';
@ -84,7 +92,7 @@ const SimpleMarketList = () => {
const { columnDefs, defaultColDef } = useColumnDefinitions({ isMobile });
const getRowId = useCallback(({ data }) => data.id, []);
const getRowId = useCallback(({ data }: GetRowIdParams) => data.id, []);
const handleRowClicked = useCallback(
({ data }: { data: SimpleMarketsType }) => {
@ -95,7 +103,7 @@ const SimpleMarketList = () => {
[navigate]
);
const onTabToNextCell = useCallback((params) => {
const onTabToNextCell = useCallback((params: TabToNextCellParams) => {
const {
api,
previousCellPosition: { rowIndex },
@ -108,7 +116,11 @@ const SimpleMarketList = () => {
}, []);
const onCellKeyDown = useCallback(
(params) => {
(
params: (CellKeyDownEvent | FullWidthCellKeyDownEvent) & {
event: KeyboardEvent;
}
) => {
const { event: { key = '' } = {}, data } = params;
if (key === 'Enter') {
handleRowClicked({ data });

View File

@ -7,6 +7,7 @@ import type { MockedResponse } from '@apollo/client/testing';
import type { MarketFilters } from './__generated__/MarketFilters';
import { FILTERS_QUERY } from './data-provider';
import filterData from './mocks/market-filters.json';
import { act } from 'react-dom/test-utils';
describe('SimpleMarketToolbar', () => {
const filterMock: MockedResponse<MarketFilters> = {
@ -58,6 +59,7 @@ describe('SimpleMarketToolbar', () => {
});
it('should be properly rendered', async () => {
act(async () => {
render(
// @ts-ignore different versions of react types in apollo and app
<MockedProvider mocks={[filterMock]} addTypename={false}>
@ -70,10 +72,12 @@ describe('SimpleMarketToolbar', () => {
});
fireEvent.click(screen.getByText('Future'));
await waitFor(() => {
expect(screen.getByTestId('market-products-menu').children).toHaveLength(
3
expect(
screen.getByTestId('market-products-menu').children
).toHaveLength(3);
expect(screen.getByTestId('market-assets-menu').children).toHaveLength(
6
);
expect(screen.getByTestId('market-assets-menu').children).toHaveLength(6);
});
fireEvent.click(screen.getByTestId('state-trigger'));
waitFor(() => {
@ -81,8 +85,10 @@ describe('SimpleMarketToolbar', () => {
expect(screen.getByRole('menu').children).toHaveLength(10);
});
});
});
it('navigation should work well', async () => {
act(async () => {
render(
// @ts-ignore different versions of react types in apollo and app
<MockedProvider mocks={[filterMock]} addTypename={false}>
@ -95,6 +101,7 @@ describe('SimpleMarketToolbar', () => {
expect(screen.getByText('Future')).toBeInTheDocument();
});
fireEvent.click(screen.getByText('Future'));
await waitFor(() => {
expect(screen.getByTestId('location-display')).toHaveTextContent(
'/markets/Active/Future'
@ -121,4 +128,5 @@ describe('SimpleMarketToolbar', () => {
);
});
});
});
});

View File

@ -1,4 +1,4 @@
import { renderHook } from '@testing-library/react-hooks';
import { renderHook } from '@testing-library/react';
import useMarketPositions from './use-market-positions';
let mockNotEmptyData = {

View File

@ -1,5 +1,5 @@
import * as React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { renderHook } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import useOrderCloseOut from './use-order-closeout';
import type { Order } from '@vegaprotocol/orders';

View File

@ -1,4 +1,4 @@
import { renderHook } from '@testing-library/react-hooks';
import { renderHook } from '@testing-library/react';
import { useQuery } from '@apollo/client';
import { BigNumber } from 'bignumber.js';
import type { Order } from '@vegaprotocol/orders';

View File

@ -1,4 +1,4 @@
import { renderHook } from '@testing-library/react-hooks';
import { renderHook } from '@testing-library/react';
import { useSettlementAccount } from './use-settlement-account';
import type { PartyBalanceQuery_party_accounts } from '../components/deal-ticket/__generated__/PartyBalanceQuery';

View File

@ -1,14 +1,15 @@
import { StrictMode } from 'react';
import * as ReactDOM from 'react-dom';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './app/app';
const rootElement = document.getElementById('root');
const root = rootElement && createRoot(rootElement);
ReactDOM.render(
root?.render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>,
document.getElementById('root')
</StrictMode>
);

View File

@ -1,14 +1,16 @@
import React from 'react';
import ReactDOM from 'react-dom';
import React, { StrictMode } from 'react';
import './styles/styles.css';
import App from './app';
import reportWebVitals from './report-web-vitals';
import { createRoot } from 'react-dom/client';
ReactDOM.render(
<React.StrictMode>
const rootElement = document.getElementById('root');
const root = rootElement && createRoot(rootElement);
root?.render(
<StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
</StrictMode>
);
// If you want to start measuring performance in your app, pass a function

View File

@ -2,12 +2,12 @@ import './styles.css';
import * as Sentry from '@sentry/react';
import { Integrations } from '@sentry/tracing';
import React from 'react';
import ReactDOM from 'react-dom';
import { createRoot } from 'react-dom/client';
import App from './app';
import reportWebVitals from './report-web-vitals';
import { ENV } from './config/env';
import { StrictMode } from 'react';
const dsn = ENV.dsn || false;
const environment = ENV.envName || 'local';
@ -38,11 +38,13 @@ if (dsn) {
Sentry.setTag('commit', commit);
}
ReactDOM.render(
<React.StrictMode>
const rootElement = document.getElementById('root');
const root = rootElement && createRoot(rootElement);
root?.render(
<StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
</StrictMode>
);
// If you want to start measuring performance in your app, pass a function

View File

@ -29,7 +29,7 @@ const ClaimIndex = ({ name }: RouteChildProps) => {
if (error) {
return (
<Callout intent={Intent.Danger} title={t('errorLoadingTranches')}>
{error}
{error.message}
</Callout>
);
}

View File

@ -28,7 +28,7 @@ export const TokenDetails = ({
if (error) {
return (
<Callout intent={Intent.Danger} title={t('errorLoadingTranches')}>
{error}
{error.message}
</Callout>
);
}

View File

@ -52,7 +52,7 @@ const RedemptionRouter = () => {
if (error) {
return (
<Callout intent={Intent.Danger} title={t('errorLoadingTranches')}>
{error}
{error.message}
</Callout>
);
}

View File

@ -24,7 +24,7 @@ const TrancheRouter = ({ name }: RouteChildProps) => {
if (error) {
return (
<Callout intent={Intent.Danger} title={t('errorLoadingTranches')}>
{error}
{error.message}
</Callout>
);
}

View File

@ -21,15 +21,16 @@ const singleRow: Accounts_party_accounts = {
};
const singleRowData = [singleRow];
it('should render successfully', async () => {
describe('AccountsTable', () => {
it('should render successfully', async () => {
await act(async () => {
const { baseElement } = render(<AccountsTable data={[]} />);
expect(baseElement).toBeTruthy();
});
});
});
it('Render correct columns', async () => {
await act(async () => {
it('should render correct columns', async () => {
act(async () => {
render(<AccountsTable data={singleRowData} />);
await waitFor(async () => {
const headers = await screen.getAllByRole('columnheader');
@ -41,10 +42,10 @@ it('Render correct columns', async () => {
).toEqual(['Asset', 'Type', 'Market', 'Balance']);
});
});
});
});
it('Correct formatting applied', async () => {
await act(async () => {
it('should apply correct formatting', async () => {
act(async () => {
render(<AccountsTable data={singleRowData} />);
await waitFor(async () => {
const cells = await screen.getAllByRole('gridcell');
@ -59,4 +60,5 @@ it('Correct formatting applied', async () => {
});
});
});
});
});

View File

@ -99,7 +99,7 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
);
const handleMarketSelect = useCallback(
({ id, name }) => {
({ id, name }: { id: string; name: string }) => {
setLookup(name);
setShowPane(false);
setMarket(id);
@ -163,7 +163,7 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
}, [showPane, setShowPane, setSkip, inputRef]);
const handleDialogOnchange = useCallback(
(isOpen) => {
(isOpen: boolean) => {
setShowPane(isOpen);
if (!isOpen) {
setLookup(lookup || market.name);

View File

@ -31,7 +31,7 @@ export const DepositManager = ({
const faucet = useSubmitFaucet();
const handleSelectAsset = useCallback(
(id) => {
(id: string) => {
const asset = assets.find((a) => a.id === id);
if (!asset) return;
update({ asset });

View File

@ -1,4 +1,4 @@
import { renderHook } from '@testing-library/react-hooks';
import { renderHook, waitFor } from '@testing-library/react';
import type { EnvironmentWithOptionalUrl } from './use-config';
import { useConfig } from './use-config';
import { Networks, ErrorType } from '../types';
@ -75,22 +75,23 @@ describe('useConfig hook', () => {
});
it('fetches configuration from the provided url', async () => {
const { result, waitForNextUpdate } = renderHook(() =>
useConfig(mockEnvironment, onError)
);
const { result } = renderHook(() => useConfig(mockEnvironment, onError));
await waitForNextUpdate();
await waitFor(() => {
expect(fetch).toHaveBeenCalledWith(mockEnvironment.VEGA_CONFIG_URL);
expect(result.current.config).toEqual(mockConfig);
});
});
it('caches the configuration', async () => {
const { result: firstResult, waitForNextUpdate: waitForFirstUpdate } =
renderHook(() => useConfig(mockEnvironment, onError));
const { result: firstResult } = renderHook(() =>
useConfig(mockEnvironment, onError)
);
await waitForFirstUpdate();
await waitFor(() => {
expect(fetch).toHaveBeenCalledTimes(1);
expect(firstResult.current.config).toEqual(mockConfig);
});
const { result: secondResult } = renderHook(() =>
useConfig(mockEnvironment, onError)
@ -104,14 +105,13 @@ describe('useConfig hook', () => {
// @ts-ignore typescript doesn't recognise the mocked instance
global.fetch.mockImplementation(() => Promise.reject());
const { result, waitForNextUpdate } = renderHook(() =>
useConfig(mockEnvironment, onError)
);
const { result } = renderHook(() => useConfig(mockEnvironment, onError));
await waitForNextUpdate();
await waitFor(() => {
expect(result.current.config).toEqual({ hosts: [] });
expect(onError).toHaveBeenCalledWith(ErrorType.CONFIG_LOAD_ERROR);
});
});
it('executes the error callback when the config validation fails', async () => {
// @ts-ignore typescript doesn't recognise the mocked instance
@ -122,12 +122,11 @@ describe('useConfig hook', () => {
})
);
const { result, waitForNextUpdate } = renderHook(() =>
useConfig(mockEnvironment, onError)
);
const { result } = renderHook(() => useConfig(mockEnvironment, onError));
await waitForNextUpdate();
await waitFor(() => {
expect(result.current.config).toBe(undefined);
expect(onError).toHaveBeenCalledWith(ErrorType.CONFIG_VALIDATION_ERROR);
});
});
});

View File

@ -0,0 +1,199 @@
// having the node switcher dialog in the environment provider breaks the test renderer
// workaround based on: https://github.com/facebook/react/issues/11565
import type { ComponentProps, ReactNode } from 'react';
import { renderHook } from '@testing-library/react';
import createClient from '../utils/apollo-client';
import { useEnvironment, EnvironmentProvider } from './use-environment';
import { Networks } from '../types';
import createMockClient from './mocks/apollo-client';
jest.mock('../utils/apollo-client');
jest.mock('react-dom', () => ({
...jest.requireActual('react-dom'),
createPortal: (node: ReactNode) => node,
}));
global.fetch = jest.fn();
const MockWrapper = (props: ComponentProps<typeof EnvironmentProvider>) => {
return <EnvironmentProvider {...props} />;
};
const MOCK_HOST = 'https://vega.host/query';
// eslint-disable-next-line @typescript-eslint/no-empty-function
const noop = () => {};
const mockEnvironmentState = {
VEGA_URL: 'https://vega.xyz',
VEGA_ENV: Networks.TESTNET,
VEGA_CONFIG_URL: 'https://vega.xyz/testnet-config.json',
VEGA_NETWORKS: {
TESTNET: 'https://testnet.url',
STAGNET: 'https://stagnet.url',
MAINNET: 'https://mainnet.url',
},
ETHEREUM_PROVIDER_URL: 'https://ether.provider',
ETHERSCAN_URL: 'https://etherscan.url',
GIT_BRANCH: 'test',
GIT_ORIGIN_URL: 'https://github.com/test/repo',
GIT_COMMIT_HASH: 'abcde01234',
GITHUB_FEEDBACK_URL: 'https://github.com/test/feedback',
setNodeSwitcherOpen: noop,
networkError: undefined,
};
const MOCK_DURATION = 76;
window.performance.getEntriesByName = jest
.fn()
.mockImplementation((url: string) => [
{
entryType: 'resource',
name: url,
startTime: 0,
toJSON: () => ({}),
duration: MOCK_DURATION,
},
]);
function setupFetch(
configUrl: string = mockEnvironmentState.VEGA_CONFIG_URL,
hosts?: string[]
) {
return (url: RequestInfo) => {
if (url === configUrl) {
return Promise.resolve({
ok: true,
json: () => Promise.resolve({ hosts: hosts || [MOCK_HOST] }),
} as Response);
}
return Promise.resolve({
ok: true,
} as Response);
};
}
beforeEach(() => {
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(setupFetch());
window.localStorage.clear();
// @ts-ignore allow adding a mock return value to mocked module
createClient.mockImplementation(() => createMockClient());
process.env['NX_VEGA_URL'] = mockEnvironmentState.VEGA_URL;
process.env['NX_VEGA_ENV'] = mockEnvironmentState.VEGA_ENV;
process.env['NX_VEGA_CONFIG_URL'] = mockEnvironmentState.VEGA_CONFIG_URL;
process.env['NX_VEGA_NETWORKS'] = JSON.stringify(
mockEnvironmentState.VEGA_NETWORKS
);
process.env['NX_ETHEREUM_PROVIDER_URL'] =
mockEnvironmentState.ETHEREUM_PROVIDER_URL;
process.env['NX_ETHERSCAN_URL'] = mockEnvironmentState.ETHERSCAN_URL;
process.env['NX_GIT_BRANCH'] = mockEnvironmentState.GIT_BRANCH;
process.env['NX_GIT_ORIGIN_URL'] = mockEnvironmentState.GIT_ORIGIN_URL;
process.env['NX_GIT_COMMIT_HASH'] = mockEnvironmentState.GIT_COMMIT_HASH;
process.env['NX_GITHUB_FEEDBACK_URL'] =
mockEnvironmentState.GITHUB_FEEDBACK_URL;
});
describe('throws error', () => {
beforeEach(() => {
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(setupFetch());
window.localStorage.clear();
// @ts-ignore allow adding a mock return value to mocked module
createClient.mockImplementation(() => createMockClient());
process.env['NX_VEGA_URL'] = mockEnvironmentState.VEGA_URL;
process.env['NX_VEGA_ENV'] = mockEnvironmentState.VEGA_ENV;
process.env['NX_VEGA_CONFIG_URL'] = mockEnvironmentState.VEGA_CONFIG_URL;
process.env['NX_VEGA_NETWORKS'] = JSON.stringify(
mockEnvironmentState.VEGA_NETWORKS
);
process.env['NX_ETHEREUM_PROVIDER_URL'] =
mockEnvironmentState.ETHEREUM_PROVIDER_URL;
process.env['NX_ETHERSCAN_URL'] = mockEnvironmentState.ETHERSCAN_URL;
process.env['NX_GIT_BRANCH'] = mockEnvironmentState.GIT_BRANCH;
process.env['NX_GIT_ORIGIN_URL'] = mockEnvironmentState.GIT_ORIGIN_URL;
process.env['NX_GIT_COMMIT_HASH'] = mockEnvironmentState.GIT_COMMIT_HASH;
process.env['NX_GITHUB_FEEDBACK_URL'] =
mockEnvironmentState.GITHUB_FEEDBACK_URL;
});
beforeEach(() => jest.resetModules()); // clears the cache of the modules
it('throws a validation error when NX_ETHERSCAN_URL is not a valid url', () => {
process.env['NX_ETHERSCAN_URL'] = 'invalid-url';
const result = () =>
renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result).toThrow(
`The NX_ETHERSCAN_URL environment variable must be a valid url`
);
});
it('throws a validation error when NX_ETHEREUM_PROVIDER_URL is not a valid url', () => {
process.env['NX_ETHEREUM_PROVIDER_URL'] = 'invalid-url';
const result = () =>
renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result).toThrow(
`The NX_ETHEREUM_PROVIDER_URL environment variable must be a valid url`
);
});
it('throws a validation error when VEGA_NETWORKS is has an invalid network as a key', () => {
process.env['NX_VEGA_NETWORKS'] = JSON.stringify({
NOT_A_NETWORK: 'https://somewhere.url',
});
const result = () =>
renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result).toThrow(
`All keys in NX_VEGA_NETWORKS must represent a valid environment: CUSTOM | TESTNET | STAGNET | STAGNET2 | DEVNET | MAINNET`
);
});
it('throws a validation error when both VEGA_URL and VEGA_CONFIG_URL are missing in the environment', () => {
delete process.env['NX_VEGA_URL'];
delete process.env['NX_VEGA_CONFIG_URL'];
const result = () =>
renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result).toThrow(
`Must provide either NX_VEGA_CONFIG_URL or NX_VEGA_URL in the environment.`
);
});
it('throws a validation error when NX_VEGA_ENV is not found in the environment', () => {
delete process.env['NX_VEGA_ENV'];
const result = () =>
renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result).toThrow(
`NX_VEGA_ENV is invalid, received "undefined" instead of: 'CUSTOM' | 'TESTNET' | 'STAGNET' | 'STAGNET2' | 'DEVNET' | 'MAINNET'`
);
});
it('throws a validation error when VEGA_ENV is not a valid network', () => {
process.env['NX_VEGA_ENV'] = 'SOMETHING';
const result = () =>
renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result).not.toThrow(
`Error processing the vega app environment:
- NX_VEGA_ENV is invalid, received "SOMETHING" instead of: CUSTOM | TESTNET | STAGNET | STAGNET2 | DEVNET | MAINNET`
);
});
});

View File

@ -1,7 +1,7 @@
// having the node switcher dialog in the environment provider breaks the test renderer
// workaround based on: https://github.com/facebook/react/issues/11565
import type { ComponentProps, ReactNode } from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { renderHook, waitFor, act } from '@testing-library/react';
import createClient from '../utils/apollo-client';
import { useEnvironment, EnvironmentProvider } from './use-environment';
import { Networks, ErrorType } from '../types';
@ -96,7 +96,7 @@ const getQuickestNode = (mockNodes: Record<string, MockRequestConfig>) => {
};
beforeEach(() => {
// @ts-ignore: typscript doesn't recognise the mock implementation
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(setupFetch());
window.localStorage.clear();
@ -126,126 +126,88 @@ afterAll(() => {
describe('useEnvironment hook', () => {
it('transforms and exposes values from the environment', async () => {
const { result, waitForNextUpdate } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitForNextUpdate();
expect(result.error).toBe(undefined);
await waitFor(() => {
expect(result.current).toEqual({
...mockEnvironmentState,
setNodeSwitcherOpen: result.current.setNodeSwitcherOpen,
});
});
});
});
it('allows for the VEGA_CONFIG_URL to be missing when there is a VEGA_URL present', async () => {
it('allows for the VEGA_CONFIG_URL to be missing when there is a VEGA_URL present', async () => {
delete process.env['NX_VEGA_CONFIG_URL'];
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_CONFIG_URL: undefined,
setNodeSwitcherOpen: result.current.setNodeSwitcherOpen,
});
});
});
it('allows for the VEGA_NETWORKS to be missing from the environment', async () => {
it('allows for the VEGA_NETWORKS to be missing from the environment', async () => {
act(async () => {
delete process.env['NX_VEGA_NETWORKS'];
const { result, waitForNextUpdate } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitForNextUpdate();
expect(result.error).toBe(undefined);
await waitFor(() => {
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_NETWORKS: {},
setNodeSwitcherOpen: result.current.setNodeSwitcherOpen,
});
});
});
});
it('throws a validation error when NX_VEGA_ENV is not found in the environment', async () => {
delete process.env['NX_VEGA_ENV'];
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result.error?.message).toContain(
`NX_VEGA_ENV is invalid, received "undefined" instead of: 'CUSTOM' | 'TESTNET' | 'STAGNET' | 'STAGNET2' | 'DEVNET' | 'MAINNET'`
);
});
it('throws a validation error when VEGA_ENV is not a valid network', async () => {
process.env['NX_VEGA_ENV'] = 'SOMETHING';
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result.error).not.toContain(
`NX_VEGA_ENV is invalid, received "SOMETHING" instead of: CUSTOM | TESTNET | STAGNET | STAGNET2 | DEVNET | MAINNET`
);
});
it('when VEGA_NETWORKS is not a valid json, prints a warning and continues without using the value from it', async () => {
it('when VEGA_NETWORKS is not a valid json, prints a warning and continues without using the value from it', async () => {
act(async () => {
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(noop);
process.env['NX_VEGA_NETWORKS'] = '{not:{valid:json';
const { result, waitForNextUpdate } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitForNextUpdate();
expect(result.error).toBe(undefined);
await waitFor(() => {
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_NETWORKS: {},
setNodeSwitcherOpen: result.current.setNodeSwitcherOpen,
});
});
expect(consoleWarnSpy).toHaveBeenCalled();
consoleWarnSpy.mockRestore();
});
});
it('throws a validation error when VEGA_NETWORKS is has an invalid network as a key', async () => {
process.env['NX_VEGA_NETWORKS'] = JSON.stringify({
NOT_A_NETWORK: 'https://somewhere.url',
});
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result.error?.message).toContain(
`All keys in NX_VEGA_NETWORKS must represent a valid environment: CUSTOM | TESTNET | STAGNET | STAGNET2 | DEVNET | MAINNET`
);
});
it('throws a validation error when both VEGA_URL and VEGA_CONFIG_URL are missing in the environment', async () => {
delete process.env['NX_VEGA_URL'];
delete process.env['NX_VEGA_CONFIG_URL'];
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result.error?.message).toContain(
`Must provide either NX_VEGA_CONFIG_URL or NX_VEGA_URL in the environment.`
);
});
it.each`
it.each`
env | etherscanUrl | providerUrl
${Networks.DEVNET} | ${'https://ropsten.etherscan.io'} | ${'https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8'}
${Networks.TESTNET} | ${'https://ropsten.etherscan.io'} | ${'https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8'}
${Networks.STAGNET} | ${'https://ropsten.etherscan.io'} | ${'https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8'}
${Networks.STAGNET2} | ${'https://ropsten.etherscan.io'} | ${'https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8'}
${Networks.MAINNET} | ${'https://etherscan.io'} | ${'https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8'}
`(
`(
'uses correct default ethereum connection variables in $env',
async ({ env, etherscanUrl, providerUrl }) => {
act(async () => {
// @ts-ignore allow adding a mock return value to mocked module
createClient.mockImplementation(() => createMockClient({ network: env }));
process.env['NX_VEGA_ENV'] = env;
delete process.env['NX_ETHEREUM_PROVIDER_URL'];
delete process.env['NX_ETHERSCAN_URL'];
const { result, waitForNextUpdate } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitForNextUpdate();
expect(result.error).toBe(undefined);
await waitFor(() => {
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_ENV: env,
@ -253,38 +215,20 @@ describe('useEnvironment hook', () => {
ETHERSCAN_URL: etherscanUrl,
setNodeSwitcherOpen: result.current.setNodeSwitcherOpen,
});
});
});
}
);
);
it('throws a validation error when NX_ETHERSCAN_URL is not a valid url', async () => {
process.env['NX_ETHERSCAN_URL'] = 'invalid-url';
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result.error?.message).toContain(
`The NX_ETHERSCAN_URL environment variable must be a valid url`
);
});
it('throws a validation error when NX_ETHEREUM_PROVIDER_URL is not a valid url', async () => {
process.env['NX_ETHEREUM_PROVIDER_URL'] = 'invalid-url';
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
expect(result.error?.message).toContain(
`The NX_ETHEREUM_PROVIDER_URL environment variable must be a valid url`
);
});
describe('node selection', () => {
describe('node selection', () => {
it('updates the VEGA_URL from the config when it is missing from the environment', async () => {
act(async () => {
delete process.env['NX_VEGA_URL'];
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_URL: MOCK_HOST,
@ -292,8 +236,10 @@ describe('useEnvironment hook', () => {
});
});
});
});
it('updates the VEGA_URL with the quickest node to respond from the config urls', async () => {
act(async () => {
delete process.env['NX_VEGA_URL'];
const mockNodes: Record<string, MockRequestConfig> = {
@ -303,7 +249,7 @@ describe('useEnvironment hook', () => {
'https://mock-node-4.com': { hasError: false, delay: 0 },
};
// @ts-ignore: typscript doesn't recognise the mock implementation
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(
setupFetch(mockEnvironmentState.VEGA_CONFIG_URL, Object.keys(mockNodes))
);
@ -314,12 +260,11 @@ describe('useEnvironment hook', () => {
const nodeUrl = getQuickestNode(mockNodes);
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_URL: nodeUrl,
@ -327,8 +272,10 @@ describe('useEnvironment hook', () => {
});
});
});
});
it('ignores failing nodes and selects the first successful one to use', async () => {
act(async () => {
delete process.env['NX_VEGA_URL'];
const mockNodes: Record<string, MockRequestConfig> = {
@ -338,7 +285,7 @@ describe('useEnvironment hook', () => {
'https://mock-node-4.com': { hasError: true, delay: 0 },
};
// @ts-ignore: typscript doesn't recognise the mock implementation
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(
setupFetch(mockEnvironmentState.VEGA_CONFIG_URL, Object.keys(mockNodes))
);
@ -349,12 +296,11 @@ describe('useEnvironment hook', () => {
const nodeUrl = getQuickestNode(mockNodes);
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_URL: nodeUrl,
@ -362,8 +308,10 @@ describe('useEnvironment hook', () => {
});
});
});
});
it('has a network error when cannot connect to any nodes', async () => {
act(async () => {
delete process.env['NX_VEGA_URL'];
const mockNodes: Record<string, MockRequestConfig> = {
@ -373,7 +321,7 @@ describe('useEnvironment hook', () => {
'https://mock-node-4.com': { hasError: true, delay: 0 },
};
// @ts-ignore: typscript doesn't recognise the mock implementation
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(
setupFetch(mockEnvironmentState.VEGA_CONFIG_URL, Object.keys(mockNodes))
);
@ -382,12 +330,11 @@ describe('useEnvironment hook', () => {
return createMockClient({ statistics: mockNodes[url] });
});
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_URL: undefined,
@ -396,21 +343,22 @@ describe('useEnvironment hook', () => {
});
});
});
});
it('has a network error when it cannot fetch the network config and there is no VEGA_URL in the environment', async () => {
act(async () => {
delete process.env['NX_VEGA_URL'];
// @ts-ignore: typscript doesn't recognise the mock implementation
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(() => {
throw new Error('Cannot fetch');
});
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_URL: undefined,
@ -419,23 +367,24 @@ describe('useEnvironment hook', () => {
});
});
});
});
it('logs an error when it cannot fetch the network config and there is a VEGA_URL in the environment', async () => {
act(async () => {
const consoleWarnSpy = jest
.spyOn(console, 'warn')
.mockImplementation(noop);
// @ts-ignore: typscript doesn't recognise the mock implementation
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(() => {
throw new Error('Cannot fetch');
});
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
setNodeSwitcherOpen: result.current.setNodeSwitcherOpen,
@ -448,13 +397,15 @@ describe('useEnvironment hook', () => {
);
});
});
});
// SKIP due to https://github.com/facebook/jest/issues/12670
// eslint-disable-next-line jest/no-disabled-tests
it.skip('has a network error when the config is invalid and there is no VEGA_URL in the environment', async () => {
act(async () => {
delete process.env['NX_VEGA_URL'];
// @ts-ignore: typscript doesn't recognise the mock implementation
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(() =>
Promise.resolve({
ok: true,
@ -462,12 +413,11 @@ describe('useEnvironment hook', () => {
})
);
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
VEGA_URL: undefined,
@ -476,15 +426,17 @@ describe('useEnvironment hook', () => {
});
});
});
});
// SKIP due to https://github.com/facebook/jest/issues/12670
// eslint-disable-next-line jest/no-disabled-tests
it.skip('logs an error when the network config in invalid and there is a VEGA_URL in the environment', async () => {
act(async () => {
const consoleWarnSpy = jest
.spyOn(console, 'warn')
.mockImplementation(noop);
// @ts-ignore: typscript doesn't recognise the mock implementation
// @ts-ignore: typescript doesn't recognize the mock implementation
global.fetch.mockImplementation(() =>
Promise.resolve({
ok: true,
@ -492,12 +444,11 @@ describe('useEnvironment hook', () => {
})
);
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
setNodeSwitcherOpen: result.current.setNodeSwitcherOpen,
@ -510,18 +461,19 @@ describe('useEnvironment hook', () => {
);
});
});
});
// SKIP due to https://github.com/facebook/jest/issues/12670
// eslint-disable-next-line jest/no-disabled-tests
it.skip('has a network error when the selected node is not a valid url', async () => {
act(async () => {
process.env['NX_VEGA_URL'] = 'not-url';
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
networkError: ErrorType.INVALID_URL,
@ -529,19 +481,20 @@ describe('useEnvironment hook', () => {
});
});
});
});
it('has a network error when cannot connect to the selected node', async () => {
act(async () => {
// @ts-ignore allow adding a mock return value to mocked module
createClient.mockImplementation(() => {
return createMockClient({ statistics: { hasError: true } });
});
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
networkError: ErrorType.CONNECTION_ERROR,
@ -549,19 +502,20 @@ describe('useEnvironment hook', () => {
});
});
});
});
it('has a network error when the selected node is not on the correct network', async () => {
act(async () => {
// @ts-ignore allow adding a mock return value to mocked module
createClient.mockImplementation(() => {
return createMockClient({ network: Networks.MAINNET });
});
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
networkError: ErrorType.INVALID_NETWORK,
@ -569,19 +523,20 @@ describe('useEnvironment hook', () => {
});
});
});
});
it('has a network error when the selected node has not ssl available', async () => {
act(async () => {
// @ts-ignore allow adding a mock return value to mocked module
createClient.mockImplementation(() => {
return createMockClient({ busEvents: { hasError: true } });
});
const { result, waitFor } = renderHook(() => useEnvironment(), {
const { result } = renderHook(() => useEnvironment(), {
wrapper: MockWrapper,
});
await waitFor(() => {
expect(result.error).toBe(undefined);
expect(result.current).toEqual({
...mockEnvironmentState,
networkError: ErrorType.SSL_ERROR,

View File

@ -1,10 +1,11 @@
import { renderHook, act } from '@testing-library/react-hooks';
import { renderHook, act } from '@testing-library/react';
import { ApolloClient } from '@apollo/client';
import createClient from '../utils/apollo-client';
import { useNodes } from './use-nodes';
import createMockClient, {
getMockStatisticsResult,
} from './mocks/apollo-client';
import { waitFor } from '@testing-library/react';
jest.mock('../utils/apollo-client');
@ -65,9 +66,7 @@ describe('useNodes hook', () => {
it('sets loading state while waiting for the results', async () => {
const node = 'https://some.url';
const { result, waitForNextUpdate } = renderHook(() =>
useNodes({ hosts: [node] })
);
const { result } = renderHook(() => useNodes({ hosts: [node] }));
expect(result.current.state[node]).toEqual({
...initialState,
@ -90,14 +89,12 @@ describe('useNodes hook', () => {
isLoading: true,
},
});
await waitForNextUpdate();
});
it('sets statistics results', async () => {
const mockResult = getMockStatisticsResult();
const node = 'https://some.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [node] }));
const { result } = renderHook(() => useNodes({ hosts: [node] }));
await waitFor(() => {
expect(result.current.state[node].block).toEqual({
@ -122,7 +119,7 @@ describe('useNodes hook', () => {
it('sets subscription result', async () => {
const node = 'https://some.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [node] }));
const { result } = renderHook(() => useNodes({ hosts: [node] }));
await waitFor(() => {
expect(result.current.state[node].ssl).toEqual({
@ -135,7 +132,7 @@ describe('useNodes hook', () => {
it('sets error when host in not a valid url', async () => {
const node = 'not-url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [node] }));
const { result } = renderHook(() => useNodes({ hosts: [node] }));
await waitFor(() => {
expect(result.current.state[node].block.hasError).toBe(true);
@ -152,7 +149,7 @@ describe('useNodes hook', () => {
);
const node = 'https://some.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [node] }));
const { result } = renderHook(() => useNodes({ hosts: [node] }));
await waitFor(() => {
expect(result.current.state[node].block).toEqual({
@ -182,7 +179,7 @@ describe('useNodes hook', () => {
);
const node = 'https://some.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [node] }));
const { result } = renderHook(() => useNodes({ hosts: [node] }));
await waitFor(() => {
expect(result.current.state[node].ssl).toEqual({
@ -196,7 +193,7 @@ describe('useNodes hook', () => {
it('allows updating block values', async () => {
const mockResult = getMockStatisticsResult();
const node = 'https://some.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [node] }));
const { result } = renderHook(() => useNodes({ hosts: [node] }));
await waitFor(() => {
expect(result.current.state[node].block.value).toEqual(
@ -216,7 +213,7 @@ describe('useNodes hook', () => {
it('does nothing when calling the block update on a non-existing node', async () => {
const mockResult = getMockStatisticsResult();
const node = 'https://some.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [node] }));
const { result } = renderHook(() => useNodes({ hosts: [node] }));
await waitFor(() => {
expect(result.current.state[node].block.value).toEqual(
@ -233,7 +230,7 @@ describe('useNodes hook', () => {
it('adds new node', async () => {
const node = 'custom-node-key';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [] }));
const { result } = renderHook(() => useNodes({ hosts: [] }));
expect(result.current.state[node]).toEqual(undefined);
@ -249,7 +246,7 @@ describe('useNodes hook', () => {
it('sets new url for node', async () => {
const node = 'https://some.url';
const newUrl = 'https://some-other.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [node] }));
const { result } = renderHook(() => useNodes({ hosts: [node] }));
act(() => {
result.current.updateNodeUrl(node, newUrl);
@ -263,7 +260,7 @@ describe('useNodes hook', () => {
it('sets error when custom node has an invalid url', async () => {
const node = 'node-key';
const url = 'not-url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [] }));
const { result } = renderHook(() => useNodes({ hosts: [] }));
expect(result.current.state[node]).toBe(undefined);
@ -288,7 +285,7 @@ describe('useNodes hook', () => {
const node = 'node-key';
const url = 'https://some.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [] }));
const { result } = renderHook(() => useNodes({ hosts: [] }));
expect(result.current.state[node]).toBe(undefined);
@ -325,7 +322,7 @@ describe('useNodes hook', () => {
const node = 'node-key';
const url = 'https://some.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [] }));
const { result } = renderHook(() => useNodes({ hosts: [] }));
expect(result.current.state[node]).toBe(undefined);
@ -345,9 +342,7 @@ describe('useNodes hook', () => {
it('exposes a collection of clients', async () => {
const url1 = 'https://some.url';
const url2 = 'https://some-other.url';
const { result, waitFor } = renderHook(() =>
useNodes({ hosts: [url1, url2] })
);
const { result } = renderHook(() => useNodes({ hosts: [url1, url2] }));
await waitFor(() => {
expect(result.current.clients[url1]).toBeInstanceOf(ApolloClient);
@ -358,7 +353,7 @@ describe('useNodes hook', () => {
it('exposes a client for the custom node', async () => {
const node = 'node-key';
const url = 'https://some.url';
const { result, waitFor } = renderHook(() => useNodes({ hosts: [] }));
const { result } = renderHook(() => useNodes({ hosts: [] }));
act(() => {
result.current.updateNodeUrl(node, url);

View File

@ -1,4 +1,4 @@
import { render, screen, waitFor } from '@testing-library/react';
import { render, screen, waitFor, act } from '@testing-library/react';
import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
import { Side } from '@vegaprotocol/types';
import type { PartialDeep } from 'type-fest';
@ -46,7 +46,8 @@ describe('FillsTable', () => {
};
});
it('correct columns are rendered', async () => {
it('should render correct columns', async () => {
act(async () => {
render(<FillsTable partyId="party-id" rowData={[generateFill()]} />);
await waitForGridToBeInTheDOM();
await waitForDataToHaveLoaded();
@ -63,8 +64,10 @@ describe('FillsTable', () => {
'Date',
]);
});
});
it('formats cells correctly for buyer fill', async () => {
it('should format cells correctly for buyer fill', async () => {
act(async () => {
const partyId = 'party-id';
const buyerFill = generateFill({
...defaultFill,
@ -100,8 +103,10 @@ describe('FillsTable', () => {
const amountCell = cells.find((c) => c.getAttribute('col-id') === 'size');
expect(amountCell).toHaveClass('text-vega-green');
});
});
it('formats cells correctly for seller fill', async () => {
it('should format cells correctly for seller fill', async () => {
act(async () => {
const partyId = 'party-id';
const buyerFill = generateFill({
...defaultFill,
@ -137,8 +142,10 @@ describe('FillsTable', () => {
const amountCell = cells.find((c) => c.getAttribute('col-id') === 'size');
expect(amountCell).toHaveClass('text-vega-red');
});
});
it('renders correct maker or taker role', async () => {
it('should render correct maker or taker role', async () => {
act(async () => {
const partyId = 'party-id';
const takerFill = generateFill({
seller: {
@ -176,4 +183,5 @@ describe('FillsTable', () => {
.find((c) => c.getAttribute('col-id') === 'aggressor')
).toHaveTextContent('Maker');
});
});
});

View File

@ -69,19 +69,22 @@ describe('ProposalForm', () => {
it('handles validation', async () => {
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve());
setup(mockSendTx);
await act(async () => {
fireEvent.click(screen.getByTestId('proposal-submit'));
});
expect(mockSendTx).not.toHaveBeenCalled();
expect(await screen.findByTestId('input-error-text')).toHaveTextContent(
'Required'
);
await act(async () => {
fireEvent.change(screen.getByTestId('proposal-data'), {
target: { value: 'invalid' },
});
});
await act(async () => {
fireEvent.click(screen.getByTestId('proposal-submit'));
});
expect(mockSendTx).not.toHaveBeenCalled();
expect(await screen.findByTestId('input-error-text')).toHaveTextContent(

View File

@ -1,6 +1,6 @@
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import { act, renderHook } from '@testing-library/react-hooks';
import { act, renderHook } from '@testing-library/react';
import type { ReactNode } from 'react';
import { VegaTxStatus, VegaWalletContext } from '@vegaprotocol/wallet';
import type {

View File

@ -1,4 +1,4 @@
import { act, renderHook } from '@testing-library/react-hooks';
import { act, renderHook } from '@testing-library/react';
import type {
VegaKeyExtended,
VegaWalletContextShape,

View File

@ -1,4 +1,4 @@
import { act, renderHook } from '@testing-library/react-hooks';
import { act, renderHook } from '@testing-library/react';
import type { Order } from '../utils';
import type {
VegaKeyExtended,

View File

@ -1,4 +1,4 @@
import { renderHook } from '@testing-library/react-hooks';
import { renderHook } from '@testing-library/react';
import {
VegaWalletOrderTimeInForce,
VegaWalletOrderType,

View File

@ -56,15 +56,16 @@ const singleRow: Positions_party_positions = {
};
const singleRowData = [singleRow];
it('should render successfully', async () => {
await act(async () => {
describe('PositionsTable', () => {
it('should render successfully', async () => {
act(async () => {
const { baseElement } = render(<PositionsTable data={[]} />);
expect(baseElement).toBeTruthy();
});
});
});
it('Render correct columns', async () => {
await act(async () => {
it('should render correct columns', async () => {
act(async () => {
render(<PositionsTable data={singleRowData} />);
await waitFor(async () => {
const headers = screen.getAllByRole('columnheader');
@ -78,10 +79,10 @@ it('Render correct columns', async () => {
]);
});
});
});
});
it('Correct formatting applied', async () => {
await act(async () => {
it('should apply correct formatting', () => {
act(async () => {
render(<PositionsTable data={singleRowData} />);
await waitFor(async () => {
const cells = screen.getAllByRole('gridcell');
@ -98,4 +99,5 @@ it('Correct formatting applied', async () => {
expect(cells[cells.length - 1]).toHaveClass('color-vega-green');
});
});
});
});

View File

@ -1,5 +1,5 @@
import { useApplyGridTransaction } from './use-apply-grid-transaction';
import { renderHook } from '@testing-library/react-hooks';
import { renderHook } from '@testing-library/react';
type Items = Array<{ id: string; value: number }>;

View File

@ -1,7 +1,11 @@
import { useState, useEffect, useRef, useCallback } from 'react';
import { useApolloClient } from '@apollo/client';
import type { OperationVariables } from '@apollo/client';
import type { Subscribe, Load } from '../lib/generic-data-provider';
import type {
Subscribe,
Load,
UpdateCallback,
} from '../lib/generic-data-provider';
/**
*
@ -54,14 +58,14 @@ export function useDataProvider<Data, Delta>({
}
return Promise.reject();
}, []);
const callback = useCallback(
const callback = useCallback<UpdateCallback<Data, Delta>>(
({ data, error, loading, delta, insertionData, totalCount }) => {
setError(error);
setLoading(loading);
if (!error && !loading) {
// if update or insert function returns true it means that component handles updates
// component can use flush() which will call callback without delta and cause data state update
if (initialized.current) {
if (initialized.current && data) {
if (delta && update && update({ delta, data })) {
return;
}

View File

@ -15,9 +15,9 @@ export const PriceCell = React.memo(
return <span data-testid="price">-</span>;
}
const decimalSeparator = getDecimalSeparator();
const valueSplit = decimalSeparator
? valueFormatted.split(decimalSeparator)
: [value];
const valueSplit: string[] = decimalSeparator
? valueFormatted.split(decimalSeparator).map((v) => `${v}`)
: [`${value}`];
return (
<span
className="font-mono relative text-ui-small text-black dark:text-white"

View File

@ -1,4 +1,4 @@
import { act, renderHook } from '@testing-library/react-hooks';
import { act, renderHook } from '@testing-library/react';
import type { VegaWalletContextShape } from './context';
import { VegaWalletContext } from './context';
import type { ReactNode } from 'react';

View File

@ -1,4 +1,4 @@
import { renderHook, act } from '@testing-library/react-hooks/dom';
import { renderHook, act } from '@testing-library/react';
import { EthTxStatus } from './use-ethereum-transaction';
import { useEthereumTransaction } from './use-ethereum-transaction';
import type { ethers } from 'ethers';

View File

@ -1,4 +1,4 @@
import { act, renderHook } from '@testing-library/react-hooks';
import { act, renderHook } from '@testing-library/react';
import { waitFor } from '@testing-library/react';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';

View File

@ -1,4 +1,4 @@
import { act, renderHook } from '@testing-library/react-hooks';
import { act, renderHook } from '@testing-library/react';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import type { ReactNode } from 'react';

View File

@ -14,6 +14,9 @@
"private": true,
"dependencies": {
"@apollo/client": "^3.5.8",
"@babel/plugin-proposal-export-default-from": "^7.18.10",
"@babel/preset-env": "^7.18.10",
"@babel/runtime": "^7.18.9",
"@blueprintjs/icons": "^3.32.0",
"@emotion/react": "^11.9.0",
"@emotion/styled": "^11.8.1",
@ -29,7 +32,7 @@
"@sentry/nextjs": "^6.19.3",
"@sentry/react": "^6.19.2",
"@sentry/tracing": "^6.19.2",
"@testing-library/user-event": "^14.2.1",
"@testing-library/user-event": "^14.4.1",
"@walletconnect/ethereum-provider": "^1.7.5",
"@web3-react/core": "8.0.20-beta.0",
"@web3-react/metamask": "8.0.16-beta.0",
@ -56,16 +59,16 @@
"immer": "^9.0.12",
"js-sha3": "^0.8.0",
"lodash": "^4.17.21",
"next": "^12.0.7",
"next": "12.0.9",
"pennant": "^0.4.12",
"postcss": "^8.4.6",
"react": "17.0.2",
"react": "18.2.0",
"react-copy-to-clipboard": "^5.0.4",
"react-dom": "17.0.2",
"react-dom": "^18.2.0",
"react-hook-form": "^7.27.0",
"react-i18next": "^11.11.4",
"react-intersection-observer": "^9.2.2",
"react-router-dom": "^6.3.0",
"react-router-dom": "6.3.0",
"react-syntax-highlighter": "^15.4.5",
"react-use-websocket": "^3.0.0",
"react-virtualized-auto-sizer": "^1.0.6",
@ -107,25 +110,24 @@
"@storybook/react": "~6.4.12",
"@svgr/webpack": "^5.4.0",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "12.1.2",
"@testing-library/react-hooks": "7.0.2",
"@testing-library/react": "13.3.0",
"@types/classnames": "^2.3.1",
"@types/faker": "^5.5.8",
"@types/jest": "27.0.2",
"@types/jest": "27.4.1",
"@types/lodash": "^4.14.171",
"@types/node": "16.11.7",
"@types/node": "18.0.4",
"@types/prismjs": "^1.26.0",
"@types/react": "17.0.39",
"@types/react": "18.0.1",
"@types/react-copy-to-clipboard": "^5.0.2",
"@types/react-dom": "17.0.9",
"@types/react-dom": "18.0.6",
"@types/react-router-dom": "5.3.1",
"@types/react-virtualized-auto-sizer": "^1.0.1",
"@types/react-window": "^1.8.5",
"@types/react-window-infinite-loader": "^1.0.6",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "5.18.0",
"@typescript-eslint/parser": "5.18.0",
"babel-jest": "27.2.3",
"@typescript-eslint/eslint-plugin": "5.32.0",
"@typescript-eslint/parser": "5.32.0",
"babel-jest": "27.5.1",
"babel-loader": "8.1.0",
"cypress": "^10.2.0",
"cypress-cucumber-preprocessor": "^4.3.1",

8723
yarn.lock

File diff suppressed because it is too large Load Diff