Compare commits
2 Commits
develop
...
chore/add-
Author | SHA1 | Date | |
---|---|---|---|
|
b80e5aca22 | ||
|
dada8521e2 |
@ -19,7 +19,10 @@ import type {
|
|||||||
OperationVariables,
|
OperationVariables,
|
||||||
ApolloQueryResult,
|
ApolloQueryResult,
|
||||||
QueryOptions,
|
QueryOptions,
|
||||||
|
ApolloError,
|
||||||
} from '@apollo/client';
|
} from '@apollo/client';
|
||||||
|
import { GraphQLError } from 'graphql';
|
||||||
|
|
||||||
import type { Subscription, Observable } from 'zen-observable-ts';
|
import type { Subscription, Observable } from 'zen-observable-ts';
|
||||||
|
|
||||||
type Item = {
|
type Item = {
|
||||||
@ -58,12 +61,16 @@ const query: Query<QueryData> = {
|
|||||||
};
|
};
|
||||||
const subscriptionQuery: Query<SubscriptionData> = query;
|
const subscriptionQuery: Query<SubscriptionData> = query;
|
||||||
|
|
||||||
|
const getData = jest.fn((r: QueryData | null) => r?.data || null);
|
||||||
|
|
||||||
|
const getDelta = jest.fn((r: SubscriptionData) => r.data);
|
||||||
|
|
||||||
const subscribe = makeDataProvider<QueryData, Data, SubscriptionData, Delta>({
|
const subscribe = makeDataProvider<QueryData, Data, SubscriptionData, Delta>({
|
||||||
query,
|
query,
|
||||||
subscriptionQuery,
|
subscriptionQuery,
|
||||||
update,
|
update,
|
||||||
getData: (r) => r?.data || null,
|
getData,
|
||||||
getDelta: (r) => r.data,
|
getDelta,
|
||||||
});
|
});
|
||||||
|
|
||||||
const combineData = jest.fn<
|
const combineData = jest.fn<
|
||||||
@ -91,8 +98,8 @@ const paginatedSubscribe = makeDataProvider<
|
|||||||
query,
|
query,
|
||||||
subscriptionQuery,
|
subscriptionQuery,
|
||||||
update,
|
update,
|
||||||
getData: (r) => r?.data || null,
|
getData,
|
||||||
getDelta: (r) => r.data,
|
getDelta,
|
||||||
pagination: {
|
pagination: {
|
||||||
first,
|
first,
|
||||||
append: defaultAppend,
|
append: defaultAppend,
|
||||||
@ -186,9 +193,20 @@ const clearPendingQueries = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe('data provider', () => {
|
describe('data provider', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
clearPendingQueries();
|
||||||
|
callback.mockClear();
|
||||||
|
getData.mockClear();
|
||||||
|
clientQuery.mockClear();
|
||||||
|
clientSubscribeUnsubscribe.mockClear();
|
||||||
|
clientSubscribeSubscribe.mockClear();
|
||||||
|
});
|
||||||
it('memoize instance and unsubscribe if no subscribers', () => {
|
it('memoize instance and unsubscribe if no subscribers', () => {
|
||||||
const subscription1 = subscribe(jest.fn(), client);
|
const variables = { var: 'val' };
|
||||||
const subscription2 = subscribe(jest.fn(), client);
|
const subscription1 = subscribe(jest.fn(), client, variables);
|
||||||
|
const subscription2 = subscribe(jest.fn(), client, { ...variables });
|
||||||
|
// const subscription1 = subscribe(jest.fn(), client);
|
||||||
|
// const subscription2 = subscribe(jest.fn(), client);
|
||||||
expect(clientSubscribeSubscribe.mock.calls.length).toEqual(1);
|
expect(clientSubscribeSubscribe.mock.calls.length).toEqual(1);
|
||||||
subscription1.unsubscribe();
|
subscription1.unsubscribe();
|
||||||
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(0);
|
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(0);
|
||||||
@ -197,7 +215,6 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('calls callback before and after initial fetch', async () => {
|
it('calls callback before and after initial fetch', async () => {
|
||||||
callback.mockClear();
|
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client);
|
||||||
expect(callback.mock.calls.length).toBe(1);
|
expect(callback.mock.calls.length).toBe(1);
|
||||||
@ -210,6 +227,49 @@ describe('data provider', () => {
|
|||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('calls callback on error', async () => {
|
||||||
|
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);
|
||||||
|
const error = new Error('Rejected by unit test');
|
||||||
|
await rejectQuery(error);
|
||||||
|
expect(getData).not.toBeCalled();
|
||||||
|
expect(callback.mock.calls.length).toBe(2);
|
||||||
|
expect(callback.mock.calls[1][0].error).toEqual(error);
|
||||||
|
expect(callback.mock.calls[1][0].loading).toBe(false);
|
||||||
|
subscription.unsubscribe();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls successful callback on NotFound error on party path', async () => {
|
||||||
|
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);
|
||||||
|
const error = new Error() as ApolloError;
|
||||||
|
const graphQLError = new GraphQLError(
|
||||||
|
'',
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
['party'],
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
type: 'NotFound',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
error.graphQLErrors = [graphQLError];
|
||||||
|
const data: Data = [];
|
||||||
|
getData.mockReturnValueOnce(data);
|
||||||
|
await rejectQuery(error);
|
||||||
|
expect(getData).toHaveBeenCalledWith(null, undefined);
|
||||||
|
expect(callback.mock.calls.length).toBe(2);
|
||||||
|
expect(callback.mock.calls[1][0].data).toEqual(data);
|
||||||
|
expect(callback.mock.calls[1][0].error).toEqual(undefined);
|
||||||
|
expect(callback.mock.calls[1][0].loading).toBe(false);
|
||||||
|
subscription.unsubscribe();
|
||||||
|
});
|
||||||
|
|
||||||
it('calls update and callback on each update', async () => {
|
it('calls update and callback on each update', async () => {
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client);
|
||||||
@ -228,8 +288,7 @@ describe('data provider', () => {
|
|||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("don't calls callback on update if data doesn't", async () => {
|
it("don't calls callback on update if data doesn't change", async () => {
|
||||||
callback.mockClear();
|
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
@ -247,10 +306,6 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('refetch data on reload', async () => {
|
it('refetch data on reload', async () => {
|
||||||
clearPendingQueries();
|
|
||||||
clientQuery.mockClear();
|
|
||||||
clientSubscribeUnsubscribe.mockClear();
|
|
||||||
clientSubscribeSubscribe.mockClear();
|
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
@ -263,9 +318,6 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('refetch data and restart subscription on reload with force', async () => {
|
it('refetch data and restart subscription on reload with force', async () => {
|
||||||
clientQuery.mockClear();
|
|
||||||
clientSubscribeUnsubscribe.mockClear();
|
|
||||||
clientSubscribeSubscribe.mockClear();
|
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
@ -278,7 +330,6 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('calls callback on flush', async () => {
|
it('calls callback on flush', async () => {
|
||||||
callback.mockClear();
|
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
@ -289,8 +340,6 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('fills data with nulls if pagination is enabled', async () => {
|
it('fills data with nulls if pagination is enabled', async () => {
|
||||||
callback.mockClear();
|
|
||||||
clearPendingQueries();
|
|
||||||
const totalCount = 1000;
|
const totalCount = 1000;
|
||||||
const data: Item[] = new Array(first).fill(null).map((v, i) => ({
|
const data: Item[] = new Array(first).fill(null).map((v, i) => ({
|
||||||
cursor: i.toString(),
|
cursor: i.toString(),
|
||||||
@ -311,7 +360,6 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('loads requested data blocks and inserts data with total count', async () => {
|
it('loads requested data blocks and inserts data with total count', async () => {
|
||||||
callback.mockClear();
|
|
||||||
const totalCount = 1000;
|
const totalCount = 1000;
|
||||||
const subscription = paginatedSubscribe(callback, client);
|
const subscription = paginatedSubscribe(callback, client);
|
||||||
await resolveQuery({
|
await resolveQuery({
|
||||||
@ -436,7 +484,6 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('loads requested data blocks and inserts data without totalCount', async () => {
|
it('loads requested data blocks and inserts data without totalCount', async () => {
|
||||||
callback.mockClear();
|
|
||||||
const totalCount = undefined;
|
const totalCount = undefined;
|
||||||
const subscription = paginatedSubscribe(callback, client);
|
const subscription = paginatedSubscribe(callback, client);
|
||||||
await resolveQuery({
|
await resolveQuery({
|
||||||
|
@ -407,6 +407,15 @@ function makeDataProviderInternal<
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onError = (e: Error) => {
|
||||||
|
error = e;
|
||||||
|
if (subscription) {
|
||||||
|
subscription.unsubscribe();
|
||||||
|
subscription = undefined;
|
||||||
|
}
|
||||||
|
notifyAll();
|
||||||
|
};
|
||||||
|
|
||||||
const initialize = async () => {
|
const initialize = async () => {
|
||||||
if (subscription) {
|
if (subscription) {
|
||||||
if (resetTimer) {
|
if (resetTimer) {
|
||||||
@ -427,14 +436,7 @@ function makeDataProviderInternal<
|
|||||||
variables,
|
variables,
|
||||||
fetchPolicy,
|
fetchPolicy,
|
||||||
})
|
})
|
||||||
.subscribe(onNext, (e) => {
|
.subscribe(onNext, onError);
|
||||||
error = e as Error;
|
|
||||||
if (subscription) {
|
|
||||||
subscription.unsubscribe();
|
|
||||||
subscription = undefined;
|
|
||||||
}
|
|
||||||
notifyAll();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
await initialFetch();
|
await initialFetch();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user