Skip to content

Commit edc704c

Browse files
authored
Merge pull request #122 from simonsobs/dev
Add tests, clean code
2 parents 31ddf71 + c3dcb12 commit edc704c

20 files changed

+241
-164
lines changed

src/api/__tests__/fc.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ export const fcMockUseQueryResponseArg = <T>(arbData: fc.Arbitrary<T>) =>
1515
export const fcMockUseSubscriptionResponseArg = <T>(arbData: fc.Arbitrary<T>) =>
1616
fc.array(fcMockUseQueryResponseArg(arbData));
1717

18+
export const fcScheduleQueueItem = fc.record({
19+
createdAt: fc.date().map((d) => d.toISOString()),
20+
id: fc.integer(),
21+
name: fc.string(),
22+
script: fc.string(),
23+
});
24+
1825
if (import.meta.vitest) {
1926
it("fcUndefinedOr()", () => {
2027
fc.assert(
@@ -50,4 +57,15 @@ if (import.meta.vitest) {
5057
}),
5158
);
5259
});
60+
61+
it("fcScheduleQueueItem()", () => {
62+
fc.assert(
63+
fc.property(fcScheduleQueueItem, (v) => {
64+
expect(v.createdAt).toBeDefined();
65+
expect(v.id).toBeDefined();
66+
expect(v.name).toBeDefined();
67+
expect(v.script).toBeDefined();
68+
}),
69+
);
70+
});
5371
}

