2022-08-26 15:39:40 +00:00
|
|
|
import {
|
|
|
|
makeDataProvider,
|
|
|
|
makeDerivedDataProvider,
|
|
|
|
defaultAppend,
|
|
|
|
} from './generic-data-provider';
|
2022-07-20 09:37:28 +00:00
|
|
|
import type {
|
2022-08-26 15:39:40 +00:00
|
|
|
CombineDerivedData,
|
chore: stagnet3 api updates (#1321)
* chore: update account, fills and orders subscriptions in data providers
* chore: update account, fills and orders subscriptions in data providers
* fixing console-lite
* fixing types in general - regen
* chore: update account, fills and orders subscriptions in data providers
* fixed console-lite unit tests, uncommented quote name
* chore: update account, fills and orders subscriptions in data providers
* type aligning of assets and proposals
* fixes liquidity data provider
* fixed accounts build errors and unit tests
* regen types, removed market name
* regen types
* fixed positions
* chore: handle updates in derived market provider, update orders
* removed taker fee mapping (renamed to maker fee)
* chore: update account, fills and orders subscriptions in data providers
* chore: update account, fills and orders subscriptions in data providers
* chore: fix Order type
* chore: fix possible null types
* chore: revert order-list.stories.tsx
* chore: derivedDataProvider fixes
* fills unit tests fixes
* orders unit tests fixes
* added eslint ingore for generated files in liquidity
* added unique key to the list element of simple market toolbar
* changed main-branch-name to develop for pr workflows
* removed redundant waitFor
* increased test timeout to 10s
* removed mocked response
* chore: disable simple market list tests
* chore: fix e2e projects mock types
* feat: [subscription-update] - uncomment some console-lite tests
* cypress: trading-accounts
* chore: replace market candles with candlesConnection
* chore: ignore gql errors, to be reverted after candlesConnectio n will be fixed
* feat: [subscription-update] - improve wrongly renamed hook
* feat: [subscription-update] - improve wrongly renamed hook
* feat: [subscription-update] - improve wrongly renamed hook 3
* chore: add pagination hangdling to derived data provier
* cypress: trading-fills
* feat: [stagnet3 api update] - remove redundant command in tests
* feat: [stagnet3 api update] - remove redundant command in tests
* chore: fix trading orders e2e tests
* chore: fix console lite e2e mocks
* chore: fix market-trade tests
* chore: use markets only in market selector, change Instrument cache policy
* chore: fix market-selector tests
* feat: [subscription-update] - improve ag grid conf for unit tests
* feat: [subscription-update] - improve ag grid conf for unit tests
* chore: fix candle types in console lite market mocks
* chore: revert error policy ignore
* chore: revert jest timeout
* chore: remove unused AccountFields
* chore: revert remove unused AccountFields
* chore: simplify node subscription probe
* chore: remove unused generated types in candles-chart
* chore: improve useMarketsList mock
* feat: [subscription-update] - increase jest timeout
* feat: [subscription-update] - fix jest timeout
* feat: [subscription-update] - fix jest timeout
* feat: [subscription-update] - try to fix failing test again
* chore: fix candles-chart types
* feat: [subscription-update] - temporary skip failing test
* feat: [subscription-update] - temporary skip failing test
* feat: [subscription-update] - temporary skip failing test
* feat: [subscription-update] - fix failling int test
* feat: [subscription-update] - try to restore commented unit tests
* feat: [subscription-update] - try to restore commented unit tests
* feat: [subscription-update] - improve fixed unit tests
Co-authored-by: asiaznik <artur@vegaprotocol.io>
Co-authored-by: maciek <maciek@vegaprotocol.io>
2022-09-20 15:24:28 +00:00
|
|
|
CombineDerivedDelta,
|
2022-10-19 09:14:18 +00:00
|
|
|
CombineInsertionData,
|
2022-07-20 09:37:28 +00:00
|
|
|
Query,
|
|
|
|
UpdateCallback,
|
|
|
|
Update,
|
|
|
|
PageInfo,
|
|
|
|
} from './generic-data-provider';
|
|
|
|
import type {
|
|
|
|
ApolloClient,
|
|
|
|
FetchResult,
|
|
|
|
SubscriptionOptions,
|
|
|
|
OperationVariables,
|
|
|
|
ApolloQueryResult,
|
|
|
|
QueryOptions,
|
|
|
|
} from '@apollo/client';
|
|
|
|
import type { Subscription, Observable } from 'zen-observable-ts';
|
|
|
|
|
|
|
|
type Item = {
|
|
|
|
cursor: string;
|
|
|
|
node: {
|
|
|
|
id: string;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
type Data = Item[];
|
|
|
|
type QueryData = {
|
|
|
|
data: Data;
|
|
|
|
pageInfo?: PageInfo;
|
|
|
|
totalCount?: number;
|
|
|
|
};
|
|
|
|
|
2022-08-26 15:39:40 +00:00
|
|
|
type CombinedData = {
|
|
|
|
totalCount?: number;
|
|
|
|
};
|
|
|
|
|
2022-07-20 09:37:28 +00:00
|
|
|
type SubscriptionData = QueryData;
|
|
|
|
type Delta = Data;
|
|
|
|
|
2022-08-26 15:39:40 +00:00
|
|
|
const update = jest.fn<
|
|
|
|
ReturnType<Update<Data, Delta>>,
|
|
|
|
Parameters<Update<Data, Delta>>
|
|
|
|
>();
|
|
|
|
|
|
|
|
const callback = jest.fn<
|
|
|
|
ReturnType<UpdateCallback<Data, Delta>>,
|
|
|
|
Parameters<UpdateCallback<Data, Delta>>
|
|
|
|
>();
|
2022-07-20 09:37:28 +00:00
|
|
|
|
2022-08-26 15:39:40 +00:00
|
|
|
const query: Query<QueryData> = {
|
|
|
|
kind: 'Document',
|
|
|
|
definitions: [],
|
|
|
|
};
|
|
|
|
const subscriptionQuery: Query<SubscriptionData> = query;
|
|
|
|
|
|
|
|
const subscribe = makeDataProvider<QueryData, Data, SubscriptionData, Delta>({
|
|
|
|
query,
|
|
|
|
subscriptionQuery,
|
|
|
|
update,
|
|
|
|
getData: (r) => r.data,
|
|
|
|
getDelta: (r) => r.data,
|
|
|
|
});
|
|
|
|
|
|
|
|
const combineData = jest.fn<
|
|
|
|
ReturnType<CombineDerivedData<CombinedData>>,
|
|
|
|
Parameters<CombineDerivedData<CombinedData>>
|
|
|
|
>();
|
|
|
|
|
chore: stagnet3 api updates (#1321)
* chore: update account, fills and orders subscriptions in data providers
* chore: update account, fills and orders subscriptions in data providers
* fixing console-lite
* fixing types in general - regen
* chore: update account, fills and orders subscriptions in data providers
* fixed console-lite unit tests, uncommented quote name
* chore: update account, fills and orders subscriptions in data providers
* type aligning of assets and proposals
* fixes liquidity data provider
* fixed accounts build errors and unit tests
* regen types, removed market name
* regen types
* fixed positions
* chore: handle updates in derived market provider, update orders
* removed taker fee mapping (renamed to maker fee)
* chore: update account, fills and orders subscriptions in data providers
* chore: update account, fills and orders subscriptions in data providers
* chore: fix Order type
* chore: fix possible null types
* chore: revert order-list.stories.tsx
* chore: derivedDataProvider fixes
* fills unit tests fixes
* orders unit tests fixes
* added eslint ingore for generated files in liquidity
* added unique key to the list element of simple market toolbar
* changed main-branch-name to develop for pr workflows
* removed redundant waitFor
* increased test timeout to 10s
* removed mocked response
* chore: disable simple market list tests
* chore: fix e2e projects mock types
* feat: [subscription-update] - uncomment some console-lite tests
* cypress: trading-accounts
* chore: replace market candles with candlesConnection
* chore: ignore gql errors, to be reverted after candlesConnectio n will be fixed
* feat: [subscription-update] - improve wrongly renamed hook
* feat: [subscription-update] - improve wrongly renamed hook
* feat: [subscription-update] - improve wrongly renamed hook 3
* chore: add pagination hangdling to derived data provier
* cypress: trading-fills
* feat: [stagnet3 api update] - remove redundant command in tests
* feat: [stagnet3 api update] - remove redundant command in tests
* chore: fix trading orders e2e tests
* chore: fix console lite e2e mocks
* chore: fix market-trade tests
* chore: use markets only in market selector, change Instrument cache policy
* chore: fix market-selector tests
* feat: [subscription-update] - improve ag grid conf for unit tests
* feat: [subscription-update] - improve ag grid conf for unit tests
* chore: fix candle types in console lite market mocks
* chore: revert error policy ignore
* chore: revert jest timeout
* chore: remove unused AccountFields
* chore: revert remove unused AccountFields
* chore: simplify node subscription probe
* chore: remove unused generated types in candles-chart
* chore: improve useMarketsList mock
* feat: [subscription-update] - increase jest timeout
* feat: [subscription-update] - fix jest timeout
* feat: [subscription-update] - fix jest timeout
* feat: [subscription-update] - try to fix failing test again
* chore: fix candles-chart types
* feat: [subscription-update] - temporary skip failing test
* feat: [subscription-update] - temporary skip failing test
* feat: [subscription-update] - temporary skip failing test
* feat: [subscription-update] - fix failling int test
* feat: [subscription-update] - try to restore commented unit tests
* feat: [subscription-update] - try to restore commented unit tests
* feat: [subscription-update] - improve fixed unit tests
Co-authored-by: asiaznik <artur@vegaprotocol.io>
Co-authored-by: maciek <maciek@vegaprotocol.io>
2022-09-20 15:24:28 +00:00
|
|
|
const combineDelta = jest.fn<
|
2022-10-19 09:14:18 +00:00
|
|
|
ReturnType<CombineDerivedDelta<CombinedData, CombinedData>>,
|
|
|
|
Parameters<CombineDerivedDelta<CombinedData, CombinedData>>
|
chore: stagnet3 api updates (#1321)
* chore: update account, fills and orders subscriptions in data providers
* chore: update account, fills and orders subscriptions in data providers
* fixing console-lite
* fixing types in general - regen
* chore: update account, fills and orders subscriptions in data providers
* fixed console-lite unit tests, uncommented quote name
* chore: update account, fills and orders subscriptions in data providers
* type aligning of assets and proposals
* fixes liquidity data provider
* fixed accounts build errors and unit tests
* regen types, removed market name
* regen types
* fixed positions
* chore: handle updates in derived market provider, update orders
* removed taker fee mapping (renamed to maker fee)
* chore: update account, fills and orders subscriptions in data providers
* chore: update account, fills and orders subscriptions in data providers
* chore: fix Order type
* chore: fix possible null types
* chore: revert order-list.stories.tsx
* chore: derivedDataProvider fixes
* fills unit tests fixes
* orders unit tests fixes
* added eslint ingore for generated files in liquidity
* added unique key to the list element of simple market toolbar
* changed main-branch-name to develop for pr workflows
* removed redundant waitFor
* increased test timeout to 10s
* removed mocked response
* chore: disable simple market list tests
* chore: fix e2e projects mock types
* feat: [subscription-update] - uncomment some console-lite tests
* cypress: trading-accounts
* chore: replace market candles with candlesConnection
* chore: ignore gql errors, to be reverted after candlesConnectio n will be fixed
* feat: [subscription-update] - improve wrongly renamed hook
* feat: [subscription-update] - improve wrongly renamed hook
* feat: [subscription-update] - improve wrongly renamed hook 3
* chore: add pagination hangdling to derived data provier
* cypress: trading-fills
* feat: [stagnet3 api update] - remove redundant command in tests
* feat: [stagnet3 api update] - remove redundant command in tests
* chore: fix trading orders e2e tests
* chore: fix console lite e2e mocks
* chore: fix market-trade tests
* chore: use markets only in market selector, change Instrument cache policy
* chore: fix market-selector tests
* feat: [subscription-update] - improve ag grid conf for unit tests
* feat: [subscription-update] - improve ag grid conf for unit tests
* chore: fix candle types in console lite market mocks
* chore: revert error policy ignore
* chore: revert jest timeout
* chore: remove unused AccountFields
* chore: revert remove unused AccountFields
* chore: simplify node subscription probe
* chore: remove unused generated types in candles-chart
* chore: improve useMarketsList mock
* feat: [subscription-update] - increase jest timeout
* feat: [subscription-update] - fix jest timeout
* feat: [subscription-update] - fix jest timeout
* feat: [subscription-update] - try to fix failing test again
* chore: fix candles-chart types
* feat: [subscription-update] - temporary skip failing test
* feat: [subscription-update] - temporary skip failing test
* feat: [subscription-update] - temporary skip failing test
* feat: [subscription-update] - fix failling int test
* feat: [subscription-update] - try to restore commented unit tests
* feat: [subscription-update] - try to restore commented unit tests
* feat: [subscription-update] - improve fixed unit tests
Co-authored-by: asiaznik <artur@vegaprotocol.io>
Co-authored-by: maciek <maciek@vegaprotocol.io>
2022-09-20 15:24:28 +00:00
|
|
|
>();
|
|
|
|
|
2022-10-19 09:14:18 +00:00
|
|
|
const combineInsertionData = jest.fn<
|
|
|
|
ReturnType<CombineInsertionData<CombinedData>>,
|
|
|
|
Parameters<CombineInsertionData<CombinedData>>
|
|
|
|
>();
|
2022-08-26 15:39:40 +00:00
|
|
|
|
|
|
|
const first = 100;
|
|
|
|
const paginatedSubscribe = makeDataProvider<
|
|
|
|
QueryData,
|
|
|
|
Data,
|
|
|
|
SubscriptionData,
|
|
|
|
Delta
|
|
|
|
>({
|
|
|
|
query,
|
|
|
|
subscriptionQuery,
|
|
|
|
update,
|
|
|
|
getData: (r) => r.data,
|
|
|
|
getDelta: (r) => r.data,
|
|
|
|
pagination: {
|
|
|
|
first,
|
|
|
|
append: defaultAppend,
|
|
|
|
getPageInfo: (r) => r?.pageInfo ?? null,
|
|
|
|
getTotalCount: (r) => r?.totalCount,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2022-10-19 09:14:18 +00:00
|
|
|
const derivedSubscribe = makeDerivedDataProvider(
|
|
|
|
[paginatedSubscribe, subscribe],
|
|
|
|
combineData,
|
|
|
|
combineDelta,
|
|
|
|
combineInsertionData
|
|
|
|
);
|
|
|
|
|
2022-08-26 15:39:40 +00:00
|
|
|
const generateData = (start = 0, size = first) => {
|
|
|
|
return new Array(size).fill(null).map((v, i) => ({
|
|
|
|
cursor: (i + start + 1).toString(),
|
|
|
|
node: {
|
|
|
|
id: (i + start + 1).toString(),
|
|
|
|
},
|
2022-07-20 09:37:28 +00:00
|
|
|
}));
|
2022-08-26 15:39:40 +00:00
|
|
|
};
|
2022-07-20 09:37:28 +00:00
|
|
|
|
2022-08-26 15:39:40 +00:00
|
|
|
const clientSubscribeUnsubscribe = jest.fn();
|
|
|
|
const clientSubscribeSubscribe = jest.fn<
|
|
|
|
Subscription,
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
[(value: FetchResult<SubscriptionData>) => void, (error: any) => void]
|
|
|
|
>(() => ({
|
|
|
|
unsubscribe: clientSubscribeUnsubscribe,
|
|
|
|
closed: false,
|
|
|
|
}));
|
|
|
|
|
|
|
|
const clientSubscribe = jest.fn<
|
|
|
|
Observable<FetchResult<SubscriptionData>>,
|
|
|
|
[SubscriptionOptions<OperationVariables, SubscriptionData>]
|
|
|
|
>(
|
|
|
|
() =>
|
|
|
|
({
|
|
|
|
subscribe: clientSubscribeSubscribe,
|
|
|
|
} as unknown as Observable<FetchResult<SubscriptionData>>)
|
|
|
|
);
|
|
|
|
|
|
|
|
const clientQueryPromises: {
|
|
|
|
resolve: (
|
|
|
|
value:
|
|
|
|
| ApolloQueryResult<QueryData>
|
|
|
|
| PromiseLike<ApolloQueryResult<QueryData>>
|
|
|
|
) => void;
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
reject: (reason?: any) => void;
|
|
|
|
}[] = [];
|
|
|
|
|
|
|
|
const clientQuery = jest.fn<
|
|
|
|
Promise<ApolloQueryResult<QueryData>>,
|
|
|
|
[QueryOptions<OperationVariables, QueryData>]
|
|
|
|
>(() => {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
clientQueryPromises.push({ resolve, reject });
|
2022-07-20 09:37:28 +00:00
|
|
|
});
|
2022-08-26 15:39:40 +00:00
|
|
|
});
|
2022-07-20 09:37:28 +00:00
|
|
|
|
2022-08-26 15:39:40 +00:00
|
|
|
const client = {
|
|
|
|
query: clientQuery,
|
|
|
|
subscribe: clientSubscribe,
|
|
|
|
} as unknown as ApolloClient<object>;
|
|
|
|
|
|
|
|
const resolveQuery = async (data: QueryData) => {
|
|
|
|
const clientQueryPromise = clientQueryPromises.shift();
|
|
|
|
if (clientQueryPromise) {
|
|
|
|
await clientQueryPromise.resolve({
|
|
|
|
data,
|
|
|
|
loading: false,
|
|
|
|
networkStatus: 8,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const rejectQuery = async (reason: Error) => {
|
|
|
|
const clientQueryPromise = clientQueryPromises.shift();
|
|
|
|
if (clientQueryPromise) {
|
|
|
|
await clientQueryPromise.reject(reason);
|
|
|
|
}
|
|
|
|
};
|
2022-07-20 09:37:28 +00:00
|
|
|
|
2022-08-26 15:39:40 +00:00
|
|
|
const clearPendingQueries = () => {
|
|
|
|
while (clientQueryPromises.length) {
|
|
|
|
clientQueryPromises.pop();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
describe('data provider', () => {
|
2022-07-20 09:37:28 +00:00
|
|
|
it('memoize instance and unsubscribe if no subscribers', () => {
|
|
|
|
const subscription1 = subscribe(jest.fn(), client);
|
|
|
|
const subscription2 = subscribe(jest.fn(), client);
|
|
|
|
expect(clientSubscribeSubscribe.mock.calls.length).toEqual(1);
|
|
|
|
subscription1.unsubscribe();
|
|
|
|
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(0);
|
|
|
|
subscription2.unsubscribe();
|
|
|
|
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('calls callback before and after initial fetch', async () => {
|
|
|
|
callback.mockClear();
|
|
|
|
const data: Item[] = [];
|
|
|
|
const subscription = subscribe(callback, client);
|
|
|
|
expect(callback.mock.calls.length).toBe(1);
|
|
|
|
expect(callback.mock.calls[0][0].data).toBe(null);
|
|
|
|
expect(callback.mock.calls[0][0].loading).toBe(true);
|
|
|
|
await resolveQuery({ data });
|
|
|
|
expect(callback.mock.calls.length).toBe(2);
|
|
|
|
expect(callback.mock.calls[1][0].data).toBe(data);
|
|
|
|
expect(callback.mock.calls[1][0].loading).toBe(false);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('calls update and callback on each update', async () => {
|
|
|
|
const data: Item[] = [];
|
|
|
|
const subscription = subscribe(callback, client);
|
|
|
|
await resolveQuery({ data });
|
|
|
|
const delta: Item[] = [];
|
|
|
|
update.mockImplementationOnce((data, delta) => [...data, ...delta]);
|
|
|
|
// calling onNext from client.subscribe({ query }).subscribe(onNext)
|
|
|
|
await clientSubscribeSubscribe.mock.calls[
|
|
|
|
clientSubscribeSubscribe.mock.calls.length - 1
|
|
|
|
][0]({ data: { data: delta } });
|
|
|
|
expect(update.mock.calls[update.mock.calls.length - 1][0]).toBe(data);
|
|
|
|
expect(update.mock.calls[update.mock.calls.length - 1][1]).toBe(delta);
|
|
|
|
expect(callback.mock.calls[callback.mock.calls.length - 1][0].delta).toBe(
|
|
|
|
delta
|
|
|
|
);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it("don't calls callback on update if data doesn't", async () => {
|
|
|
|
callback.mockClear();
|
|
|
|
const data: Item[] = [];
|
|
|
|
const subscription = subscribe(callback, client);
|
|
|
|
await resolveQuery({ data });
|
|
|
|
const delta: Item[] = [];
|
|
|
|
update.mockImplementationOnce((data, delta) => data);
|
|
|
|
const callbackCallsLength = callback.mock.calls.length;
|
|
|
|
// calling onNext from client.subscribe({ query }).subscribe(onNext)
|
|
|
|
await clientSubscribeSubscribe.mock.calls[
|
|
|
|
clientSubscribeSubscribe.mock.calls.length - 1
|
|
|
|
][0]({ data: { data: delta } });
|
|
|
|
expect(update.mock.calls[update.mock.calls.length - 1][0]).toBe(data);
|
|
|
|
expect(update.mock.calls[update.mock.calls.length - 1][1]).toBe(delta);
|
|
|
|
expect(callback.mock.calls.length).toBe(callbackCallsLength);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('refetch data on reload', async () => {
|
2022-08-26 15:39:40 +00:00
|
|
|
clearPendingQueries();
|
2022-07-20 09:37:28 +00:00
|
|
|
clientQuery.mockClear();
|
|
|
|
clientSubscribeUnsubscribe.mockClear();
|
|
|
|
clientSubscribeSubscribe.mockClear();
|
|
|
|
const data: Item[] = [];
|
|
|
|
const subscription = subscribe(callback, client);
|
|
|
|
await resolveQuery({ data });
|
|
|
|
subscription.reload();
|
|
|
|
await resolveQuery({ data });
|
|
|
|
expect(clientQuery.mock.calls.length).toBe(2);
|
|
|
|
expect(clientSubscribeSubscribe.mock.calls.length).toBe(1);
|
|
|
|
expect(clientSubscribeUnsubscribe.mock.calls.length).toBe(0);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('refetch data and restart subscription on reload with force', async () => {
|
|
|
|
clientQuery.mockClear();
|
|
|
|
clientSubscribeUnsubscribe.mockClear();
|
|
|
|
clientSubscribeSubscribe.mockClear();
|
|
|
|
const data: Item[] = [];
|
|
|
|
const subscription = subscribe(callback, client);
|
|
|
|
await resolveQuery({ data });
|
|
|
|
subscription.reload(true);
|
|
|
|
await resolveQuery({ data });
|
|
|
|
expect(clientQuery.mock.calls.length).toBe(2);
|
|
|
|
expect(clientSubscribeSubscribe.mock.calls.length).toBe(2);
|
|
|
|
expect(clientSubscribeUnsubscribe.mock.calls.length).toBe(1);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('calls callback on flush', async () => {
|
|
|
|
callback.mockClear();
|
|
|
|
const data: Item[] = [];
|
|
|
|
const subscription = subscribe(callback, client);
|
|
|
|
await resolveQuery({ data });
|
|
|
|
const callbackCallsLength = callback.mock.calls.length;
|
|
|
|
subscription.flush();
|
|
|
|
expect(callback.mock.calls.length).toBe(callbackCallsLength + 1);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
2022-08-26 15:39:40 +00:00
|
|
|
it('fills data with nulls if pagination is enabled', async () => {
|
2022-07-20 09:37:28 +00:00
|
|
|
callback.mockClear();
|
2022-08-26 15:39:40 +00:00
|
|
|
clearPendingQueries();
|
2022-07-20 09:37:28 +00:00
|
|
|
const totalCount = 1000;
|
|
|
|
const data: Item[] = new Array(first).fill(null).map((v, i) => ({
|
|
|
|
cursor: i.toString(),
|
|
|
|
node: {
|
|
|
|
id: i.toString(),
|
|
|
|
},
|
|
|
|
}));
|
|
|
|
const subscription = paginatedSubscribe(callback, client);
|
|
|
|
await resolveQuery({
|
|
|
|
data,
|
|
|
|
totalCount,
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(callback.mock.calls[1][0].data?.length).toBe(totalCount);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('loads requested data blocks and inserts data with total count', async () => {
|
|
|
|
callback.mockClear();
|
|
|
|
const totalCount = 1000;
|
|
|
|
const subscription = paginatedSubscribe(callback, client);
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(),
|
|
|
|
totalCount,
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '100',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// load next page
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.load && subscription.load();
|
2022-07-20 09:37:28 +00:00
|
|
|
let lastQueryArgs =
|
|
|
|
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
|
|
|
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
|
|
|
after: '100',
|
|
|
|
first,
|
|
|
|
});
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(100),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '200',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// load page with skip
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.load && subscription.load(500, 600);
|
2022-07-20 09:37:28 +00:00
|
|
|
lastQueryArgs =
|
|
|
|
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
|
|
|
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
|
|
|
after: '200',
|
|
|
|
first,
|
|
|
|
skip: 300,
|
|
|
|
});
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(500),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '600',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// load in the gap
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.load && subscription.load(400, 500);
|
2022-07-20 09:37:28 +00:00
|
|
|
lastQueryArgs =
|
|
|
|
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
|
|
|
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
|
|
|
after: '200',
|
|
|
|
first,
|
|
|
|
skip: 200,
|
|
|
|
});
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(400),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '500',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// load page after last block
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.load && subscription.load(700, 800);
|
2022-07-20 09:37:28 +00:00
|
|
|
lastQueryArgs =
|
|
|
|
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
|
|
|
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
|
|
|
after: '600',
|
|
|
|
first,
|
|
|
|
skip: 100,
|
|
|
|
});
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(700),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '800',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// load last page shorter than expected
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.load && subscription.load(950, 1050);
|
2022-07-20 09:37:28 +00:00
|
|
|
lastQueryArgs =
|
|
|
|
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
|
|
|
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
|
|
|
after: '800',
|
|
|
|
first,
|
|
|
|
skip: 150,
|
|
|
|
});
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(950, 20),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: false,
|
|
|
|
endCursor: '970',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
let lastCallbackArgs = callback.mock.calls[callback.mock.calls.length - 1];
|
|
|
|
expect(lastCallbackArgs[0].totalCount).toBe(970);
|
|
|
|
|
|
|
|
// load next page when pageInfo.hasNextPage === false
|
|
|
|
const clientQueryCallsLength = clientQuery.mock.calls.length;
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.load && subscription.load();
|
2022-07-20 09:37:28 +00:00
|
|
|
expect(clientQuery.mock.calls.length).toBe(clientQueryCallsLength);
|
|
|
|
|
|
|
|
// load last page longer than expected
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.load && subscription.load(960, 1000);
|
2022-07-20 09:37:28 +00:00
|
|
|
lastQueryArgs =
|
|
|
|
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
|
|
|
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
|
|
|
after: '960',
|
|
|
|
first,
|
|
|
|
});
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(960, 40),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '1000',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
lastCallbackArgs = callback.mock.calls[callback.mock.calls.length - 1];
|
|
|
|
expect(lastCallbackArgs[0].totalCount).toBe(1000);
|
|
|
|
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('loads requested data blocks and inserts data without totalCount', async () => {
|
|
|
|
callback.mockClear();
|
|
|
|
const totalCount = undefined;
|
|
|
|
const subscription = paginatedSubscribe(callback, client);
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(),
|
|
|
|
totalCount,
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '100',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
let lastCallbackArgs = callback.mock.calls[callback.mock.calls.length - 1];
|
|
|
|
expect(lastCallbackArgs[0].totalCount).toBe(undefined);
|
|
|
|
|
|
|
|
// load next page
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.load && subscription.load();
|
2022-07-20 09:37:28 +00:00
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(100),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '200',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
lastCallbackArgs = callback.mock.calls[callback.mock.calls.length - 1];
|
|
|
|
expect(lastCallbackArgs[0].totalCount).toBe(undefined);
|
|
|
|
|
|
|
|
// load last page
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.load && subscription.load();
|
2022-07-20 09:37:28 +00:00
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(200, 50),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: false,
|
|
|
|
endCursor: '250',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
lastCallbackArgs = callback.mock.calls[callback.mock.calls.length - 1];
|
|
|
|
expect(lastCallbackArgs[0].totalCount).toBe(250);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('sets total count when first page has no next page', async () => {
|
|
|
|
const subscription = paginatedSubscribe(callback, client);
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: false,
|
|
|
|
endCursor: '100',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
const lastCallbackArgs =
|
|
|
|
callback.mock.calls[callback.mock.calls.length - 1];
|
|
|
|
expect(lastCallbackArgs[0].totalCount).toBe(100);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
});
|
2022-08-26 15:39:40 +00:00
|
|
|
|
|
|
|
describe('derived data provider', () => {
|
|
|
|
it('memoize instance and unsubscribe if no subscribers', () => {
|
|
|
|
clientSubscribeSubscribe.mockClear();
|
|
|
|
clientSubscribeUnsubscribe.mockClear();
|
|
|
|
const variables = {};
|
|
|
|
const subscription1 = derivedSubscribe(jest.fn(), client, variables);
|
|
|
|
const subscription2 = derivedSubscribe(jest.fn(), client, variables);
|
|
|
|
expect(clientSubscribeSubscribe.mock.calls.length).toEqual(2);
|
|
|
|
subscription1.unsubscribe();
|
|
|
|
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(0);
|
|
|
|
subscription2.unsubscribe();
|
|
|
|
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(2);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('calls callback on each meaningful update, uses combineData function', async () => {
|
|
|
|
clearPendingQueries();
|
2022-10-19 09:14:18 +00:00
|
|
|
const totalCount = 1000;
|
|
|
|
const part1 = {
|
|
|
|
data: generateData(),
|
|
|
|
totalCount,
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '100',
|
|
|
|
},
|
|
|
|
};
|
2022-08-26 15:39:40 +00:00
|
|
|
const part2: Item[] = [];
|
|
|
|
const callback = jest.fn<
|
2022-10-19 09:14:18 +00:00
|
|
|
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
|
|
|
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
2022-08-26 15:39:40 +00:00
|
|
|
>();
|
|
|
|
const subscription = derivedSubscribe(callback, client);
|
|
|
|
const data = { totalCount: 0 };
|
|
|
|
combineData.mockReturnValueOnce(data);
|
|
|
|
expect(callback.mock.calls.length).toBe(0);
|
2022-10-19 09:14:18 +00:00
|
|
|
await resolveQuery(part1);
|
2022-08-26 15:39:40 +00:00
|
|
|
expect(combineData.mock.calls.length).toBe(0);
|
|
|
|
expect(callback.mock.calls.length).toBe(0);
|
|
|
|
await resolveQuery({ data: part2 });
|
|
|
|
expect(combineData.mock.calls.length).toBe(1);
|
2022-10-19 09:14:18 +00:00
|
|
|
expect(combineData.mock.calls[0][0][0]).toBe(part1.data);
|
2022-08-26 15:39:40 +00:00
|
|
|
expect(combineData.mock.calls[0][0][1]).toBe(part2);
|
|
|
|
expect(callback.mock.calls.length).toBe(1);
|
|
|
|
expect(callback.mock.calls[0][0].data).toBe(data);
|
|
|
|
expect(callback.mock.calls[0][0].loading).toBe(false);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('callback with error if any dependency has error, reloads all dependencies on reload', async () => {
|
2022-10-19 09:14:18 +00:00
|
|
|
clearPendingQueries();
|
2022-08-26 15:39:40 +00:00
|
|
|
combineData.mockClear();
|
|
|
|
const part1: Item[] = [];
|
|
|
|
const part2: Item[] = [];
|
|
|
|
const callback = jest.fn<
|
2022-10-19 09:14:18 +00:00
|
|
|
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
|
|
|
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
2022-08-26 15:39:40 +00:00
|
|
|
>();
|
2022-10-19 09:14:18 +00:00
|
|
|
expect(callback.mock.calls.length).toBe(0);
|
2022-08-26 15:39:40 +00:00
|
|
|
const subscription = derivedSubscribe(callback, client);
|
|
|
|
const data = { totalCount: 0 };
|
|
|
|
combineData.mockReturnValueOnce(data);
|
|
|
|
expect(callback.mock.calls.length).toBe(0);
|
|
|
|
await resolveQuery({ data: part1 });
|
|
|
|
expect(combineData.mock.calls.length).toBe(0);
|
|
|
|
expect(callback.mock.calls.length).toBe(0);
|
|
|
|
const error = new Error('');
|
|
|
|
await rejectQuery(error);
|
|
|
|
expect(combineData.mock.calls.length).toBe(0);
|
|
|
|
expect(callback.mock.calls.length).toBe(1);
|
|
|
|
expect(callback.mock.calls[0][0].error).toBe(error);
|
|
|
|
expect(callback.mock.calls[0][0].loading).toBe(false);
|
|
|
|
subscription.reload();
|
2022-09-27 18:48:53 +00:00
|
|
|
expect(callback.mock.calls.length).toBe(2);
|
|
|
|
expect(callback.mock.calls[1][0].loading).toBe(true);
|
2022-08-26 15:39:40 +00:00
|
|
|
await resolveQuery({ data: part1 });
|
2022-09-27 18:48:53 +00:00
|
|
|
expect(callback.mock.calls.length).toBe(2);
|
2022-08-26 15:39:40 +00:00
|
|
|
await resolveQuery({ data: part2 });
|
2022-09-27 18:48:53 +00:00
|
|
|
expect(callback.mock.calls.length).toBe(3);
|
|
|
|
expect(callback.mock.calls[2][0].data).toStrictEqual(data);
|
|
|
|
expect(callback.mock.calls[2][0].loading).toBe(false);
|
|
|
|
expect(callback.mock.calls[2][0].error).toBeUndefined();
|
2022-08-26 15:39:40 +00:00
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
2022-10-19 09:14:18 +00:00
|
|
|
|
|
|
|
it('pass isUpdate on any dependency isUpdate, uses result of combineDelta as delta in next callback', async () => {
|
|
|
|
clearPendingQueries();
|
|
|
|
combineData.mockClear();
|
|
|
|
const part1: Item[] = [];
|
|
|
|
const part2: Item[] = [];
|
|
|
|
const callback = jest.fn<
|
|
|
|
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
|
|
|
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
|
|
|
>();
|
|
|
|
const subscription = derivedSubscribe(callback, client);
|
|
|
|
const data = { totalCount: 0 };
|
|
|
|
combineData.mockReturnValueOnce(data);
|
|
|
|
await resolveQuery({ data: part1 });
|
|
|
|
await resolveQuery({ data: part2 });
|
|
|
|
expect(combineData).toBeCalledTimes(1);
|
|
|
|
expect(callback).toBeCalledTimes(1);
|
|
|
|
update.mockImplementation((data, delta) => [...data, ...delta]);
|
|
|
|
combineData.mockReturnValueOnce({ ...data });
|
|
|
|
const combinedDelta = {};
|
|
|
|
combineDelta.mockReturnValueOnce(combinedDelta);
|
|
|
|
// calling onNext from client.subscribe({ query }).subscribe(onNext)
|
|
|
|
const delta: Item[] = [];
|
|
|
|
await clientSubscribeSubscribe.mock.calls[
|
|
|
|
clientSubscribeSubscribe.mock.calls.length - 1
|
|
|
|
][0]({ data: { data: delta } });
|
|
|
|
expect(combineDelta).toBeCalledTimes(1);
|
|
|
|
expect(combineData).toBeCalledTimes(2);
|
|
|
|
expect(callback).toBeCalledTimes(2);
|
|
|
|
expect(callback.mock.calls[1][0].isUpdate).toBe(true);
|
|
|
|
expect(callback.mock.calls[1][0].delta).toBe(combinedDelta);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('pass isInsert on any dependency isInsert, uses result of combineInsertionData as insertionData in next callback', async () => {
|
|
|
|
clearPendingQueries();
|
|
|
|
combineData.mockClear();
|
|
|
|
combineDelta.mockClear();
|
|
|
|
const callback = jest.fn<
|
|
|
|
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
|
|
|
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
|
|
|
>();
|
|
|
|
const subscription = derivedSubscribe(callback, client);
|
|
|
|
const data = { totalCount: 0 };
|
|
|
|
combineData.mockReturnValueOnce(data);
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '100',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
await resolveQuery({ data: [] });
|
|
|
|
expect(combineData).toBeCalledTimes(1);
|
|
|
|
expect(callback).toBeCalledTimes(1);
|
|
|
|
update.mockImplementation((data, delta) => [...data, ...delta]);
|
|
|
|
combineData.mockReturnValueOnce({ ...data });
|
|
|
|
const combinedInsertionData = {};
|
|
|
|
combineInsertionData.mockReturnValueOnce(combinedInsertionData);
|
|
|
|
subscription.load && subscription.load();
|
|
|
|
const lastQueryArgs =
|
|
|
|
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
|
|
|
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
|
|
|
after: '100',
|
|
|
|
first,
|
|
|
|
});
|
|
|
|
await resolveQuery({
|
|
|
|
data: generateData(100),
|
|
|
|
pageInfo: {
|
|
|
|
hasNextPage: true,
|
|
|
|
endCursor: '200',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
expect(combineInsertionData).toBeCalledTimes(1);
|
|
|
|
expect(combineData).toBeCalledTimes(2);
|
|
|
|
expect(callback).toBeCalledTimes(2);
|
|
|
|
expect(callback.mock.calls[1][0].isInsert).toBe(true);
|
|
|
|
expect(callback.mock.calls[1][0].insertionData).toBe(combinedInsertionData);
|
|
|
|
subscription.unsubscribe();
|
|
|
|
});
|
2022-08-26 15:39:40 +00:00
|
|
|
});
|