chore: add market-depth-provider unit tests (#1839)

This commit is contained in:
Bartłomiej Głownia 2022-10-24 14:30:22 +02:00 committed by GitHub
parent ee3b9a56c9
commit 786b85fde2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 30 deletions

View File

@ -7,7 +7,7 @@ import {
ThemeContext,
getNumberFormat,
} from '@vegaprotocol/react-helpers';
import dataProvider from './market-depth-provider';
import { marketDepthProvider } from './market-depth-provider';
import {
useCallback,
useEffect,
@ -115,7 +115,7 @@ export const DepthChartContainer = ({ marketId }: DepthChartManagerProps) => {
);
const { data, error, loading } = useDataProvider({
dataProvider,
dataProvider: marketDepthProvider,
update,
variables,
});

View File

@ -1,6 +1,6 @@
export * from './__generated___/MarketDepth';
export * from './depth-chart';
export * from './market-depth-provider';
export { marketDepthProvider } from './market-depth-provider';
export * from './orderbook-container';
export * from './orderbook-data';
export * from './orderbook-manager';

View File

@ -0,0 +1,76 @@
import { update } from './market-depth-provider';
import { captureException } from '@sentry/react';
const reload = jest.fn();
jest.mock('@sentry/react', () => {
const original = jest.requireActual('@sentry/react'); // Step 2.
return {
...original,
captureException: jest.fn(),
};
});
jest.mock('./orderbook-data', () => ({
updateLevels: jest.fn((arg) => arg),
}));
describe('market depth provider update', () => {
it('omits overlapping updates', () => {
const data = {
id: '1',
depth: {
sequenceNumber: '1',
},
};
const delta = {
marketId: '2',
sequenceNumber: '',
previousSequenceNumber: '',
};
const updatedData = update(data, [delta], reload);
expect(updatedData).toBe(data);
});
it('omits not matching market', () => {
const data = {
id: '1',
depth: {
sequenceNumber: '10',
},
};
const delta = [
{
marketId: '1',
sequenceNumber: '5',
previousSequenceNumber: '',
},
{
marketId: '1',
sequenceNumber: '10',
previousSequenceNumber: '',
},
];
expect(update(data, delta.slice(0, 1), reload)).toBe(data);
expect(update(data, delta.slice(1, 2), reload)).toBe(data);
});
it('restarts and captureException when there is gap in updates', () => {
const data = {
id: '1',
depth: {
sequenceNumber: '10',
},
};
const delta = [
{
marketId: '1',
sequenceNumber: '16',
previousSequenceNumber: '12',
},
];
const updatedData = update(data, delta, reload);
expect(updatedData).toBe(data);
expect(reload).toBeCalled();
expect(captureException).toBeCalled();
});
});

View File

@ -12,40 +12,34 @@ import type {
MarketDepthUpdateSubscription,
} from './__generated___/MarketDepth';
const sequenceNumbers: Record<string, number> = {};
const update: Update<
export const update: Update<
ReturnType<typeof getData>,
ReturnType<typeof getDelta>
> = (data, deltas, reload) => {
if (!data) {
return;
return data;
}
for (const delta of deltas) {
if (delta.marketId !== data.id) {
continue;
}
const currentSequenceNumber = Number(delta.sequenceNumber);
if (currentSequenceNumber <= sequenceNumbers[delta.marketId]) {
if (Number(delta.sequenceNumber) <= Number(data.depth.sequenceNumber)) {
return data;
}
if (
delta.previousSequenceNumber !==
sequenceNumbers[delta.marketId].toString()
) {
if (delta.previousSequenceNumber !== data.depth.sequenceNumber) {
captureException(
new Error(
`Sequence number gap in marketsDepthUpdate for {data.id}, {sequenceNumbers[delta.marketId]} - {delta.previousSequenceNumber}`
)
);
delete sequenceNumbers[delta.marketId];
reload();
return;
return data;
}
sequenceNumbers[delta.marketId] = Number(currentSequenceNumber);
const updatedData = {
...data,
depth: { ...data.depth },
depth: {
...data.depth,
},
};
if (delta.buy) {
updatedData.depth.buy = updateLevels(data.depth.buy ?? [], delta.buy);
@ -53,19 +47,14 @@ const update: Update<
if (delta.sell) {
updatedData.depth.sell = updateLevels(data.depth.sell ?? [], delta.sell);
}
updatedData.depth.sequenceNumber = delta.sequenceNumber;
return updatedData;
}
return data;
};
const getData = (responseData: MarketDepthQuery) => {
if (responseData.market?.id) {
sequenceNumbers[responseData.market.id] = Number(
responseData.market.depth.sequenceNumber
);
}
return responseData.market;
};
const getData = (responseData: MarketDepthQuery) => responseData.market;
const getDelta = (subscriptionData: MarketDepthUpdateSubscription) =>
subscriptionData.marketsDepthUpdate;
@ -76,5 +65,3 @@ export const marketDepthProvider = makeDataProvider({
getData,
getDelta,
});
export default marketDepthProvider;

View File

@ -2,7 +2,7 @@ import throttle from 'lodash/throttle';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { Orderbook } from './orderbook';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import marketDepthProvider from './market-depth-provider';
import { marketDepthProvider } from './market-depth-provider';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import type { MarketData } from '@vegaprotocol/market-list';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

View File

@ -1,7 +1,7 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import throttle from 'lodash/throttle';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import dataProvider from './market-depth-provider';
import { marketDepthProvider } from './market-depth-provider';
import type { MarketDepthQuery } from './__generated___/MarketDepth';
interface Props {
@ -39,7 +39,7 @@ export const useOrderBookData = ({
);
const { data, error, loading } = useDataProvider({
dataProvider,
dataProvider: marketDepthProvider,
update,
variables,
});