src/api/__tests__/mock-use-query-response.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,13 @@ describe("mockUseQueryResponse()", () => {
5353
expect(response).toBe(returned);
5454

5555
// Assert initially undefined.
56+
expect(response.fetching.value).toBe(true);
5657
expect(response.error.value).toBeUndefined();
5758
expect(response.data.value).toBeUndefined();
5859

5960
// Await until the values are assigned.
6061
const state = await response;
62+
expect(response.fetching.value).toBe(false);
6163

6264
// Confirm the object returned by await contains the same objects.
6365
expect(state.data).toBe(response.data);

src/api/__tests__/mock-use-query-response.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { OnReady } from "@/utils/on-ready";
77
type MockUseQueryResponse<T> = OnReady<{
88
data: Ref<T | undefined>;
99
error: Ref<Error | undefined>;
10+
fetching: Ref<boolean>;
1011
}>;
1112

1213
interface MockUseQueryResponseArg<T> {
@@ -19,12 +20,14 @@ export function mockUseQueryResponse<T>(
1920
): MockUseQueryResponse<T> {
2021
const data = ref<T | undefined>(undefined);
2122
const error = ref<Error | undefined>(undefined);
23+
const fetching = ref<boolean>(true);
2224

2325
const ready = (async () => {
2426
await Promise.resolve();
2527
data.value = arg.data;
2628
error.value = arg.error;
29+
fetching.value = false;
2730
})();
2831

29-
return onReady({ data, error }, ready) as MockUseQueryResponse<T>;
32+
return onReady({ data, error, fetching }, ready) as MockUseQueryResponse<T>;
3033
}

src/api/__tests__/run-property-test.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { mockUseSubscriptionResponse } from "./mock-use-subscription-response";
1111
interface _UseSubscribeXXXReturn<R> {
1212
data: ComputedRef<R | undefined>;
1313
error: ComputedRef<Error | undefined>;
14+
loading: ComputedRef<boolean>;
1415
}
1516

1617
type UseSubscribeXXXReturn<R> = _UseSubscribeXXXReturn<R> &
@@ -39,11 +40,22 @@ export async function runPropertyTest<QueryData, SubData, R>(
3940
const { response: subRes, issue } = mockUseSubscriptionResponse<SubData>(subArg);
4041
vi.mocked(useSubscription<SubData>).mockReturnValue(subRes as SubRes);
4142

42-
const { data, error } = await useSubscribeXXX();
43+
const { data, error, loading, then } = useSubscribeXXX();
44+
45+
// Assert loading and undefined values.
46+
expect(loading.value).toBe(true);
47+
expect(error.value).toBeUndefined();
48+
expect(data.value).toBeUndefined();
49+
50+
// Wait until loading ends.
51+
await then();
52+
expect(loading.value).toBe(false);
4353

4454
// Assert initial values are from query.
4555
expect(error.value).toBe(queryArg.error);
46-
expect(data.value).toBe(queryArg.error ? undefined : mapQuery(queryArg.data));
56+
expect(data.value).toStrictEqual(
57+
queryArg.error ? undefined : mapQuery(queryArg.data),
58+
);
4759

4860
// Assert the subsequent values are issued from subscription backed up by query.
4961
for (const issued of issue) {
@@ -52,7 +64,7 @@ export async function runPropertyTest<QueryData, SubData, R>(
5264
? undefined
5365
: (mapSub(issued.data) ?? mapQuery(queryArg.data));
5466
expect(error.value).toBe(expectedError);
55-
expect(data.value).toBe(expectedData);
67+
expect(data.value).toStrictEqual(expectedData);
5668
}
5769
}),
5870
);

src/api/__tests__/use-subscriptions.spec.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,27 @@ import type {
66
CtrlStateSSubscription,
77
CtrlRunNoQuery,
88
CtrlRunNoSSubscription,
9+
CtrlTraceIdsQuery,
10+
CtrlTraceIdsSSubscription,
11+
CtrlContinuousEnabledQuery,
12+
CtrlContinuousEnabledSSubscription,
13+
ScheduleAutoModeModeQuery,
14+
QScheduleAutoModeStateQuery,
15+
ScheduleAutoModeStateSSubscription,
16+
ScheduleAutoModeModeSSubscription,
17+
ScheduleQueueItemsQuery,
18+
ScheduleQueueItemsSSubscription,
919
} from "@/graphql/codegen/generated";
1020

21+
import { useSubscribeContinuousEnabled } from "../use-continuous-enabled-subscription";
1122
import { useSubscribeRunNo } from "../use-run-no-subscription";
23+
import { useSubscribeScheduleAutoModeMode } from "../use-schedule-auto-mode-mode-subscription";
24+
import { useSubscribeScheduleAutoModeState } from "../use-schedule-auto-mode-state-subscription";
25+
import { useSubscribeScheduleQueueItems } from "../use-schedule-queue-items-subscription";
1226
import { useSubscribeState } from "../use-state-subscription";
27+
import { useSubscribeTraceIds } from "../use-trace_ids-subscription";
1328

29+
import { fcScheduleQueueItem } from "./fc";
1430
import { runPropertyTest } from "./run-property-test";
1531

1632
// Mock functions used in runPropertyTest()
@@ -50,3 +66,118 @@ it("useSubscribeRunNo", async () => {
5066

5167
await runPropertyTest(useSubscribeRunNo, mapQuery, mapSub, fcQueryData, fcSubData);
5268
});
69+
70+
it("useSubscribeTraceIds", async () => {
71+
type QueryData = CtrlTraceIdsQuery;
72+
type SubData = CtrlTraceIdsSSubscription;
73+
74+
const mapQuery = (d: QueryData | undefined) => d?.ctrl.traceIds;
75+
const mapSub = (d: SubData | undefined) => d?.ctrlTraceIds;
76+
77+
const fcTraceIds = fc.array(fc.integer());
78+
const fcQueryData: fc.Arbitrary<QueryData> = fc.record({
79+
ctrl: fc.record({ traceIds: fcTraceIds }),
80+
});
81+
const fcSubData: fc.Arbitrary<SubData> = fc.record({
82+
ctrlTraceIds: fcTraceIds,
83+
});
84+
85+
await runPropertyTest(useSubscribeTraceIds, mapQuery, mapSub, fcQueryData, fcSubData);
86+
});
87+
88+
it("useSubscribeContinuousEnabled", async () => {
89+
type QueryData = CtrlContinuousEnabledQuery;
90+
type SubData = CtrlContinuousEnabledSSubscription;
91+
92+
const mapQuery = (d: QueryData | undefined) => d?.ctrl.continuousEnabled;
93+
const mapSub = (d: SubData | undefined) => d?.ctrlContinuousEnabled;
94+
95+
const fcContinuousEnabled = fc.boolean();
96+
const fcQueryData: fc.Arbitrary<QueryData> = fc.record({
97+
ctrl: fc.record({ continuousEnabled: fcContinuousEnabled }),
98+
});
99+
const fcSubData: fc.Arbitrary<SubData> = fc.record({
100+
ctrlContinuousEnabled: fcContinuousEnabled,
101+
});
102+
103+
await runPropertyTest(
104+
useSubscribeContinuousEnabled,
105+
mapQuery,
106+
mapSub,
107+
fcQueryData,
108+
fcSubData,
109+
);
110+
});
111+
112+
it("useSubscribeScheduleAutoModeMode", async () => {
113+
type QueryData = ScheduleAutoModeModeQuery;
114+
type SubData = ScheduleAutoModeModeSSubscription;
115+
116+
const mapQuery = (d: QueryData | undefined) => d?.schedule.autoMode.mode;
117+
const mapSub = (d: SubData | undefined) => d?.scheduleAutoModeMode;
118+
119+
const fcScheduleAutoMode = fc.string();
120+
const fcQueryData: fc.Arbitrary<QueryData> = fc.record({
121+
schedule: fc.record({ autoMode: fc.record({ mode: fcScheduleAutoMode }) }),
122+
});
123+
const fcSubData: fc.Arbitrary<SubData> = fc.record({
124+
scheduleAutoModeMode: fcScheduleAutoMode,
125+
});
126+
127+
await runPropertyTest(
128+
useSubscribeScheduleAutoModeMode,
129+
mapQuery,
130+
mapSub,
131+
fcQueryData,
132+
fcSubData,
133+
);
134+
});
135+
136+
it("useSubscribeScheduleAutoModeState", async () => {
137+
type QueryData = QScheduleAutoModeStateQuery;
138+
type SubData = ScheduleAutoModeStateSSubscription;
139+
140+
const mapQuery = (d: QueryData | undefined) => d?.schedule.autoMode.state;
141+
const mapSub = (d: SubData | undefined) => d?.scheduleAutoModeState;
142+
143+
const fcScheduleAutoModeState = fc.string();
144+
const fcQueryData: fc.Arbitrary<QueryData> = fc.record({
145+
schedule: fc.record({ autoMode: fc.record({ state: fcScheduleAutoModeState }) }),
146+
});
147+
const fcSubData: fc.Arbitrary<SubData> = fc.record({
148+
scheduleAutoModeState: fcScheduleAutoModeState,
149+
});
150+
151+
await runPropertyTest(
152+
useSubscribeScheduleAutoModeState,
153+
mapQuery,
154+
mapSub,
155+
fcQueryData,
156+
fcSubData,
157+
);
158+
});
159+
160+
it("useSubscribeScheduleQueueItems", async () => {
161+
type QueryData = ScheduleQueueItemsQuery;
162+
type SubData = ScheduleQueueItemsSSubscription;
163+
164+
const mapQuery = (d: QueryData | undefined) => d?.schedule.queue.items;
165+
const mapSub = (d: SubData | undefined) => d?.scheduleQueueItems;
166+
167+
const fcQueryData: fc.Arbitrary<QueryData> = fc.record({
168+
schedule: fc.record({
169+
queue: fc.record({ items: fc.array(fcScheduleQueueItem) }),
170+
}),
171+
});
172+
const fcSubData: fc.Arbitrary<SubData> = fc.record({
173+
scheduleQueueItems: fc.array(fcScheduleQueueItem),
174+
});
175+
176+
await runPropertyTest(
177+
useSubscribeScheduleQueueItems,
178+
mapQuery,
179+
mapSub,
180+
fcQueryData,
181+
fcSubData,
182+
);
183+
});
Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,25 @@
1-
import type { ComputedRef } from "vue";
2-
import { computed } from "vue";
3-
41
import {
52
useCtrlContinuousEnabledQuery,
63
useCtrlContinuousEnabledSSubscription,
74
} from "@/graphql/codegen/generated";
8-
import { onReady } from "@/utils/on-ready";
9-
import type { OnReady } from "@/utils/on-ready";
10-
11-
interface _ContinuousEnabledSubscription {
12-
continuousEnabled: ComputedRef<boolean | undefined>;
13-
error: ComputedRef<Error | undefined>;
14-
subscription: ReturnType<typeof useCtrlContinuousEnabledSSubscription>;
15-
query: ReturnType<typeof useCtrlContinuousEnabledQuery>;
16-
}
175

18-
type ContinuousEnabledSubscription = OnReady<_ContinuousEnabledSubscription>;
6+
import { useQueryBackedSubscription } from "./use-query-backed-subscription";
197

20-
export function useSubscribeContinuousEnabled(): ContinuousEnabledSubscription {
8+
export function useSubscribeContinuousEnabled() {
219
const query = useCtrlContinuousEnabledQuery({
2210
requestPolicy: "network-only",
2311
variables: {},
2412
});
2513
const subscription = useCtrlContinuousEnabledSSubscription({ variables: {} });
2614

27-
const error = computed(() => subscription.error?.value || query.error?.value);
15+
const mapQueryData = (d: typeof query.data) => d.value?.ctrl.continuousEnabled;
16+
const mapSubscriptionData = (d: typeof subscription.data) =>
17+
d.value?.ctrlContinuousEnabled;
2818

29-
const continuousEnabled = computed(() =>
30-
error.value
31-
? undefined
32-
: subscription.data?.value?.ctrlContinuousEnabled ||
33-
query.data?.value?.ctrl.continuousEnabled,
34-
);
35-
36-
const ret = { continuousEnabled, error, subscription, query };
37-
38-
return onReady(ret, query);
19+
return useQueryBackedSubscription({
20+
query,
21+
subscription,
22+
mapQueryData,
23+
mapSubscriptionData,
24+
});
3925
}

src/api/use-query-backed-subscription.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { computed } from "vue";
12
import type { ComputedRef, Ref } from "vue";
23
import { UseQueryResponse, UseSubscriptionResponse } from "@urql/vue";
34

@@ -16,16 +17,20 @@ interface UseQueryBackedSubscriptionOptions<T, Q, S> {
1617
type UseQueryBackedSubscriptionReturn<T> = OnReady<{
1718
data: ComputedRef<T | undefined>;
1819
error: ComputedRef<Error | undefined>;
20+
loading: ComputedRef<boolean>;
1921
}>;
2022

2123
export function useQueryBackedSubscription<T, Q, S>(
2224
options: UseQueryBackedSubscriptionOptions<T, Q, S>,
2325
): UseQueryBackedSubscriptionReturn<T> {
24-
const ret = useMappedWithFallback({
26+
const mapped = useMappedWithFallback({
2527
response1: options.subscription,
2628
response2: options.query,
2729
map1: options.mapSubscriptionData,
2830
map2: options.mapQueryData,
2931
});
32+
const loading = computed(() => options.query.fetching?.value);
33+
34+
const ret = { ...mapped, loading };
3035
return onReady(ret, options.query);
3136
}

src/api/use-run-no-subscription.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
1-
import type { ComputedRef } from "vue";
2-
31
import {
42
useCtrlRunNoQuery,
53
useCtrlRunNoSSubscription,
64
} from "@/graphql/codegen/generated";
75

86
import { useQueryBackedSubscription } from "./use-query-backed-subscription";
97

10-
interface _RunNoSubscription {
11-
data: ComputedRef<number | undefined>;
12-
error: ComputedRef<Error | undefined>;
13-
}
14-
15-
type RunNoSubscription = _RunNoSubscription & PromiseLike<_RunNoSubscription>;
16-
17-
export function useSubscribeRunNo(): RunNoSubscription {
8+
export function useSubscribeRunNo() {
189
const query = useCtrlRunNoQuery({ requestPolicy: "network-only", variables: {} });
1910
const subscription = useCtrlRunNoSSubscription({ variables: {} });
2011

0 commit comments

Comments
 (0)