@noego/testing 0.1.0 → 0.4.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/dist/index.d.ts CHANGED
@@ -1,262 +1,318 @@
1
- import { Clock, Instant, Duration, Scheduler, ScheduleInput, ScheduledTaskHandle, ScheduledTaskId, IdGenerator, BrandedId, RandomSource, FetchRequest, FetchResponse, FetchError, FetchClient, ProcessCommand, ProcessEvent, ProcessRunner, ProcessResult, SpawnCommand, ProcessHandle, KeyValueStore, Key, Codec, PutOptions, ObjectStore, ObjectKey, StoredObject, StoredObjectInput, ObjectVersion, DomainEvent, EventBus, EventHandler, Subscription, LogSink, LogEnvelope, TelemetrySink, TelemetryEnvelope, TraceSink, TraceEnvelope } from '@noego/runtime';
1
+ import { IContainer, ApplicationModule } from '@noego/ioc';
2
2
 
3
3
  /**
4
- * Deterministic clock. Time never moves unless the test moves it.
5
- * Defaults to a fixed instant so snapshots are stable.
4
+ * Lowercase `test.*` descriptors immutable frozen values.
5
+ *
6
+ * Descriptors carry NO mutable state (no cursors, no counters, no histories);
7
+ * all mutable invocation state lives in the built environment, so one
8
+ * descriptor value is safe to share across builders and repeated builds.
6
9
  */
