chore(trading): prevent node poll if query fails (#3411)
This commit is contained in:
parent
8553904d81
commit
dfa3355a68
@ -1,6 +1,6 @@
|
|||||||
import type { MockedResponse } from '@apollo/react-testing';
|
import type { MockedResponse } from '@apollo/react-testing';
|
||||||
import { MockedProvider } from '@apollo/react-testing';
|
import { MockedProvider } from '@apollo/react-testing';
|
||||||
import { render, screen, waitFor } from '@testing-library/react';
|
import { act, render, screen, waitFor } from '@testing-library/react';
|
||||||
import { RadioGroup } from '@vegaprotocol/ui-toolkit';
|
import { RadioGroup } from '@vegaprotocol/ui-toolkit';
|
||||||
import type {
|
import type {
|
||||||
BlockTimeSubscription,
|
BlockTimeSubscription,
|
||||||
@ -9,6 +9,7 @@ import type {
|
|||||||
import { BlockTimeDocument } from '../../utils/__generated__/Node';
|
import { BlockTimeDocument } from '../../utils/__generated__/Node';
|
||||||
import { StatisticsDocument } from '../../utils/__generated__/Node';
|
import { StatisticsDocument } from '../../utils/__generated__/Node';
|
||||||
import type { RowDataProps } from './row-data';
|
import type { RowDataProps } from './row-data';
|
||||||
|
import { POLL_INTERVAL } from './row-data';
|
||||||
import { BLOCK_THRESHOLD, RowData } from './row-data';
|
import { BLOCK_THRESHOLD, RowData } from './row-data';
|
||||||
import type { HeaderEntry } from '@vegaprotocol/apollo-client';
|
import type { HeaderEntry } from '@vegaprotocol/apollo-client';
|
||||||
import { useHeaderStore } from '@vegaprotocol/apollo-client';
|
import { useHeaderStore } from '@vegaprotocol/apollo-client';
|
||||||
@ -25,7 +26,7 @@ const statsQueryMock: MockedResponse<StatisticsQuery> = {
|
|||||||
result: {
|
result: {
|
||||||
data: {
|
data: {
|
||||||
statistics: {
|
statistics: {
|
||||||
blockHeight: '1234',
|
blockHeight: '1234', // the actual value used in the component is the value from the header store
|
||||||
vegaTime: new Date().toISOString(),
|
vegaTime: new Date().toISOString(),
|
||||||
chainId: 'test-chain-id',
|
chainId: 'test-chain-id',
|
||||||
},
|
},
|
||||||
@ -251,4 +252,105 @@ describe('RowData', () => {
|
|||||||
|
|
||||||
expect(mockOnBlockHeight).toHaveBeenCalledWith(blockHeight);
|
expect(mockOnBlockHeight).toHaveBeenCalledWith(blockHeight);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should poll the query unless an errors is returned', async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const createStatsQueryMock = (
|
||||||
|
blockHeight: string
|
||||||
|
): MockedResponse<StatisticsQuery> => {
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
query: StatisticsDocument,
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
statistics: {
|
||||||
|
blockHeight,
|
||||||
|
vegaTime: new Date().toISOString(),
|
||||||
|
chainId: 'test-chain-id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFailedStatsQueryMock = (): MockedResponse<StatisticsQuery> => {
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
query: StatisticsDocument,
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: undefined,
|
||||||
|
},
|
||||||
|
error: new Error('failed'),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mockHeaders(props.url);
|
||||||
|
const statsQueryMock1 = createStatsQueryMock('1234');
|
||||||
|
const statsQueryMock2 = createStatsQueryMock('1235');
|
||||||
|
const statsQueryMock3 = createFailedStatsQueryMock();
|
||||||
|
const statsQueryMock4 = createStatsQueryMock('1236');
|
||||||
|
render(
|
||||||
|
<MockedProvider
|
||||||
|
mocks={[
|
||||||
|
statsQueryMock1,
|
||||||
|
statsQueryMock2,
|
||||||
|
statsQueryMock3,
|
||||||
|
statsQueryMock4,
|
||||||
|
subMock,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<RadioGroup>
|
||||||
|
{/* Radio group required as radio is being render in isolation */}
|
||||||
|
<RowData {...props} />
|
||||||
|
</RadioGroup>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByTestId('block-height-cell')).toHaveTextContent(
|
||||||
|
'Checking'
|
||||||
|
);
|
||||||
|
|
||||||
|
// statsQueryMock1 should be rendered
|
||||||
|
await waitFor(() => {
|
||||||
|
const elem = screen.getByTestId('query-block-height');
|
||||||
|
expect(elem).toHaveAttribute('data-query-block-height', '1234');
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(POLL_INTERVAL);
|
||||||
|
});
|
||||||
|
|
||||||
|
// statsQueryMock2 should be rendered
|
||||||
|
await waitFor(() => {
|
||||||
|
const elem = screen.getByTestId('query-block-height');
|
||||||
|
expect(elem).toHaveAttribute('data-query-block-height', '1235');
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(POLL_INTERVAL);
|
||||||
|
});
|
||||||
|
|
||||||
|
// statsQueryMock3 should FAIL!
|
||||||
|
await waitFor(() => {
|
||||||
|
const elem = screen.getByTestId('query-block-height');
|
||||||
|
expect(elem).toHaveAttribute('data-query-block-height', 'failed');
|
||||||
|
});
|
||||||
|
|
||||||
|
// run the timer again, but statsQueryMock4's result should not be
|
||||||
|
// rendered even though its successful, because the poll
|
||||||
|
// should have been stopped
|
||||||
|
await act(async () => {
|
||||||
|
jest.advanceTimersByTime(POLL_INTERVAL);
|
||||||
|
});
|
||||||
|
|
||||||
|
// should still render the result of statsQueryMock3
|
||||||
|
await waitFor(() => {
|
||||||
|
const elem = screen.getByTestId('query-block-height');
|
||||||
|
expect(elem).toHaveAttribute('data-query-block-height', 'failed');
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
} from '../../utils/__generated__/Node';
|
} from '../../utils/__generated__/Node';
|
||||||
import { LayoutCell } from './layout-cell';
|
import { LayoutCell } from './layout-cell';
|
||||||
|
|
||||||
const POLL_INTERVAL = 1000;
|
export const POLL_INTERVAL = 1000;
|
||||||
export const BLOCK_THRESHOLD = 3;
|
export const BLOCK_THRESHOLD = 3;
|
||||||
|
|
||||||
export interface RowDataProps {
|
export interface RowDataProps {
|
||||||
@ -60,18 +60,22 @@ export const RowData = ({
|
|||||||
|
|
||||||
// handle polling
|
// handle polling
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleStartPoll = () => startPolling(POLL_INTERVAL);
|
const handleStartPoll = () => {
|
||||||
|
if (error) return;
|
||||||
|
startPolling(POLL_INTERVAL);
|
||||||
|
};
|
||||||
const handleStopPoll = () => stopPolling();
|
const handleStopPoll = () => stopPolling();
|
||||||
|
|
||||||
|
// start polling on mount, but only if there is no error
|
||||||
|
if (error) {
|
||||||
|
handleStopPoll();
|
||||||
|
} else {
|
||||||
|
handleStartPoll();
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('blur', handleStopPoll);
|
window.addEventListener('blur', handleStopPoll);
|
||||||
window.addEventListener('focus', handleStartPoll);
|
window.addEventListener('focus', handleStartPoll);
|
||||||
|
|
||||||
handleStartPoll();
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
stopPolling();
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('blur', handleStopPoll);
|
window.removeEventListener('blur', handleStopPoll);
|
||||||
window.removeEventListener('focus', handleStartPoll);
|
window.removeEventListener('focus', handleStartPoll);
|
||||||
@ -81,6 +85,7 @@ export const RowData = ({
|
|||||||
// measure response time
|
// measure response time
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isValidUrl(url)) return;
|
if (!isValidUrl(url)) return;
|
||||||
|
if (typeof window.performance.getEntriesByName !== 'function') return; // protection for test environment
|
||||||
// every time we get data measure response speed
|
// every time we get data measure response speed
|
||||||
const requestUrl = new URL(url);
|
const requestUrl = new URL(url);
|
||||||
const requests = window.performance.getEntriesByName(requestUrl.href);
|
const requests = window.performance.getEntriesByName(requestUrl.href);
|
||||||
@ -176,8 +181,15 @@ export const RowData = ({
|
|||||||
isLoading={loading}
|
isLoading={loading}
|
||||||
hasError={getHasError()}
|
hasError={getHasError()}
|
||||||
dataTestId="block-height-cell"
|
dataTestId="block-height-cell"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
data-testid="query-block-height"
|
||||||
|
data-query-block-height={
|
||||||
|
error ? 'failed' : data?.statistics.blockHeight
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{getBlockDisplayValue(headers?.blockHeight, error)}
|
{getBlockDisplayValue(headers?.blockHeight, error)}
|
||||||
|
</span>
|
||||||
</LayoutCell>
|
</LayoutCell>
|
||||||
<LayoutCell
|
<LayoutCell
|
||||||
label={t('Subscription')}
|
label={t('Subscription')}
|
||||||
|
Loading…
Reference in New Issue
Block a user