@signalium/query 0.1.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/cjs/EntityMap.js +2 -2
- package/dist/cjs/EntityMap.js.map +1 -1
- package/dist/cjs/NetworkManager.js +105 -0
- package/dist/cjs/NetworkManager.js.map +1 -0
- package/dist/cjs/QueryClient.js +390 -76
- package/dist/cjs/QueryClient.js.map +1 -1
- package/dist/cjs/QueryStore.js +295 -3
- package/dist/cjs/QueryStore.js.map +1 -1
- package/dist/cjs/index.js +18 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/parseEntities.js +3 -0
- package/dist/cjs/parseEntities.js.map +1 -1
- package/dist/cjs/proxy.js +19 -0
- package/dist/cjs/proxy.js.map +1 -1
- package/dist/cjs/query.js +40 -2
- package/dist/cjs/query.js.map +1 -1
- package/dist/cjs/stores/async.js +6 -0
- package/dist/cjs/stores/async.js.map +1 -0
- package/dist/cjs/stores/sync.js +7 -0
- package/dist/cjs/stores/sync.js.map +1 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/cjs/type-utils.js +3 -0
- package/dist/cjs/type-utils.js.map +1 -0
- package/dist/cjs/types.js +19 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/EntityMap.js +3 -3
- package/dist/esm/EntityMap.js.map +1 -1
- package/dist/esm/NetworkManager.d.ts +48 -0
- package/dist/esm/NetworkManager.d.ts.map +1 -0
- package/dist/esm/NetworkManager.js +101 -0
- package/dist/esm/NetworkManager.js.map +1 -0
- package/dist/esm/QueryClient.d.ts +81 -25
- package/dist/esm/QueryClient.d.ts.map +1 -1
- package/dist/esm/QueryClient.js +390 -76
- package/dist/esm/QueryClient.js.map +1 -1
- package/dist/esm/QueryStore.d.ts +64 -2
- package/dist/esm/QueryStore.d.ts.map +1 -1
- package/dist/esm/QueryStore.js +293 -2
- package/dist/esm/QueryStore.js.map +1 -1
- package/dist/esm/index.d.ts +6 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +4 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/parseEntities.d.ts.map +1 -1
- package/dist/esm/parseEntities.js +3 -0
- package/dist/esm/parseEntities.js.map +1 -1
- package/dist/esm/proxy.d.ts +6 -0
- package/dist/esm/proxy.d.ts.map +1 -1
- package/dist/esm/proxy.js +18 -0
- package/dist/esm/proxy.js.map +1 -1
- package/dist/esm/query.d.ts +30 -29
- package/dist/esm/query.d.ts.map +1 -1
- package/dist/esm/query.js +39 -3
- package/dist/esm/query.js.map +1 -1
- package/dist/esm/stores/async.d.ts +2 -0
- package/dist/esm/stores/async.d.ts.map +1 -0
- package/dist/esm/stores/async.js +2 -0
- package/dist/esm/stores/async.js.map +1 -0
- package/dist/esm/stores/sync.d.ts +2 -0
- package/dist/esm/stores/sync.d.ts.map +1 -0
- package/dist/esm/stores/sync.js +2 -0
- package/dist/esm/stores/sync.js.map +1 -0
- package/dist/esm/type-utils.d.ts +12 -0
- package/dist/esm/type-utils.d.ts.map +1 -0
- package/dist/esm/type-utils.js +2 -0
- package/dist/esm/type-utils.js.map +1 -0
- package/dist/esm/types.d.ts +62 -5
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js +18 -0
- package/dist/esm/types.js.map +1 -1
- package/index.d.ts +1 -0
- package/package.json +25 -4
- package/stores/async.d.ts +1 -0
- package/stores/async.js +15 -0
- package/stores/sync.d.ts +1 -0
- package/stores/sync.js +15 -0
- package/.turbo/turbo-build.log +0 -12
- package/ENTITY_STORE_DESIGN.md +0 -386
- package/dist/tsconfig.esm.tsbuildinfo +0 -1
- package/src/EntityMap.ts +0 -63
- package/src/QueryClient.ts +0 -482
- package/src/QueryStore.ts +0 -322
- package/src/__tests__/caching-persistence.test.ts +0 -983
- package/src/__tests__/entity-system.test.ts +0 -556
- package/src/__tests__/gc-time.test.ts +0 -327
- package/src/__tests__/mock-fetch.test.ts +0 -186
- package/src/__tests__/parse-entities.test.ts +0 -425
- package/src/__tests__/path-interpolation.test.ts +0 -225
- package/src/__tests__/reactivity.test.ts +0 -424
- package/src/__tests__/refetch-interval.test.ts +0 -262
- package/src/__tests__/rest-query-api.test.ts +0 -568
- package/src/__tests__/stale-time.test.ts +0 -357
- package/src/__tests__/type-to-string.test.ts +0 -129
- package/src/__tests__/utils.ts +0 -258
- package/src/__tests__/validation-edge-cases.test.ts +0 -821
- package/src/errors.ts +0 -124
- package/src/index.ts +0 -7
- package/src/parseEntities.ts +0 -213
- package/src/pathInterpolator.ts +0 -74
- package/src/proxy.ts +0 -257
- package/src/query.ts +0 -164
- package/src/react/__tests__/basic.test.tsx +0 -926
- package/src/react/__tests__/component.test.tsx +0 -984
- package/src/react/__tests__/utils.tsx +0 -71
- package/src/typeDefs.ts +0 -351
- package/src/types.ts +0 -132
- package/src/utils.ts +0 -66
- package/tsconfig.cjs.json +0 -14
- package/tsconfig.esm.json +0 -13
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -65
|
@@ -1,357 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
|
2
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
3
|
-
import { SyncQueryStore, MemoryPersistentStore, updatedAtKeyFor } from '../QueryStore.js';
|
|
4
|
-
import { QueryClient } from '../QueryClient.js';
|
|
5
|
-
import { query } from '../query.js';
|
|
6
|
-
import { createMockFetch, testWithClient, sleep } from './utils.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* StaleTime Tests
|
|
10
|
-
*
|
|
11
|
-
* Tests staleTime behavior: serving cached data while refetching in background
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
describe('StaleTime', () => {
|
|
15
|
-
let client: QueryClient;
|
|
16
|
-
let mockFetch: ReturnType<typeof createMockFetch>;
|
|
17
|
-
let kv: any;
|
|
18
|
-
let store: any;
|
|
19
|
-
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
client?.destroy();
|
|
22
|
-
kv = new MemoryPersistentStore();
|
|
23
|
-
store = new SyncQueryStore(kv);
|
|
24
|
-
mockFetch = createMockFetch();
|
|
25
|
-
client = new QueryClient(store, { fetch: mockFetch as any });
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
describe('Fresh Data', () => {
|
|
29
|
-
it('should not refetch when data is fresh (within staleTime)', async () => {
|
|
30
|
-
// Set up query with 10 second staleTime
|
|
31
|
-
const getItem = query(t => ({
|
|
32
|
-
path: '/item',
|
|
33
|
-
response: { value: t.string },
|
|
34
|
-
cache: { staleTime: 10000 }, // 10 seconds
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
mockFetch.get('/item', { value: 'first' });
|
|
38
|
-
|
|
39
|
-
await testWithClient(client, async () => {
|
|
40
|
-
// First fetch
|
|
41
|
-
const relay1 = getItem();
|
|
42
|
-
await relay1;
|
|
43
|
-
expect(relay1.value).toEqual({ value: 'first' });
|
|
44
|
-
expect(mockFetch.calls).toHaveLength(1);
|
|
45
|
-
|
|
46
|
-
// Second access immediately (data is fresh)
|
|
47
|
-
mockFetch.get('/item', { value: 'second' });
|
|
48
|
-
const relay2 = getItem();
|
|
49
|
-
|
|
50
|
-
// Force evaluation
|
|
51
|
-
relay2.value;
|
|
52
|
-
await sleep(50);
|
|
53
|
-
|
|
54
|
-
// Should use cached data without refetch
|
|
55
|
-
expect(relay2.value).toEqual({ value: 'first' });
|
|
56
|
-
expect(mockFetch.calls).toHaveLength(1); // Still only one call
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should use fresh data from disk cache without refetch', async () => {
|
|
61
|
-
const getItem = query(t => ({
|
|
62
|
-
path: '/item',
|
|
63
|
-
response: { data: t.number },
|
|
64
|
-
cache: { staleTime: 5000 },
|
|
65
|
-
}));
|
|
66
|
-
|
|
67
|
-
mockFetch.get('/item', { data: 42 });
|
|
68
|
-
|
|
69
|
-
await testWithClient(client, async () => {
|
|
70
|
-
const relay1 = getItem();
|
|
71
|
-
await relay1;
|
|
72
|
-
expect(mockFetch.calls).toHaveLength(1);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// Create new client with same store (simulating app restart)
|
|
76
|
-
mockFetch.reset();
|
|
77
|
-
mockFetch.get('/item', { data: 99 }, { delay: 50 });
|
|
78
|
-
const client2 = new QueryClient(store, { fetch: mockFetch as any });
|
|
79
|
-
|
|
80
|
-
await testWithClient(client2, async () => {
|
|
81
|
-
const relay = getItem();
|
|
82
|
-
|
|
83
|
-
// Should immediately have cached value
|
|
84
|
-
relay.value;
|
|
85
|
-
await sleep(10);
|
|
86
|
-
expect(relay.value).toEqual({ data: 42 });
|
|
87
|
-
|
|
88
|
-
// Should not refetch since data is still fresh
|
|
89
|
-
await sleep(100);
|
|
90
|
-
expect(mockFetch.calls).toHaveLength(0);
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
describe('Stale Data', () => {
|
|
96
|
-
it('should serve stale data immediately while refetching in background', async () => {
|
|
97
|
-
const getItem = query(t => ({
|
|
98
|
-
path: '/item',
|
|
99
|
-
response: { count: t.number },
|
|
100
|
-
staleTime: 100, // 100ms
|
|
101
|
-
}));
|
|
102
|
-
|
|
103
|
-
mockFetch.get('/item', { count: 1 });
|
|
104
|
-
|
|
105
|
-
await testWithClient(client, async () => {
|
|
106
|
-
// Initial fetch
|
|
107
|
-
const relay1 = getItem();
|
|
108
|
-
await relay1;
|
|
109
|
-
expect(relay1.value).toEqual({ count: 1 });
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// Wait for data to become stale, and unwatch query entirely
|
|
113
|
-
await sleep(200);
|
|
114
|
-
|
|
115
|
-
await testWithClient(client, async () => {
|
|
116
|
-
// Set up new response
|
|
117
|
-
mockFetch.get('/item', { count: 2 }, { delay: 50 });
|
|
118
|
-
|
|
119
|
-
// Access again - should serve stale data immediately
|
|
120
|
-
const relay2 = getItem();
|
|
121
|
-
relay2.value;
|
|
122
|
-
await sleep(10);
|
|
123
|
-
|
|
124
|
-
// Should have stale data immediately
|
|
125
|
-
expect(relay2.value).toEqual({ count: 1 });
|
|
126
|
-
|
|
127
|
-
// Wait for background refetch to complete
|
|
128
|
-
await sleep(100);
|
|
129
|
-
|
|
130
|
-
// Should now have fresh data
|
|
131
|
-
expect(relay2.value).toEqual({ count: 2 });
|
|
132
|
-
expect(mockFetch.calls).toHaveLength(2);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('should refetch stale data from disk cache', async () => {
|
|
137
|
-
const getItem = query(t => ({
|
|
138
|
-
path: '/data',
|
|
139
|
-
response: { version: t.number },
|
|
140
|
-
staleTime: 100,
|
|
141
|
-
}));
|
|
142
|
-
|
|
143
|
-
mockFetch.get('/data', { version: 1 });
|
|
144
|
-
|
|
145
|
-
await testWithClient(client, async () => {
|
|
146
|
-
const relay = getItem();
|
|
147
|
-
await relay;
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
// Wait for data to become stale
|
|
151
|
-
await sleep(150);
|
|
152
|
-
|
|
153
|
-
// Create new client
|
|
154
|
-
mockFetch.reset();
|
|
155
|
-
mockFetch.get('/data', { version: 2 }, { delay: 50 });
|
|
156
|
-
const client2 = new QueryClient(store, { fetch: mockFetch as any });
|
|
157
|
-
|
|
158
|
-
await testWithClient(client2, async () => {
|
|
159
|
-
const relay = getItem();
|
|
160
|
-
|
|
161
|
-
// Should have cached value immediately
|
|
162
|
-
relay.value;
|
|
163
|
-
await sleep(10);
|
|
164
|
-
expect(relay.value).toEqual({ version: 1 });
|
|
165
|
-
|
|
166
|
-
// Should trigger background refetch
|
|
167
|
-
await sleep(100);
|
|
168
|
-
|
|
169
|
-
expect(relay.value).toEqual({ version: 2 });
|
|
170
|
-
expect(mockFetch.calls).toHaveLength(1);
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it('should handle no staleTime (always refetch)', async () => {
|
|
175
|
-
const getItem = query(t => ({
|
|
176
|
-
path: '/item',
|
|
177
|
-
response: { value: t.string },
|
|
178
|
-
// No staleTime configured
|
|
179
|
-
}));
|
|
180
|
-
|
|
181
|
-
mockFetch.get('/item', { value: 'first' });
|
|
182
|
-
|
|
183
|
-
await testWithClient(client, async () => {
|
|
184
|
-
const relay1 = getItem();
|
|
185
|
-
await relay1;
|
|
186
|
-
expect(mockFetch.calls).toHaveLength(1);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
// Access again immediately
|
|
190
|
-
await testWithClient(client, async () => {
|
|
191
|
-
mockFetch.get('/item', { value: 'second' }, { delay: 50 });
|
|
192
|
-
const relay2 = getItem();
|
|
193
|
-
|
|
194
|
-
relay2.value;
|
|
195
|
-
await sleep(10);
|
|
196
|
-
|
|
197
|
-
// Should have cached value
|
|
198
|
-
expect(relay2.value).toEqual({ value: 'first' });
|
|
199
|
-
|
|
200
|
-
// But should refetch in background
|
|
201
|
-
await sleep(100);
|
|
202
|
-
|
|
203
|
-
expect(relay2.value).toEqual({ value: 'second' });
|
|
204
|
-
expect(mockFetch.calls).toHaveLength(2);
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
describe('Edge Cases', () => {
|
|
210
|
-
it('should handle staleTime of 0 (always stale)', async () => {
|
|
211
|
-
const getItem = query(t => ({
|
|
212
|
-
path: '/item',
|
|
213
|
-
response: { n: t.number },
|
|
214
|
-
cache: { staleTime: 0 },
|
|
215
|
-
}));
|
|
216
|
-
|
|
217
|
-
mockFetch.get('/item', { n: 1 });
|
|
218
|
-
|
|
219
|
-
await testWithClient(client, async () => {
|
|
220
|
-
const relay1 = getItem();
|
|
221
|
-
await relay1;
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
await testWithClient(client, async () => {
|
|
225
|
-
mockFetch.get('/item', { n: 2 }, { delay: 50 });
|
|
226
|
-
const relay2 = getItem();
|
|
227
|
-
|
|
228
|
-
// Should serve cached but refetch immediately
|
|
229
|
-
relay2.value;
|
|
230
|
-
await sleep(10);
|
|
231
|
-
expect(relay2.value).toEqual({ n: 1 });
|
|
232
|
-
|
|
233
|
-
await sleep(100);
|
|
234
|
-
expect(relay2.value).toEqual({ n: 2 });
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it('should handle very long staleTime', async () => {
|
|
239
|
-
vi.useFakeTimers();
|
|
240
|
-
|
|
241
|
-
try {
|
|
242
|
-
const getItem = query(t => ({
|
|
243
|
-
path: '/item',
|
|
244
|
-
response: { data: t.string },
|
|
245
|
-
cache: { staleTime: 1000 * 60 * 60 }, // 1 hour
|
|
246
|
-
}));
|
|
247
|
-
|
|
248
|
-
mockFetch.get('/item', { data: 'cached' });
|
|
249
|
-
|
|
250
|
-
// First subscription - fetch initial data
|
|
251
|
-
await testWithClient(client, async () => {
|
|
252
|
-
const relay1 = getItem();
|
|
253
|
-
await relay1;
|
|
254
|
-
expect(relay1.value).toEqual({ data: 'cached' });
|
|
255
|
-
expect(mockFetch.calls).toHaveLength(1);
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
// Unsubscribed now (testWithClient ended)
|
|
259
|
-
|
|
260
|
-
// Second subscription - should still use cache (data is fresh)
|
|
261
|
-
mockFetch.reset();
|
|
262
|
-
mockFetch.get('/item', { data: 'fresh1' });
|
|
263
|
-
await testWithClient(client, async () => {
|
|
264
|
-
const relay2 = getItem();
|
|
265
|
-
relay2.value;
|
|
266
|
-
await vi.advanceTimersByTimeAsync(100);
|
|
267
|
-
|
|
268
|
-
// Should use cached data without refetch (still fresh)
|
|
269
|
-
expect(relay2.value).toEqual({ data: 'cached' });
|
|
270
|
-
expect(mockFetch.calls).toHaveLength(0);
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// Advance time by 30 minutes - still within 1 hour staleTime
|
|
274
|
-
await vi.advanceTimersByTimeAsync(30 * 60 * 1000);
|
|
275
|
-
|
|
276
|
-
// Third subscription - data should still be fresh
|
|
277
|
-
mockFetch.reset();
|
|
278
|
-
mockFetch.get('/item', { data: 'fresh2' });
|
|
279
|
-
await testWithClient(client, async () => {
|
|
280
|
-
const relay3 = getItem();
|
|
281
|
-
relay3.value;
|
|
282
|
-
await vi.advanceTimersByTimeAsync(100);
|
|
283
|
-
|
|
284
|
-
// Should still use cached data (within 1 hour)
|
|
285
|
-
expect(relay3.value).toEqual({ data: 'cached' });
|
|
286
|
-
expect(mockFetch.calls).toHaveLength(0);
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// Advance time past the 1 hour mark (31 more minutes = 61 minutes total)
|
|
290
|
-
await vi.advanceTimersByTimeAsync(31 * 60 * 1000);
|
|
291
|
-
|
|
292
|
-
// Fourth subscription - data should now be stale and trigger refetch
|
|
293
|
-
mockFetch.reset();
|
|
294
|
-
mockFetch.get('/item', { data: 'fresh-after-hour' }, { delay: 100 });
|
|
295
|
-
await testWithClient(client, async () => {
|
|
296
|
-
const relay4 = getItem();
|
|
297
|
-
|
|
298
|
-
// Should serve stale data immediately
|
|
299
|
-
relay4.value;
|
|
300
|
-
await vi.advanceTimersByTimeAsync(10);
|
|
301
|
-
expect(relay4.value).toEqual({ data: 'cached' });
|
|
302
|
-
|
|
303
|
-
// Wait for background refetch to complete
|
|
304
|
-
await vi.advanceTimersByTimeAsync(100);
|
|
305
|
-
|
|
306
|
-
// Should now have fresh data
|
|
307
|
-
expect(relay4.value).toEqual({ data: 'fresh-after-hour' });
|
|
308
|
-
expect(mockFetch.calls).toHaveLength(1);
|
|
309
|
-
});
|
|
310
|
-
} finally {
|
|
311
|
-
vi.useRealTimers();
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
it('should handle concurrent access to stale data', async () => {
|
|
316
|
-
const getItem = query(t => ({
|
|
317
|
-
path: '/item',
|
|
318
|
-
response: { id: t.number },
|
|
319
|
-
cache: { staleTime: 50 },
|
|
320
|
-
}));
|
|
321
|
-
|
|
322
|
-
mockFetch.get('/item', { id: 1 });
|
|
323
|
-
|
|
324
|
-
await testWithClient(client, async () => {
|
|
325
|
-
const relay1 = getItem();
|
|
326
|
-
await relay1;
|
|
327
|
-
|
|
328
|
-
await sleep(100); // Make stale
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
await testWithClient(client, async () => {
|
|
332
|
-
mockFetch.get('/item', { id: 2 }, { delay: 100 });
|
|
333
|
-
|
|
334
|
-
// Multiple concurrent accesses
|
|
335
|
-
const relay2 = getItem();
|
|
336
|
-
const relay3 = getItem();
|
|
337
|
-
const relay4 = getItem();
|
|
338
|
-
|
|
339
|
-
// All should be the same relay
|
|
340
|
-
expect(relay2).toBe(relay3);
|
|
341
|
-
expect(relay3).toBe(relay4);
|
|
342
|
-
|
|
343
|
-
// Should serve stale data immediately
|
|
344
|
-
relay2.value;
|
|
345
|
-
await sleep(10);
|
|
346
|
-
expect(relay2.value).toEqual({ id: 1 });
|
|
347
|
-
|
|
348
|
-
// Wait for refetch
|
|
349
|
-
await sleep(100);
|
|
350
|
-
expect(relay2.value).toEqual({ id: 2 });
|
|
351
|
-
|
|
352
|
-
// Should only refetch once
|
|
353
|
-
expect(mockFetch.calls).toHaveLength(2);
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
});
|
|
357
|
-
});
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { typeToString } from '../errors.js';
|
|
3
|
-
import { t } from '../typeDefs.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Unit tests for typeToString function
|
|
7
|
-
* Tests the debug logging representation of TypeDef types
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
describe('typeToString', () => {
|
|
11
|
-
describe('Primitive Types', () => {
|
|
12
|
-
it('should convert string type to "string"', () => {
|
|
13
|
-
expect(typeToString(t.string)).toBe('string');
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('should convert number type to "number"', () => {
|
|
17
|
-
expect(typeToString(t.number)).toBe('number');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should convert boolean type to "boolean"', () => {
|
|
21
|
-
expect(typeToString(t.boolean)).toBe('boolean');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should convert null type to "null"', () => {
|
|
25
|
-
expect(typeToString(t.null)).toBe('null');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should convert undefined type to "undefined"', () => {
|
|
29
|
-
expect(typeToString(t.undefined)).toBe('undefined');
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
describe('Constant Values', () => {
|
|
34
|
-
it('should convert string constant to quoted string', () => {
|
|
35
|
-
expect(typeToString(t.const('user'))).toBe('"user"');
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('should convert boolean constant to boolean string', () => {
|
|
39
|
-
expect(typeToString(t.const(true))).toBe('true');
|
|
40
|
-
expect(typeToString(t.const(false))).toBe('false');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should convert number constant to number string', () => {
|
|
44
|
-
const numConst = t.const(42);
|
|
45
|
-
expect(typeToString(numConst)).toBe('42');
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
describe('Union Types', () => {
|
|
50
|
-
it('should convert primitive union types', () => {
|
|
51
|
-
const unionType = t.union(t.string, t.number);
|
|
52
|
-
const result = typeToString(unionType);
|
|
53
|
-
// Union of primitives should show both types
|
|
54
|
-
expect(result).toMatch(/string.*number|number.*string/);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('should convert union with null', () => {
|
|
58
|
-
const unionType = t.union(t.string, t.null);
|
|
59
|
-
const result = typeToString(unionType);
|
|
60
|
-
expect(result).toContain('null');
|
|
61
|
-
expect(result).toContain('string');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should convert union with undefined', () => {
|
|
65
|
-
const unionType = t.union(t.number, t.undefined);
|
|
66
|
-
const result = typeToString(unionType);
|
|
67
|
-
expect(result).toContain('undefined');
|
|
68
|
-
expect(result).toContain('number');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should convert value union with types', () => {
|
|
72
|
-
// Union with both types and values
|
|
73
|
-
const unionType = t.union(t.string, t.const('admin'));
|
|
74
|
-
const result = typeToString(unionType);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('Array Types', () => {
|
|
79
|
-
it('should convert array of primitives', () => {
|
|
80
|
-
expect(typeToString(t.array(t.string))).toBe('Array<string>');
|
|
81
|
-
expect(typeToString(t.array(t.number))).toBe('Array<number>');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('should convert nested arrays', () => {
|
|
85
|
-
const nestedArray = t.array(t.array(t.string));
|
|
86
|
-
expect(typeToString(nestedArray)).toBe('Array<Array<string>>');
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
describe('Record Types', () => {
|
|
91
|
-
it('should convert record of primitives', () => {
|
|
92
|
-
expect(typeToString(t.record(t.string))).toBe('Record<string, string>');
|
|
93
|
-
expect(typeToString(t.record(t.number))).toBe('Record<string, number>');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should convert record of arrays', () => {
|
|
97
|
-
const recordOfArrays = t.record(t.array(t.string));
|
|
98
|
-
expect(typeToString(recordOfArrays)).toBe('Record<string, Array<string>>');
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe('Object Types', () => {
|
|
103
|
-
it('should convert object without typename', () => {
|
|
104
|
-
const obj = t.object({ name: t.string, age: t.number });
|
|
105
|
-
expect(typeToString(obj)).toBe('object');
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
describe('Complex Nested Types', () => {
|
|
110
|
-
it('should handle array of records', () => {
|
|
111
|
-
const type = t.array(t.record(t.string));
|
|
112
|
-
expect(typeToString(type)).toBe('Array<Record<string, string>>');
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('should handle record of arrays', () => {
|
|
116
|
-
const type = t.record(t.array(t.number));
|
|
117
|
-
expect(typeToString(type)).toBe('Record<string, Array<number>>');
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should handle union of primitives with null and undefined', () => {
|
|
121
|
-
const type = t.union(t.string, t.number, t.null, t.undefined);
|
|
122
|
-
const result = typeToString(type);
|
|
123
|
-
expect(result).toContain('string');
|
|
124
|
-
expect(result).toContain('number');
|
|
125
|
-
expect(result).toContain('null');
|
|
126
|
-
expect(result).toContain('undefined');
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
});
|