7
- declare class ManualClock extends Clock {
8
- static readonly defaultStart: Instant;
9
- private current;
10
- constructor(start?: Instant);
11
- now(): Instant;
12
- set(instant: Instant): void;
13
- advanceBy(duration: Duration): void;
10
+ declare const DESCRIPTOR: unique symbol;
11
+ /** A raw custom method wrapper: (original) => replacement. NOT auto-watched. */
12
+ type RawMethodWrapper = (original: (...args: any[]) => any) => (...args: any[]) => any;
13
+ interface ReturnsDescriptor {
14
+ readonly [DESCRIPTOR]: true;
15
+ readonly kind: 'returns';
16
+ readonly value: unknown;
14
17
  }
15
-
16
- interface PendingTask {
17
- readonly id: ScheduledTaskId;
18
- readonly label: string;
19
- readonly deadline: Instant;
18
+ interface ThrowsDescriptor {
19
+ readonly [DESCRIPTOR]: true;
20
+ readonly kind: 'throws';
21
+ readonly error: unknown;
20
22
  }
21
- /**
22
- * Deterministic scheduler driven by a ManualClock.
23
- *
24
- * Locked semantics:
25
- * - deadlines are (scheduledAt + delay);
26
- * - equal deadlines run in insertion order;
27
- * - cancelled tasks never execute;
28
- * - callbacks scheduled by callbacks are ordered deterministically (insertion
29
- * sequence is global and monotonic);
30
- * - async callbacks settle before advancing continues;
31
- * - runUntilIdle fails with a bounded diagnostic on infinite reschedule loops;
32
- * - assertNoPendingTasks fails teardown when tasks remain, unless allowed;
33
- * - CHOSEN MODEL: advancing time RUNS every task whose deadline falls inside
34
- * the advanced window, in deadline order. advanceBy(Duration.zero) runs
35
- * tasks already due.
36
- */
37
- declare class ManualScheduler extends Scheduler {
38
- private readonly clock;
39
- private readonly tasks;
40
- private nextSequence;
41
- private nextId;
42
- constructor(clock: ManualClock);
43
- schedule(input: ScheduleInput): ScheduledTaskHandle;
44
- pending(): PendingTask[];
45
- /** Advance the clock, running every task due inside the window in order. */
46
- advanceBy(duration: Duration): Promise<void>;
47
- /** Advance to the earliest pending deadline and run exactly that task. */
48
- runNext(): Promise<void>;
49
- /** Run tasks (advancing time as needed) until none remain. */
50
- runUntilIdle(options?: {
51
- maxTasks?: number;
52
- }): Promise<void>;
53
- /** Teardown assertion: fails when pending tasks remain, unless allowed. */
54
- assertNoPendingTasks(options?: {
55
- allow?: boolean;
56
- }): void;
57
- private live;
58
- private nextDue;
59
- private execute;
60
- private remove;
23
+ interface OriginalDescriptor {
24
+ readonly [DESCRIPTOR]: true;
25
+ readonly kind: 'original';
61
26
  }
62
-
63
- /**
64
- * Deterministic ID generator: "<brand>-1", "<brand>-2", … per brand.
65
- * Fixed IDs keep snapshots stable; isolation makes collisions impossible.
66
- */
67
- declare class SequenceIdGenerator extends IdGenerator {
68
- private readonly counters;
69
- next<TBrand extends string>(brand: TBrand): BrandedId<TBrand>;
27
+ interface CallsDescriptor {
28
+ readonly [DESCRIPTOR]: true;
29
+ readonly kind: 'calls';
30
+ readonly script: readonly BehaviorDescriptor[];
70
31
  }
71
-
72
- /**
73
- * Deterministic random source (mulberry32). The same seed always yields the
74
- * same sequence.
75
- */
76
- declare class SeededRandomSource extends RandomSource {
77
- private state;
78
- constructor(seed?: number);
79
- private nextUint32;
80
- bytes(length: number): Uint8Array;
81
- integer(minInclusive: number, maxExclusive: number): number;
32
+ type BehaviorDescriptor = ReturnsDescriptor | ThrowsDescriptor | OriginalDescriptor | CallsDescriptor;
33
+ interface WatchDescriptor {
34
+ readonly [DESCRIPTOR]: true;
35
+ readonly kind: 'watch';
36
+ readonly wrapper?: RawMethodWrapper;
82
37
  }
83
-
84
- interface FetchScriptEntry {
85
- /** Human-readable description used in failure diagnostics. */
86
- readonly describe: string;
87
- /** Typed predicate the incoming request must satisfy. */
88
- readonly matches: (request: FetchRequest) => boolean;
89
- /** Either respond or fail with a normalized FetchError. */
90
- readonly respond: (request: FetchRequest) => FetchResponse | FetchError;
38
+ interface ExpectationDescriptor {
39
+ readonly [DESCRIPTOR]: true;
40
+ readonly kind: 'expect';
41
+ /** Exact required call count; 0 for never(). */
42
+ readonly expected: number;
43
+ /** Behavior used for allowed calls; undefined = original effective behavior. */
44
+ readonly behavior?: BehaviorDescriptor;
45
+ }
46
+ /** Everything installable through .methods({...}). */
47
+ type MethodDescriptor = BehaviorDescriptor | WatchDescriptor | ExpectationDescriptor | RawMethodWrapper;
48
+ declare const test: {
49
+ /** Return the supplied value when the method is called. Auto-watches. */
50
+ returns(value: unknown): ReturnsDescriptor;
51
+ /** Throw/reject with the supplied error. Auto-watches. */
52
+ throws(error: unknown): ThrowsDescriptor;
53
+ /** Invoke the original effective method. Auto-watches. */
54
+ original(): OriginalDescriptor;
55
+ /**
56
+ * Per-invocation behavior script: call 1 uses entry 1, and so on. A call
57
+ * after exhaustion fails immediately. Unused entries do not fail verification.
58
+ */
59
+ calls(script: readonly BehaviorDescriptor[]): CallsDescriptor;
60
+ /**
61
+ * Keep original behavior and record calls. With a raw wrapper argument, the
62
+ * wrapper's behavior runs and is recorded.
63
+ */
64
+ watch(wrapper?: RawMethodWrapper): WatchDescriptor;
65
+ /** Require exactly one call; with no behavior, the original runs. */
66
+ once(behavior?: BehaviorDescriptor): ExpectationDescriptor;
67
+ /** Require exactly `count` calls; with no behavior, the original runs. */
68
+ times(count: number, behavior?: BehaviorDescriptor): ExpectationDescriptor;
69
+ /** Require zero calls; the first invocation fails and skips the original. */
70
+ never(): ExpectationDescriptor;
71
+ /** Read the recorded history for a watched method in one environment. */
72
+ inspect(environment: unknown, token: unknown, method: string): MethodInspection;
73
+ };
74
+ /** Symbol under which a built environment exposes its watch registry. */
75
+ declare const ENV_REGISTRY: unique symbol;
76
+ interface RecordedCall {
77
+ /** 1-based invocation index in this environment. */
78
+ readonly index: number;
79
+ readonly args: readonly unknown[];
80
+ /** Present once the call returned (resolved value for async methods). */
81
+ readonly result?: unknown;
82
+ /** Present once the call threw/rejected. */
83
+ readonly error?: unknown;
84
+ /** True while an async outcome is still pending. */
85
+ readonly pending: boolean;
86
+ readonly timestamp: number;
87
+ }
88
+ interface MethodInspection {
89
+ readonly count: number;
90
+ readonly calls: readonly RecordedCall[];
91
91
  }
92
+
92
93
  /**
93
- * Scripted FetchClient. Scripts are consumed strictly in order; an unexpected
94
- * or mismatched call fails immediately with a diagnostic.
94
+ * Environment-owned method behavior/observation runtime.
95
+ *
96
+ * All mutable state (histories, expectation counters, calls-script cursors)
97
+ * lives here, created fresh at every build(). Descriptors stay immutable.
95
98
  */
96
- declare class ScriptedFetchClient extends FetchClient {
97
- private readonly script;
98
- private cursor;
99
- readonly executed: FetchRequest[];
100
- constructor(script: readonly FetchScriptEntry[]);
101
- execute(request: FetchRequest): Promise<FetchResponse>;
102
- /** Teardown assertion: every scripted call must have been consumed. */
103
- assertScriptConsumed(): void;
104
- }
105
99
 
106
- /** Spawn handle with test-only deterministic delivery control. */
107
- interface ScriptedSpawnHandle extends ProcessHandle {
108
- /** Deliver all scripted events now (deterministic, test-controlled). */
109
- flush(): void;
100
+ interface MutableCall {
101
+ index: number;
102
+ args: readonly unknown[];
103
+ result?: unknown;
104
+ error?: unknown;
105
+ pending: boolean;
106
+ timestamp: number;
110
107
  }
111
- interface ProcessScriptEntry {
112
- readonly describe: string;
113
- readonly matches: (command: ProcessCommand) => boolean;
114
- /** Events emitted (for spawn) / folded into the result (for run). */
115
- readonly events: readonly ProcessEvent[];
108
+ declare class MethodState {
109
+ readonly tokenName: string;
110
+ readonly method: string;
111
+ readonly descriptor: Exclude<MethodDescriptor, RawMethodWrapper>;
112
+ readonly calls: MutableCall[];
113
+ /** Actual invocation count (includes the call currently executing). */
114
+ actual: number;
115
+ /** Cursor into a test.calls() script. */
116
+ scriptCursor: number;
117
+ constructor(tokenName: string, method: string, descriptor: Exclude<MethodDescriptor, RawMethodWrapper>);
118
+ get expectation(): ExpectationDescriptor | undefined;
119
+ inspection(): MethodInspection;
116
120
  }
117
- /**
118
- * Scripted ProcessRunner. Scripts are consumed in order; unexpected commands
119
- * fail immediately. Spawned handles emit their declared events when
120
- * flush() is called, keeping delivery under test control.
121
- */
122
- declare class ScriptedProcessRunner extends ProcessRunner {
123
- private readonly script;
124
- private cursor;
125
- private readonly openHandles;
126
- constructor(script: readonly ProcessScriptEntry[]);
127
- private consume;
128
- run(command: ProcessCommand): Promise<ProcessResult>;
129
- spawn(command: SpawnCommand): ScriptedSpawnHandle;
130
- /** Teardown assertion: no spawned process may remain open. */
131
- assertNoOpenHandles(): void;
121
+ /** One method-config entry: how it was keyed, and its per-method descriptors. */
122
+ interface MethodConfigEntry {
123
+ /** Exact token (class/symbol/string) or a name string matched lazily. */
124
+ readonly key: unknown;
125
+ readonly byName: boolean;
126
+ readonly methods: ReadonlyMap<string, MethodDescriptor>;
127
+ }
128
+ declare class WatchRegistry {
129
+ /** entry-identity → method → state. Entries share states across instances. */
130
+ private readonly states;
131
+ private readonly nameIndex;
132
+ private readonly entries;
133
+ /** Class-token entries that identity-matched at least one construction. */
134
+ private readonly matchedEntryKeys;
135
+ /** Constructed class tokens that matched NO entry, by display name. */
136
+ private readonly unmatchedConstructedByName;
137
+ addEntry(entry: MethodConfigEntry): void;
138
+ private entryLabel;
139
+ /** Entries applying to a resolving token (exact identity or name match). */
140
+ matchEntries(token: unknown): MethodConfigEntry[];
141
+ state(entryKey: unknown, method: string): MethodState | undefined;
142
+ inspect(token: unknown, method: string): MethodInspection;
143
+ /**
144
+ * Class-token entries that never identity-matched a construction while a
145
+ * DIFFERENT class with the same display name did construct. This is the
146
+ * split-module-registry signature (a test-file class object vs the graph's
147
+ * own load of the same file) — or two genuinely distinct same-named tokens
148
+ * where the configured one never resolved. Either way the configured
149
+ * behavior silently did not apply, which must be loud.
150
+ */
151
+ private identitySplits;
152
+ /** Repeatable snapshot check of all exact expectations. */
153
+ verify(): void;
132
154
  }
133
155
 
134
156
  /**
135
- * Deterministic in-memory KeyValueStore with clock-driven TTL semantics.
136
- * Passes the same contract as KV/Redis adapters.
157
+ * `testIoc` the canonical shared real-IoC test composition builder.
158
+ *
159
+ * Persistent immutable: every fluent call returns a new derived builder
160
+ * sharing the ordered write log structurally. Non-conflicting writes are
161
+ * order-insensitive; the last write to the same effective identity wins on
162
+ * that derived branch. `.build()` is non-consuming and creates fresh runtime,
163
+ * watch, and expectation state (spec 15, PBR-01..15).
137
164
  */
138
- declare class MemoryKeyValueStore extends KeyValueStore {
139
- private readonly clock;
140
- private readonly entries;
141
- constructor(clock: Clock);
142
- get<T>(key: Key, codec: Codec<T>): Promise<T | null>;
143
- put<T>(key: Key, value: T, codec: Codec<T>, options?: PutOptions): Promise<void>;
144
- delete(key: Key): Promise<void>;
145
- }
146
165
 
166
+ type Token = unknown;
167
+ type ClassLike = new (...args: any[]) => any;
168
+ /** Config maps accept plain objects (string keys) or Maps (exact tokens). */
147
169
  /**
148
- * Deterministic in-memory ObjectStore with monotonically increasing versions.
149
- * Passes the same contract as R2/S3 adapters.
170
+ * Composition input (spec 04 §2). The CANONICAL entry form is an array of
171
+ * tuples token-first, exact identity:
172
+ *
173
+ * .classes([[ProjectRepository, MemoryProjectRepository]])
174
+ *
175
+ * A `ReadonlyMap<Token, V>` is equivalent (token-keyed). A name-keyed
176
+ * `Record<string, V>` remains accepted as COMPATIBILITY input: string keys
177
+ * resolve against known token display names, fail on unknown names, and
178
+ * fail on ambiguous names (two tokens sharing one display name never
179
+ * collapse into one entry — tokens are identities, names are labels).
150
180
  */
151
- declare class MemoryObjectStore extends ObjectStore {
152
- private readonly objects;
153
- private nextVersion;
154
- read(key: ObjectKey): Promise<StoredObject | null>;
155
- write(key: ObjectKey, object: StoredObjectInput): Promise<ObjectVersion>;
156
- delete(key: ObjectKey): Promise<void>;
181
+ type ConfigMap<V> = ReadonlyArray<readonly [Token, V]> | ReadonlyMap<Token, V> | Record<string, V>;
182
+ type MethodsConfig = ConfigMap<Record<string, MethodDescriptor> | ReadonlyMap<string, MethodDescriptor>>;
183
+ type UseInput = ApplicationModule | TestIocBuilder;
184
+ type Write = {
185
+ op: 'use';
186
+ module: ApplicationModule;
187
+ } | {
188
+ op: 'classes';
189
+ key: Token;
190
+ byName: boolean;
191
+ implementation: ClassLike;
192
+ } | {
193
+ op: 'functions';
194
+ key: Token;
195
+ byName: boolean;
196
+ factory: (...args: any[]) => any;
197
+ } | {
198
+ op: 'values';
199
+ key: Token;
200
+ byName: boolean;
201
+ value: unknown;
202
+ } | {
203
+ op: 'methods';
204
+ key: Token;
205
+ byName: boolean;
206
+ methods: ReadonlyMap<string, MethodDescriptor>;
207
+ };
208
+ interface TestEnvironment {
209
+ readonly root: IContainer;
210
+ get<T>(token: unknown, params?: any[]): Promise<T> | T;
211
+ instance<T>(cls: new (...args: any[]) => T, params?: any[]): Promise<T> | T;
212
+ extend(): IContainer;
213
+ verify(): Promise<void>;
214
+ dispose(): Promise<void>;
215
+ readonly [ENV_REGISTRY]: WatchRegistry;
157
216
  }
217
+ declare class TestIocBuilder {
218
+ private readonly log;
219
+ private constructor();
220
+ /** @internal */
221
+ static create(inputs: readonly UseInput[]): TestIocBuilder;
222
+ /** @internal — read by .use(builderPreset) */
223
+ get writes(): readonly Write[];
224
+ private derive;
225
+ private useAll;
226
+ /** Apply a reusable composition preset: an ApplicationModule or a builder. */
227
+ use(preset: UseInput): TestIocBuilder;
228
+ /** Replace the implementation for IoC class tokens in the built environment. */
229
+ classes(config: ConfigMap<ClassLike>): TestIocBuilder;
230
+ /** Replace IoC factory/provider registrations. */
231
+ functions(config: ConfigMap<(...args: any[]) => any>): TestIocBuilder;
232
+ /** Provide/replace IoC value registrations. */
233
+ values(config: ConfigMap<unknown>): TestIocBuilder;
234
+ /** Install method behavior/observation descriptors on IoC-managed instances. */
235
+ methods(config: MethodsConfig): TestIocBuilder;
236
+ /** Materialize a fresh, isolated real-IoC environment. Non-consuming. */
237
+ build(): Promise<TestEnvironment>;
238
+ /**
239
+ * Register a class binding. When token === implementation this is a plain
240
+ * class registration. Otherwise an alias factory resolves the implementation
241
+ * through real IoC, mirroring the implementation's effective lifetime so
242
+ * lifetime validation (captive-lifetime checks) stays honest.
243
+ */
244
+ private registerClassBinding;
245
+ }
246
+ /** Create a persistent immutable real-IoC test composition builder. */
247
+ declare function testIoc(...inputs: UseInput[]): TestIocBuilder;
158
248
 
159
- type DeliveryMode = "immediate" | "queued";
160
249
  /**
161
- * Recording EventBus. Records exact publication order. Delivery modes:
162
- * - immediate (default): handlers run during publish;
163
- * - queued: events buffer until deliverQueued() is called.
164
- * Active subscriptions at teardown fail assertNoActiveSubscriptions().
250
+ * Diagnostics are first-class: every error names the real token/method and
251
+ * what was expected vs what happened, never only internal wrapper machinery.
165
252
  */
166
- declare class RecordingEventBus<TEvent extends DomainEvent> extends EventBus<TEvent> {
167
- private readonly mode;
168
- readonly published: TEvent[];
169
- private readonly handlers;
170
- private readonly queue;
171
- constructor(mode?: DeliveryMode);
172
- publish(event: TEvent): Promise<void>;
173
- subscribe(handler: EventHandler<TEvent>): Subscription;
174
- /** Deliver buffered events (queued mode) in publication order. */
175
- deliverQueued(): Promise<void>;
176
- get activeSubscriptionCount(): number;
177
- assertNoActiveSubscriptions(): void;
178
- private deliver;
253
+ declare class TestingError extends Error {
254
+ constructor(message: string);
179
255
  }
180
-
181
- /** In-memory LogSink recording envelopes in emission order. */
182
- declare class RecordingLogSink extends LogSink {
183
- readonly envelopes: LogEnvelope[];
184
- emit(envelope: LogEnvelope): void;
256
+ /** Thrown at build() when the installed @noego/ioc lacks the decoration seam. */
257
+ declare class MissingIocSeamError extends TestingError {
258
+ constructor();
185
259
  }
186
- /** In-memory TraceSink recording envelopes in emission order. */
187
- declare class RecordingTraceSink extends TraceSink {
188
- readonly envelopes: TraceEnvelope[];
189
- emit(envelope: TraceEnvelope): void;
260
+ /** test.inspect() on a method that is not watched in this environment. */
261
+ declare class UnwatchedInspectionError extends TestingError {
262
+ constructor(token: string, method: string);
190
263
  }
191
- /** In-memory TelemetrySink recording envelopes in emission order. */
192
- declare class RecordingTelemetrySink extends TelemetrySink {
193
- readonly envelopes: TelemetryEnvelope[];
194
- emit(envelope: TelemetryEnvelope): void;
264
+ /** A call arrived after a test.calls([...]) script was fully consumed. */
265
+ declare class CallScriptExhaustedError extends TestingError {
266
+ constructor(token: string, method: string, scriptLength: number, callIndex: number);
195
267
  }
196
- /** LogSink that drops everything (for suites that assert nothing about logs). */
197
- declare class NoopLogSink extends LogSink {
198
- emit(_envelope: LogEnvelope): void;
268
+ /** An exact expectation (once/times/never) was exceeded at call time. */
269
+ declare class ExpectationOverflowError extends TestingError {
270
+ constructor(token: string, method: string, expected: number, attempted: number);
199
271
  }
200
-
201
- /**
202
- * Behavioral contract every Clock implementation must satisfy.
203
- * Runs inside the caller's jest context.
204
- */
205
- declare function runClockContract(name: string, setup: () => {
206
- clock: Clock;
207
- }): void;
208
-
209
- interface KeyValueStoreContractContext {
210
- store: KeyValueStore;
211
- /** Move the store's time source forward (real adapters may wait/mock). */
212
- advanceBy: (duration: Duration) => Promise<void>;
213
- /** Whether the implementation supports TTL expiry. */
214
- supportsTtl: boolean;
272
+ /** Aggregated under-count failures reported by env.verify(). */
273
+ declare class VerificationError extends TestingError {
274
+ constructor(failures: readonly {
275
+ token: string;
276
+ method: string;
277
+ expected: number;
278
+ actual: number;
279
+ }[]);
215
280
  }
216
- /**
217
- * Behavioral contract every KeyValueStore implementation must satisfy —
218
- * memory, KV, and Redis adapters alike.
219
- */
220
- declare function runKeyValueStoreContract(name: string, setup: () => KeyValueStoreContractContext): void;
221
-
222
- /**
223
- * Behavioral contract every ObjectStore implementation must satisfy —
224
- * memory, R2, S3, and filesystem adapters alike.
225
- */
226
- declare function runObjectStoreContract(name: string, setup: () => {
227
- store: ObjectStore;
228
- }): void;
229
-
230
- interface TestEvent extends DomainEvent {
231
- readonly type: "test-event";
232
- readonly value: number;
281
+ /** .methods configured for a token whose resolved value has no such callable method. */
282
+ declare class MethodNotCallableError extends TestingError {
283
+ constructor(token: string, method: string);
284
+ }
285
+ /** .methods configured for a token that resolved to a non-object value. */
286
+ declare class NonObjectMethodTargetError extends TestingError {
287
+ constructor(token: string);
233
288
  }
234
- declare const testEvent: (value: number) => TestEvent;
235
- interface EventBusContractContext {
236
- bus: EventBus<TestEvent>;
237
- /** Force delivery of any buffered events (no-op for immediate buses). */
238
- deliver: () => Promise<void>;
289
+ /** A string configuration key could not be resolved to a known IoC token. */
290
+ declare class UnknownTokenKeyError extends TestingError {
291
+ constructor(key: string, space: string, known: readonly string[]);
292
+ }
293
+ /** Invalid descriptor construction (e.g. test.times(-1)). */
294
+ declare class InvalidDescriptorError extends TestingError {
239
295
  }
240
296
  /**
241
- * Behavioral contract every EventBus implementation must satisfy.
297
+ * A name-keyed compatibility entry referred to a display name claimed by
298
+ * two or more distinct tokens. Tokens are identities; names are labels —
299
+ * pass the exact token in canonical tuple form instead (spec 04 §5).
242
300
  */
243
- declare function runEventBusContract(name: string, setup: () => EventBusContractContext): void;
244
-
245
- interface LeakCheck {
246
- /** Which resource family this check guards (timers, subscriptions, …). */
247
- readonly name: string;
248
- /** Returns a description per leaked resource; empty means clean. */
249
- readonly check: () => readonly string[];
301
+ declare class AmbiguousNameKeyError extends TestingError {
302
+ constructor(name: string, space: string);
250
303
  }
251
304
  /**
252
- * Aggregates leak checks and fails teardown with one clear report listing
253
- * every leaked resource across all registered checks.
305
+ * A .methods() class token never matched any constructed instance while a
306
+ * DIFFERENT class with the same display name did construct — the configured
307
+ * behavior silently did not apply. Usual cause: two module registries loaded
308
+ * the same source file (e.g. a vitest test file's import vs a framework
309
+ * harness's native import of the production graph); fix by routing the
310
+ * harness's imports through the caller's registry (testApp:
311
+ * `.importer((p) => import(p))`) or by passing the token the graph actually
312
+ * uses.
254
313
  */
255
- declare class LeakDetector {
256
- private readonly checks;
257
- register(check: LeakCheck): void;
258
- findLeaks(): string[];
259
- assertNoLeaks(): void;
314
+ declare class TokenIdentitySplitError extends TestingError {
315
+ constructor(names: readonly string[]);
260
316
  }
261
317
 
262
- export { type DeliveryMode, type EventBusContractContext, type FetchScriptEntry, type KeyValueStoreContractContext, type LeakCheck, LeakDetector, ManualClock, ManualScheduler, MemoryKeyValueStore, MemoryObjectStore, NoopLogSink, type PendingTask, type ProcessScriptEntry, RecordingEventBus, RecordingLogSink, RecordingTelemetrySink, RecordingTraceSink, ScriptedFetchClient, ScriptedProcessRunner, type ScriptedSpawnHandle, SeededRandomSource, SequenceIdGenerator, type TestEvent, runClockContract, runEventBusContract, runKeyValueStoreContract, runObjectStoreContract, testEvent };
318
+ export { AmbiguousNameKeyError, type BehaviorDescriptor, CallScriptExhaustedError, type CallsDescriptor, type ConfigMap, ENV_REGISTRY, type ExpectationDescriptor, ExpectationOverflowError, InvalidDescriptorError, type MethodDescriptor, type MethodInspection, MethodNotCallableError, type MethodsConfig, MissingIocSeamError, NonObjectMethodTargetError, type OriginalDescriptor, type RawMethodWrapper, type RecordedCall, type ReturnsDescriptor, type TestEnvironment, TestIocBuilder, TestingError, type ThrowsDescriptor, TokenIdentitySplitError, UnknownTokenKeyError, UnwatchedInspectionError, type UseInput, VerificationError, type WatchDescriptor, test, testIoc };