@dudousxd/nestjs-telescope-testing 1.12.0 → 1.13.0

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/README.md CHANGED
@@ -56,3 +56,15 @@ import { InMemoryStorageProvider } from '@dudousxd/nestjs-telescope-testing';
56
56
 
57
57
  const storage = new InMemoryStorageProvider();
58
58
  ```
59
+
60
+ ## `describeStorageProvider` (conformance suite)
61
+
62
+ The `StorageProvider` contract as a Vitest suite, on the `/conformance` subpath (Vitest is an optional peer, needed only there). Every adapter in this repo runs it; run it against yours:
63
+
64
+ ```ts
65
+ import { describeStorageProvider } from '@dudousxd/nestjs-telescope-testing/conformance';
66
+
67
+ describeStorageProvider('MyStorageProvider', () => new MyStorageProvider());
68
+ ```
69
+
70
+ Optional SPI members (`pruneScoped`, `pruneScopedBatch`, leases, `markFamilySeen`, `RollupStore`) are tested only when present. Options: `retention: 'ttl'` (prune is a no-op), `afterSeed` (move seeded data, e.g. across a tier boundary), `teardown`, `skip`, `timeoutMs`.
@@ -0,0 +1,36 @@
1
+ import type { Entry, StorageProvider } from '@dudousxd/nestjs-telescope';
2
+ export interface StorageConformanceOptions {
3
+ /**
4
+ * Runs after every store() a READ test uses to seed its data. A composite store uses it to
5
+ * move part of what was just stored somewhere else — `tieredStorage` archives the older half
6
+ * to its cold tier — so the read assertions also cover data that lives behind the boundary.
7
+ * Write tests (`update`, `prune*`, leases) never call it: those operations target the
8
+ * provider's primary store by contract.
9
+ */
10
+ afterSeed?: (provider: StorageProvider, seeded: Entry[]) => Promise<void>;
11
+ /**
12
+ * How the provider expires data. `'delete'` (the default) asserts the `prune*` methods delete
13
+ * what they say they delete. `'ttl'` is for stores whose retention is the database's own TTL:
14
+ * `prune*` must then be no-ops that report zero and leave every entry in place.
15
+ */
16
+ retention?: 'delete' | 'ttl';
17
+ /** Releases the provider after each test. Defaults to `provider.close?.()`. */
18
+ teardown?: (provider: StorageProvider) => void | Promise<void>;
19
+ /** When set, the whole suite is registered as skipped, with this as the reason. */
20
+ skip?: string;
21
+ /** Per-test timeout for stores that talk to a real server. */
22
+ timeoutMs?: number;
23
+ }
24
+ /**
25
+ * Registers the `StorageProvider` contract as a Vitest suite. Every test gets a fresh provider
26
+ * from `factory`, initialised and cleared, so a factory may hand back the same instance each
27
+ * time (e.g. one connection to a container) as long as `clear()` empties it.
28
+ *
29
+ * Optional SPI members (`pruneScoped`, `pruneScopedBatch`, the lease pair, `markFamilySeen`, the
30
+ * rollup pair) are only exercised when the provider has them; a provider that omits one is not
31
+ * failed for it.
32
+ */
33
+ export declare function describeStorageProvider(name: string, factory: () => StorageProvider | Promise<StorageProvider>, options?: StorageConformanceOptions): void;
34
+ /** A complete entry with neutral defaults; `over` wins. */
35
+ export declare function makeEntry(over?: Partial<Entry>): Entry;
36
+ //# sourceMappingURL=storage-conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-conformance.d.ts","sourceRoot":"","sources":["../src/storage-conformance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EAGL,eAAe,EAEhB,MAAM,4BAA4B,CAAC;AAIpC,MAAM,WAAW,yBAAyB;IACxC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E;;;;OAIG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,EACzD,OAAO,GAAE,yBAA8B,GACtC,IAAI,CAoqBN;AAED,2DAA2D;AAC3D,wBAAgB,SAAS,CAAC,IAAI,GAAE,OAAO,CAAC,KAAK,CAAM,GAAG,KAAK,CAiB1D"}
@@ -0,0 +1,666 @@
1
+ import { HISTOGRAM_BUCKET_COUNT, isRollupStore } from '@dudousxd/nestjs-telescope';
2
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
3
+ const SECOND = 1000;
4
+ /**
5
+ * Registers the `StorageProvider` contract as a Vitest suite. Every test gets a fresh provider
6
+ * from `factory`, initialised and cleared, so a factory may hand back the same instance each
7
+ * time (e.g. one connection to a container) as long as `clear()` empties it.
8
+ *
9
+ * Optional SPI members (`pruneScoped`, `pruneScopedBatch`, the lease pair, `markFamilySeen`, the
10
+ * rollup pair) are only exercised when the provider has them; a provider that omits one is not
11
+ * failed for it.
12
+ */
13
+ export function describeStorageProvider(name, factory, options = {}) {
14
+ const suite = options.skip !== undefined ? describe.skip : describe;
15
+ const title = options.skip !== undefined
16
+ ? `StorageProvider conformance: ${name} (skipped: ${options.skip})`
17
+ : `StorageProvider conformance: ${name}`;
18
+ suite(title, { timeout: options.timeoutMs ?? 30_000 }, () => {
19
+ let provider;
20
+ // Whole seconds, two hours back: inside any sane retention window, and far enough from
21
+ // "now" that a store partitioning by hour never sees a test straddle the current hour.
22
+ const base = Math.floor((Date.now() - 2 * 60 * 60 * SECOND) / SECOND) * SECOND;
23
+ const at = (offsetSeconds) => new Date(base + offsetSeconds * SECOND);
24
+ const ttl = options.retention === 'ttl';
25
+ const seed = async (entries) => {
26
+ await provider.store(entries);
27
+ await options.afterSeed?.(provider, entries);
28
+ };
29
+ const all = async (query = {}) => {
30
+ const out = [];
31
+ let cursor;
32
+ for (let page = 0; page < 1000; page += 1) {
33
+ const result = await provider.get({ ...query, ...(cursor ? { cursor } : {}) });
34
+ out.push(...result.data);
35
+ if (result.nextCursor === null)
36
+ return out;
37
+ cursor = result.nextCursor;
38
+ }
39
+ throw new Error('pagination did not terminate');
40
+ };
41
+ const ids = (entries) => entries.map((entry) => entry.id);
42
+ beforeEach(async () => {
43
+ provider = await factory();
44
+ await provider.init?.();
45
+ await provider.clear();
46
+ });
47
+ afterEach(async () => {
48
+ if (options.teardown)
49
+ await options.teardown(provider);
50
+ else
51
+ await provider.close?.();
52
+ });
53
+ describe('store / find', () => {
54
+ it('round-trips every field', async () => {
55
+ const original = makeEntry({
56
+ id: 'e-0001',
57
+ batchId: 'batch-a',
58
+ type: 'query',
59
+ familyHash: 'fam-1',
60
+ content: { sql: 'select 1', bindings: [1, 'two'], nested: { ok: true } },
61
+ tags: ['slow', 'user:42'],
62
+ sequence: 3,
63
+ durationMs: 125,
64
+ origin: 'queue',
65
+ instanceId: 'pod-1',
66
+ traceId: 'trace-1',
67
+ spanId: 'span-1',
68
+ createdAt: at(10),
69
+ });
70
+ await seed([original]);
71
+ const found = await provider.find('e-0001');
72
+ expect(found).not.toBeNull();
73
+ const { batch, ...entry } = found;
74
+ expect(entry.createdAt).toBeInstanceOf(Date);
75
+ expect(entry).toEqual(original);
76
+ expect(ids(batch)).toEqual(['e-0001']);
77
+ });
78
+ it('round-trips nulls and empty tags', async () => {
79
+ const original = makeEntry({ id: 'e-0001', createdAt: at(1) });
80
+ await seed([original]);
81
+ const found = await provider.find('e-0001');
82
+ expect(found?.familyHash).toBeNull();
83
+ expect(found?.durationMs).toBeNull();
84
+ expect(found?.traceId).toBeNull();
85
+ expect(found?.spanId).toBeNull();
86
+ expect(found?.tags).toEqual([]);
87
+ });
88
+ it('returns null for an unknown id', async () => {
89
+ await seed([makeEntry({ id: 'e-0001', createdAt: at(1) })]);
90
+ expect(await provider.find('missing')).toBeNull();
91
+ });
92
+ it("returns the entry's batch ordered by sequence", async () => {
93
+ await seed([
94
+ makeEntry({ id: 'e-0003', batchId: 'b1', sequence: 2, createdAt: at(3) }),
95
+ makeEntry({ id: 'e-0001', batchId: 'b1', sequence: 0, createdAt: at(1) }),
96
+ makeEntry({ id: 'e-0002', batchId: 'b1', sequence: 1, createdAt: at(2) }),
97
+ makeEntry({ id: 'e-0004', batchId: 'b2', sequence: 0, createdAt: at(4) }),
98
+ ]);
99
+ const found = await provider.find('e-0002');
100
+ expect(found?.id).toBe('e-0002');
101
+ expect(ids(found?.batch ?? [])).toEqual(['e-0001', 'e-0002', 'e-0003']);
102
+ });
103
+ it('accepts an empty store() call', async () => {
104
+ await provider.store([]);
105
+ expect((await provider.get({})).data).toEqual([]);
106
+ });
107
+ });
108
+ describe('get: order and paging', () => {
109
+ it('returns newest first, ties broken by id descending', async () => {
110
+ await seed([
111
+ makeEntry({ id: 'e-0001', createdAt: at(1) }),
112
+ makeEntry({ id: 'e-0003', createdAt: at(2) }),
113
+ makeEntry({ id: 'e-0002', createdAt: at(2) }),
114
+ makeEntry({ id: 'e-0004', createdAt: at(3) }),
115
+ ]);
116
+ const page = await provider.get({});
117
+ expect(ids(page.data)).toEqual(['e-0004', 'e-0003', 'e-0002', 'e-0001']);
118
+ expect(page.nextCursor).toBeNull();
119
+ });
120
+ it('defaults the page size to 50', async () => {
121
+ await seed(series(60, (i) => ({ createdAt: at(i) })));
122
+ const page = await provider.get({});
123
+ expect(page.data).toHaveLength(50);
124
+ expect(page.nextCursor).not.toBeNull();
125
+ });
126
+ it('pages through every entry exactly once, in order', async () => {
127
+ const entries = series(23, (i) => ({ createdAt: at(Math.floor(i / 3)) }));
128
+ await seed(entries);
129
+ const seen = [];
130
+ let cursor;
131
+ let pages = 0;
132
+ do {
133
+ const page = await provider.get({ limit: 5, ...(cursor ? { cursor } : {}) });
134
+ expect(page.data.length).toBeLessThanOrEqual(5);
135
+ seen.push(...ids(page.data));
136
+ cursor = page.nextCursor ?? undefined;
137
+ pages += 1;
138
+ } while (cursor !== undefined && pages < 20);
139
+ expect(seen).toEqual(ids(sortNewestFirst(entries)));
140
+ expect(pages).toBe(5);
141
+ });
142
+ it('has no next cursor when the last page is exactly full', async () => {
143
+ await seed(series(4, (i) => ({ createdAt: at(i) })));
144
+ const first = await provider.get({ limit: 2 });
145
+ expect(first.nextCursor).not.toBeNull();
146
+ const second = await provider.get({ limit: 2, cursor: first.nextCursor });
147
+ expect(ids(second.data)).toEqual(['e-0001', 'e-0000']);
148
+ expect(second.nextCursor).toBeNull();
149
+ });
150
+ it('resumes from the cursor position when the cursor entry is gone', async () => {
151
+ const entries = series(5, (i) => ({ createdAt: at(i) }));
152
+ await seed(entries);
153
+ const first = await provider.get({ limit: 2 });
154
+ expect(ids(first.data)).toEqual(['e-0004', 'e-0003']);
155
+ // Rebuild the store without the entry the cursor points at.
156
+ await provider.clear();
157
+ await seed(entries.filter((entry) => entry.id !== 'e-0003'));
158
+ const next = await provider.get({ limit: 2, cursor: first.nextCursor });
159
+ expect(ids(next.data)).toEqual(['e-0002', 'e-0001']);
160
+ });
161
+ it('ignores an undecodable cursor', async () => {
162
+ await seed(series(3, (i) => ({ createdAt: at(i) })));
163
+ const page = await provider.get({ cursor: 'not a cursor' });
164
+ expect(ids(page.data)).toEqual(['e-0002', 'e-0001', 'e-0000']);
165
+ });
166
+ it('keeps keyset paging stable across concurrent inserts', async () => {
167
+ await seed(series(6, (i) => ({ createdAt: at(10 + i) })));
168
+ const first = await provider.get({ limit: 3 });
169
+ expect(ids(first.data)).toEqual(['e-0005', 'e-0004', 'e-0003']);
170
+ // One entry newer than everything (must not appear behind the cursor) and one older
171
+ // than everything (must, since it is strictly older than the cursor position).
172
+ await provider.store([
173
+ makeEntry({ id: 'e-0100', createdAt: at(100) }),
174
+ makeEntry({ id: 'e-0099', createdAt: at(0) }),
175
+ ]);
176
+ const rest = [];
177
+ let cursor = first.nextCursor;
178
+ while (cursor !== null) {
179
+ const page = await provider.get({ limit: 3, cursor });
180
+ rest.push(...ids(page.data));
181
+ cursor = page.nextCursor;
182
+ }
183
+ expect(rest).toEqual(['e-0002', 'e-0001', 'e-0000', 'e-0099']);
184
+ });
185
+ it('returns strictly older entries for a cursor on a timestamp tie', async () => {
186
+ await seed([
187
+ makeEntry({ id: 'e-0001', createdAt: at(5) }),
188
+ makeEntry({ id: 'e-0002', createdAt: at(5) }),
189
+ makeEntry({ id: 'e-0003', createdAt: at(5) }),
190
+ makeEntry({ id: 'e-0000', createdAt: at(4) }),
191
+ ]);
192
+ const first = await provider.get({ limit: 2 });
193
+ expect(ids(first.data)).toEqual(['e-0003', 'e-0002']);
194
+ const second = await provider.get({ limit: 2, cursor: first.nextCursor });
195
+ expect(ids(second.data)).toEqual(['e-0001', 'e-0000']);
196
+ });
197
+ });
198
+ describe('get: filters', () => {
199
+ const fixture = () => [
200
+ makeEntry({
201
+ id: 'e-0001',
202
+ type: 'request',
203
+ batchId: 'b1',
204
+ tags: ['status:200'],
205
+ familyHash: null,
206
+ traceId: 't1',
207
+ content: { uri: '/Users/Profile' },
208
+ createdAt: at(1),
209
+ }),
210
+ makeEntry({
211
+ id: 'e-0002',
212
+ type: 'query',
213
+ batchId: 'b1',
214
+ sequence: 1,
215
+ tags: ['slow'],
216
+ familyHash: 'f1',
217
+ traceId: 't1',
218
+ content: { sql: 'SELECT * FROM users' },
219
+ createdAt: at(2),
220
+ }),
221
+ makeEntry({
222
+ id: 'e-0003',
223
+ type: 'query',
224
+ batchId: 'b2',
225
+ tags: ['slow', 'user:7'],
226
+ familyHash: 'f1',
227
+ traceId: 't2',
228
+ content: { sql: 'select * from orders' },
229
+ createdAt: at(3),
230
+ }),
231
+ makeEntry({
232
+ id: 'e-0004',
233
+ type: 'exception',
234
+ batchId: 'b2',
235
+ sequence: 1,
236
+ tags: ['failed'],
237
+ familyHash: 'f2',
238
+ content: { message: 'Boom in Users' },
239
+ createdAt: at(4),
240
+ }),
241
+ ];
242
+ const cases = [
243
+ ['type', { type: 'query' }, ['e-0003', 'e-0002']],
244
+ ['tag', { tag: 'slow' }, ['e-0003', 'e-0002']],
245
+ ['tag (exact, not substring)', { tag: 'user' }, []],
246
+ ['familyHash', { familyHash: 'f1' }, ['e-0003', 'e-0002']],
247
+ ['batchId', { batchId: 'b2' }, ['e-0004', 'e-0003']],
248
+ ['traceId', { traceId: 't1' }, ['e-0002', 'e-0001']],
249
+ [
250
+ 'search (case-insensitive substring of content)',
251
+ { search: 'users' },
252
+ ['e-0004', 'e-0002', 'e-0001'],
253
+ ],
254
+ ['ids', { ids: ['e-0004', 'e-0001', 'missing'] }, ['e-0004', 'e-0001']],
255
+ ['empty ids', { ids: [] }, []],
256
+ ['before (exclusive)', { before: at(3) }, ['e-0002', 'e-0001']],
257
+ ['after (exclusive)', { after: at(2) }, ['e-0004', 'e-0003']],
258
+ ['before + after', { after: at(1), before: at(4) }, ['e-0003', 'e-0002']],
259
+ ['type + tag', { type: 'query', tag: 'user:7' }, ['e-0003']],
260
+ ['type + batchId', { type: 'query', batchId: 'b1' }, ['e-0002']],
261
+ ['no match', { type: 'mail' }, []],
262
+ ];
263
+ for (const [label, query, expected] of cases) {
264
+ it(`filters by ${label}`, async () => {
265
+ await seed(fixture());
266
+ expect(ids(await all(query))).toEqual(expected);
267
+ });
268
+ }
269
+ it('pages an ids query by cursor without losing or repeating any', async () => {
270
+ await seed(fixture());
271
+ expect(ids(await all({ ids: ['e-0001', 'e-0002', 'e-0003', 'e-0004'], limit: 1 }))).toEqual(['e-0004', 'e-0003', 'e-0002', 'e-0001']);
272
+ });
273
+ it('composes filters with the cursor', async () => {
274
+ await seed([
275
+ ...fixture(),
276
+ makeEntry({ id: 'e-0005', type: 'query', tags: ['slow'], createdAt: at(5) }),
277
+ ]);
278
+ const first = await provider.get({ type: 'query', limit: 2 });
279
+ expect(ids(first.data)).toEqual(['e-0005', 'e-0003']);
280
+ const second = await provider.get({
281
+ type: 'query',
282
+ limit: 2,
283
+ cursor: first.nextCursor,
284
+ });
285
+ expect(ids(second.data)).toEqual(['e-0002']);
286
+ expect(second.nextCursor).toBeNull();
287
+ });
288
+ it('nulls content under omitContent and keeps every other field', async () => {
289
+ const entries = fixture();
290
+ await seed(entries);
291
+ const page = await provider.get({ omitContent: true });
292
+ expect(page.data).toHaveLength(4);
293
+ for (const entry of page.data) {
294
+ expect(entry.content).toBeNull();
295
+ const original = entries.find((candidate) => candidate.id === entry.id);
296
+ expect({ ...entry, content: original?.content }).toEqual(original);
297
+ }
298
+ });
299
+ it('applies search before omitContent nulls the content', async () => {
300
+ await seed(fixture());
301
+ const page = await provider.get({ search: 'orders', omitContent: true });
302
+ expect(ids(page.data)).toEqual(['e-0003']);
303
+ expect(page.data[0]?.content).toBeNull();
304
+ });
305
+ });
306
+ describe('batch', () => {
307
+ it('returns only the batch, ordered by sequence', async () => {
308
+ await seed([
309
+ makeEntry({ id: 'e-0001', batchId: 'b1', sequence: 2, createdAt: at(1) }),
310
+ makeEntry({ id: 'e-0002', batchId: 'b1', sequence: 0, createdAt: at(2) }),
311
+ makeEntry({ id: 'e-0003', batchId: 'b2', sequence: 1, createdAt: at(3) }),
312
+ makeEntry({ id: 'e-0004', batchId: 'b1', sequence: 1, createdAt: at(4) }),
313
+ ]);
314
+ expect(ids(await provider.batch('b1'))).toEqual(['e-0002', 'e-0004', 'e-0001']);
315
+ expect(ids(await provider.batch('b2'))).toEqual(['e-0003']);
316
+ });
317
+ it('returns an empty list for an unknown batch', async () => {
318
+ await seed([makeEntry({ id: 'e-0001', createdAt: at(1) })]);
319
+ expect(await provider.batch('missing')).toEqual([]);
320
+ });
321
+ });
322
+ describe('tags', () => {
323
+ const tagged = () => [
324
+ makeEntry({ id: 'e-0001', tags: ['user:1', 'slow'], createdAt: at(1) }),
325
+ makeEntry({ id: 'e-0002', tags: ['user:2', 'slow'], createdAt: at(2) }),
326
+ makeEntry({ id: 'e-0003', tags: ['user:1', 'Failed'], createdAt: at(3) }),
327
+ makeEntry({ id: 'e-0004', tags: ['slow', 'Failed'], createdAt: at(4) }),
328
+ // Newest, so a provider returning first-seen order fails the ordering assertion.
329
+ makeEntry({ id: 'e-0005', tags: ['aaa'], createdAt: at(5) }),
330
+ makeEntry({ id: 'e-0006', tags: [], createdAt: at(6) }),
331
+ ];
332
+ it('counts every tag, most used first, ties alphabetical', async () => {
333
+ await seed(tagged());
334
+ expect(await provider.tags()).toEqual([
335
+ { tag: 'slow', count: 3 },
336
+ { tag: 'Failed', count: 2 },
337
+ { tag: 'user:1', count: 2 },
338
+ { tag: 'aaa', count: 1 },
339
+ { tag: 'user:2', count: 1 },
340
+ ]);
341
+ });
342
+ it('anchors prefix at the start of the tag', async () => {
343
+ await seed(tagged());
344
+ expect(await provider.tags('user:')).toEqual([
345
+ { tag: 'user:1', count: 2 },
346
+ { tag: 'user:2', count: 1 },
347
+ ]);
348
+ expect(await provider.tags('ser')).toEqual([]);
349
+ });
350
+ it('matches search anywhere in the tag, case-insensitively', async () => {
351
+ await seed(tagged());
352
+ expect(await provider.tags(undefined, { search: 'AIL' })).toEqual([
353
+ { tag: 'Failed', count: 2 },
354
+ ]);
355
+ expect(await provider.tags('user:', { search: '2' })).toEqual([
356
+ { tag: 'user:2', count: 1 },
357
+ ]);
358
+ });
359
+ it('pages with limit and offset over the ordered list', async () => {
360
+ await seed(tagged());
361
+ // A provider may ignore the bound (the controller re-applies it), but whatever it
362
+ // returns must page to the same window.
363
+ const window = async (limit, offset) => {
364
+ const rows = await provider.tags(undefined, { limit, offset });
365
+ return rows.length > limit ? rows.slice(offset, offset + limit) : rows;
366
+ };
367
+ expect(await window(2, 0)).toEqual([
368
+ { tag: 'slow', count: 3 },
369
+ { tag: 'Failed', count: 2 },
370
+ ]);
371
+ expect(await window(2, 2)).toEqual([
372
+ { tag: 'user:1', count: 2 },
373
+ { tag: 'aaa', count: 1 },
374
+ ]);
375
+ expect(await window(2, 4)).toEqual([{ tag: 'user:2', count: 1 }]);
376
+ expect(await window(2, 6)).toEqual([]);
377
+ });
378
+ });
379
+ describe('update', () => {
380
+ it('patches the given fields and leaves the rest', async () => {
381
+ const original = makeEntry({
382
+ id: 'e-0001',
383
+ content: { status: null },
384
+ tags: ['pending'],
385
+ createdAt: at(1),
386
+ });
387
+ await provider.store([original]);
388
+ await provider.update('e-0001', {
389
+ content: { status: 200 },
390
+ durationMs: 42,
391
+ tags: ['status:200'],
392
+ });
393
+ const found = await provider.find('e-0001');
394
+ expect(found?.content).toEqual({ status: 200 });
395
+ expect(found?.durationMs).toBe(42);
396
+ expect(found?.tags).toEqual(['status:200']);
397
+ expect(found?.batchId).toBe(original.batchId);
398
+ expect(found?.createdAt.getTime()).toBe(original.createdAt.getTime());
399
+ });
400
+ it('never changes the id', async () => {
401
+ await provider.store([makeEntry({ id: 'e-0001', createdAt: at(1) })]);
402
+ await provider.update('e-0001', { id: 'e-9999', durationMs: 1 });
403
+ expect((await provider.find('e-0001'))?.durationMs).toBe(1);
404
+ expect(await provider.find('e-9999')).toBeNull();
405
+ });
406
+ it('is a no-op for an unknown id', async () => {
407
+ await provider.store([makeEntry({ id: 'e-0001', createdAt: at(1) })]);
408
+ await provider.update('missing', { durationMs: 1 });
409
+ expect(ids(await all())).toEqual(['e-0001']);
410
+ });
411
+ it('is reflected by get() and keeps a single copy of the entry', async () => {
412
+ await provider.store([
413
+ makeEntry({ id: 'e-0001', createdAt: at(1) }),
414
+ makeEntry({ id: 'e-0002', createdAt: at(2) }),
415
+ ]);
416
+ await provider.update('e-0001', { durationMs: 7 });
417
+ await provider.update('e-0001', { durationMs: 8 });
418
+ const entries = await all();
419
+ expect(ids(entries)).toEqual(['e-0002', 'e-0001']);
420
+ expect(entries[1]?.durationMs).toBe(8);
421
+ });
422
+ });
423
+ describe('prune', () => {
424
+ const aged = () => [
425
+ makeEntry({ id: 'e-0001', type: 'query', createdAt: at(1) }),
426
+ makeEntry({ id: 'e-0002', type: 'request', createdAt: at(2) }),
427
+ makeEntry({ id: 'e-0003', type: 'query', createdAt: at(3) }),
428
+ makeEntry({ id: 'e-0004', type: 'exception', createdAt: at(4) }),
429
+ makeEntry({ id: 'e-0005', type: 'query', createdAt: at(5) }),
430
+ ];
431
+ if (ttl) {
432
+ it('prune is a no-op reporting zero', async () => {
433
+ await provider.store(aged());
434
+ expect(await provider.prune(at(10))).toBe(0);
435
+ expect(await provider.prune(at(10), 1)).toBe(0);
436
+ expect(await all()).toHaveLength(5);
437
+ });
438
+ it('pruneScoped and pruneScopedBatch, when present, are no-ops reporting zero', async () => {
439
+ await provider.store(aged());
440
+ if (provider.pruneScoped) {
441
+ expect(await provider.pruneScoped({ before: at(10), type: 'query' })).toBe(0);
442
+ }
443
+ if (provider.pruneScopedBatch) {
444
+ expect(await provider.pruneScopedBatch({ before: at(10), limit: 10 })).toEqual({
445
+ deleted: 0,
446
+ hasMore: false,
447
+ });
448
+ }
449
+ expect(await all()).toHaveLength(5);
450
+ });
451
+ return;
452
+ }
453
+ it('deletes entries strictly older than the cutoff and reports the count', async () => {
454
+ await provider.store(aged());
455
+ expect(await provider.prune(at(3))).toBe(2);
456
+ expect(ids(await all())).toEqual(['e-0005', 'e-0004', 'e-0003']);
457
+ });
458
+ it('keepLast spares the newest N of the doomed entries', async () => {
459
+ await provider.store(aged());
460
+ expect(await provider.prune(at(4), 1)).toBe(2);
461
+ expect(ids(await all())).toEqual(['e-0005', 'e-0004', 'e-0003']);
462
+ });
463
+ it('deletes nothing when nothing is older than the cutoff', async () => {
464
+ await provider.store(aged());
465
+ expect(await provider.prune(at(0))).toBe(0);
466
+ expect(await all()).toHaveLength(5);
467
+ });
468
+ it('pruneScoped by type', async () => {
469
+ if (!provider.pruneScoped)
470
+ return;
471
+ await provider.store(aged());
472
+ expect(await provider.pruneScoped({ before: at(5), type: 'query' })).toBe(2);
473
+ expect(ids(await all())).toEqual(['e-0005', 'e-0004', 'e-0002']);
474
+ });
475
+ it('pruneScoped excluding types', async () => {
476
+ if (!provider.pruneScoped)
477
+ return;
478
+ await provider.store(aged());
479
+ expect(await provider.pruneScoped({ before: at(5), excludeTypes: ['query'] })).toBe(2);
480
+ expect(ids(await all())).toEqual(['e-0005', 'e-0003', 'e-0001']);
481
+ });
482
+ it('pruneScoped with keepLast', async () => {
483
+ if (!provider.pruneScoped)
484
+ return;
485
+ await provider.store(aged());
486
+ expect(await provider.pruneScoped({ before: at(6), type: 'query', keepLast: 1 })).toBe(2);
487
+ expect(ids(await all())).toEqual(['e-0005', 'e-0004', 'e-0002']);
488
+ });
489
+ it('pruneScoped with no selector covers every type', async () => {
490
+ if (!provider.pruneScoped)
491
+ return;
492
+ await provider.store(aged());
493
+ expect(await provider.pruneScoped({ before: at(3) })).toBe(2);
494
+ expect(ids(await all())).toEqual(['e-0005', 'e-0004', 'e-0003']);
495
+ });
496
+ it('pruneScopedBatch deletes at most limit, oldest first, and reports hasMore', async () => {
497
+ if (!provider.pruneScopedBatch)
498
+ return;
499
+ await provider.store(aged());
500
+ const first = await provider.pruneScopedBatch({ before: at(5), limit: 3 });
501
+ expect(first).toEqual({ deleted: 3, hasMore: true });
502
+ expect(ids(await all())).toEqual(['e-0005', 'e-0004']);
503
+ const second = await provider.pruneScopedBatch({ before: at(5), limit: 3 });
504
+ expect(second.deleted).toBe(1);
505
+ expect(second.hasMore).toBe(false);
506
+ expect(ids(await all())).toEqual(['e-0005']);
507
+ });
508
+ it('pruneScopedBatch honours type and excludeTypes', async () => {
509
+ if (!provider.pruneScopedBatch)
510
+ return;
511
+ await provider.store(aged());
512
+ expect(await provider.pruneScopedBatch({ before: at(6), type: 'query', limit: 10 })).toEqual({ deleted: 3, hasMore: false });
513
+ expect(ids(await all())).toEqual(['e-0004', 'e-0002']);
514
+ const excluded = await provider.pruneScopedBatch({
515
+ before: at(6),
516
+ excludeTypes: ['exception'],
517
+ limit: 10,
518
+ });
519
+ expect(excluded.deleted).toBe(1);
520
+ expect(ids(await all())).toEqual(['e-0004']);
521
+ });
522
+ it('pruneScopedBatch reports an empty scope as drained', async () => {
523
+ if (!provider.pruneScopedBatch)
524
+ return;
525
+ await provider.store(aged());
526
+ expect(await provider.pruneScopedBatch({ before: at(0), limit: 10 })).toEqual({
527
+ deleted: 0,
528
+ hasMore: false,
529
+ });
530
+ });
531
+ });
532
+ describe('leases', () => {
533
+ const capable = () => typeof provider.tryAcquireLease === 'function' &&
534
+ typeof provider.releaseLease === 'function';
535
+ it('declares tryAcquireLease and releaseLease together or not at all', () => {
536
+ expect(typeof provider.tryAcquireLease).toBe(typeof provider.releaseLease);
537
+ });
538
+ it('grants a free lease and refuses another owner while it is held', async () => {
539
+ if (!capable())
540
+ return;
541
+ const now = Date.now();
542
+ expect(await provider.tryAcquireLease?.('k', 'a', 60_000, now)).toBe(true);
543
+ expect(await provider.tryAcquireLease?.('k', 'b', 60_000, now + 1)).toBe(false);
544
+ expect(await provider.tryAcquireLease?.('other', 'b', 60_000, now + 1)).toBe(true);
545
+ });
546
+ it('is re-entrant for the same owner', async () => {
547
+ if (!capable())
548
+ return;
549
+ const now = Date.now();
550
+ expect(await provider.tryAcquireLease?.('k', 'a', 60_000, now)).toBe(true);
551
+ expect(await provider.tryAcquireLease?.('k', 'a', 60_000, now + 1)).toBe(true);
552
+ });
553
+ it('grants an expired lease to a new owner', async () => {
554
+ if (!capable())
555
+ return;
556
+ expect(await provider.tryAcquireLease?.('k', 'a', 150, Date.now())).toBe(true);
557
+ await sleep(300);
558
+ expect(await provider.tryAcquireLease?.('k', 'b', 60_000, Date.now())).toBe(true);
559
+ expect(await provider.tryAcquireLease?.('k', 'a', 60_000, Date.now())).toBe(false);
560
+ });
561
+ it('releases only for the owner, idempotently', async () => {
562
+ if (!capable())
563
+ return;
564
+ const now = Date.now();
565
+ await provider.tryAcquireLease?.('k', 'a', 60_000, now);
566
+ await provider.releaseLease?.('k', 'b');
567
+ expect(await provider.tryAcquireLease?.('k', 'b', 60_000, now + 1)).toBe(false);
568
+ await provider.releaseLease?.('k', 'a');
569
+ await provider.releaseLease?.('k', 'a');
570
+ expect(await provider.tryAcquireLease?.('k', 'b', 60_000, now + 2)).toBe(true);
571
+ });
572
+ });
573
+ describe('markFamilySeen', () => {
574
+ it('is true for a new family, false inside the window, true again after it', async () => {
575
+ if (!provider.markFamilySeen)
576
+ return;
577
+ expect(await provider.markFamilySeen('fam', Date.now(), 150)).toBe(true);
578
+ expect(await provider.markFamilySeen('fam', Date.now(), 150)).toBe(false);
579
+ expect(await provider.markFamilySeen('other', Date.now(), 150)).toBe(true);
580
+ await sleep(300);
581
+ expect(await provider.markFamilySeen('fam', Date.now(), 150)).toBe(true);
582
+ });
583
+ });
584
+ describe('rollups', () => {
585
+ const rollups = () => (isRollupStore(provider) ? provider : null);
586
+ const delta = (over) => {
587
+ const histogram = new Array(HISTOGRAM_BUCKET_COUNT).fill(0);
588
+ histogram[2] = over.count ?? 1;
589
+ return { metric: 'request', bucketStart: 0, count: 1, sum: 5, max: 5, histogram, ...over };
590
+ };
591
+ it('merges deltas additively per (metric, bucket) and keeps the max', async () => {
592
+ const store = rollups();
593
+ if (!store)
594
+ return;
595
+ const bucket = Math.floor(base / 60_000) * 60_000;
596
+ await store.recordRollups([delta({ bucketStart: bucket, count: 2, sum: 10, max: 6 })]);
597
+ await store.recordRollups([
598
+ delta({ bucketStart: bucket, count: 3, sum: 9, max: 4 }),
599
+ delta({ metric: 'query', bucketStart: bucket, count: 1, sum: 1, max: 1 }),
600
+ ]);
601
+ const [request] = await store.queryRollups(['request'], bucket, bucket);
602
+ expect(request).toMatchObject({ metric: 'request', bucketStart: bucket });
603
+ expect(request?.count).toBe(5);
604
+ expect(request?.sum).toBe(19);
605
+ expect(request?.max).toBe(6);
606
+ expect(request?.histogram).toHaveLength(HISTOGRAM_BUCKET_COUNT);
607
+ expect(request?.histogram[2]).toBe(5);
608
+ });
609
+ it('returns buckets inside the inclusive range for the asked metrics only', async () => {
610
+ const store = rollups();
611
+ if (!store)
612
+ return;
613
+ const bucket = Math.floor(base / 60_000) * 60_000;
614
+ await store.recordRollups([
615
+ delta({ bucketStart: bucket }),
616
+ delta({ bucketStart: bucket + 60_000 }),
617
+ delta({ bucketStart: bucket + 120_000 }),
618
+ delta({ metric: 'query', bucketStart: bucket + 60_000 }),
619
+ ]);
620
+ const found = await store.queryRollups(['request'], bucket + 60_000, bucket + 120_000);
621
+ expect(found.map((row) => [row.metric, row.bucketStart]).sort()).toEqual([
622
+ ['request', bucket + 60_000],
623
+ ['request', bucket + 120_000],
624
+ ].sort());
625
+ });
626
+ });
627
+ describe('clear', () => {
628
+ it('removes every entry', async () => {
629
+ await provider.store(series(3, (i) => ({ createdAt: at(i) })));
630
+ await provider.clear();
631
+ expect((await provider.get({})).data).toEqual([]);
632
+ expect(await provider.tags()).toEqual([]);
633
+ });
634
+ });
635
+ });
636
+ }
637
+ /** A complete entry with neutral defaults; `over` wins. */
638
+ export function makeEntry(over = {}) {
639
+ return {
640
+ id: 'e-0000',
641
+ batchId: 'batch',
642
+ type: 'request',
643
+ familyHash: null,
644
+ content: {},
645
+ tags: [],
646
+ sequence: 0,
647
+ durationMs: null,
648
+ origin: 'http',
649
+ instanceId: 'instance',
650
+ traceId: null,
651
+ spanId: null,
652
+ createdAt: new Date(0),
653
+ ...over,
654
+ };
655
+ }
656
+ /** `count` entries with ids `e-0000`… — fixed-width, so string order matches numeric order. */
657
+ function series(count, over) {
658
+ return Array.from({ length: count }, (_, index) => makeEntry({ id: `e-${String(index).padStart(4, '0')}`, ...over(index) }));
659
+ }
660
+ function sortNewestFirst(entries) {
661
+ return [...entries].sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime() || (a.id < b.id ? 1 : a.id > b.id ? -1 : 0));
662
+ }
663
+ function sleep(ms) {
664
+ return new Promise((resolve) => setTimeout(resolve, ms));
665
+ }
666
+ //# sourceMappingURL=storage-conformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-conformance.js","sourceRoot":"","sources":["../src/storage-conformance.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,23 @@
1
1
  {
2
2
  "name": "@dudousxd/nestjs-telescope-testing",
3
- "version": "1.12.0",
4
- "description": "Test utilities for @dudousxd/nestjs-telescope — FakeClock, watcher harness, InMemoryStorageProvider re-export.",
3
+ "version": "1.13.0",
4
+ "description": "Test utilities for @dudousxd/nestjs-telescope — FakeClock, watcher harness, InMemoryStorageProvider re-export, and the StorageProvider conformance suite.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/DavideCarvalho/nestjs-telescope.git",
9
9
  "directory": "packages/testing"
10
10
  },
11
+ "homepage": "https://davidecarvalho.github.io/aviary/docs/telescope",
12
+ "bugs": {
13
+ "url": "https://github.com/DavideCarvalho/nestjs-telescope/issues"
14
+ },
15
+ "keywords": [
16
+ "nestjs",
17
+ "telescope",
18
+ "testing",
19
+ "observability"
20
+ ],
11
21
  "author": "Davi Carvalho <davi@goflip.ai>",
12
22
  "type": "module",
13
23
  "sideEffects": false,
@@ -18,6 +28,11 @@
18
28
  "types": "./dist/index.d.ts",
19
29
  "import": "./dist/index.js",
20
30
  "default": "./dist/index.js"
31
+ },
32
+ "./conformance": {
33
+ "types": "./dist/storage-conformance.d.ts",
34
+ "import": "./dist/storage-conformance.js",
35
+ "default": "./dist/storage-conformance.js"
21
36
  }
22
37
  },
23
38
  "files": [
@@ -25,23 +40,23 @@
25
40
  "README.md"
26
41
  ],
27
42
  "peerDependencies": {
28
- "@dudousxd/nestjs-telescope": "^1.27.0"
43
+ "vitest": ">=2.0.0",
44
+ "@dudousxd/nestjs-telescope": "^1.30.0"
29
45
  },
30
46
  "devDependencies": {
31
- "@types/node": "^20.0.0",
32
- "typescript": "^5.4.0",
33
- "vitest": "^3.0.0",
34
- "@dudousxd/nestjs-telescope": "1.27.0"
47
+ "@types/node": "20.19.43",
48
+ "typescript": "5.9.3",
49
+ "vitest": "3.2.7",
50
+ "@dudousxd/nestjs-telescope": "1.30.0"
35
51
  },
36
52
  "engines": {
37
53
  "node": ">=20"
38
54
  },
39
- "keywords": [
40
- "nestjs",
41
- "telescope",
42
- "testing",
43
- "observability"
44
- ],
55
+ "peerDependenciesMeta": {
56
+ "vitest": {
57
+ "optional": true
58
+ }
59
+ },
45
60
  "scripts": {
46
61
  "build": "tsc -p tsconfig.json",
47
62
  "test": "vitest run --passWithNoTests",