@dudousxd/nestjs-telescope-testing
Test utilities — a deterministic FakeClock, a no-NestJS watcher harness, the in-memory storage provider re-exported for tests, and the StorageProvider conformance suite.
pnpm add -D @dudousxd/nestjs-telescope-testingTest utilities for Telescope: a deterministic clock, a watcher harness that needs no NestJS app, and the in-memory store re-exported so tests need one import.
FakeClock
A deterministic clock you can pass as the now option to the Recorder:
import { FakeClock } from '@dudousxd/nestjs-telescope-testing';
const clock = new FakeClock(0);
clock.now(); // 0
clock.advance(500); // move forward 500 ms
clock.now(); // 500
clock.set(1000); // jump to absolute ms
clock.now(); // 1000collectWatcherEntries
Registers a Watcher against a minimal capturing WatcherContext and returns everything it recorded — no NestJS app required:
import { collectWatcherEntries } from '@dudousxd/nestjs-telescope-testing';
import type { Watcher, WatcherContext } from '@dudousxd/nestjs-telescope';
const myWatcher: Watcher = {
type: 'demo',
register(ctx: WatcherContext) {
ctx.record({ type: 'demo', content: { hello: 'world' } });
},
};
const { recorded, context } = await collectWatcherEntries(myWatcher);
// recorded[0] => { type: 'demo', content: { hello: 'world' } }
// You can also drive batch handles:
const handle = context.beginBatch('manual');
// handle.id => 'batch-0'
handle.end();InMemoryStorageProvider
Re-exported from core so tests only need one import:
import { InMemoryStorageProvider } from '@dudousxd/nestjs-telescope-testing';
const storage = new InMemoryStorageProvider();describeStorageProvider
The StorageProvider contract as a Vitest suite — the one every adapter in this repo runs, and the one a custom adapter should run too. It lives on a subpath so the rest of the package does not require Vitest:
import { describeStorageProvider } from '@dudousxd/nestjs-telescope-testing/conformance';
describeStorageProvider('MyStorageProvider', () => new MyStorageProvider(), {
// retention: 'ttl', // prune* are no-ops (the database expires rows itself)
// afterSeed: async (p, seeded) => {}, // move part of the seeded data elsewhere
// teardown: (p) => {}, // instead of p.close()
// skip: 'no database', // register the suite as skipped, with a reason
// timeoutMs: 30_000,
});It covers store/find/get with every EntryQuery filter, newest-first keyset paging (createdAt DESC, id DESC) including ties, concurrent inserts and cursors whose entry is gone, batch, tags (order, prefix, search, paging), update, prune with keepLast, and — only when the provider has them — pruneScoped, pruneScopedBatch, the lease pair, markFamilySeen and RollupStore. makeEntry(over?) from the same subpath builds a complete Entry for your own tests.
@dudousxd/nestjs-telescope-ai
AI-powered exception diagnosis — turn a captured exception into a markdown triage report (probable cause, where to look, suggested fix, confidence) using the Vercel AI SDK with any provider.
Recipes
Copy-pasteable cookbook for extending Telescope — a custom storage adapter, custom watchers, dashboard login, custom tags and redaction, request-context capture, archiving to S3 before prune, reporting frontend errors, and AI exception diagnosis.