Skip to content

Commit

Permalink
Add tests for query and subscription operations
Browse files Browse the repository at this point in the history
  • Loading branch information
kitten committed Sep 30, 2020
1 parent 4101cf4 commit d906eea
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 14 deletions.
4 changes: 4 additions & 0 deletions packages/svelte-urql/src/operationStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ it('adds getters and setters for known values', () => {
store.subscribe(subscriber);
expect(subscriber).toHaveBeenCalledTimes(1);

const state = subscriber.mock.calls[0][0];
expect(state.stale).toBe(true);
expect(state.query).toBe('{ update }');

store.query = '{ imperative }';
expect(subscriber).toHaveBeenCalledTimes(2);
expect(store.query).toBe('{ imperative }');
Expand Down
38 changes: 25 additions & 13 deletions packages/svelte-urql/src/operationStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,19 @@ export function operationStore<Data = any, Vars = object>(
state.update = update;
state.subscribe = store.subscribe;

let result = state;
for (const prop in internal) {
Object.defineProperty(state, prop, {
configurable: false,
get: () => internal[prop],
set(value) {
internal[prop] = value;
if (!_internalUpdate) invalidate();
},
});
}

if (process.env.NODE_ENV !== 'production') {
result = { ...state };
const result = { ...state };

for (const prop in state) {
Object.defineProperty(result, prop, {
Expand All @@ -110,18 +120,20 @@ export function operationStore<Data = any, Vars = object>(
},
});
}
}

for (const prop in internal) {
Object.defineProperty(result, prop, {
configurable: false,
get: () => internal[prop],
set(value) {
internal[prop] = value;
if (!_internalUpdate) invalidate();
},
});
for (const prop in internal) {
Object.defineProperty(result, prop, {
configurable: false,
get: () => internal[prop],
set(value) {
internal[prop] = value;
if (!_internalUpdate) invalidate();
},
});
}

return result;
}

return result as OperationStore<Data, Vars>;
return state;
}
165 changes: 165 additions & 0 deletions packages/svelte-urql/src/operations.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { makeSubject } from 'wonka';
import { createClient } from '@urql/core';
import { operationStore } from './operationStore';
import { query, subscription } from './operations';

const client = createClient({ url: '/graphql' });

jest.mock('./context', () => ({ getClient: () => client }));
jest.mock('svelte', () => ({ onDestroy: () => undefined }));

beforeEach(() => {
jest.resetAllMocks();
});

describe('query', () => {
it('susbcribes to a query and updates data', () => {
const subscriber = jest.fn();
const subject = makeSubject<any>();
const executeQuery = jest
.spyOn(client, 'executeQuery')
.mockImplementation(() => subject.source);

const store = operationStore('{ test }');
store.subscribe(subscriber);

query(store);

expect(executeQuery).toHaveBeenCalledWith(
{
key: expect.any(Number),
query: expect.any(Object),
variables: {},
},
undefined
);

expect(subscriber).toHaveBeenCalledTimes(2);
expect(store.fetching).toBe(true);

subject.next({ data: { test: true } });
expect(subscriber).toHaveBeenCalledTimes(3);
expect(store.data).toEqual({ test: true });

subject.complete();
expect(subscriber).toHaveBeenCalledTimes(4);
expect(store.fetching).toBe(false);
});

it('updates the executed query when inputs change', () => {
const subscriber = jest.fn();
const subject = makeSubject<any>();
const executeQuery = jest
.spyOn(client, 'executeQuery')
.mockImplementation(() => subject.source);

const store = operationStore('{ test }');
store.subscribe(subscriber);

query(store);

expect(executeQuery).toHaveBeenCalledWith(
{
key: expect.any(Number),
query: expect.any(Object),
variables: {},
},
undefined
);

subject.next({ data: { test: true } });
expect(subscriber).toHaveBeenCalledTimes(3);
expect(store.data).toEqual({ test: true });

store.variables = { test: true };
expect(executeQuery).toHaveBeenCalledTimes(2);
expect(executeQuery).toHaveBeenCalledWith(
{
key: expect.any(Number),
query: expect.any(Object),
variables: { test: true },
},
undefined
);

expect(subscriber).toHaveBeenCalledTimes(5);
expect(store.fetching).toBe(true);
expect(store.data).toEqual({ test: true });
});
});

describe('subscription', () => {
it('susbcribes to a subscription and updates data', () => {
const subscriber = jest.fn();
const subject = makeSubject<any>();
const executeQuery = jest
.spyOn(client, 'executeSubscription')
.mockImplementation(() => subject.source);

const store = operationStore('subscription { test }');
store.subscribe(subscriber);

subscription(store);

expect(executeQuery).toHaveBeenCalledWith(
{
key: expect.any(Number),
query: expect.any(Object),
variables: {},
},
undefined
);

expect(subscriber).toHaveBeenCalledTimes(2);
expect(store.fetching).toBe(true);

subject.next({ data: { test: true } });
expect(subscriber).toHaveBeenCalledTimes(3);
expect(store.data).toEqual({ test: true });

subject.complete();
expect(subscriber).toHaveBeenCalledTimes(4);
expect(store.fetching).toBe(false);
});

it('updates the executed subscription when inputs change', () => {
const subscriber = jest.fn();
const subject = makeSubject<any>();
const executeSubscription = jest
.spyOn(client, 'executeQuery')
.mockImplementation(() => subject.source);

const store = operationStore('{ test }');
store.subscribe(subscriber);

query(store);

expect(executeSubscription).toHaveBeenCalledWith(
{
key: expect.any(Number),
query: expect.any(Object),
variables: {},
},
undefined
);

subject.next({ data: { test: true } });
expect(subscriber).toHaveBeenCalledTimes(3);
expect(store.data).toEqual({ test: true });

store.variables = { test: true };
expect(executeSubscription).toHaveBeenCalledTimes(2);
expect(executeSubscription).toHaveBeenCalledWith(
{
key: expect.any(Number),
query: expect.any(Object),
variables: { test: true },
},
undefined
);

expect(subscriber).toHaveBeenCalledTimes(5);
expect(store.fetching).toBe(true);
expect(store.data).toEqual({ test: true });
});
});
6 changes: 5 additions & 1 deletion packages/svelte-urql/src/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { onDestroy } from 'svelte';

import {
pipe,
map,
make,
scan,
concat,
Expand Down Expand Up @@ -43,7 +44,10 @@ export function query<T = any, V = object>(
switchMap(request => {
return concat<Partial<OperationStore>>([
fromValue({ fetching: true, stale: false }),
client.executeQuery(request, store.context!),
pipe(
client.executeQuery(request, store.context!),
map(result => ({ fetching: false, ...result }))
),
fromValue({ fetching: false, stale: false }),
]);
}),
Expand Down

0 comments on commit d906eea

Please sign in to comment.