@noego/testing 0.2.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.cjs CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ AmbiguousNameKeyError: () => AmbiguousNameKeyError,
23
24
  CallScriptExhaustedError: () => CallScriptExhaustedError,
24
25
  ENV_REGISTRY: () => ENV_REGISTRY,
25
26
  ExpectationOverflowError: () => ExpectationOverflowError,
@@ -29,6 +30,7 @@ __export(index_exports, {
29
30
  NonObjectMethodTargetError: () => NonObjectMethodTargetError,
30
31
  TestIocBuilder: () => TestIocBuilder,
31
32
  TestingError: () => TestingError,
33
+ TokenIdentitySplitError: () => TokenIdentitySplitError,
32
34
  UnknownTokenKeyError: () => UnknownTokenKeyError,
33
35
  UnwatchedInspectionError: () => UnwatchedInspectionError,
34
36
  VerificationError: () => VerificationError,
@@ -107,6 +109,22 @@ var UnknownTokenKeyError = class extends TestingError {
107
109
  };
108
110
  var InvalidDescriptorError = class extends TestingError {
109
111
  };
112
+ var AmbiguousNameKeyError = class extends TestingError {
113
+ constructor(name, space) {
114
+ super(
115
+ `.${space}() key "${name}" is ambiguous: multiple distinct tokens share that display name. Use the canonical tuple form with the exact token: .${space}([[TheToken, ...]]).`
116
+ );
117
+ this.name = "AmbiguousNameKeyError";
118
+ }
119
+ };
120
+ var TokenIdentitySplitError = class extends TestingError {
121
+ constructor(names) {
122
+ super(
123
+ `token identity split: .methods() entr${names.length === 1 ? "y" : "ies"} for ${names.map((name) => `"${name}"`).join(", ")} never matched a constructed instance, but a DIFFERENT class with the same name was constructed. Two module registries have loaded the same class file (test-file import vs harness graph import) \u2014 the configured behavior did not apply. Route the harness's imports through your registry (e.g. testApp .importer((p) => import(p))) or pass the exact token the graph uses.`
124
+ );
125
+ this.name = "TokenIdentitySplitError";
126
+ }
127
+ };
110
128
 
111
129
  // src/descriptors.ts
112
130
  var DESCRIPTOR = /* @__PURE__ */ Symbol.for("noego:testing:descriptor");
@@ -227,6 +245,10 @@ var WatchRegistry = class {
227
245
  states = /* @__PURE__ */ new Map();
228
246
  nameIndex = /* @__PURE__ */ new Map();
229
247
  entries = [];
248
+ /** Class-token entries that identity-matched at least one construction. */
249
+ matchedEntryKeys = /* @__PURE__ */ new Set();
250
+ /** Constructed class tokens that matched NO entry, by display name. */
251
+ unmatchedConstructedByName = /* @__PURE__ */ new Map();
230
252
  addEntry(entry) {
231
253
  this.entries.push(entry);
232
254
  const byMethod = /* @__PURE__ */ new Map();
@@ -246,9 +268,15 @@ var WatchRegistry = class {
246
268
  /** Entries applying to a resolving token (exact identity or name match). */
247
269
  matchEntries(token) {
248
270
  const name = typeof token === "function" ? token.name : typeof token === "string" ? token : void 0;
249
- return this.entries.filter(
271
+ const matched = this.entries.filter(
250
272
  (entry) => entry.key === token || entry.byName && name !== void 0 && entry.key === name
251
273
  );
274
+ if (matched.length) {
275
+ for (const entry of matched) this.matchedEntryKeys.add(entry.key);
276
+ } else if (typeof token === "function" && name) {
277
+ this.unmatchedConstructedByName.set(name, token);
278
+ }
279
+ return matched;
252
280
  }
253
281
  state(entryKey, method) {
254
282
  return this.states.get(entryKey)?.get(method);
@@ -264,8 +292,34 @@ var WatchRegistry = class {
264
292
  }
265
293
  throw new UnwatchedInspectionError(label, method);
266
294
  }
295
+ /**
296
+ * Class-token entries that never identity-matched a construction while a
297
+ * DIFFERENT class with the same display name did construct. This is the
298
+ * split-module-registry signature (a test-file class object vs the graph's
299
+ * own load of the same file) — or two genuinely distinct same-named tokens
300
+ * where the configured one never resolved. Either way the configured
301
+ * behavior silently did not apply, which must be loud.
302
+ */
303
+ identitySplits() {
304
+ const splits = [];
305
+ for (const entry of this.entries) {
306
+ if (entry.byName || typeof entry.key !== "function") continue;
307
+ if (this.matchedEntryKeys.has(entry.key)) continue;
308
+ const name = entry.key.name;
309
+ if (!name) continue;
310
+ const constructed = this.unmatchedConstructedByName.get(name);
311
+ if (constructed !== void 0 && constructed !== entry.key) {
312
+ splits.push({ name, entryToken: entry.key });
313
+ }
314
+ }
315
+ return splits;
316
+ }
267
317
  /** Repeatable snapshot check of all exact expectations. */
268
318
  verify() {
319
+ const splits = this.identitySplits();
320
+ if (splits.length) {
321
+ throw new TokenIdentitySplitError(splits.map((split) => split.name));
322
+ }
269
323
  const failures = [];
270
324
  for (const byMethod of this.states.values()) {
271
325
  for (const state of byMethod.values()) {
@@ -414,7 +468,16 @@ function buildMethodWrapper(target, method, descriptor, state) {
414
468
  // src/builder.ts
415
469
  var COMPONENT_OPTIONS_KEY = /* @__PURE__ */ Symbol.for("ioc:component:options");
416
470
  function* configEntries(config) {
417
- if (config instanceof Map) {
471
+ if (Array.isArray(config)) {
472
+ for (const entry of config) {
473
+ if (!Array.isArray(entry) || entry.length !== 2) {
474
+ throw new InvalidDescriptorError(
475
+ "canonical composition entries are [token, value] tuples, e.g. .classes([[Token, Impl]])"
476
+ );
477
+ }
478
+ yield [entry[0], false, entry[1]];
479
+ }
480
+ } else if (config instanceof Map) {
418
481
  for (const [key, value] of config) yield [key, false, value];
419
482
  } else {
420
483
  for (const key of [...Object.getOwnPropertyNames(config), ...Object.getOwnPropertySymbols(config)]) {
@@ -517,16 +580,24 @@ var TestIocBuilder = class _TestIocBuilder {
517
580
  throw new MissingIocSeamError();
518
581
  }
519
582
  const knownByName = /* @__PURE__ */ new Map();
583
+ const ambiguousNames = /* @__PURE__ */ new Set();
520
584
  const knownLifetimes = /* @__PURE__ */ new Map();
521
585
  const note = (token, loadAs) => {
522
- if (typeof token === "function" && token.name) knownByName.set(token.name, token);
523
- else if (typeof token === "string") knownByName.set(token, token);
586
+ const name = typeof token === "function" && token.name ? token.name : typeof token === "string" ? token : null;
587
+ if (name !== null) {
588
+ const existing = knownByName.get(name);
589
+ if (existing !== void 0 && existing !== token) ambiguousNames.add(name);
590
+ knownByName.set(name, token);
591
+ }
524
592
  if (loadAs !== void 0) knownLifetimes.set(token, loadAs);
525
593
  };
526
594
  const effective = /* @__PURE__ */ new Map();
527
595
  const methodWrites = [];
528
596
  const resolveKey = (key, byName, space) => {
529
597
  if (!byName) return key;
598
+ if (ambiguousNames.has(key)) {
599
+ throw new AmbiguousNameKeyError(key, space);
600
+ }
530
601
  const known = knownByName.get(key);
531
602
  if (known !== void 0) return known;
532
603
  if (space === "values" || space === "functions") return key;
@@ -571,8 +642,13 @@ var TestIocBuilder = class _TestIocBuilder {
571
642
  space: "class",
572
643
  token,
573
644
  implementation: write.implementation,
574
- // preserve configured lifetime unless the replacement declares its own scope
575
- loadAs: componentScope(write.implementation) ?? knownLifetimes.get(token)
645
+ // Lifetime priority: the replacement's own @Component scope, then
646
+ // the lifetime the composition already knows for the token, then
647
+ // the TOKEN class's declared @Component scope — a plain stub
648
+ // class replacing a Singleton-scoped production service must not
649
+ // silently degrade to Transient (captive-lifetime validation
650
+ // would reject the production dependents).
651
+ loadAs: componentScope(write.implementation) ?? knownLifetimes.get(token) ?? componentScope(token)
576
652
  });
577
653
  break;
578
654
  }
@@ -597,6 +673,9 @@ var TestIocBuilder = class _TestIocBuilder {
597
673
  break;
598
674
  }
599
675
  case "methods": {
676
+ if (write.byName && ambiguousNames.has(write.key)) {
677
+ throw new AmbiguousNameKeyError(write.key, "methods");
678
+ }
600
679
  const token = write.byName && knownByName.has(write.key) ? knownByName.get(write.key) : write.key;
601
680
  methodWrites.push({
602
681
  key: token,
@@ -672,6 +751,7 @@ function testIoc(...inputs) {
672
751
  }
673
752
  // Annotate the CommonJS export names for ESM import in node:
674
753
  0 && (module.exports = {
754
+ AmbiguousNameKeyError,
675
755
  CallScriptExhaustedError,
676
756
  ENV_REGISTRY,
677
757
  ExpectationOverflowError,
@@ -681,6 +761,7 @@ function testIoc(...inputs) {
681
761
  NonObjectMethodTargetError,
682
762
  TestIocBuilder,
683
763
  TestingError,
764
+ TokenIdentitySplitError,
684
765
  UnknownTokenKeyError,
685
766
  UnwatchedInspectionError,
686
767
  VerificationError,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/builder.ts","../src/errors.ts","../src/descriptors.ts","../src/method_state.ts"],"sourcesContent":["/**\n * @noego/testing — the canonical shared owner of real-IoC test composition\n * (`testIoc`) and the lowercase `test.*` method behavior/watch/expectation\n * language, built on @noego/ioc's production seams.\n *\n * The former generic runtime-mirror doubles (ManualClock, ScriptedFetchClient,\n * memory stores, recording sinks, contract suites, LeakDetector, …) are\n * retired; pin 0.1.x if you still need them, and see the NoEgo runtime/testing\n * deprecation plan for per-export dispositions.\n */\n\nexport { testIoc, TestIocBuilder } from './builder';\nexport type { TestEnvironment, ConfigMap, MethodsConfig, UseInput } from './builder';\n\nexport { test, ENV_REGISTRY } from './descriptors';\nexport type {\n BehaviorDescriptor,\n CallsDescriptor,\n ExpectationDescriptor,\n MethodDescriptor,\n MethodInspection,\n OriginalDescriptor,\n RawMethodWrapper,\n RecordedCall,\n ReturnsDescriptor,\n ThrowsDescriptor,\n WatchDescriptor,\n} from './descriptors';\n\nexport {\n TestingError,\n MissingIocSeamError,\n UnwatchedInspectionError,\n CallScriptExhaustedError,\n ExpectationOverflowError,\n VerificationError,\n MethodNotCallableError,\n NonObjectMethodTargetError,\n UnknownTokenKeyError,\n InvalidDescriptorError,\n} from './errors';\n","/**\n * `testIoc` — the canonical shared real-IoC test composition builder.\n *\n * Persistent immutable: every fluent call returns a new derived builder\n * sharing the ordered write log structurally. Non-conflicting writes are\n * order-insensitive; the last write to the same effective identity wins on\n * that derived branch. `.build()` is non-consuming and creates fresh runtime,\n * watch, and expectation state (spec 15, PBR-01..15).\n */\n\nimport {\n createContainer,\n flattenModule,\n LoadAs,\n SCOPED_CONTAINER,\n type ApplicationModule,\n type IContainer,\n} from '@noego/ioc';\n\nimport { ENV_REGISTRY, isDescriptor, type MethodDescriptor } from './descriptors';\nimport { createMethodDecorator, WatchRegistry, tokenLabel } from './method_state';\nimport { InvalidDescriptorError, MissingIocSeamError, UnknownTokenKeyError } from './errors';\n\nconst COMPONENT_OPTIONS_KEY = Symbol.for('ioc:component:options');\n\ntype Token = unknown;\ntype ClassLike = new (...args: any[]) => any;\n\n/** Config maps accept plain objects (string keys) or Maps (exact tokens). */\nexport type ConfigMap<V> = Record<string, V> | ReadonlyMap<Token, V>;\n\nexport type MethodsConfig = ConfigMap<Record<string, MethodDescriptor> | ReadonlyMap<string, MethodDescriptor>>;\n\nexport type UseInput = ApplicationModule | TestIocBuilder;\n\ntype Write =\n | { op: 'use'; module: ApplicationModule }\n | { op: 'classes'; key: Token; byName: boolean; implementation: ClassLike }\n | { op: 'functions'; key: Token; byName: boolean; factory: (...args: any[]) => any }\n | { op: 'values'; key: Token; byName: boolean; value: unknown }\n | { op: 'methods'; key: Token; byName: boolean; methods: ReadonlyMap<string, MethodDescriptor> };\n\nexport interface TestEnvironment {\n readonly root: IContainer;\n get<T>(token: unknown, params?: any[]): Promise<T> | T;\n instance<T>(cls: new (...args: any[]) => T, params?: any[]): Promise<T> | T;\n extend(): IContainer;\n verify(): Promise<void>;\n dispose(): Promise<void>;\n readonly [ENV_REGISTRY]: WatchRegistry;\n}\n\nfunction* configEntries<V>(config: ConfigMap<V>): Iterable<[Token, boolean, V]> {\n if (config instanceof Map) {\n for (const [key, value] of config) yield [key, false, value];\n } else {\n for (const key of [...Object.getOwnPropertyNames(config), ...Object.getOwnPropertySymbols(config)]) {\n yield [key, typeof key === 'string', (config as any)[key]];\n }\n }\n}\n\nfunction componentScope(cls: any): LoadAs | undefined {\n const options =\n typeof Reflect !== 'undefined' && (Reflect as any).getMetadata\n ? (Reflect as any).getMetadata(COMPONENT_OPTIONS_KEY, cls)\n : undefined;\n return options?.scope;\n}\n\nfunction lifetimeToLoadAs(lifetime: string): LoadAs {\n if (lifetime === 'singleton') return LoadAs.Singleton;\n if (lifetime === 'scoped') return LoadAs.Scoped;\n return LoadAs.Transient;\n}\n\nexport class TestIocBuilder {\n private constructor(private readonly log: readonly Write[]) {\n Object.freeze(this);\n }\n\n /** @internal */\n static create(inputs: readonly UseInput[]): TestIocBuilder {\n return new TestIocBuilder([]).useAll(inputs);\n }\n\n /** @internal — read by .use(builderPreset) */\n get writes(): readonly Write[] {\n return this.log;\n }\n\n private derive(writes: Write[]): TestIocBuilder {\n return new TestIocBuilder([...this.log, ...writes]);\n }\n\n private useAll(inputs: readonly UseInput[]): TestIocBuilder {\n let builder: TestIocBuilder = this;\n for (const input of inputs) builder = builder.use(input);\n return builder;\n }\n\n /** Apply a reusable composition preset: an ApplicationModule or a builder. */\n use(preset: UseInput): TestIocBuilder {\n if (preset instanceof TestIocBuilder) {\n return this.derive([...preset.writes]);\n }\n return this.derive([{ op: 'use', module: preset }]);\n }\n\n /** Replace the implementation for IoC class tokens in the built environment. */\n classes(config: ConfigMap<ClassLike>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, implementation] of configEntries(config)) {\n if (typeof implementation !== 'function' || !implementation.prototype) {\n throw new InvalidDescriptorError(\n `.classes() value for \"${tokenLabel(key)}\" must be a class constructor.`,\n );\n }\n writes.push({ op: 'classes', key, byName, implementation });\n }\n return this.derive(writes);\n }\n\n /** Replace IoC factory/provider registrations. */\n functions(config: ConfigMap<(...args: any[]) => any>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, factory] of configEntries(config)) {\n if (typeof factory !== 'function') {\n throw new InvalidDescriptorError(`.functions() value for \"${tokenLabel(key)}\" must be a function.`);\n }\n writes.push({ op: 'functions', key, byName, factory });\n }\n return this.derive(writes);\n }\n\n /** Provide/replace IoC value registrations. */\n values(config: ConfigMap<unknown>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, value] of configEntries(config)) {\n writes.push({ op: 'values', key, byName, value });\n }\n return this.derive(writes);\n }\n\n /** Install method behavior/observation descriptors on IoC-managed instances. */\n methods(config: MethodsConfig): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, methodsInput] of configEntries(config)) {\n const methods = new Map<string, MethodDescriptor>();\n const entries =\n methodsInput instanceof Map\n ? methodsInput.entries()\n : Object.entries(methodsInput as Record<string, MethodDescriptor>);\n for (const [name, descriptor] of entries) {\n if (typeof descriptor !== 'function' && !isDescriptor(descriptor)) {\n throw new InvalidDescriptorError(\n `.methods() entry ${tokenLabel(key)}.${name} must be a test.* descriptor or a raw wrapper function.`,\n );\n }\n methods.set(name, descriptor);\n }\n writes.push({ op: 'methods', key, byName, methods });\n }\n return this.derive(writes);\n }\n\n /** Materialize a fresh, isolated real-IoC environment. Non-consuming. */\n async build(): Promise<TestEnvironment> {\n const root = createContainer();\n if (typeof (root as any).setInstanceDecorator !== 'function') {\n throw new MissingIocSeamError();\n }\n\n // ---- Materialize the ordered log: last write wins per effective identity\n // Known tokens (for resolving string keys of classes/functions/values)\n const knownByName = new Map<string, Token>();\n const knownLifetimes = new Map<Token, LoadAs>();\n const note = (token: Token, loadAs: LoadAs | undefined) => {\n if (typeof token === 'function' && (token as any).name) knownByName.set((token as any).name, token);\n else if (typeof token === 'string') knownByName.set(token, token);\n if (loadAs !== undefined) knownLifetimes.set(token, loadAs);\n };\n\n type Effective =\n | { space: 'class'; token: Token; implementation: ClassLike; loadAs?: LoadAs }\n | { space: 'factory'; token: Token; factory: (...args: any[]) => any; loadAs?: LoadAs; deps?: Token[] }\n | { space: 'value'; token: Token; value: unknown };\n\n // ordered map: identity → latest effective write (Map preserves first-write\n // position which is fine — later writes replace content, LWW)\n const effective = new Map<Token, Effective>();\n const methodWrites: { key: Token; byName: boolean; methods: Map<string, MethodDescriptor> }[] = [];\n\n const resolveKey = (key: Token, byName: boolean, space: string): Token => {\n if (!byName) return key;\n const known = knownByName.get(key as string);\n if (known !== undefined) return known;\n if (space === 'values' || space === 'functions') return key; // string tokens are first-class\n throw new UnknownTokenKeyError(key as string, space, [...knownByName.keys()]);\n };\n\n for (const write of this.log) {\n switch (write.op) {\n case 'use': {\n for (const reg of flattenModule(write.module)) {\n const loadAs = lifetimeToLoadAs(reg.lifetime);\n note(reg.token, loadAs);\n if (reg.kind === 'class') {\n note(reg.implementation as Token, loadAs);\n effective.set(reg.token, {\n space: 'class',\n token: reg.token,\n implementation: reg.implementation as ClassLike,\n loadAs,\n });\n knownLifetimes.set(reg.token, loadAs);\n knownLifetimes.set(reg.implementation as Token, loadAs);\n } else if (reg.kind === 'factory') {\n effective.set(reg.token, {\n space: 'factory',\n token: reg.token,\n factory: reg.implementation as (...args: any[]) => any,\n loadAs,\n deps: [...reg.dependencies],\n });\n } else {\n effective.set(reg.token, { space: 'value', token: reg.token, value: reg.implementation });\n knownLifetimes.set(reg.token, LoadAs.Singleton);\n }\n }\n break;\n }\n case 'classes': {\n const token = resolveKey(write.key, write.byName, 'classes');\n note(write.implementation, undefined);\n if (!write.byName) note(token, undefined);\n effective.set(token, {\n space: 'class',\n token,\n implementation: write.implementation,\n // preserve configured lifetime unless the replacement declares its own scope\n loadAs: componentScope(write.implementation) ?? knownLifetimes.get(token),\n });\n break;\n }\n case 'functions': {\n const token = resolveKey(write.key, write.byName, 'functions');\n const prior = effective.get(token);\n effective.set(token, {\n space: 'factory',\n token,\n factory: write.factory,\n // preserve configured lifetime unless the scenario overrides it\n loadAs: prior && prior.space === 'factory' ? prior.loadAs : knownLifetimes.get(token),\n deps: prior && prior.space === 'factory' ? prior.deps : undefined,\n });\n note(token, undefined);\n break;\n }\n case 'values': {\n const token = resolveKey(write.key, write.byName, 'values');\n effective.set(token, { space: 'value', token, value: write.value });\n note(token, LoadAs.Singleton);\n break;\n }\n case 'methods': {\n const token = write.byName && knownByName.has(write.key as string)\n ? knownByName.get(write.key as string)!\n : write.key;\n methodWrites.push({\n key: token,\n byName: write.byName && !knownByName.has(write.key as string),\n methods: new Map(write.methods),\n });\n break;\n }\n }\n }\n\n // ---- Apply effective registrations to the fresh root\n for (const entry of effective.values()) {\n if (entry.space === 'class') {\n this.registerClassBinding(root, entry.token, entry.implementation, entry.loadAs);\n } else if (entry.space === 'factory') {\n root.registerFunction(entry.token, entry.factory, {\n loadAs: entry.loadAs,\n param: entry.deps,\n } as any);\n } else {\n const value = entry.value;\n root.registerFunction(entry.token, () => value, { loadAs: LoadAs.Singleton } as any);\n }\n }\n\n // ---- Fresh watch/expectation state + the ioc decoration seam\n const registry = new WatchRegistry();\n // merge method writes: LWW per (entry key, method), deep-merge per token\n const mergedMethods = new Map<Token, { byName: boolean; methods: Map<string, MethodDescriptor> }>();\n for (const write of methodWrites) {\n const existing = mergedMethods.get(write.key);\n if (existing) {\n for (const [name, descriptor] of write.methods) existing.methods.set(name, descriptor);\n } else {\n mergedMethods.set(write.key, { byName: write.byName, methods: new Map(write.methods) });\n }\n }\n for (const [key, { byName, methods }] of mergedMethods) {\n registry.addEntry({ key, byName, methods });\n }\n (root as any).setInstanceDecorator(createMethodDecorator(registry));\n\n const env: TestEnvironment = {\n root: root as IContainer,\n get: (token, params) => root.get(token as any, params),\n instance: (cls, params) => root.instance(cls, params),\n extend: () => root.extend() as IContainer,\n verify: async () => registry.verify(),\n dispose: () => root.dispose(),\n [ENV_REGISTRY]: registry,\n };\n return env;\n }\n\n /**\n * Register a class binding. When token === implementation this is a plain\n * class registration. Otherwise an alias factory resolves the implementation\n * through real IoC, mirroring the implementation's effective lifetime so\n * lifetime validation (captive-lifetime checks) stays honest.\n */\n private registerClassBinding(\n root: IContainer,\n token: Token,\n implementation: ClassLike,\n configuredLoadAs?: LoadAs,\n ): void {\n const loadAs = configuredLoadAs ?? componentScope(implementation) ?? LoadAs.Transient;\n root.registerClass(implementation as any, configuredLoadAs !== undefined ? ({ loadAs } as any) : undefined);\n if (token === implementation) return;\n\n if (loadAs === LoadAs.Singleton) {\n root.registerFunction(token, () => root.get(implementation as any), {\n loadAs: LoadAs.Singleton,\n } as any);\n } else {\n root.registerFunction(token, (scope: IContainer) => scope.get(implementation as any), {\n loadAs,\n param: [SCOPED_CONTAINER],\n } as any);\n }\n }\n}\n\n/** Create a persistent immutable real-IoC test composition builder. */\nexport function testIoc(...inputs: UseInput[]): TestIocBuilder {\n return TestIocBuilder.create(inputs);\n}\n","/**\n * Diagnostics are first-class: every error names the real token/method and\n * what was expected vs what happened, never only internal wrapper machinery.\n */\n\nexport class TestingError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** Thrown at build() when the installed @noego/ioc lacks the decoration seam. */\nexport class MissingIocSeamError extends TestingError {\n constructor() {\n super(\n '@noego/testing requires an @noego/ioc version that provides ' +\n 'Container.setInstanceDecorator (>= 0.5.x with the instance-decoration seam). ' +\n 'Upgrade @noego/ioc.',\n );\n }\n}\n\n/** test.inspect() on a method that is not watched in this environment. */\nexport class UnwatchedInspectionError extends TestingError {\n constructor(token: string, method: string) {\n super(\n `Method \"${method}\" on ${token} is not watched in this environment. ` +\n 'Only watched methods are inspectable — install test.watch() or any ' +\n 'test.* behavior/expectation descriptor for it.',\n );\n }\n}\n\n/** A call arrived after a test.calls([...]) script was fully consumed. */\nexport class CallScriptExhaustedError extends TestingError {\n constructor(token: string, method: string, scriptLength: number, callIndex: number) {\n super(\n `Call #${callIndex} to ${token}.${method} exceeds its test.calls() script ` +\n `of ${scriptLength} ${scriptLength === 1 ? 'entry' : 'entries'}.`,\n );\n }\n}\n\n/** An exact expectation (once/times/never) was exceeded at call time. */\nexport class ExpectationOverflowError extends TestingError {\n constructor(token: string, method: string, expected: number, attempted: number) {\n super(\n expected === 0\n ? `${token}.${method} was expected never to be called, but it was invoked.`\n : `${token}.${method} was expected exactly ${expected} ` +\n `${expected === 1 ? 'call' : 'calls'}, but call #${attempted} arrived.`,\n );\n }\n}\n\n/** Aggregated under-count failures reported by env.verify(). */\nexport class VerificationError extends TestingError {\n constructor(failures: readonly { token: string; method: string; expected: number; actual: number }[]) {\n super(\n 'Exact method expectations were not satisfied:\\n' +\n failures\n .map(\n (f) =>\n ` - ${f.token}.${f.method}: expected exactly ${f.expected} ` +\n `${f.expected === 1 ? 'call' : 'calls'}, observed ${f.actual}`,\n )\n .join('\\n'),\n );\n }\n}\n\n/** .methods configured for a token whose resolved value has no such callable method. */\nexport class MethodNotCallableError extends TestingError {\n constructor(token: string, method: string) {\n super(\n `Cannot install a test.* descriptor on ${token}.${method}: the resolved ` +\n 'instance has no callable method with that name.',\n );\n }\n}\n\n/** .methods configured for a token that resolved to a non-object value. */\nexport class NonObjectMethodTargetError extends TestingError {\n constructor(token: string) {\n super(\n `.methods() is configured for ${token}, but that token resolved to a ` +\n 'non-object value. Method descriptors apply only to IoC-managed instances.',\n );\n }\n}\n\n/** A string configuration key could not be resolved to a known IoC token. */\nexport class UnknownTokenKeyError extends TestingError {\n constructor(key: string, space: string, known: readonly string[]) {\n super(\n `Unknown ${space} key \"${key}\" — it does not match any token known to this ` +\n 'builder. Pass the class/token itself via a Map, or include the ' +\n 'registration through .use(...). Known tokens: ' +\n (known.length ? known.join(', ') : '(none)'),\n );\n }\n}\n\n/** Invalid descriptor construction (e.g. test.times(-1)). */\nexport class InvalidDescriptorError extends TestingError {}\n","/**\n * Lowercase `test.*` descriptors — immutable frozen values.\n *\n * Descriptors carry NO mutable state (no cursors, no counters, no histories);\n * all mutable invocation state lives in the built environment, so one\n * descriptor value is safe to share across builders and repeated builds.\n */\n\nimport { InvalidDescriptorError } from './errors';\n\nexport const DESCRIPTOR = Symbol.for('noego:testing:descriptor');\n\n/** A raw custom method wrapper: (original) => replacement. NOT auto-watched. */\nexport type RawMethodWrapper = (\n original: (...args: any[]) => any,\n) => (...args: any[]) => any;\n\nexport interface ReturnsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'returns';\n readonly value: unknown;\n}\n\nexport interface ThrowsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'throws';\n readonly error: unknown;\n}\n\nexport interface OriginalDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'original';\n}\n\nexport interface CallsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'calls';\n readonly script: readonly BehaviorDescriptor[];\n}\n\nexport type BehaviorDescriptor =\n | ReturnsDescriptor\n | ThrowsDescriptor\n | OriginalDescriptor\n | CallsDescriptor;\n\nexport interface WatchDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'watch';\n readonly wrapper?: RawMethodWrapper;\n}\n\nexport interface ExpectationDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'expect';\n /** Exact required call count; 0 for never(). */\n readonly expected: number;\n /** Behavior used for allowed calls; undefined = original effective behavior. */\n readonly behavior?: BehaviorDescriptor;\n}\n\n/** Everything installable through .methods({...}). */\nexport type MethodDescriptor =\n | BehaviorDescriptor\n | WatchDescriptor\n | ExpectationDescriptor\n | RawMethodWrapper;\n\nexport function isDescriptor(value: unknown): value is Exclude<MethodDescriptor, RawMethodWrapper> {\n return typeof value === 'object' && value !== null && (value as any)[DESCRIPTOR] === true;\n}\n\nfunction frozen<T extends object>(value: T): T {\n return Object.freeze(value);\n}\n\nfunction assertBehavior(value: unknown, where: string): asserts value is BehaviorDescriptor {\n if (!isDescriptor(value) || !['returns', 'throws', 'original', 'calls'].includes((value as any).kind)) {\n throw new InvalidDescriptorError(\n `${where} requires a behavior descriptor (test.returns/throws/original/calls).`,\n );\n }\n}\n\nexport const test = {\n /** Return the supplied value when the method is called. Auto-watches. */\n returns(value: unknown): ReturnsDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'returns' as const, value });\n },\n\n /** Throw/reject with the supplied error. Auto-watches. */\n throws(error: unknown): ThrowsDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'throws' as const, error });\n },\n\n /** Invoke the original effective method. Auto-watches. */\n original(): OriginalDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'original' as const });\n },\n\n /**\n * Per-invocation behavior script: call 1 uses entry 1, and so on. A call\n * after exhaustion fails immediately. Unused entries do not fail verification.\n */\n calls(script: readonly BehaviorDescriptor[]): CallsDescriptor {\n if (!Array.isArray(script)) {\n throw new InvalidDescriptorError('test.calls() requires an array of behavior descriptors.');\n }\n script.forEach((entry, i) => assertBehavior(entry, `test.calls() entry #${i + 1}`));\n return frozen({ [DESCRIPTOR]: true as const, kind: 'calls' as const, script: Object.freeze([...script]) });\n },\n\n /**\n * Keep original behavior and record calls. With a raw wrapper argument, the\n * wrapper's behavior runs and is recorded.\n */\n watch(wrapper?: RawMethodWrapper): WatchDescriptor {\n if (wrapper !== undefined && typeof wrapper !== 'function') {\n throw new InvalidDescriptorError('test.watch() accepts only a raw wrapper function.');\n }\n return frozen({ [DESCRIPTOR]: true as const, kind: 'watch' as const, wrapper });\n },\n\n /** Require exactly one call; with no behavior, the original runs. */\n once(behavior?: BehaviorDescriptor): ExpectationDescriptor {\n if (behavior !== undefined) assertBehavior(behavior, 'test.once()');\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: 1, behavior });\n },\n\n /** Require exactly `count` calls; with no behavior, the original runs. */\n times(count: number, behavior?: BehaviorDescriptor): ExpectationDescriptor {\n if (!Number.isInteger(count) || count < 0) {\n throw new InvalidDescriptorError(\n `test.times() requires a non-negative integer count, received ${String(count)}.`,\n );\n }\n if (behavior !== undefined) assertBehavior(behavior, 'test.times()');\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: count, behavior });\n },\n\n /** Require zero calls; the first invocation fails and skips the original. */\n never(): ExpectationDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: 0 });\n },\n\n /** Read the recorded history for a watched method in one environment. */\n inspect(environment: unknown, token: unknown, method: string): MethodInspection {\n const registry = (environment as any)?.[ENV_REGISTRY];\n if (!registry) {\n throw new InvalidDescriptorError(\n 'test.inspect() requires a built @noego/testing environment as its first argument.',\n );\n }\n return registry.inspect(token, method);\n },\n};\n\nObject.freeze(test);\n\n/** Symbol under which a built environment exposes its watch registry. */\nexport const ENV_REGISTRY = Symbol.for('noego:testing:env-registry');\n\nexport interface RecordedCall {\n /** 1-based invocation index in this environment. */\n readonly index: number;\n readonly args: readonly unknown[];\n /** Present once the call returned (resolved value for async methods). */\n readonly result?: unknown;\n /** Present once the call threw/rejected. */\n readonly error?: unknown;\n /** True while an async outcome is still pending. */\n readonly pending: boolean;\n readonly timestamp: number;\n}\n\nexport interface MethodInspection {\n readonly count: number;\n readonly calls: readonly RecordedCall[];\n}\n","/**\n * Environment-owned method behavior/observation runtime.\n *\n * All mutable state (histories, expectation counters, calls-script cursors)\n * lives here, created fresh at every build(). Descriptors stay immutable.\n */\n\nimport {\n type BehaviorDescriptor,\n type ExpectationDescriptor,\n type MethodDescriptor,\n type MethodInspection,\n type RawMethodWrapper,\n type RecordedCall,\n isDescriptor,\n} from './descriptors';\nimport {\n CallScriptExhaustedError,\n ExpectationOverflowError,\n MethodNotCallableError,\n NonObjectMethodTargetError,\n UnwatchedInspectionError,\n VerificationError,\n} from './errors';\n\nconst CONTEXT_WRAPPED = Symbol.for('ioc:context-wrapped');\nconst CONTEXT_OWNER = Symbol.for('ioc:context-owner');\n\nexport function tokenLabel(token: unknown): string {\n if (typeof token === 'function') return (token as { name?: string }).name || '[anonymous class]';\n if (typeof token === 'symbol') return String(token);\n return String(token);\n}\n\ninterface MutableCall {\n index: number;\n args: readonly unknown[];\n result?: unknown;\n error?: unknown;\n pending: boolean;\n timestamp: number;\n}\n\nexport class MethodState {\n readonly calls: MutableCall[] = [];\n /** Actual invocation count (includes the call currently executing). */\n actual = 0;\n /** Cursor into a test.calls() script. */\n scriptCursor = 0;\n\n constructor(\n readonly tokenName: string,\n readonly method: string,\n readonly descriptor: Exclude<MethodDescriptor, RawMethodWrapper>,\n ) {}\n\n get expectation(): ExpectationDescriptor | undefined {\n return this.descriptor.kind === 'expect' ? this.descriptor : undefined;\n }\n\n inspection(): MethodInspection {\n return {\n count: this.calls.length,\n calls: this.calls.map((c) => ({ ...c, args: [...c.args] }) as RecordedCall),\n };\n }\n}\n\n/** One method-config entry: how it was keyed, and its per-method descriptors. */\nexport interface MethodConfigEntry {\n /** Exact token (class/symbol/string) or a name string matched lazily. */\n readonly key: unknown;\n readonly byName: boolean;\n readonly methods: ReadonlyMap<string, MethodDescriptor>;\n}\n\nexport class WatchRegistry {\n /** entry-identity → method → state. Entries share states across instances. */\n private readonly states = new Map<unknown, Map<string, MethodState>>();\n private readonly nameIndex = new Map<string, unknown>();\n private readonly entries: MethodConfigEntry[] = [];\n\n addEntry(entry: MethodConfigEntry): void {\n this.entries.push(entry);\n const byMethod = new Map<string, MethodState>();\n for (const [method, descriptor] of entry.methods) {\n if (typeof descriptor === 'function') continue; // raw wrapper: unwatched, no state\n byMethod.set(method, new MethodState(this.entryLabel(entry), method, descriptor));\n }\n this.states.set(entry.key, byMethod);\n if (entry.byName) this.nameIndex.set(entry.key as string, entry.key);\n else if (typeof entry.key === 'function' && (entry.key as any).name) {\n this.nameIndex.set((entry.key as any).name, entry.key);\n }\n }\n\n private entryLabel(entry: MethodConfigEntry): string {\n return entry.byName ? String(entry.key) : tokenLabel(entry.key);\n }\n\n /** Entries applying to a resolving token (exact identity or name match). */\n matchEntries(token: unknown): MethodConfigEntry[] {\n const name = typeof token === 'function' ? (token as any).name : typeof token === 'string' ? token : undefined;\n return this.entries.filter(\n (entry) => entry.key === token || (entry.byName && name !== undefined && entry.key === name),\n );\n }\n\n state(entryKey: unknown, method: string): MethodState | undefined {\n return this.states.get(entryKey)?.get(method);\n }\n\n inspect(token: unknown, method: string): MethodInspection {\n const label = tokenLabel(token);\n const keys: unknown[] = [token];\n const name = typeof token === 'function' ? (token as any).name : typeof token === 'string' ? token : undefined;\n if (name !== undefined && this.nameIndex.has(name)) keys.push(this.nameIndex.get(name));\n for (const key of keys) {\n const state = this.states.get(key)?.get(method);\n if (state) return state.inspection();\n }\n throw new UnwatchedInspectionError(label, method);\n }\n\n /** Repeatable snapshot check of all exact expectations. */\n verify(): void {\n const failures: { token: string; method: string; expected: number; actual: number }[] = [];\n for (const byMethod of this.states.values()) {\n for (const state of byMethod.values()) {\n const expectation = state.expectation;\n if (!expectation) continue;\n if (state.actual !== expectation.expected) {\n failures.push({\n token: state.tokenName,\n method: state.method,\n expected: expectation.expected,\n actual: state.actual,\n });\n }\n }\n }\n if (failures.length) throw new VerificationError(failures);\n }\n}\n\nfunction isPromiseLike(value: unknown): value is Promise<unknown> {\n return !!value && typeof (value as any).then === 'function';\n}\n\nfunction recordOutcome(call: MutableCall, outcome: unknown, threw: boolean): unknown {\n if (!threw && isPromiseLike(outcome)) {\n call.pending = true;\n outcome.then(\n (value) => {\n call.result = value;\n call.pending = false;\n },\n (error) => {\n call.error = error;\n call.pending = false;\n },\n );\n return outcome;\n }\n call.pending = false;\n if (threw) call.error = outcome;\n else call.result = outcome;\n return outcome;\n}\n\n/**\n * Build the ioc instance decorator for one environment.\n *\n * Identity-stable (WeakMap), preserves sync/async call shape and `this`\n * binding, forwards the ioc context symbols by delegating to the underlying\n * (context-wrapped) target for everything unconfigured.\n */\nexport function createMethodDecorator(registry: WatchRegistry): (instance: any, token: any) => any {\n const wrappers = new WeakMap<object, any>();\n\n return function decorate(instance: any, token: any): any {\n const entries = registry.matchEntries(token);\n if (entries.length === 0) return instance;\n\n if (instance === null || (typeof instance !== 'object' && typeof instance !== 'function')) {\n throw new NonObjectMethodTargetError(tokenLabel(token));\n }\n\n if (wrappers.has(instance)) return wrappers.get(instance);\n\n // Effective per-method config: entries merge in write order, LWW per method\n const effective = new Map<string, { entryKey: unknown; descriptor: MethodDescriptor }>();\n for (const entry of entries) {\n for (const [method, descriptor] of entry.methods) {\n effective.set(method, { entryKey: entry.key, descriptor });\n }\n }\n\n // Validate configured methods exist and are callable\n for (const method of effective.keys()) {\n if (typeof instance[method] !== 'function') {\n throw new MethodNotCallableError(tokenLabel(token), method);\n }\n }\n\n const methodCache = new Map<string, (...args: any[]) => any>();\n\n const proxy = new Proxy(instance, {\n get(target, prop, receiver) {\n if (typeof prop === 'string' && effective.has(prop)) {\n let wrapped = methodCache.get(prop);\n if (!wrapped) {\n const { entryKey, descriptor } = effective.get(prop)!;\n wrapped = buildMethodWrapper(target, prop, descriptor, registry.state(entryKey, prop));\n methodCache.set(prop, wrapped);\n }\n return wrapped;\n }\n // Everything else (including ioc context symbols) delegates to the\n // underlying — usually context-wrapped — target.\n if (prop === CONTEXT_WRAPPED || prop === CONTEXT_OWNER) return (target as any)[prop];\n return Reflect.get(target, prop, receiver);\n },\n });\n\n wrappers.set(instance, proxy);\n return proxy;\n };\n}\n\nfunction buildMethodWrapper(\n target: any,\n method: string,\n descriptor: MethodDescriptor,\n state: MethodState | undefined,\n): (...args: any[]) => any {\n // The original effective method, read through the underlying target so the\n // ioc context proxy still owns context entry for real invocations.\n const callOriginal = (self: any, args: any[]) => {\n const fn = target[method];\n return fn.apply(self === undefined ? target : self, args);\n };\n\n // Raw custom wrapper: installed as-is, NOT watched, no recording.\n if (typeof descriptor === 'function') {\n const replacement = descriptor((...args: any[]) => callOriginal(target, args));\n return function (this: any, ...args: any[]) {\n return replacement.apply(this, args);\n };\n }\n\n if (!isDescriptor(descriptor)) {\n // Should be unreachable: builder validates descriptors on write.\n throw new TypeError(`Invalid method descriptor for ${method}`);\n }\n\n return function (this: any, ...args: any[]) {\n if (!state) throw new TypeError(`Missing method state for ${method}`);\n\n const expectation = state.expectation;\n const attempted = state.actual + 1;\n\n // Overflow fails immediately and never runs behavior/original\n if (expectation && attempted > expectation.expected) {\n state.actual = attempted;\n throw new ExpectationOverflowError(state.tokenName, method, expectation.expected, attempted);\n }\n\n state.actual = attempted;\n const call: MutableCall = {\n index: attempted,\n args: [...args],\n pending: false,\n timestamp: Date.now(),\n };\n state.calls.push(call);\n\n // Effective behavior for this invocation\n let behavior: BehaviorDescriptor | 'original-effective' | RawMethodWrapper;\n const base =\n descriptor.kind === 'expect'\n ? (descriptor.behavior ?? 'original-effective')\n : descriptor.kind === 'watch'\n ? (descriptor.wrapper ?? 'original-effective')\n : descriptor;\n\n if (base !== 'original-effective' && typeof base !== 'function' && base !== undefined && base.kind === 'calls') {\n if (state.scriptCursor >= base.script.length) {\n throw new CallScriptExhaustedError(state.tokenName, method, base.script.length, attempted);\n }\n behavior = base.script[state.scriptCursor]!;\n state.scriptCursor += 1;\n } else {\n behavior = base;\n }\n\n try {\n let outcome: unknown;\n if (behavior === 'original-effective') {\n outcome = callOriginal(this, args);\n } else if (typeof behavior === 'function') {\n // test.watch(rawWrapper): wrapper behavior runs and is recorded\n outcome = behavior((...inner: any[]) => callOriginal(this, inner)).apply(this, args);\n } else if (behavior.kind === 'returns') {\n outcome = behavior.value;\n } else if (behavior.kind === 'throws') {\n throw behavior.error;\n } else if (behavior.kind === 'original') {\n outcome = callOriginal(this, args);\n } else {\n throw new TypeError(`Nested test.calls() scripts are not supported (${method}).`);\n }\n return recordOutcome(call, outcome, false);\n } catch (error) {\n recordOutcome(call, error, true);\n throw error;\n }\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/builder.ts","../src/errors.ts","../src/descriptors.ts","../src/method_state.ts"],"sourcesContent":["/**\n * @noego/testing — the canonical shared owner of real-IoC test composition\n * (`testIoc`) and the lowercase `test.*` method behavior/watch/expectation\n * language, built on @noego/ioc's production seams.\n *\n * The former generic runtime-mirror doubles (ManualClock, ScriptedFetchClient,\n * memory stores, recording sinks, contract suites, LeakDetector, …) are\n * retired; pin 0.1.x if you still need them, and see the NoEgo runtime/testing\n * deprecation plan for per-export dispositions.\n */\n\nexport { testIoc, TestIocBuilder } from './builder';\nexport type { TestEnvironment, ConfigMap, MethodsConfig, UseInput } from './builder';\n\nexport { test, ENV_REGISTRY } from './descriptors';\nexport type {\n BehaviorDescriptor,\n CallsDescriptor,\n ExpectationDescriptor,\n MethodDescriptor,\n MethodInspection,\n OriginalDescriptor,\n RawMethodWrapper,\n RecordedCall,\n ReturnsDescriptor,\n ThrowsDescriptor,\n WatchDescriptor,\n} from './descriptors';\n\nexport {\n TestingError,\n MissingIocSeamError,\n UnwatchedInspectionError,\n CallScriptExhaustedError,\n ExpectationOverflowError,\n VerificationError,\n MethodNotCallableError,\n NonObjectMethodTargetError,\n UnknownTokenKeyError,\n AmbiguousNameKeyError,\n TokenIdentitySplitError,\n InvalidDescriptorError,\n} from './errors';\n","/**\n * `testIoc` — the canonical shared real-IoC test composition builder.\n *\n * Persistent immutable: every fluent call returns a new derived builder\n * sharing the ordered write log structurally. Non-conflicting writes are\n * order-insensitive; the last write to the same effective identity wins on\n * that derived branch. `.build()` is non-consuming and creates fresh runtime,\n * watch, and expectation state (spec 15, PBR-01..15).\n */\n\nimport {\n createContainer,\n flattenModule,\n LoadAs,\n SCOPED_CONTAINER,\n type ApplicationModule,\n type IContainer,\n} from '@noego/ioc';\n\nimport { ENV_REGISTRY, isDescriptor, type MethodDescriptor } from './descriptors';\nimport { createMethodDecorator, WatchRegistry, tokenLabel } from './method_state';\nimport { InvalidDescriptorError, MissingIocSeamError, UnknownTokenKeyError, AmbiguousNameKeyError,\n} from './errors';\n\nconst COMPONENT_OPTIONS_KEY = Symbol.for('ioc:component:options');\n\ntype Token = unknown;\ntype ClassLike = new (...args: any[]) => any;\n\n/** Config maps accept plain objects (string keys) or Maps (exact tokens). */\n/**\n * Composition input (spec 04 §2). The CANONICAL entry form is an array of\n * tuples — token-first, exact identity:\n *\n * .classes([[ProjectRepository, MemoryProjectRepository]])\n *\n * A `ReadonlyMap<Token, V>` is equivalent (token-keyed). A name-keyed\n * `Record<string, V>` remains accepted as COMPATIBILITY input: string keys\n * resolve against known token display names, fail on unknown names, and\n * fail on ambiguous names (two tokens sharing one display name never\n * collapse into one entry — tokens are identities, names are labels).\n */\nexport type ConfigMap<V> =\n | ReadonlyArray<readonly [Token, V]>\n | ReadonlyMap<Token, V>\n | Record<string, V>;\n\nexport type MethodsConfig = ConfigMap<Record<string, MethodDescriptor> | ReadonlyMap<string, MethodDescriptor>>;\n\nexport type UseInput = ApplicationModule | TestIocBuilder;\n\ntype Write =\n | { op: 'use'; module: ApplicationModule }\n | { op: 'classes'; key: Token; byName: boolean; implementation: ClassLike }\n | { op: 'functions'; key: Token; byName: boolean; factory: (...args: any[]) => any }\n | { op: 'values'; key: Token; byName: boolean; value: unknown }\n | { op: 'methods'; key: Token; byName: boolean; methods: ReadonlyMap<string, MethodDescriptor> };\n\nexport interface TestEnvironment {\n readonly root: IContainer;\n get<T>(token: unknown, params?: any[]): Promise<T> | T;\n instance<T>(cls: new (...args: any[]) => T, params?: any[]): Promise<T> | T;\n extend(): IContainer;\n verify(): Promise<void>;\n dispose(): Promise<void>;\n readonly [ENV_REGISTRY]: WatchRegistry;\n}\n\nfunction* configEntries<V>(config: ConfigMap<V>): Iterable<[Token, boolean, V]> {\n if (Array.isArray(config)) {\n // Canonical tuple form: exact token identity, never name resolution.\n for (const entry of config as ReadonlyArray<readonly [Token, V]>) {\n if (!Array.isArray(entry) || entry.length !== 2) {\n throw new InvalidDescriptorError(\n 'canonical composition entries are [token, value] tuples, e.g. .classes([[Token, Impl]])',\n );\n }\n yield [entry[0], false, entry[1]];\n }\n } else if (config instanceof Map) {\n for (const [key, value] of config) yield [key, false, value];\n } else {\n for (const key of [...Object.getOwnPropertyNames(config), ...Object.getOwnPropertySymbols(config)]) {\n yield [key, typeof key === 'string', (config as any)[key]];\n }\n }\n}\n\nfunction componentScope(cls: any): LoadAs | undefined {\n const options =\n typeof Reflect !== 'undefined' && (Reflect as any).getMetadata\n ? (Reflect as any).getMetadata(COMPONENT_OPTIONS_KEY, cls)\n : undefined;\n return options?.scope;\n}\n\nfunction lifetimeToLoadAs(lifetime: string): LoadAs {\n if (lifetime === 'singleton') return LoadAs.Singleton;\n if (lifetime === 'scoped') return LoadAs.Scoped;\n return LoadAs.Transient;\n}\n\nexport class TestIocBuilder {\n private constructor(private readonly log: readonly Write[]) {\n Object.freeze(this);\n }\n\n /** @internal */\n static create(inputs: readonly UseInput[]): TestIocBuilder {\n return new TestIocBuilder([]).useAll(inputs);\n }\n\n /** @internal — read by .use(builderPreset) */\n get writes(): readonly Write[] {\n return this.log;\n }\n\n private derive(writes: Write[]): TestIocBuilder {\n return new TestIocBuilder([...this.log, ...writes]);\n }\n\n private useAll(inputs: readonly UseInput[]): TestIocBuilder {\n let builder: TestIocBuilder = this;\n for (const input of inputs) builder = builder.use(input);\n return builder;\n }\n\n /** Apply a reusable composition preset: an ApplicationModule or a builder. */\n use(preset: UseInput): TestIocBuilder {\n if (preset instanceof TestIocBuilder) {\n return this.derive([...preset.writes]);\n }\n return this.derive([{ op: 'use', module: preset }]);\n }\n\n /** Replace the implementation for IoC class tokens in the built environment. */\n classes(config: ConfigMap<ClassLike>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, implementation] of configEntries(config)) {\n if (typeof implementation !== 'function' || !implementation.prototype) {\n throw new InvalidDescriptorError(\n `.classes() value for \"${tokenLabel(key)}\" must be a class constructor.`,\n );\n }\n writes.push({ op: 'classes', key, byName, implementation });\n }\n return this.derive(writes);\n }\n\n /** Replace IoC factory/provider registrations. */\n functions(config: ConfigMap<(...args: any[]) => any>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, factory] of configEntries(config)) {\n if (typeof factory !== 'function') {\n throw new InvalidDescriptorError(`.functions() value for \"${tokenLabel(key)}\" must be a function.`);\n }\n writes.push({ op: 'functions', key, byName, factory });\n }\n return this.derive(writes);\n }\n\n /** Provide/replace IoC value registrations. */\n values(config: ConfigMap<unknown>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, value] of configEntries(config)) {\n writes.push({ op: 'values', key, byName, value });\n }\n return this.derive(writes);\n }\n\n /** Install method behavior/observation descriptors on IoC-managed instances. */\n methods(config: MethodsConfig): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, methodsInput] of configEntries(config)) {\n const methods = new Map<string, MethodDescriptor>();\n const entries =\n methodsInput instanceof Map\n ? methodsInput.entries()\n : Object.entries(methodsInput as Record<string, MethodDescriptor>);\n for (const [name, descriptor] of entries) {\n if (typeof descriptor !== 'function' && !isDescriptor(descriptor)) {\n throw new InvalidDescriptorError(\n `.methods() entry ${tokenLabel(key)}.${name} must be a test.* descriptor or a raw wrapper function.`,\n );\n }\n methods.set(name, descriptor);\n }\n writes.push({ op: 'methods', key, byName, methods });\n }\n return this.derive(writes);\n }\n\n /** Materialize a fresh, isolated real-IoC environment. Non-consuming. */\n async build(): Promise<TestEnvironment> {\n const root = createContainer();\n if (typeof (root as any).setInstanceDecorator !== 'function') {\n throw new MissingIocSeamError();\n }\n\n // ---- Materialize the ordered log: last write wins per effective identity\n // Known tokens (for resolving string keys of classes/functions/values)\n const knownByName = new Map<string, Token>();\n /** Display names claimed by more than one distinct token (spec 04 §5/§17). */\n const ambiguousNames = new Set<string>();\n const knownLifetimes = new Map<Token, LoadAs>();\n const note = (token: Token, loadAs: LoadAs | undefined) => {\n const name =\n typeof token === 'function' && (token as any).name\n ? (token as any).name as string\n : typeof token === 'string'\n ? token\n : null;\n if (name !== null) {\n const existing = knownByName.get(name);\n if (existing !== undefined && existing !== token) ambiguousNames.add(name);\n knownByName.set(name, token);\n }\n if (loadAs !== undefined) knownLifetimes.set(token, loadAs);\n };\n\n type Effective =\n | { space: 'class'; token: Token; implementation: ClassLike; loadAs?: LoadAs }\n | { space: 'factory'; token: Token; factory: (...args: any[]) => any; loadAs?: LoadAs; deps?: Token[] }\n | { space: 'value'; token: Token; value: unknown };\n\n // ordered map: identity → latest effective write (Map preserves first-write\n // position which is fine — later writes replace content, LWW)\n const effective = new Map<Token, Effective>();\n const methodWrites: { key: Token; byName: boolean; methods: Map<string, MethodDescriptor> }[] = [];\n\n const resolveKey = (key: Token, byName: boolean, space: string): Token => {\n if (!byName) return key;\n if (ambiguousNames.has(key as string)) {\n throw new AmbiguousNameKeyError(key as string, space);\n }\n const known = knownByName.get(key as string);\n if (known !== undefined) return known;\n if (space === 'values' || space === 'functions') return key; // string tokens are first-class\n throw new UnknownTokenKeyError(key as string, space, [...knownByName.keys()]);\n };\n\n for (const write of this.log) {\n switch (write.op) {\n case 'use': {\n for (const reg of flattenModule(write.module)) {\n const loadAs = lifetimeToLoadAs(reg.lifetime);\n note(reg.token, loadAs);\n if (reg.kind === 'class') {\n note(reg.implementation as Token, loadAs);\n effective.set(reg.token, {\n space: 'class',\n token: reg.token,\n implementation: reg.implementation as ClassLike,\n loadAs,\n });\n knownLifetimes.set(reg.token, loadAs);\n knownLifetimes.set(reg.implementation as Token, loadAs);\n } else if (reg.kind === 'factory') {\n effective.set(reg.token, {\n space: 'factory',\n token: reg.token,\n factory: reg.implementation as (...args: any[]) => any,\n loadAs,\n deps: [...reg.dependencies],\n });\n } else {\n effective.set(reg.token, { space: 'value', token: reg.token, value: reg.implementation });\n knownLifetimes.set(reg.token, LoadAs.Singleton);\n }\n }\n break;\n }\n case 'classes': {\n const token = resolveKey(write.key, write.byName, 'classes');\n note(write.implementation, undefined);\n if (!write.byName) note(token, undefined);\n effective.set(token, {\n space: 'class',\n token,\n implementation: write.implementation,\n // Lifetime priority: the replacement's own @Component scope, then\n // the lifetime the composition already knows for the token, then\n // the TOKEN class's declared @Component scope — a plain stub\n // class replacing a Singleton-scoped production service must not\n // silently degrade to Transient (captive-lifetime validation\n // would reject the production dependents).\n loadAs:\n componentScope(write.implementation)\n ?? knownLifetimes.get(token)\n ?? componentScope(token),\n });\n break;\n }\n case 'functions': {\n const token = resolveKey(write.key, write.byName, 'functions');\n const prior = effective.get(token);\n effective.set(token, {\n space: 'factory',\n token,\n factory: write.factory,\n // preserve configured lifetime unless the scenario overrides it\n loadAs: prior && prior.space === 'factory' ? prior.loadAs : knownLifetimes.get(token),\n deps: prior && prior.space === 'factory' ? prior.deps : undefined,\n });\n note(token, undefined);\n break;\n }\n case 'values': {\n const token = resolveKey(write.key, write.byName, 'values');\n effective.set(token, { space: 'value', token, value: write.value });\n note(token, LoadAs.Singleton);\n break;\n }\n case 'methods': {\n if (write.byName && ambiguousNames.has(write.key as string)) {\n throw new AmbiguousNameKeyError(write.key as string, 'methods');\n }\n const token = write.byName && knownByName.has(write.key as string)\n ? knownByName.get(write.key as string)!\n : write.key;\n methodWrites.push({\n key: token,\n byName: write.byName && !knownByName.has(write.key as string),\n methods: new Map(write.methods),\n });\n break;\n }\n }\n }\n\n // ---- Apply effective registrations to the fresh root\n for (const entry of effective.values()) {\n if (entry.space === 'class') {\n this.registerClassBinding(root, entry.token, entry.implementation, entry.loadAs);\n } else if (entry.space === 'factory') {\n root.registerFunction(entry.token, entry.factory, {\n loadAs: entry.loadAs,\n param: entry.deps,\n } as any);\n } else {\n const value = entry.value;\n root.registerFunction(entry.token, () => value, { loadAs: LoadAs.Singleton } as any);\n }\n }\n\n // ---- Fresh watch/expectation state + the ioc decoration seam\n const registry = new WatchRegistry();\n // merge method writes: LWW per (entry key, method), deep-merge per token\n const mergedMethods = new Map<Token, { byName: boolean; methods: Map<string, MethodDescriptor> }>();\n for (const write of methodWrites) {\n const existing = mergedMethods.get(write.key);\n if (existing) {\n for (const [name, descriptor] of write.methods) existing.methods.set(name, descriptor);\n } else {\n mergedMethods.set(write.key, { byName: write.byName, methods: new Map(write.methods) });\n }\n }\n for (const [key, { byName, methods }] of mergedMethods) {\n registry.addEntry({ key, byName, methods });\n }\n (root as any).setInstanceDecorator(createMethodDecorator(registry));\n\n const env: TestEnvironment = {\n root: root as IContainer,\n get: (token, params) => root.get(token as any, params),\n instance: (cls, params) => root.instance(cls, params),\n extend: () => root.extend() as IContainer,\n verify: async () => registry.verify(),\n dispose: () => root.dispose(),\n [ENV_REGISTRY]: registry,\n };\n return env;\n }\n\n /**\n * Register a class binding. When token === implementation this is a plain\n * class registration. Otherwise an alias factory resolves the implementation\n * through real IoC, mirroring the implementation's effective lifetime so\n * lifetime validation (captive-lifetime checks) stays honest.\n */\n private registerClassBinding(\n root: IContainer,\n token: Token,\n implementation: ClassLike,\n configuredLoadAs?: LoadAs,\n ): void {\n const loadAs = configuredLoadAs ?? componentScope(implementation) ?? LoadAs.Transient;\n root.registerClass(implementation as any, configuredLoadAs !== undefined ? ({ loadAs } as any) : undefined);\n if (token === implementation) return;\n\n if (loadAs === LoadAs.Singleton) {\n root.registerFunction(token, () => root.get(implementation as any), {\n loadAs: LoadAs.Singleton,\n } as any);\n } else {\n root.registerFunction(token, (scope: IContainer) => scope.get(implementation as any), {\n loadAs,\n param: [SCOPED_CONTAINER],\n } as any);\n }\n }\n}\n\n/** Create a persistent immutable real-IoC test composition builder. */\nexport function testIoc(...inputs: UseInput[]): TestIocBuilder {\n return TestIocBuilder.create(inputs);\n}\n","/**\n * Diagnostics are first-class: every error names the real token/method and\n * what was expected vs what happened, never only internal wrapper machinery.\n */\n\nexport class TestingError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** Thrown at build() when the installed @noego/ioc lacks the decoration seam. */\nexport class MissingIocSeamError extends TestingError {\n constructor() {\n super(\n '@noego/testing requires an @noego/ioc version that provides ' +\n 'Container.setInstanceDecorator (>= 0.5.x with the instance-decoration seam). ' +\n 'Upgrade @noego/ioc.',\n );\n }\n}\n\n/** test.inspect() on a method that is not watched in this environment. */\nexport class UnwatchedInspectionError extends TestingError {\n constructor(token: string, method: string) {\n super(\n `Method \"${method}\" on ${token} is not watched in this environment. ` +\n 'Only watched methods are inspectable — install test.watch() or any ' +\n 'test.* behavior/expectation descriptor for it.',\n );\n }\n}\n\n/** A call arrived after a test.calls([...]) script was fully consumed. */\nexport class CallScriptExhaustedError extends TestingError {\n constructor(token: string, method: string, scriptLength: number, callIndex: number) {\n super(\n `Call #${callIndex} to ${token}.${method} exceeds its test.calls() script ` +\n `of ${scriptLength} ${scriptLength === 1 ? 'entry' : 'entries'}.`,\n );\n }\n}\n\n/** An exact expectation (once/times/never) was exceeded at call time. */\nexport class ExpectationOverflowError extends TestingError {\n constructor(token: string, method: string, expected: number, attempted: number) {\n super(\n expected === 0\n ? `${token}.${method} was expected never to be called, but it was invoked.`\n : `${token}.${method} was expected exactly ${expected} ` +\n `${expected === 1 ? 'call' : 'calls'}, but call #${attempted} arrived.`,\n );\n }\n}\n\n/** Aggregated under-count failures reported by env.verify(). */\nexport class VerificationError extends TestingError {\n constructor(failures: readonly { token: string; method: string; expected: number; actual: number }[]) {\n super(\n 'Exact method expectations were not satisfied:\\n' +\n failures\n .map(\n (f) =>\n ` - ${f.token}.${f.method}: expected exactly ${f.expected} ` +\n `${f.expected === 1 ? 'call' : 'calls'}, observed ${f.actual}`,\n )\n .join('\\n'),\n );\n }\n}\n\n/** .methods configured for a token whose resolved value has no such callable method. */\nexport class MethodNotCallableError extends TestingError {\n constructor(token: string, method: string) {\n super(\n `Cannot install a test.* descriptor on ${token}.${method}: the resolved ` +\n 'instance has no callable method with that name.',\n );\n }\n}\n\n/** .methods configured for a token that resolved to a non-object value. */\nexport class NonObjectMethodTargetError extends TestingError {\n constructor(token: string) {\n super(\n `.methods() is configured for ${token}, but that token resolved to a ` +\n 'non-object value. Method descriptors apply only to IoC-managed instances.',\n );\n }\n}\n\n/** A string configuration key could not be resolved to a known IoC token. */\nexport class UnknownTokenKeyError extends TestingError {\n constructor(key: string, space: string, known: readonly string[]) {\n super(\n `Unknown ${space} key \"${key}\" — it does not match any token known to this ` +\n 'builder. Pass the class/token itself via a Map, or include the ' +\n 'registration through .use(...). Known tokens: ' +\n (known.length ? known.join(', ') : '(none)'),\n );\n }\n}\n\n/** Invalid descriptor construction (e.g. test.times(-1)). */\nexport class InvalidDescriptorError extends TestingError {}\n\n/**\n * A name-keyed compatibility entry referred to a display name claimed by\n * two or more distinct tokens. Tokens are identities; names are labels —\n * pass the exact token in canonical tuple form instead (spec 04 §5).\n */\nexport class AmbiguousNameKeyError extends TestingError {\n constructor(name: string, space: string) {\n super(\n `.${space}() key \"${name}\" is ambiguous: multiple distinct tokens share that display name. ` +\n `Use the canonical tuple form with the exact token: .${space}([[TheToken, ...]]).`,\n );\n this.name = 'AmbiguousNameKeyError';\n }\n}\n\n\n/**\n * A .methods() class token never matched any constructed instance while a\n * DIFFERENT class with the same display name did construct — the configured\n * behavior silently did not apply. Usual cause: two module registries loaded\n * the same source file (e.g. a vitest test file's import vs a framework\n * harness's native import of the production graph); fix by routing the\n * harness's imports through the caller's registry (testApp:\n * `.importer((p) => import(p))`) or by passing the token the graph actually\n * uses.\n */\nexport class TokenIdentitySplitError extends TestingError {\n constructor(names: readonly string[]) {\n super(\n `token identity split: .methods() entr${names.length === 1 ? 'y' : 'ies'} for ` +\n `${names.map((name) => `\"${name}\"`).join(', ')} never matched a constructed instance, ` +\n `but a DIFFERENT class with the same name was constructed. Two module registries ` +\n `have loaded the same class file (test-file import vs harness graph import) — the ` +\n `configured behavior did not apply. Route the harness's imports through your ` +\n `registry (e.g. testApp .importer((p) => import(p))) or pass the exact token the graph uses.`,\n );\n this.name = 'TokenIdentitySplitError';\n }\n}\n","/**\n * Lowercase `test.*` descriptors — immutable frozen values.\n *\n * Descriptors carry NO mutable state (no cursors, no counters, no histories);\n * all mutable invocation state lives in the built environment, so one\n * descriptor value is safe to share across builders and repeated builds.\n */\n\nimport { InvalidDescriptorError } from './errors';\n\nexport const DESCRIPTOR = Symbol.for('noego:testing:descriptor');\n\n/** A raw custom method wrapper: (original) => replacement. NOT auto-watched. */\nexport type RawMethodWrapper = (\n original: (...args: any[]) => any,\n) => (...args: any[]) => any;\n\nexport interface ReturnsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'returns';\n readonly value: unknown;\n}\n\nexport interface ThrowsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'throws';\n readonly error: unknown;\n}\n\nexport interface OriginalDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'original';\n}\n\nexport interface CallsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'calls';\n readonly script: readonly BehaviorDescriptor[];\n}\n\nexport type BehaviorDescriptor =\n | ReturnsDescriptor\n | ThrowsDescriptor\n | OriginalDescriptor\n | CallsDescriptor;\n\nexport interface WatchDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'watch';\n readonly wrapper?: RawMethodWrapper;\n}\n\nexport interface ExpectationDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'expect';\n /** Exact required call count; 0 for never(). */\n readonly expected: number;\n /** Behavior used for allowed calls; undefined = original effective behavior. */\n readonly behavior?: BehaviorDescriptor;\n}\n\n/** Everything installable through .methods({...}). */\nexport type MethodDescriptor =\n | BehaviorDescriptor\n | WatchDescriptor\n | ExpectationDescriptor\n | RawMethodWrapper;\n\nexport function isDescriptor(value: unknown): value is Exclude<MethodDescriptor, RawMethodWrapper> {\n return typeof value === 'object' && value !== null && (value as any)[DESCRIPTOR] === true;\n}\n\nfunction frozen<T extends object>(value: T): T {\n return Object.freeze(value);\n}\n\nfunction assertBehavior(value: unknown, where: string): asserts value is BehaviorDescriptor {\n if (!isDescriptor(value) || !['returns', 'throws', 'original', 'calls'].includes((value as any).kind)) {\n throw new InvalidDescriptorError(\n `${where} requires a behavior descriptor (test.returns/throws/original/calls).`,\n );\n }\n}\n\nexport const test = {\n /** Return the supplied value when the method is called. Auto-watches. */\n returns(value: unknown): ReturnsDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'returns' as const, value });\n },\n\n /** Throw/reject with the supplied error. Auto-watches. */\n throws(error: unknown): ThrowsDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'throws' as const, error });\n },\n\n /** Invoke the original effective method. Auto-watches. */\n original(): OriginalDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'original' as const });\n },\n\n /**\n * Per-invocation behavior script: call 1 uses entry 1, and so on. A call\n * after exhaustion fails immediately. Unused entries do not fail verification.\n */\n calls(script: readonly BehaviorDescriptor[]): CallsDescriptor {\n if (!Array.isArray(script)) {\n throw new InvalidDescriptorError('test.calls() requires an array of behavior descriptors.');\n }\n script.forEach((entry, i) => assertBehavior(entry, `test.calls() entry #${i + 1}`));\n return frozen({ [DESCRIPTOR]: true as const, kind: 'calls' as const, script: Object.freeze([...script]) });\n },\n\n /**\n * Keep original behavior and record calls. With a raw wrapper argument, the\n * wrapper's behavior runs and is recorded.\n */\n watch(wrapper?: RawMethodWrapper): WatchDescriptor {\n if (wrapper !== undefined && typeof wrapper !== 'function') {\n throw new InvalidDescriptorError('test.watch() accepts only a raw wrapper function.');\n }\n return frozen({ [DESCRIPTOR]: true as const, kind: 'watch' as const, wrapper });\n },\n\n /** Require exactly one call; with no behavior, the original runs. */\n once(behavior?: BehaviorDescriptor): ExpectationDescriptor {\n if (behavior !== undefined) assertBehavior(behavior, 'test.once()');\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: 1, behavior });\n },\n\n /** Require exactly `count` calls; with no behavior, the original runs. */\n times(count: number, behavior?: BehaviorDescriptor): ExpectationDescriptor {\n if (!Number.isInteger(count) || count < 0) {\n throw new InvalidDescriptorError(\n `test.times() requires a non-negative integer count, received ${String(count)}.`,\n );\n }\n if (behavior !== undefined) assertBehavior(behavior, 'test.times()');\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: count, behavior });\n },\n\n /** Require zero calls; the first invocation fails and skips the original. */\n never(): ExpectationDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: 0 });\n },\n\n /** Read the recorded history for a watched method in one environment. */\n inspect(environment: unknown, token: unknown, method: string): MethodInspection {\n const registry = (environment as any)?.[ENV_REGISTRY];\n if (!registry) {\n throw new InvalidDescriptorError(\n 'test.inspect() requires a built @noego/testing environment as its first argument.',\n );\n }\n return registry.inspect(token, method);\n },\n};\n\nObject.freeze(test);\n\n/** Symbol under which a built environment exposes its watch registry. */\nexport const ENV_REGISTRY = Symbol.for('noego:testing:env-registry');\n\nexport interface RecordedCall {\n /** 1-based invocation index in this environment. */\n readonly index: number;\n readonly args: readonly unknown[];\n /** Present once the call returned (resolved value for async methods). */\n readonly result?: unknown;\n /** Present once the call threw/rejected. */\n readonly error?: unknown;\n /** True while an async outcome is still pending. */\n readonly pending: boolean;\n readonly timestamp: number;\n}\n\nexport interface MethodInspection {\n readonly count: number;\n readonly calls: readonly RecordedCall[];\n}\n","/**\n * Environment-owned method behavior/observation runtime.\n *\n * All mutable state (histories, expectation counters, calls-script cursors)\n * lives here, created fresh at every build(). Descriptors stay immutable.\n */\n\nimport {\n type BehaviorDescriptor,\n type ExpectationDescriptor,\n type MethodDescriptor,\n type MethodInspection,\n type RawMethodWrapper,\n type RecordedCall,\n isDescriptor,\n} from './descriptors';\nimport {\n CallScriptExhaustedError,\n TokenIdentitySplitError,\n ExpectationOverflowError,\n MethodNotCallableError,\n NonObjectMethodTargetError,\n UnwatchedInspectionError,\n VerificationError,\n} from './errors';\n\nconst CONTEXT_WRAPPED = Symbol.for('ioc:context-wrapped');\nconst CONTEXT_OWNER = Symbol.for('ioc:context-owner');\n\nexport function tokenLabel(token: unknown): string {\n if (typeof token === 'function') return (token as { name?: string }).name || '[anonymous class]';\n if (typeof token === 'symbol') return String(token);\n return String(token);\n}\n\ninterface MutableCall {\n index: number;\n args: readonly unknown[];\n result?: unknown;\n error?: unknown;\n pending: boolean;\n timestamp: number;\n}\n\nexport class MethodState {\n readonly calls: MutableCall[] = [];\n /** Actual invocation count (includes the call currently executing). */\n actual = 0;\n /** Cursor into a test.calls() script. */\n scriptCursor = 0;\n\n constructor(\n readonly tokenName: string,\n readonly method: string,\n readonly descriptor: Exclude<MethodDescriptor, RawMethodWrapper>,\n ) {}\n\n get expectation(): ExpectationDescriptor | undefined {\n return this.descriptor.kind === 'expect' ? this.descriptor : undefined;\n }\n\n inspection(): MethodInspection {\n return {\n count: this.calls.length,\n calls: this.calls.map((c) => ({ ...c, args: [...c.args] }) as RecordedCall),\n };\n }\n}\n\n/** One method-config entry: how it was keyed, and its per-method descriptors. */\nexport interface MethodConfigEntry {\n /** Exact token (class/symbol/string) or a name string matched lazily. */\n readonly key: unknown;\n readonly byName: boolean;\n readonly methods: ReadonlyMap<string, MethodDescriptor>;\n}\n\nexport class WatchRegistry {\n /** entry-identity → method → state. Entries share states across instances. */\n private readonly states = new Map<unknown, Map<string, MethodState>>();\n private readonly nameIndex = new Map<string, unknown>();\n private readonly entries: MethodConfigEntry[] = [];\n /** Class-token entries that identity-matched at least one construction. */\n private readonly matchedEntryKeys = new Set<unknown>();\n /** Constructed class tokens that matched NO entry, by display name. */\n private readonly unmatchedConstructedByName = new Map<string, unknown>();\n\n addEntry(entry: MethodConfigEntry): void {\n this.entries.push(entry);\n const byMethod = new Map<string, MethodState>();\n for (const [method, descriptor] of entry.methods) {\n if (typeof descriptor === 'function') continue; // raw wrapper: unwatched, no state\n byMethod.set(method, new MethodState(this.entryLabel(entry), method, descriptor));\n }\n this.states.set(entry.key, byMethod);\n if (entry.byName) this.nameIndex.set(entry.key as string, entry.key);\n else if (typeof entry.key === 'function' && (entry.key as any).name) {\n this.nameIndex.set((entry.key as any).name, entry.key);\n }\n }\n\n private entryLabel(entry: MethodConfigEntry): string {\n return entry.byName ? String(entry.key) : tokenLabel(entry.key);\n }\n\n /** Entries applying to a resolving token (exact identity or name match). */\n matchEntries(token: unknown): MethodConfigEntry[] {\n const name = typeof token === 'function' ? (token as any).name : typeof token === 'string' ? token : undefined;\n const matched = this.entries.filter(\n (entry) => entry.key === token || (entry.byName && name !== undefined && entry.key === name),\n );\n // Split-registry tripwire bookkeeping (spec 04 §17 \"duplicate\n // human-readable token names without identity collision\"): remember which\n // class-token entries genuinely bound, and which constructions bound\n // nothing — verify() cross-references the two by display name.\n if (matched.length) {\n for (const entry of matched) this.matchedEntryKeys.add(entry.key);\n } else if (typeof token === 'function' && name) {\n this.unmatchedConstructedByName.set(name, token);\n }\n return matched;\n }\n\n state(entryKey: unknown, method: string): MethodState | undefined {\n return this.states.get(entryKey)?.get(method);\n }\n\n inspect(token: unknown, method: string): MethodInspection {\n const label = tokenLabel(token);\n const keys: unknown[] = [token];\n const name = typeof token === 'function' ? (token as any).name : typeof token === 'string' ? token : undefined;\n if (name !== undefined && this.nameIndex.has(name)) keys.push(this.nameIndex.get(name));\n for (const key of keys) {\n const state = this.states.get(key)?.get(method);\n if (state) return state.inspection();\n }\n throw new UnwatchedInspectionError(label, method);\n }\n\n /**\n * Class-token entries that never identity-matched a construction while a\n * DIFFERENT class with the same display name did construct. This is the\n * split-module-registry signature (a test-file class object vs the graph's\n * own load of the same file) — or two genuinely distinct same-named tokens\n * where the configured one never resolved. Either way the configured\n * behavior silently did not apply, which must be loud.\n */\n private identitySplits(): { name: string; entryToken: unknown }[] {\n const splits: { name: string; entryToken: unknown }[] = [];\n for (const entry of this.entries) {\n if (entry.byName || typeof entry.key !== 'function') continue;\n if (this.matchedEntryKeys.has(entry.key)) continue;\n const name = (entry.key as { name?: string }).name;\n if (!name) continue;\n const constructed = this.unmatchedConstructedByName.get(name);\n if (constructed !== undefined && constructed !== entry.key) {\n splits.push({ name, entryToken: entry.key });\n }\n }\n return splits;\n }\n\n /** Repeatable snapshot check of all exact expectations. */\n verify(): void {\n const splits = this.identitySplits();\n if (splits.length) {\n throw new TokenIdentitySplitError(splits.map((split) => split.name));\n }\n const failures: { token: string; method: string; expected: number; actual: number }[] = [];\n for (const byMethod of this.states.values()) {\n for (const state of byMethod.values()) {\n const expectation = state.expectation;\n if (!expectation) continue;\n if (state.actual !== expectation.expected) {\n failures.push({\n token: state.tokenName,\n method: state.method,\n expected: expectation.expected,\n actual: state.actual,\n });\n }\n }\n }\n if (failures.length) throw new VerificationError(failures);\n }\n}\n\nfunction isPromiseLike(value: unknown): value is Promise<unknown> {\n return !!value && typeof (value as any).then === 'function';\n}\n\nfunction recordOutcome(call: MutableCall, outcome: unknown, threw: boolean): unknown {\n if (!threw && isPromiseLike(outcome)) {\n call.pending = true;\n outcome.then(\n (value) => {\n call.result = value;\n call.pending = false;\n },\n (error) => {\n call.error = error;\n call.pending = false;\n },\n );\n return outcome;\n }\n call.pending = false;\n if (threw) call.error = outcome;\n else call.result = outcome;\n return outcome;\n}\n\n/**\n * Build the ioc instance decorator for one environment.\n *\n * Identity-stable (WeakMap), preserves sync/async call shape and `this`\n * binding, forwards the ioc context symbols by delegating to the underlying\n * (context-wrapped) target for everything unconfigured.\n */\nexport function createMethodDecorator(registry: WatchRegistry): (instance: any, token: any) => any {\n const wrappers = new WeakMap<object, any>();\n\n return function decorate(instance: any, token: any): any {\n const entries = registry.matchEntries(token);\n if (entries.length === 0) return instance;\n\n if (instance === null || (typeof instance !== 'object' && typeof instance !== 'function')) {\n throw new NonObjectMethodTargetError(tokenLabel(token));\n }\n\n if (wrappers.has(instance)) return wrappers.get(instance);\n\n // Effective per-method config: entries merge in write order, LWW per method\n const effective = new Map<string, { entryKey: unknown; descriptor: MethodDescriptor }>();\n for (const entry of entries) {\n for (const [method, descriptor] of entry.methods) {\n effective.set(method, { entryKey: entry.key, descriptor });\n }\n }\n\n // Validate configured methods exist and are callable\n for (const method of effective.keys()) {\n if (typeof instance[method] !== 'function') {\n throw new MethodNotCallableError(tokenLabel(token), method);\n }\n }\n\n const methodCache = new Map<string, (...args: any[]) => any>();\n\n const proxy = new Proxy(instance, {\n get(target, prop, receiver) {\n if (typeof prop === 'string' && effective.has(prop)) {\n let wrapped = methodCache.get(prop);\n if (!wrapped) {\n const { entryKey, descriptor } = effective.get(prop)!;\n wrapped = buildMethodWrapper(target, prop, descriptor, registry.state(entryKey, prop));\n methodCache.set(prop, wrapped);\n }\n return wrapped;\n }\n // Everything else (including ioc context symbols) delegates to the\n // underlying — usually context-wrapped — target.\n if (prop === CONTEXT_WRAPPED || prop === CONTEXT_OWNER) return (target as any)[prop];\n return Reflect.get(target, prop, receiver);\n },\n });\n\n wrappers.set(instance, proxy);\n return proxy;\n };\n}\n\nfunction buildMethodWrapper(\n target: any,\n method: string,\n descriptor: MethodDescriptor,\n state: MethodState | undefined,\n): (...args: any[]) => any {\n // The original effective method, read through the underlying target so the\n // ioc context proxy still owns context entry for real invocations.\n const callOriginal = (self: any, args: any[]) => {\n const fn = target[method];\n return fn.apply(self === undefined ? target : self, args);\n };\n\n // Raw custom wrapper: installed as-is, NOT watched, no recording.\n if (typeof descriptor === 'function') {\n const replacement = descriptor((...args: any[]) => callOriginal(target, args));\n return function (this: any, ...args: any[]) {\n return replacement.apply(this, args);\n };\n }\n\n if (!isDescriptor(descriptor)) {\n // Should be unreachable: builder validates descriptors on write.\n throw new TypeError(`Invalid method descriptor for ${method}`);\n }\n\n return function (this: any, ...args: any[]) {\n if (!state) throw new TypeError(`Missing method state for ${method}`);\n\n const expectation = state.expectation;\n const attempted = state.actual + 1;\n\n // Overflow fails immediately and never runs behavior/original\n if (expectation && attempted > expectation.expected) {\n state.actual = attempted;\n throw new ExpectationOverflowError(state.tokenName, method, expectation.expected, attempted);\n }\n\n state.actual = attempted;\n const call: MutableCall = {\n index: attempted,\n args: [...args],\n pending: false,\n timestamp: Date.now(),\n };\n state.calls.push(call);\n\n // Effective behavior for this invocation\n let behavior: BehaviorDescriptor | 'original-effective' | RawMethodWrapper;\n const base =\n descriptor.kind === 'expect'\n ? (descriptor.behavior ?? 'original-effective')\n : descriptor.kind === 'watch'\n ? (descriptor.wrapper ?? 'original-effective')\n : descriptor;\n\n if (base !== 'original-effective' && typeof base !== 'function' && base !== undefined && base.kind === 'calls') {\n if (state.scriptCursor >= base.script.length) {\n throw new CallScriptExhaustedError(state.tokenName, method, base.script.length, attempted);\n }\n behavior = base.script[state.scriptCursor]!;\n state.scriptCursor += 1;\n } else {\n behavior = base;\n }\n\n try {\n let outcome: unknown;\n if (behavior === 'original-effective') {\n outcome = callOriginal(this, args);\n } else if (typeof behavior === 'function') {\n // test.watch(rawWrapper): wrapper behavior runs and is recorded\n outcome = behavior((...inner: any[]) => callOriginal(this, inner)).apply(this, args);\n } else if (behavior.kind === 'returns') {\n outcome = behavior.value;\n } else if (behavior.kind === 'throws') {\n throw behavior.error;\n } else if (behavior.kind === 'original') {\n outcome = callOriginal(this, args);\n } else {\n throw new TypeError(`Nested test.calls() scripts are not supported (${method}).`);\n }\n return recordOutcome(call, outcome, false);\n } catch (error) {\n recordOutcome(call, error, true);\n throw error;\n }\n };\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -130,12 +130,25 @@ declare class WatchRegistry {
130
130
  private readonly states;
131
131
  private readonly nameIndex;
132
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;
133
137
  addEntry(entry: MethodConfigEntry): void;
134
138
  private entryLabel;
135
139
  /** Entries applying to a resolving token (exact identity or name match). */
136
140
  matchEntries(token: unknown): MethodConfigEntry[];
137
141
  state(entryKey: unknown, method: string): MethodState | undefined;
138
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;
139
152
  /** Repeatable snapshot check of all exact expectations. */
140
153
  verify(): void;
141
154
  }
@@ -153,7 +166,19 @@ declare class WatchRegistry {
153
166
  type Token = unknown;
154
167
  type ClassLike = new (...args: any[]) => any;
155
168
  /** Config maps accept plain objects (string keys) or Maps (exact tokens). */
156
- type ConfigMap<V> = Record<string, V> | ReadonlyMap<Token, V>;
169
+ /**
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).
180
+ */
181
+ type ConfigMap<V> = ReadonlyArray<readonly [Token, V]> | ReadonlyMap<Token, V> | Record<string, V>;
157
182
  type MethodsConfig = ConfigMap<Record<string, MethodDescriptor> | ReadonlyMap<string, MethodDescriptor>>;
158
183
  type UseInput = ApplicationModule | TestIocBuilder;
159
184
  type Write = {
@@ -268,5 +293,26 @@ declare class UnknownTokenKeyError extends TestingError {
268
293
  /** Invalid descriptor construction (e.g. test.times(-1)). */
269
294
  declare class InvalidDescriptorError extends TestingError {
270
295
  }
296
+ /**
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).
300
+ */
301
+ declare class AmbiguousNameKeyError extends TestingError {
302
+ constructor(name: string, space: string);
303
+ }
304
+ /**
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.
313
+ */
314
+ declare class TokenIdentitySplitError extends TestingError {
315
+ constructor(names: readonly string[]);
316
+ }
271
317
 
272
- export { 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, UnknownTokenKeyError, UnwatchedInspectionError, type UseInput, VerificationError, type WatchDescriptor, test, testIoc };
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 };
package/dist/index.d.ts CHANGED
@@ -130,12 +130,25 @@ declare class WatchRegistry {
130
130
  private readonly states;
131
131
  private readonly nameIndex;
132
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;
133
137
  addEntry(entry: MethodConfigEntry): void;
134
138
  private entryLabel;
135
139
  /** Entries applying to a resolving token (exact identity or name match). */
136
140
  matchEntries(token: unknown): MethodConfigEntry[];
137
141
  state(entryKey: unknown, method: string): MethodState | undefined;
138
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;
139
152
  /** Repeatable snapshot check of all exact expectations. */
140
153
  verify(): void;
141
154
  }
@@ -153,7 +166,19 @@ declare class WatchRegistry {
153
166
  type Token = unknown;
154
167
  type ClassLike = new (...args: any[]) => any;
155
168
  /** Config maps accept plain objects (string keys) or Maps (exact tokens). */
156
- type ConfigMap<V> = Record<string, V> | ReadonlyMap<Token, V>;
169
+ /**
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).
180
+ */
181
+ type ConfigMap<V> = ReadonlyArray<readonly [Token, V]> | ReadonlyMap<Token, V> | Record<string, V>;
157
182
  type MethodsConfig = ConfigMap<Record<string, MethodDescriptor> | ReadonlyMap<string, MethodDescriptor>>;
158
183
  type UseInput = ApplicationModule | TestIocBuilder;
159
184
  type Write = {
@@ -268,5 +293,26 @@ declare class UnknownTokenKeyError extends TestingError {
268
293
  /** Invalid descriptor construction (e.g. test.times(-1)). */
269
294
  declare class InvalidDescriptorError extends TestingError {
270
295
  }
296
+ /**
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).
300
+ */
301
+ declare class AmbiguousNameKeyError extends TestingError {
302
+ constructor(name: string, space: string);
303
+ }
304
+ /**
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.
313
+ */
314
+ declare class TokenIdentitySplitError extends TestingError {
315
+ constructor(names: readonly string[]);
316
+ }
271
317
 
272
- export { 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, UnknownTokenKeyError, UnwatchedInspectionError, type UseInput, VerificationError, type WatchDescriptor, test, testIoc };
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 };
package/dist/index.js CHANGED
@@ -73,6 +73,22 @@ var UnknownTokenKeyError = class extends TestingError {
73
73
  };
74
74
  var InvalidDescriptorError = class extends TestingError {
75
75
  };
76
+ var AmbiguousNameKeyError = class extends TestingError {
77
+ constructor(name, space) {
78
+ super(
79
+ `.${space}() key "${name}" is ambiguous: multiple distinct tokens share that display name. Use the canonical tuple form with the exact token: .${space}([[TheToken, ...]]).`
80
+ );
81
+ this.name = "AmbiguousNameKeyError";
82
+ }
83
+ };
84
+ var TokenIdentitySplitError = class extends TestingError {
85
+ constructor(names) {
86
+ super(
87
+ `token identity split: .methods() entr${names.length === 1 ? "y" : "ies"} for ${names.map((name) => `"${name}"`).join(", ")} never matched a constructed instance, but a DIFFERENT class with the same name was constructed. Two module registries have loaded the same class file (test-file import vs harness graph import) \u2014 the configured behavior did not apply. Route the harness's imports through your registry (e.g. testApp .importer((p) => import(p))) or pass the exact token the graph uses.`
88
+ );
89
+ this.name = "TokenIdentitySplitError";
90
+ }
91
+ };
76
92
 
77
93
  // src/descriptors.ts
78
94
  var DESCRIPTOR = /* @__PURE__ */ Symbol.for("noego:testing:descriptor");
@@ -193,6 +209,10 @@ var WatchRegistry = class {
193
209
  states = /* @__PURE__ */ new Map();
194
210
  nameIndex = /* @__PURE__ */ new Map();
195
211
  entries = [];
212
+ /** Class-token entries that identity-matched at least one construction. */
213
+ matchedEntryKeys = /* @__PURE__ */ new Set();
214
+ /** Constructed class tokens that matched NO entry, by display name. */
215
+ unmatchedConstructedByName = /* @__PURE__ */ new Map();
196
216
  addEntry(entry) {
197
217
  this.entries.push(entry);
198
218
  const byMethod = /* @__PURE__ */ new Map();
@@ -212,9 +232,15 @@ var WatchRegistry = class {
212
232
  /** Entries applying to a resolving token (exact identity or name match). */
213
233
  matchEntries(token) {
214
234
  const name = typeof token === "function" ? token.name : typeof token === "string" ? token : void 0;
215
- return this.entries.filter(
235
+ const matched = this.entries.filter(
216
236
  (entry) => entry.key === token || entry.byName && name !== void 0 && entry.key === name
217
237
  );
238
+ if (matched.length) {
239
+ for (const entry of matched) this.matchedEntryKeys.add(entry.key);
240
+ } else if (typeof token === "function" && name) {
241
+ this.unmatchedConstructedByName.set(name, token);
242
+ }
243
+ return matched;
218
244
  }
219
245
  state(entryKey, method) {
220
246
  return this.states.get(entryKey)?.get(method);
@@ -230,8 +256,34 @@ var WatchRegistry = class {
230
256
  }
231
257
  throw new UnwatchedInspectionError(label, method);
232
258
  }
259
+ /**
260
+ * Class-token entries that never identity-matched a construction while a
261
+ * DIFFERENT class with the same display name did construct. This is the
262
+ * split-module-registry signature (a test-file class object vs the graph's
263
+ * own load of the same file) — or two genuinely distinct same-named tokens
264
+ * where the configured one never resolved. Either way the configured
265
+ * behavior silently did not apply, which must be loud.
266
+ */
267
+ identitySplits() {
268
+ const splits = [];
269
+ for (const entry of this.entries) {
270
+ if (entry.byName || typeof entry.key !== "function") continue;
271
+ if (this.matchedEntryKeys.has(entry.key)) continue;
272
+ const name = entry.key.name;
273
+ if (!name) continue;
274
+ const constructed = this.unmatchedConstructedByName.get(name);
275
+ if (constructed !== void 0 && constructed !== entry.key) {
276
+ splits.push({ name, entryToken: entry.key });
277
+ }
278
+ }
279
+ return splits;
280
+ }
233
281
  /** Repeatable snapshot check of all exact expectations. */
234
282
  verify() {
283
+ const splits = this.identitySplits();
284
+ if (splits.length) {
285
+ throw new TokenIdentitySplitError(splits.map((split) => split.name));
286
+ }
235
287
  const failures = [];
236
288
  for (const byMethod of this.states.values()) {
237
289
  for (const state of byMethod.values()) {
@@ -380,7 +432,16 @@ function buildMethodWrapper(target, method, descriptor, state) {
380
432
  // src/builder.ts
381
433
  var COMPONENT_OPTIONS_KEY = /* @__PURE__ */ Symbol.for("ioc:component:options");
382
434
  function* configEntries(config) {
383
- if (config instanceof Map) {
435
+ if (Array.isArray(config)) {
436
+ for (const entry of config) {
437
+ if (!Array.isArray(entry) || entry.length !== 2) {
438
+ throw new InvalidDescriptorError(
439
+ "canonical composition entries are [token, value] tuples, e.g. .classes([[Token, Impl]])"
440
+ );
441
+ }
442
+ yield [entry[0], false, entry[1]];
443
+ }
444
+ } else if (config instanceof Map) {
384
445
  for (const [key, value] of config) yield [key, false, value];
385
446
  } else {
386
447
  for (const key of [...Object.getOwnPropertyNames(config), ...Object.getOwnPropertySymbols(config)]) {
@@ -483,16 +544,24 @@ var TestIocBuilder = class _TestIocBuilder {
483
544
  throw new MissingIocSeamError();
484
545
  }
485
546
  const knownByName = /* @__PURE__ */ new Map();
547
+ const ambiguousNames = /* @__PURE__ */ new Set();
486
548
  const knownLifetimes = /* @__PURE__ */ new Map();
487
549
  const note = (token, loadAs) => {
488
- if (typeof token === "function" && token.name) knownByName.set(token.name, token);
489
- else if (typeof token === "string") knownByName.set(token, token);
550
+ const name = typeof token === "function" && token.name ? token.name : typeof token === "string" ? token : null;
551
+ if (name !== null) {
552
+ const existing = knownByName.get(name);
553
+ if (existing !== void 0 && existing !== token) ambiguousNames.add(name);
554
+ knownByName.set(name, token);
555
+ }
490
556
  if (loadAs !== void 0) knownLifetimes.set(token, loadAs);
491
557
  };
492
558
  const effective = /* @__PURE__ */ new Map();
493
559
  const methodWrites = [];
494
560
  const resolveKey = (key, byName, space) => {
495
561
  if (!byName) return key;
562
+ if (ambiguousNames.has(key)) {
563
+ throw new AmbiguousNameKeyError(key, space);
564
+ }
496
565
  const known = knownByName.get(key);
497
566
  if (known !== void 0) return known;
498
567
  if (space === "values" || space === "functions") return key;
@@ -537,8 +606,13 @@ var TestIocBuilder = class _TestIocBuilder {
537
606
  space: "class",
538
607
  token,
539
608
  implementation: write.implementation,
540
- // preserve configured lifetime unless the replacement declares its own scope
541
- loadAs: componentScope(write.implementation) ?? knownLifetimes.get(token)
609
+ // Lifetime priority: the replacement's own @Component scope, then
610
+ // the lifetime the composition already knows for the token, then
611
+ // the TOKEN class's declared @Component scope — a plain stub
612
+ // class replacing a Singleton-scoped production service must not
613
+ // silently degrade to Transient (captive-lifetime validation
614
+ // would reject the production dependents).
615
+ loadAs: componentScope(write.implementation) ?? knownLifetimes.get(token) ?? componentScope(token)
542
616
  });
543
617
  break;
544
618
  }
@@ -563,6 +637,9 @@ var TestIocBuilder = class _TestIocBuilder {
563
637
  break;
564
638
  }
565
639
  case "methods": {
640
+ if (write.byName && ambiguousNames.has(write.key)) {
641
+ throw new AmbiguousNameKeyError(write.key, "methods");
642
+ }
566
643
  const token = write.byName && knownByName.has(write.key) ? knownByName.get(write.key) : write.key;
567
644
  methodWrites.push({
568
645
  key: token,
@@ -637,6 +714,7 @@ function testIoc(...inputs) {
637
714
  return TestIocBuilder.create(inputs);
638
715
  }
639
716
  export {
717
+ AmbiguousNameKeyError,
640
718
  CallScriptExhaustedError,
641
719
  ENV_REGISTRY,
642
720
  ExpectationOverflowError,
@@ -646,6 +724,7 @@ export {
646
724
  NonObjectMethodTargetError,
647
725
  TestIocBuilder,
648
726
  TestingError,
727
+ TokenIdentitySplitError,
649
728
  UnknownTokenKeyError,
650
729
  UnwatchedInspectionError,
651
730
  VerificationError,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/builder.ts","../src/errors.ts","../src/descriptors.ts","../src/method_state.ts"],"sourcesContent":["/**\n * `testIoc` — the canonical shared real-IoC test composition builder.\n *\n * Persistent immutable: every fluent call returns a new derived builder\n * sharing the ordered write log structurally. Non-conflicting writes are\n * order-insensitive; the last write to the same effective identity wins on\n * that derived branch. `.build()` is non-consuming and creates fresh runtime,\n * watch, and expectation state (spec 15, PBR-01..15).\n */\n\nimport {\n createContainer,\n flattenModule,\n LoadAs,\n SCOPED_CONTAINER,\n type ApplicationModule,\n type IContainer,\n} from '@noego/ioc';\n\nimport { ENV_REGISTRY, isDescriptor, type MethodDescriptor } from './descriptors';\nimport { createMethodDecorator, WatchRegistry, tokenLabel } from './method_state';\nimport { InvalidDescriptorError, MissingIocSeamError, UnknownTokenKeyError } from './errors';\n\nconst COMPONENT_OPTIONS_KEY = Symbol.for('ioc:component:options');\n\ntype Token = unknown;\ntype ClassLike = new (...args: any[]) => any;\n\n/** Config maps accept plain objects (string keys) or Maps (exact tokens). */\nexport type ConfigMap<V> = Record<string, V> | ReadonlyMap<Token, V>;\n\nexport type MethodsConfig = ConfigMap<Record<string, MethodDescriptor> | ReadonlyMap<string, MethodDescriptor>>;\n\nexport type UseInput = ApplicationModule | TestIocBuilder;\n\ntype Write =\n | { op: 'use'; module: ApplicationModule }\n | { op: 'classes'; key: Token; byName: boolean; implementation: ClassLike }\n | { op: 'functions'; key: Token; byName: boolean; factory: (...args: any[]) => any }\n | { op: 'values'; key: Token; byName: boolean; value: unknown }\n | { op: 'methods'; key: Token; byName: boolean; methods: ReadonlyMap<string, MethodDescriptor> };\n\nexport interface TestEnvironment {\n readonly root: IContainer;\n get<T>(token: unknown, params?: any[]): Promise<T> | T;\n instance<T>(cls: new (...args: any[]) => T, params?: any[]): Promise<T> | T;\n extend(): IContainer;\n verify(): Promise<void>;\n dispose(): Promise<void>;\n readonly [ENV_REGISTRY]: WatchRegistry;\n}\n\nfunction* configEntries<V>(config: ConfigMap<V>): Iterable<[Token, boolean, V]> {\n if (config instanceof Map) {\n for (const [key, value] of config) yield [key, false, value];\n } else {\n for (const key of [...Object.getOwnPropertyNames(config), ...Object.getOwnPropertySymbols(config)]) {\n yield [key, typeof key === 'string', (config as any)[key]];\n }\n }\n}\n\nfunction componentScope(cls: any): LoadAs | undefined {\n const options =\n typeof Reflect !== 'undefined' && (Reflect as any).getMetadata\n ? (Reflect as any).getMetadata(COMPONENT_OPTIONS_KEY, cls)\n : undefined;\n return options?.scope;\n}\n\nfunction lifetimeToLoadAs(lifetime: string): LoadAs {\n if (lifetime === 'singleton') return LoadAs.Singleton;\n if (lifetime === 'scoped') return LoadAs.Scoped;\n return LoadAs.Transient;\n}\n\nexport class TestIocBuilder {\n private constructor(private readonly log: readonly Write[]) {\n Object.freeze(this);\n }\n\n /** @internal */\n static create(inputs: readonly UseInput[]): TestIocBuilder {\n return new TestIocBuilder([]).useAll(inputs);\n }\n\n /** @internal — read by .use(builderPreset) */\n get writes(): readonly Write[] {\n return this.log;\n }\n\n private derive(writes: Write[]): TestIocBuilder {\n return new TestIocBuilder([...this.log, ...writes]);\n }\n\n private useAll(inputs: readonly UseInput[]): TestIocBuilder {\n let builder: TestIocBuilder = this;\n for (const input of inputs) builder = builder.use(input);\n return builder;\n }\n\n /** Apply a reusable composition preset: an ApplicationModule or a builder. */\n use(preset: UseInput): TestIocBuilder {\n if (preset instanceof TestIocBuilder) {\n return this.derive([...preset.writes]);\n }\n return this.derive([{ op: 'use', module: preset }]);\n }\n\n /** Replace the implementation for IoC class tokens in the built environment. */\n classes(config: ConfigMap<ClassLike>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, implementation] of configEntries(config)) {\n if (typeof implementation !== 'function' || !implementation.prototype) {\n throw new InvalidDescriptorError(\n `.classes() value for \"${tokenLabel(key)}\" must be a class constructor.`,\n );\n }\n writes.push({ op: 'classes', key, byName, implementation });\n }\n return this.derive(writes);\n }\n\n /** Replace IoC factory/provider registrations. */\n functions(config: ConfigMap<(...args: any[]) => any>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, factory] of configEntries(config)) {\n if (typeof factory !== 'function') {\n throw new InvalidDescriptorError(`.functions() value for \"${tokenLabel(key)}\" must be a function.`);\n }\n writes.push({ op: 'functions', key, byName, factory });\n }\n return this.derive(writes);\n }\n\n /** Provide/replace IoC value registrations. */\n values(config: ConfigMap<unknown>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, value] of configEntries(config)) {\n writes.push({ op: 'values', key, byName, value });\n }\n return this.derive(writes);\n }\n\n /** Install method behavior/observation descriptors on IoC-managed instances. */\n methods(config: MethodsConfig): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, methodsInput] of configEntries(config)) {\n const methods = new Map<string, MethodDescriptor>();\n const entries =\n methodsInput instanceof Map\n ? methodsInput.entries()\n : Object.entries(methodsInput as Record<string, MethodDescriptor>);\n for (const [name, descriptor] of entries) {\n if (typeof descriptor !== 'function' && !isDescriptor(descriptor)) {\n throw new InvalidDescriptorError(\n `.methods() entry ${tokenLabel(key)}.${name} must be a test.* descriptor or a raw wrapper function.`,\n );\n }\n methods.set(name, descriptor);\n }\n writes.push({ op: 'methods', key, byName, methods });\n }\n return this.derive(writes);\n }\n\n /** Materialize a fresh, isolated real-IoC environment. Non-consuming. */\n async build(): Promise<TestEnvironment> {\n const root = createContainer();\n if (typeof (root as any).setInstanceDecorator !== 'function') {\n throw new MissingIocSeamError();\n }\n\n // ---- Materialize the ordered log: last write wins per effective identity\n // Known tokens (for resolving string keys of classes/functions/values)\n const knownByName = new Map<string, Token>();\n const knownLifetimes = new Map<Token, LoadAs>();\n const note = (token: Token, loadAs: LoadAs | undefined) => {\n if (typeof token === 'function' && (token as any).name) knownByName.set((token as any).name, token);\n else if (typeof token === 'string') knownByName.set(token, token);\n if (loadAs !== undefined) knownLifetimes.set(token, loadAs);\n };\n\n type Effective =\n | { space: 'class'; token: Token; implementation: ClassLike; loadAs?: LoadAs }\n | { space: 'factory'; token: Token; factory: (...args: any[]) => any; loadAs?: LoadAs; deps?: Token[] }\n | { space: 'value'; token: Token; value: unknown };\n\n // ordered map: identity → latest effective write (Map preserves first-write\n // position which is fine — later writes replace content, LWW)\n const effective = new Map<Token, Effective>();\n const methodWrites: { key: Token; byName: boolean; methods: Map<string, MethodDescriptor> }[] = [];\n\n const resolveKey = (key: Token, byName: boolean, space: string): Token => {\n if (!byName) return key;\n const known = knownByName.get(key as string);\n if (known !== undefined) return known;\n if (space === 'values' || space === 'functions') return key; // string tokens are first-class\n throw new UnknownTokenKeyError(key as string, space, [...knownByName.keys()]);\n };\n\n for (const write of this.log) {\n switch (write.op) {\n case 'use': {\n for (const reg of flattenModule(write.module)) {\n const loadAs = lifetimeToLoadAs(reg.lifetime);\n note(reg.token, loadAs);\n if (reg.kind === 'class') {\n note(reg.implementation as Token, loadAs);\n effective.set(reg.token, {\n space: 'class',\n token: reg.token,\n implementation: reg.implementation as ClassLike,\n loadAs,\n });\n knownLifetimes.set(reg.token, loadAs);\n knownLifetimes.set(reg.implementation as Token, loadAs);\n } else if (reg.kind === 'factory') {\n effective.set(reg.token, {\n space: 'factory',\n token: reg.token,\n factory: reg.implementation as (...args: any[]) => any,\n loadAs,\n deps: [...reg.dependencies],\n });\n } else {\n effective.set(reg.token, { space: 'value', token: reg.token, value: reg.implementation });\n knownLifetimes.set(reg.token, LoadAs.Singleton);\n }\n }\n break;\n }\n case 'classes': {\n const token = resolveKey(write.key, write.byName, 'classes');\n note(write.implementation, undefined);\n if (!write.byName) note(token, undefined);\n effective.set(token, {\n space: 'class',\n token,\n implementation: write.implementation,\n // preserve configured lifetime unless the replacement declares its own scope\n loadAs: componentScope(write.implementation) ?? knownLifetimes.get(token),\n });\n break;\n }\n case 'functions': {\n const token = resolveKey(write.key, write.byName, 'functions');\n const prior = effective.get(token);\n effective.set(token, {\n space: 'factory',\n token,\n factory: write.factory,\n // preserve configured lifetime unless the scenario overrides it\n loadAs: prior && prior.space === 'factory' ? prior.loadAs : knownLifetimes.get(token),\n deps: prior && prior.space === 'factory' ? prior.deps : undefined,\n });\n note(token, undefined);\n break;\n }\n case 'values': {\n const token = resolveKey(write.key, write.byName, 'values');\n effective.set(token, { space: 'value', token, value: write.value });\n note(token, LoadAs.Singleton);\n break;\n }\n case 'methods': {\n const token = write.byName && knownByName.has(write.key as string)\n ? knownByName.get(write.key as string)!\n : write.key;\n methodWrites.push({\n key: token,\n byName: write.byName && !knownByName.has(write.key as string),\n methods: new Map(write.methods),\n });\n break;\n }\n }\n }\n\n // ---- Apply effective registrations to the fresh root\n for (const entry of effective.values()) {\n if (entry.space === 'class') {\n this.registerClassBinding(root, entry.token, entry.implementation, entry.loadAs);\n } else if (entry.space === 'factory') {\n root.registerFunction(entry.token, entry.factory, {\n loadAs: entry.loadAs,\n param: entry.deps,\n } as any);\n } else {\n const value = entry.value;\n root.registerFunction(entry.token, () => value, { loadAs: LoadAs.Singleton } as any);\n }\n }\n\n // ---- Fresh watch/expectation state + the ioc decoration seam\n const registry = new WatchRegistry();\n // merge method writes: LWW per (entry key, method), deep-merge per token\n const mergedMethods = new Map<Token, { byName: boolean; methods: Map<string, MethodDescriptor> }>();\n for (const write of methodWrites) {\n const existing = mergedMethods.get(write.key);\n if (existing) {\n for (const [name, descriptor] of write.methods) existing.methods.set(name, descriptor);\n } else {\n mergedMethods.set(write.key, { byName: write.byName, methods: new Map(write.methods) });\n }\n }\n for (const [key, { byName, methods }] of mergedMethods) {\n registry.addEntry({ key, byName, methods });\n }\n (root as any).setInstanceDecorator(createMethodDecorator(registry));\n\n const env: TestEnvironment = {\n root: root as IContainer,\n get: (token, params) => root.get(token as any, params),\n instance: (cls, params) => root.instance(cls, params),\n extend: () => root.extend() as IContainer,\n verify: async () => registry.verify(),\n dispose: () => root.dispose(),\n [ENV_REGISTRY]: registry,\n };\n return env;\n }\n\n /**\n * Register a class binding. When token === implementation this is a plain\n * class registration. Otherwise an alias factory resolves the implementation\n * through real IoC, mirroring the implementation's effective lifetime so\n * lifetime validation (captive-lifetime checks) stays honest.\n */\n private registerClassBinding(\n root: IContainer,\n token: Token,\n implementation: ClassLike,\n configuredLoadAs?: LoadAs,\n ): void {\n const loadAs = configuredLoadAs ?? componentScope(implementation) ?? LoadAs.Transient;\n root.registerClass(implementation as any, configuredLoadAs !== undefined ? ({ loadAs } as any) : undefined);\n if (token === implementation) return;\n\n if (loadAs === LoadAs.Singleton) {\n root.registerFunction(token, () => root.get(implementation as any), {\n loadAs: LoadAs.Singleton,\n } as any);\n } else {\n root.registerFunction(token, (scope: IContainer) => scope.get(implementation as any), {\n loadAs,\n param: [SCOPED_CONTAINER],\n } as any);\n }\n }\n}\n\n/** Create a persistent immutable real-IoC test composition builder. */\nexport function testIoc(...inputs: UseInput[]): TestIocBuilder {\n return TestIocBuilder.create(inputs);\n}\n","/**\n * Diagnostics are first-class: every error names the real token/method and\n * what was expected vs what happened, never only internal wrapper machinery.\n */\n\nexport class TestingError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** Thrown at build() when the installed @noego/ioc lacks the decoration seam. */\nexport class MissingIocSeamError extends TestingError {\n constructor() {\n super(\n '@noego/testing requires an @noego/ioc version that provides ' +\n 'Container.setInstanceDecorator (>= 0.5.x with the instance-decoration seam). ' +\n 'Upgrade @noego/ioc.',\n );\n }\n}\n\n/** test.inspect() on a method that is not watched in this environment. */\nexport class UnwatchedInspectionError extends TestingError {\n constructor(token: string, method: string) {\n super(\n `Method \"${method}\" on ${token} is not watched in this environment. ` +\n 'Only watched methods are inspectable — install test.watch() or any ' +\n 'test.* behavior/expectation descriptor for it.',\n );\n }\n}\n\n/** A call arrived after a test.calls([...]) script was fully consumed. */\nexport class CallScriptExhaustedError extends TestingError {\n constructor(token: string, method: string, scriptLength: number, callIndex: number) {\n super(\n `Call #${callIndex} to ${token}.${method} exceeds its test.calls() script ` +\n `of ${scriptLength} ${scriptLength === 1 ? 'entry' : 'entries'}.`,\n );\n }\n}\n\n/** An exact expectation (once/times/never) was exceeded at call time. */\nexport class ExpectationOverflowError extends TestingError {\n constructor(token: string, method: string, expected: number, attempted: number) {\n super(\n expected === 0\n ? `${token}.${method} was expected never to be called, but it was invoked.`\n : `${token}.${method} was expected exactly ${expected} ` +\n `${expected === 1 ? 'call' : 'calls'}, but call #${attempted} arrived.`,\n );\n }\n}\n\n/** Aggregated under-count failures reported by env.verify(). */\nexport class VerificationError extends TestingError {\n constructor(failures: readonly { token: string; method: string; expected: number; actual: number }[]) {\n super(\n 'Exact method expectations were not satisfied:\\n' +\n failures\n .map(\n (f) =>\n ` - ${f.token}.${f.method}: expected exactly ${f.expected} ` +\n `${f.expected === 1 ? 'call' : 'calls'}, observed ${f.actual}`,\n )\n .join('\\n'),\n );\n }\n}\n\n/** .methods configured for a token whose resolved value has no such callable method. */\nexport class MethodNotCallableError extends TestingError {\n constructor(token: string, method: string) {\n super(\n `Cannot install a test.* descriptor on ${token}.${method}: the resolved ` +\n 'instance has no callable method with that name.',\n );\n }\n}\n\n/** .methods configured for a token that resolved to a non-object value. */\nexport class NonObjectMethodTargetError extends TestingError {\n constructor(token: string) {\n super(\n `.methods() is configured for ${token}, but that token resolved to a ` +\n 'non-object value. Method descriptors apply only to IoC-managed instances.',\n );\n }\n}\n\n/** A string configuration key could not be resolved to a known IoC token. */\nexport class UnknownTokenKeyError extends TestingError {\n constructor(key: string, space: string, known: readonly string[]) {\n super(\n `Unknown ${space} key \"${key}\" — it does not match any token known to this ` +\n 'builder. Pass the class/token itself via a Map, or include the ' +\n 'registration through .use(...). Known tokens: ' +\n (known.length ? known.join(', ') : '(none)'),\n );\n }\n}\n\n/** Invalid descriptor construction (e.g. test.times(-1)). */\nexport class InvalidDescriptorError extends TestingError {}\n","/**\n * Lowercase `test.*` descriptors — immutable frozen values.\n *\n * Descriptors carry NO mutable state (no cursors, no counters, no histories);\n * all mutable invocation state lives in the built environment, so one\n * descriptor value is safe to share across builders and repeated builds.\n */\n\nimport { InvalidDescriptorError } from './errors';\n\nexport const DESCRIPTOR = Symbol.for('noego:testing:descriptor');\n\n/** A raw custom method wrapper: (original) => replacement. NOT auto-watched. */\nexport type RawMethodWrapper = (\n original: (...args: any[]) => any,\n) => (...args: any[]) => any;\n\nexport interface ReturnsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'returns';\n readonly value: unknown;\n}\n\nexport interface ThrowsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'throws';\n readonly error: unknown;\n}\n\nexport interface OriginalDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'original';\n}\n\nexport interface CallsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'calls';\n readonly script: readonly BehaviorDescriptor[];\n}\n\nexport type BehaviorDescriptor =\n | ReturnsDescriptor\n | ThrowsDescriptor\n | OriginalDescriptor\n | CallsDescriptor;\n\nexport interface WatchDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'watch';\n readonly wrapper?: RawMethodWrapper;\n}\n\nexport interface ExpectationDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'expect';\n /** Exact required call count; 0 for never(). */\n readonly expected: number;\n /** Behavior used for allowed calls; undefined = original effective behavior. */\n readonly behavior?: BehaviorDescriptor;\n}\n\n/** Everything installable through .methods({...}). */\nexport type MethodDescriptor =\n | BehaviorDescriptor\n | WatchDescriptor\n | ExpectationDescriptor\n | RawMethodWrapper;\n\nexport function isDescriptor(value: unknown): value is Exclude<MethodDescriptor, RawMethodWrapper> {\n return typeof value === 'object' && value !== null && (value as any)[DESCRIPTOR] === true;\n}\n\nfunction frozen<T extends object>(value: T): T {\n return Object.freeze(value);\n}\n\nfunction assertBehavior(value: unknown, where: string): asserts value is BehaviorDescriptor {\n if (!isDescriptor(value) || !['returns', 'throws', 'original', 'calls'].includes((value as any).kind)) {\n throw new InvalidDescriptorError(\n `${where} requires a behavior descriptor (test.returns/throws/original/calls).`,\n );\n }\n}\n\nexport const test = {\n /** Return the supplied value when the method is called. Auto-watches. */\n returns(value: unknown): ReturnsDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'returns' as const, value });\n },\n\n /** Throw/reject with the supplied error. Auto-watches. */\n throws(error: unknown): ThrowsDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'throws' as const, error });\n },\n\n /** Invoke the original effective method. Auto-watches. */\n original(): OriginalDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'original' as const });\n },\n\n /**\n * Per-invocation behavior script: call 1 uses entry 1, and so on. A call\n * after exhaustion fails immediately. Unused entries do not fail verification.\n */\n calls(script: readonly BehaviorDescriptor[]): CallsDescriptor {\n if (!Array.isArray(script)) {\n throw new InvalidDescriptorError('test.calls() requires an array of behavior descriptors.');\n }\n script.forEach((entry, i) => assertBehavior(entry, `test.calls() entry #${i + 1}`));\n return frozen({ [DESCRIPTOR]: true as const, kind: 'calls' as const, script: Object.freeze([...script]) });\n },\n\n /**\n * Keep original behavior and record calls. With a raw wrapper argument, the\n * wrapper's behavior runs and is recorded.\n */\n watch(wrapper?: RawMethodWrapper): WatchDescriptor {\n if (wrapper !== undefined && typeof wrapper !== 'function') {\n throw new InvalidDescriptorError('test.watch() accepts only a raw wrapper function.');\n }\n return frozen({ [DESCRIPTOR]: true as const, kind: 'watch' as const, wrapper });\n },\n\n /** Require exactly one call; with no behavior, the original runs. */\n once(behavior?: BehaviorDescriptor): ExpectationDescriptor {\n if (behavior !== undefined) assertBehavior(behavior, 'test.once()');\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: 1, behavior });\n },\n\n /** Require exactly `count` calls; with no behavior, the original runs. */\n times(count: number, behavior?: BehaviorDescriptor): ExpectationDescriptor {\n if (!Number.isInteger(count) || count < 0) {\n throw new InvalidDescriptorError(\n `test.times() requires a non-negative integer count, received ${String(count)}.`,\n );\n }\n if (behavior !== undefined) assertBehavior(behavior, 'test.times()');\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: count, behavior });\n },\n\n /** Require zero calls; the first invocation fails and skips the original. */\n never(): ExpectationDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: 0 });\n },\n\n /** Read the recorded history for a watched method in one environment. */\n inspect(environment: unknown, token: unknown, method: string): MethodInspection {\n const registry = (environment as any)?.[ENV_REGISTRY];\n if (!registry) {\n throw new InvalidDescriptorError(\n 'test.inspect() requires a built @noego/testing environment as its first argument.',\n );\n }\n return registry.inspect(token, method);\n },\n};\n\nObject.freeze(test);\n\n/** Symbol under which a built environment exposes its watch registry. */\nexport const ENV_REGISTRY = Symbol.for('noego:testing:env-registry');\n\nexport interface RecordedCall {\n /** 1-based invocation index in this environment. */\n readonly index: number;\n readonly args: readonly unknown[];\n /** Present once the call returned (resolved value for async methods). */\n readonly result?: unknown;\n /** Present once the call threw/rejected. */\n readonly error?: unknown;\n /** True while an async outcome is still pending. */\n readonly pending: boolean;\n readonly timestamp: number;\n}\n\nexport interface MethodInspection {\n readonly count: number;\n readonly calls: readonly RecordedCall[];\n}\n","/**\n * Environment-owned method behavior/observation runtime.\n *\n * All mutable state (histories, expectation counters, calls-script cursors)\n * lives here, created fresh at every build(). Descriptors stay immutable.\n */\n\nimport {\n type BehaviorDescriptor,\n type ExpectationDescriptor,\n type MethodDescriptor,\n type MethodInspection,\n type RawMethodWrapper,\n type RecordedCall,\n isDescriptor,\n} from './descriptors';\nimport {\n CallScriptExhaustedError,\n ExpectationOverflowError,\n MethodNotCallableError,\n NonObjectMethodTargetError,\n UnwatchedInspectionError,\n VerificationError,\n} from './errors';\n\nconst CONTEXT_WRAPPED = Symbol.for('ioc:context-wrapped');\nconst CONTEXT_OWNER = Symbol.for('ioc:context-owner');\n\nexport function tokenLabel(token: unknown): string {\n if (typeof token === 'function') return (token as { name?: string }).name || '[anonymous class]';\n if (typeof token === 'symbol') return String(token);\n return String(token);\n}\n\ninterface MutableCall {\n index: number;\n args: readonly unknown[];\n result?: unknown;\n error?: unknown;\n pending: boolean;\n timestamp: number;\n}\n\nexport class MethodState {\n readonly calls: MutableCall[] = [];\n /** Actual invocation count (includes the call currently executing). */\n actual = 0;\n /** Cursor into a test.calls() script. */\n scriptCursor = 0;\n\n constructor(\n readonly tokenName: string,\n readonly method: string,\n readonly descriptor: Exclude<MethodDescriptor, RawMethodWrapper>,\n ) {}\n\n get expectation(): ExpectationDescriptor | undefined {\n return this.descriptor.kind === 'expect' ? this.descriptor : undefined;\n }\n\n inspection(): MethodInspection {\n return {\n count: this.calls.length,\n calls: this.calls.map((c) => ({ ...c, args: [...c.args] }) as RecordedCall),\n };\n }\n}\n\n/** One method-config entry: how it was keyed, and its per-method descriptors. */\nexport interface MethodConfigEntry {\n /** Exact token (class/symbol/string) or a name string matched lazily. */\n readonly key: unknown;\n readonly byName: boolean;\n readonly methods: ReadonlyMap<string, MethodDescriptor>;\n}\n\nexport class WatchRegistry {\n /** entry-identity → method → state. Entries share states across instances. */\n private readonly states = new Map<unknown, Map<string, MethodState>>();\n private readonly nameIndex = new Map<string, unknown>();\n private readonly entries: MethodConfigEntry[] = [];\n\n addEntry(entry: MethodConfigEntry): void {\n this.entries.push(entry);\n const byMethod = new Map<string, MethodState>();\n for (const [method, descriptor] of entry.methods) {\n if (typeof descriptor === 'function') continue; // raw wrapper: unwatched, no state\n byMethod.set(method, new MethodState(this.entryLabel(entry), method, descriptor));\n }\n this.states.set(entry.key, byMethod);\n if (entry.byName) this.nameIndex.set(entry.key as string, entry.key);\n else if (typeof entry.key === 'function' && (entry.key as any).name) {\n this.nameIndex.set((entry.key as any).name, entry.key);\n }\n }\n\n private entryLabel(entry: MethodConfigEntry): string {\n return entry.byName ? String(entry.key) : tokenLabel(entry.key);\n }\n\n /** Entries applying to a resolving token (exact identity or name match). */\n matchEntries(token: unknown): MethodConfigEntry[] {\n const name = typeof token === 'function' ? (token as any).name : typeof token === 'string' ? token : undefined;\n return this.entries.filter(\n (entry) => entry.key === token || (entry.byName && name !== undefined && entry.key === name),\n );\n }\n\n state(entryKey: unknown, method: string): MethodState | undefined {\n return this.states.get(entryKey)?.get(method);\n }\n\n inspect(token: unknown, method: string): MethodInspection {\n const label = tokenLabel(token);\n const keys: unknown[] = [token];\n const name = typeof token === 'function' ? (token as any).name : typeof token === 'string' ? token : undefined;\n if (name !== undefined && this.nameIndex.has(name)) keys.push(this.nameIndex.get(name));\n for (const key of keys) {\n const state = this.states.get(key)?.get(method);\n if (state) return state.inspection();\n }\n throw new UnwatchedInspectionError(label, method);\n }\n\n /** Repeatable snapshot check of all exact expectations. */\n verify(): void {\n const failures: { token: string; method: string; expected: number; actual: number }[] = [];\n for (const byMethod of this.states.values()) {\n for (const state of byMethod.values()) {\n const expectation = state.expectation;\n if (!expectation) continue;\n if (state.actual !== expectation.expected) {\n failures.push({\n token: state.tokenName,\n method: state.method,\n expected: expectation.expected,\n actual: state.actual,\n });\n }\n }\n }\n if (failures.length) throw new VerificationError(failures);\n }\n}\n\nfunction isPromiseLike(value: unknown): value is Promise<unknown> {\n return !!value && typeof (value as any).then === 'function';\n}\n\nfunction recordOutcome(call: MutableCall, outcome: unknown, threw: boolean): unknown {\n if (!threw && isPromiseLike(outcome)) {\n call.pending = true;\n outcome.then(\n (value) => {\n call.result = value;\n call.pending = false;\n },\n (error) => {\n call.error = error;\n call.pending = false;\n },\n );\n return outcome;\n }\n call.pending = false;\n if (threw) call.error = outcome;\n else call.result = outcome;\n return outcome;\n}\n\n/**\n * Build the ioc instance decorator for one environment.\n *\n * Identity-stable (WeakMap), preserves sync/async call shape and `this`\n * binding, forwards the ioc context symbols by delegating to the underlying\n * (context-wrapped) target for everything unconfigured.\n */\nexport function createMethodDecorator(registry: WatchRegistry): (instance: any, token: any) => any {\n const wrappers = new WeakMap<object, any>();\n\n return function decorate(instance: any, token: any): any {\n const entries = registry.matchEntries(token);\n if (entries.length === 0) return instance;\n\n if (instance === null || (typeof instance !== 'object' && typeof instance !== 'function')) {\n throw new NonObjectMethodTargetError(tokenLabel(token));\n }\n\n if (wrappers.has(instance)) return wrappers.get(instance);\n\n // Effective per-method config: entries merge in write order, LWW per method\n const effective = new Map<string, { entryKey: unknown; descriptor: MethodDescriptor }>();\n for (const entry of entries) {\n for (const [method, descriptor] of entry.methods) {\n effective.set(method, { entryKey: entry.key, descriptor });\n }\n }\n\n // Validate configured methods exist and are callable\n for (const method of effective.keys()) {\n if (typeof instance[method] !== 'function') {\n throw new MethodNotCallableError(tokenLabel(token), method);\n }\n }\n\n const methodCache = new Map<string, (...args: any[]) => any>();\n\n const proxy = new Proxy(instance, {\n get(target, prop, receiver) {\n if (typeof prop === 'string' && effective.has(prop)) {\n let wrapped = methodCache.get(prop);\n if (!wrapped) {\n const { entryKey, descriptor } = effective.get(prop)!;\n wrapped = buildMethodWrapper(target, prop, descriptor, registry.state(entryKey, prop));\n methodCache.set(prop, wrapped);\n }\n return wrapped;\n }\n // Everything else (including ioc context symbols) delegates to the\n // underlying — usually context-wrapped — target.\n if (prop === CONTEXT_WRAPPED || prop === CONTEXT_OWNER) return (target as any)[prop];\n return Reflect.get(target, prop, receiver);\n },\n });\n\n wrappers.set(instance, proxy);\n return proxy;\n };\n}\n\nfunction buildMethodWrapper(\n target: any,\n method: string,\n descriptor: MethodDescriptor,\n state: MethodState | undefined,\n): (...args: any[]) => any {\n // The original effective method, read through the underlying target so the\n // ioc context proxy still owns context entry for real invocations.\n const callOriginal = (self: any, args: any[]) => {\n const fn = target[method];\n return fn.apply(self === undefined ? target : self, args);\n };\n\n // Raw custom wrapper: installed as-is, NOT watched, no recording.\n if (typeof descriptor === 'function') {\n const replacement = descriptor((...args: any[]) => callOriginal(target, args));\n return function (this: any, ...args: any[]) {\n return replacement.apply(this, args);\n };\n }\n\n if (!isDescriptor(descriptor)) {\n // Should be unreachable: builder validates descriptors on write.\n throw new TypeError(`Invalid method descriptor for ${method}`);\n }\n\n return function (this: any, ...args: any[]) {\n if (!state) throw new TypeError(`Missing method state for ${method}`);\n\n const expectation = state.expectation;\n const attempted = state.actual + 1;\n\n // Overflow fails immediately and never runs behavior/original\n if (expectation && attempted > expectation.expected) {\n state.actual = attempted;\n throw new ExpectationOverflowError(state.tokenName, method, expectation.expected, attempted);\n }\n\n state.actual = attempted;\n const call: MutableCall = {\n index: attempted,\n args: [...args],\n pending: false,\n timestamp: Date.now(),\n };\n state.calls.push(call);\n\n // Effective behavior for this invocation\n let behavior: BehaviorDescriptor | 'original-effective' | RawMethodWrapper;\n const base =\n descriptor.kind === 'expect'\n ? (descriptor.behavior ?? 'original-effective')\n : descriptor.kind === 'watch'\n ? (descriptor.wrapper ?? 'original-effective')\n : descriptor;\n\n if (base !== 'original-effective' && typeof base !== 'function' && base !== undefined && base.kind === 'calls') {\n if (state.scriptCursor >= base.script.length) {\n throw new CallScriptExhaustedError(state.tokenName, method, base.script.length, attempted);\n }\n behavior = base.script[state.scriptCursor]!;\n state.scriptCursor += 1;\n } else {\n behavior = base;\n }\n\n try {\n let outcome: unknown;\n if (behavior === 'original-effective') {\n outcome = callOriginal(this, args);\n } else if (typeof behavior === 'function') {\n // test.watch(rawWrapper): wrapper behavior runs and is recorded\n outcome = behavior((...inner: any[]) => callOriginal(this, inner)).apply(this, args);\n } else if (behavior.kind === 'returns') {\n outcome = behavior.value;\n } else if (behavior.kind === 'throws') {\n throw behavior.error;\n } else if (behavior.kind === 'original') {\n outcome = callOriginal(this, args);\n } else {\n throw new TypeError(`Nested test.calls() scripts are not supported (${method}).`);\n }\n return recordOutcome(call, outcome, false);\n } catch (error) {\n recordOutcome(call, error, true);\n throw error;\n }\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/builder.ts","../src/errors.ts","../src/descriptors.ts","../src/method_state.ts"],"sourcesContent":["/**\n * `testIoc` — the canonical shared real-IoC test composition builder.\n *\n * Persistent immutable: every fluent call returns a new derived builder\n * sharing the ordered write log structurally. Non-conflicting writes are\n * order-insensitive; the last write to the same effective identity wins on\n * that derived branch. `.build()` is non-consuming and creates fresh runtime,\n * watch, and expectation state (spec 15, PBR-01..15).\n */\n\nimport {\n createContainer,\n flattenModule,\n LoadAs,\n SCOPED_CONTAINER,\n type ApplicationModule,\n type IContainer,\n} from '@noego/ioc';\n\nimport { ENV_REGISTRY, isDescriptor, type MethodDescriptor } from './descriptors';\nimport { createMethodDecorator, WatchRegistry, tokenLabel } from './method_state';\nimport { InvalidDescriptorError, MissingIocSeamError, UnknownTokenKeyError, AmbiguousNameKeyError,\n} from './errors';\n\nconst COMPONENT_OPTIONS_KEY = Symbol.for('ioc:component:options');\n\ntype Token = unknown;\ntype ClassLike = new (...args: any[]) => any;\n\n/** Config maps accept plain objects (string keys) or Maps (exact tokens). */\n/**\n * Composition input (spec 04 §2). The CANONICAL entry form is an array of\n * tuples — token-first, exact identity:\n *\n * .classes([[ProjectRepository, MemoryProjectRepository]])\n *\n * A `ReadonlyMap<Token, V>` is equivalent (token-keyed). A name-keyed\n * `Record<string, V>` remains accepted as COMPATIBILITY input: string keys\n * resolve against known token display names, fail on unknown names, and\n * fail on ambiguous names (two tokens sharing one display name never\n * collapse into one entry — tokens are identities, names are labels).\n */\nexport type ConfigMap<V> =\n | ReadonlyArray<readonly [Token, V]>\n | ReadonlyMap<Token, V>\n | Record<string, V>;\n\nexport type MethodsConfig = ConfigMap<Record<string, MethodDescriptor> | ReadonlyMap<string, MethodDescriptor>>;\n\nexport type UseInput = ApplicationModule | TestIocBuilder;\n\ntype Write =\n | { op: 'use'; module: ApplicationModule }\n | { op: 'classes'; key: Token; byName: boolean; implementation: ClassLike }\n | { op: 'functions'; key: Token; byName: boolean; factory: (...args: any[]) => any }\n | { op: 'values'; key: Token; byName: boolean; value: unknown }\n | { op: 'methods'; key: Token; byName: boolean; methods: ReadonlyMap<string, MethodDescriptor> };\n\nexport interface TestEnvironment {\n readonly root: IContainer;\n get<T>(token: unknown, params?: any[]): Promise<T> | T;\n instance<T>(cls: new (...args: any[]) => T, params?: any[]): Promise<T> | T;\n extend(): IContainer;\n verify(): Promise<void>;\n dispose(): Promise<void>;\n readonly [ENV_REGISTRY]: WatchRegistry;\n}\n\nfunction* configEntries<V>(config: ConfigMap<V>): Iterable<[Token, boolean, V]> {\n if (Array.isArray(config)) {\n // Canonical tuple form: exact token identity, never name resolution.\n for (const entry of config as ReadonlyArray<readonly [Token, V]>) {\n if (!Array.isArray(entry) || entry.length !== 2) {\n throw new InvalidDescriptorError(\n 'canonical composition entries are [token, value] tuples, e.g. .classes([[Token, Impl]])',\n );\n }\n yield [entry[0], false, entry[1]];\n }\n } else if (config instanceof Map) {\n for (const [key, value] of config) yield [key, false, value];\n } else {\n for (const key of [...Object.getOwnPropertyNames(config), ...Object.getOwnPropertySymbols(config)]) {\n yield [key, typeof key === 'string', (config as any)[key]];\n }\n }\n}\n\nfunction componentScope(cls: any): LoadAs | undefined {\n const options =\n typeof Reflect !== 'undefined' && (Reflect as any).getMetadata\n ? (Reflect as any).getMetadata(COMPONENT_OPTIONS_KEY, cls)\n : undefined;\n return options?.scope;\n}\n\nfunction lifetimeToLoadAs(lifetime: string): LoadAs {\n if (lifetime === 'singleton') return LoadAs.Singleton;\n if (lifetime === 'scoped') return LoadAs.Scoped;\n return LoadAs.Transient;\n}\n\nexport class TestIocBuilder {\n private constructor(private readonly log: readonly Write[]) {\n Object.freeze(this);\n }\n\n /** @internal */\n static create(inputs: readonly UseInput[]): TestIocBuilder {\n return new TestIocBuilder([]).useAll(inputs);\n }\n\n /** @internal — read by .use(builderPreset) */\n get writes(): readonly Write[] {\n return this.log;\n }\n\n private derive(writes: Write[]): TestIocBuilder {\n return new TestIocBuilder([...this.log, ...writes]);\n }\n\n private useAll(inputs: readonly UseInput[]): TestIocBuilder {\n let builder: TestIocBuilder = this;\n for (const input of inputs) builder = builder.use(input);\n return builder;\n }\n\n /** Apply a reusable composition preset: an ApplicationModule or a builder. */\n use(preset: UseInput): TestIocBuilder {\n if (preset instanceof TestIocBuilder) {\n return this.derive([...preset.writes]);\n }\n return this.derive([{ op: 'use', module: preset }]);\n }\n\n /** Replace the implementation for IoC class tokens in the built environment. */\n classes(config: ConfigMap<ClassLike>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, implementation] of configEntries(config)) {\n if (typeof implementation !== 'function' || !implementation.prototype) {\n throw new InvalidDescriptorError(\n `.classes() value for \"${tokenLabel(key)}\" must be a class constructor.`,\n );\n }\n writes.push({ op: 'classes', key, byName, implementation });\n }\n return this.derive(writes);\n }\n\n /** Replace IoC factory/provider registrations. */\n functions(config: ConfigMap<(...args: any[]) => any>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, factory] of configEntries(config)) {\n if (typeof factory !== 'function') {\n throw new InvalidDescriptorError(`.functions() value for \"${tokenLabel(key)}\" must be a function.`);\n }\n writes.push({ op: 'functions', key, byName, factory });\n }\n return this.derive(writes);\n }\n\n /** Provide/replace IoC value registrations. */\n values(config: ConfigMap<unknown>): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, value] of configEntries(config)) {\n writes.push({ op: 'values', key, byName, value });\n }\n return this.derive(writes);\n }\n\n /** Install method behavior/observation descriptors on IoC-managed instances. */\n methods(config: MethodsConfig): TestIocBuilder {\n const writes: Write[] = [];\n for (const [key, byName, methodsInput] of configEntries(config)) {\n const methods = new Map<string, MethodDescriptor>();\n const entries =\n methodsInput instanceof Map\n ? methodsInput.entries()\n : Object.entries(methodsInput as Record<string, MethodDescriptor>);\n for (const [name, descriptor] of entries) {\n if (typeof descriptor !== 'function' && !isDescriptor(descriptor)) {\n throw new InvalidDescriptorError(\n `.methods() entry ${tokenLabel(key)}.${name} must be a test.* descriptor or a raw wrapper function.`,\n );\n }\n methods.set(name, descriptor);\n }\n writes.push({ op: 'methods', key, byName, methods });\n }\n return this.derive(writes);\n }\n\n /** Materialize a fresh, isolated real-IoC environment. Non-consuming. */\n async build(): Promise<TestEnvironment> {\n const root = createContainer();\n if (typeof (root as any).setInstanceDecorator !== 'function') {\n throw new MissingIocSeamError();\n }\n\n // ---- Materialize the ordered log: last write wins per effective identity\n // Known tokens (for resolving string keys of classes/functions/values)\n const knownByName = new Map<string, Token>();\n /** Display names claimed by more than one distinct token (spec 04 §5/§17). */\n const ambiguousNames = new Set<string>();\n const knownLifetimes = new Map<Token, LoadAs>();\n const note = (token: Token, loadAs: LoadAs | undefined) => {\n const name =\n typeof token === 'function' && (token as any).name\n ? (token as any).name as string\n : typeof token === 'string'\n ? token\n : null;\n if (name !== null) {\n const existing = knownByName.get(name);\n if (existing !== undefined && existing !== token) ambiguousNames.add(name);\n knownByName.set(name, token);\n }\n if (loadAs !== undefined) knownLifetimes.set(token, loadAs);\n };\n\n type Effective =\n | { space: 'class'; token: Token; implementation: ClassLike; loadAs?: LoadAs }\n | { space: 'factory'; token: Token; factory: (...args: any[]) => any; loadAs?: LoadAs; deps?: Token[] }\n | { space: 'value'; token: Token; value: unknown };\n\n // ordered map: identity → latest effective write (Map preserves first-write\n // position which is fine — later writes replace content, LWW)\n const effective = new Map<Token, Effective>();\n const methodWrites: { key: Token; byName: boolean; methods: Map<string, MethodDescriptor> }[] = [];\n\n const resolveKey = (key: Token, byName: boolean, space: string): Token => {\n if (!byName) return key;\n if (ambiguousNames.has(key as string)) {\n throw new AmbiguousNameKeyError(key as string, space);\n }\n const known = knownByName.get(key as string);\n if (known !== undefined) return known;\n if (space === 'values' || space === 'functions') return key; // string tokens are first-class\n throw new UnknownTokenKeyError(key as string, space, [...knownByName.keys()]);\n };\n\n for (const write of this.log) {\n switch (write.op) {\n case 'use': {\n for (const reg of flattenModule(write.module)) {\n const loadAs = lifetimeToLoadAs(reg.lifetime);\n note(reg.token, loadAs);\n if (reg.kind === 'class') {\n note(reg.implementation as Token, loadAs);\n effective.set(reg.token, {\n space: 'class',\n token: reg.token,\n implementation: reg.implementation as ClassLike,\n loadAs,\n });\n knownLifetimes.set(reg.token, loadAs);\n knownLifetimes.set(reg.implementation as Token, loadAs);\n } else if (reg.kind === 'factory') {\n effective.set(reg.token, {\n space: 'factory',\n token: reg.token,\n factory: reg.implementation as (...args: any[]) => any,\n loadAs,\n deps: [...reg.dependencies],\n });\n } else {\n effective.set(reg.token, { space: 'value', token: reg.token, value: reg.implementation });\n knownLifetimes.set(reg.token, LoadAs.Singleton);\n }\n }\n break;\n }\n case 'classes': {\n const token = resolveKey(write.key, write.byName, 'classes');\n note(write.implementation, undefined);\n if (!write.byName) note(token, undefined);\n effective.set(token, {\n space: 'class',\n token,\n implementation: write.implementation,\n // Lifetime priority: the replacement's own @Component scope, then\n // the lifetime the composition already knows for the token, then\n // the TOKEN class's declared @Component scope — a plain stub\n // class replacing a Singleton-scoped production service must not\n // silently degrade to Transient (captive-lifetime validation\n // would reject the production dependents).\n loadAs:\n componentScope(write.implementation)\n ?? knownLifetimes.get(token)\n ?? componentScope(token),\n });\n break;\n }\n case 'functions': {\n const token = resolveKey(write.key, write.byName, 'functions');\n const prior = effective.get(token);\n effective.set(token, {\n space: 'factory',\n token,\n factory: write.factory,\n // preserve configured lifetime unless the scenario overrides it\n loadAs: prior && prior.space === 'factory' ? prior.loadAs : knownLifetimes.get(token),\n deps: prior && prior.space === 'factory' ? prior.deps : undefined,\n });\n note(token, undefined);\n break;\n }\n case 'values': {\n const token = resolveKey(write.key, write.byName, 'values');\n effective.set(token, { space: 'value', token, value: write.value });\n note(token, LoadAs.Singleton);\n break;\n }\n case 'methods': {\n if (write.byName && ambiguousNames.has(write.key as string)) {\n throw new AmbiguousNameKeyError(write.key as string, 'methods');\n }\n const token = write.byName && knownByName.has(write.key as string)\n ? knownByName.get(write.key as string)!\n : write.key;\n methodWrites.push({\n key: token,\n byName: write.byName && !knownByName.has(write.key as string),\n methods: new Map(write.methods),\n });\n break;\n }\n }\n }\n\n // ---- Apply effective registrations to the fresh root\n for (const entry of effective.values()) {\n if (entry.space === 'class') {\n this.registerClassBinding(root, entry.token, entry.implementation, entry.loadAs);\n } else if (entry.space === 'factory') {\n root.registerFunction(entry.token, entry.factory, {\n loadAs: entry.loadAs,\n param: entry.deps,\n } as any);\n } else {\n const value = entry.value;\n root.registerFunction(entry.token, () => value, { loadAs: LoadAs.Singleton } as any);\n }\n }\n\n // ---- Fresh watch/expectation state + the ioc decoration seam\n const registry = new WatchRegistry();\n // merge method writes: LWW per (entry key, method), deep-merge per token\n const mergedMethods = new Map<Token, { byName: boolean; methods: Map<string, MethodDescriptor> }>();\n for (const write of methodWrites) {\n const existing = mergedMethods.get(write.key);\n if (existing) {\n for (const [name, descriptor] of write.methods) existing.methods.set(name, descriptor);\n } else {\n mergedMethods.set(write.key, { byName: write.byName, methods: new Map(write.methods) });\n }\n }\n for (const [key, { byName, methods }] of mergedMethods) {\n registry.addEntry({ key, byName, methods });\n }\n (root as any).setInstanceDecorator(createMethodDecorator(registry));\n\n const env: TestEnvironment = {\n root: root as IContainer,\n get: (token, params) => root.get(token as any, params),\n instance: (cls, params) => root.instance(cls, params),\n extend: () => root.extend() as IContainer,\n verify: async () => registry.verify(),\n dispose: () => root.dispose(),\n [ENV_REGISTRY]: registry,\n };\n return env;\n }\n\n /**\n * Register a class binding. When token === implementation this is a plain\n * class registration. Otherwise an alias factory resolves the implementation\n * through real IoC, mirroring the implementation's effective lifetime so\n * lifetime validation (captive-lifetime checks) stays honest.\n */\n private registerClassBinding(\n root: IContainer,\n token: Token,\n implementation: ClassLike,\n configuredLoadAs?: LoadAs,\n ): void {\n const loadAs = configuredLoadAs ?? componentScope(implementation) ?? LoadAs.Transient;\n root.registerClass(implementation as any, configuredLoadAs !== undefined ? ({ loadAs } as any) : undefined);\n if (token === implementation) return;\n\n if (loadAs === LoadAs.Singleton) {\n root.registerFunction(token, () => root.get(implementation as any), {\n loadAs: LoadAs.Singleton,\n } as any);\n } else {\n root.registerFunction(token, (scope: IContainer) => scope.get(implementation as any), {\n loadAs,\n param: [SCOPED_CONTAINER],\n } as any);\n }\n }\n}\n\n/** Create a persistent immutable real-IoC test composition builder. */\nexport function testIoc(...inputs: UseInput[]): TestIocBuilder {\n return TestIocBuilder.create(inputs);\n}\n","/**\n * Diagnostics are first-class: every error names the real token/method and\n * what was expected vs what happened, never only internal wrapper machinery.\n */\n\nexport class TestingError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** Thrown at build() when the installed @noego/ioc lacks the decoration seam. */\nexport class MissingIocSeamError extends TestingError {\n constructor() {\n super(\n '@noego/testing requires an @noego/ioc version that provides ' +\n 'Container.setInstanceDecorator (>= 0.5.x with the instance-decoration seam). ' +\n 'Upgrade @noego/ioc.',\n );\n }\n}\n\n/** test.inspect() on a method that is not watched in this environment. */\nexport class UnwatchedInspectionError extends TestingError {\n constructor(token: string, method: string) {\n super(\n `Method \"${method}\" on ${token} is not watched in this environment. ` +\n 'Only watched methods are inspectable — install test.watch() or any ' +\n 'test.* behavior/expectation descriptor for it.',\n );\n }\n}\n\n/** A call arrived after a test.calls([...]) script was fully consumed. */\nexport class CallScriptExhaustedError extends TestingError {\n constructor(token: string, method: string, scriptLength: number, callIndex: number) {\n super(\n `Call #${callIndex} to ${token}.${method} exceeds its test.calls() script ` +\n `of ${scriptLength} ${scriptLength === 1 ? 'entry' : 'entries'}.`,\n );\n }\n}\n\n/** An exact expectation (once/times/never) was exceeded at call time. */\nexport class ExpectationOverflowError extends TestingError {\n constructor(token: string, method: string, expected: number, attempted: number) {\n super(\n expected === 0\n ? `${token}.${method} was expected never to be called, but it was invoked.`\n : `${token}.${method} was expected exactly ${expected} ` +\n `${expected === 1 ? 'call' : 'calls'}, but call #${attempted} arrived.`,\n );\n }\n}\n\n/** Aggregated under-count failures reported by env.verify(). */\nexport class VerificationError extends TestingError {\n constructor(failures: readonly { token: string; method: string; expected: number; actual: number }[]) {\n super(\n 'Exact method expectations were not satisfied:\\n' +\n failures\n .map(\n (f) =>\n ` - ${f.token}.${f.method}: expected exactly ${f.expected} ` +\n `${f.expected === 1 ? 'call' : 'calls'}, observed ${f.actual}`,\n )\n .join('\\n'),\n );\n }\n}\n\n/** .methods configured for a token whose resolved value has no such callable method. */\nexport class MethodNotCallableError extends TestingError {\n constructor(token: string, method: string) {\n super(\n `Cannot install a test.* descriptor on ${token}.${method}: the resolved ` +\n 'instance has no callable method with that name.',\n );\n }\n}\n\n/** .methods configured for a token that resolved to a non-object value. */\nexport class NonObjectMethodTargetError extends TestingError {\n constructor(token: string) {\n super(\n `.methods() is configured for ${token}, but that token resolved to a ` +\n 'non-object value. Method descriptors apply only to IoC-managed instances.',\n );\n }\n}\n\n/** A string configuration key could not be resolved to a known IoC token. */\nexport class UnknownTokenKeyError extends TestingError {\n constructor(key: string, space: string, known: readonly string[]) {\n super(\n `Unknown ${space} key \"${key}\" — it does not match any token known to this ` +\n 'builder. Pass the class/token itself via a Map, or include the ' +\n 'registration through .use(...). Known tokens: ' +\n (known.length ? known.join(', ') : '(none)'),\n );\n }\n}\n\n/** Invalid descriptor construction (e.g. test.times(-1)). */\nexport class InvalidDescriptorError extends TestingError {}\n\n/**\n * A name-keyed compatibility entry referred to a display name claimed by\n * two or more distinct tokens. Tokens are identities; names are labels —\n * pass the exact token in canonical tuple form instead (spec 04 §5).\n */\nexport class AmbiguousNameKeyError extends TestingError {\n constructor(name: string, space: string) {\n super(\n `.${space}() key \"${name}\" is ambiguous: multiple distinct tokens share that display name. ` +\n `Use the canonical tuple form with the exact token: .${space}([[TheToken, ...]]).`,\n );\n this.name = 'AmbiguousNameKeyError';\n }\n}\n\n\n/**\n * A .methods() class token never matched any constructed instance while a\n * DIFFERENT class with the same display name did construct — the configured\n * behavior silently did not apply. Usual cause: two module registries loaded\n * the same source file (e.g. a vitest test file's import vs a framework\n * harness's native import of the production graph); fix by routing the\n * harness's imports through the caller's registry (testApp:\n * `.importer((p) => import(p))`) or by passing the token the graph actually\n * uses.\n */\nexport class TokenIdentitySplitError extends TestingError {\n constructor(names: readonly string[]) {\n super(\n `token identity split: .methods() entr${names.length === 1 ? 'y' : 'ies'} for ` +\n `${names.map((name) => `\"${name}\"`).join(', ')} never matched a constructed instance, ` +\n `but a DIFFERENT class with the same name was constructed. Two module registries ` +\n `have loaded the same class file (test-file import vs harness graph import) — the ` +\n `configured behavior did not apply. Route the harness's imports through your ` +\n `registry (e.g. testApp .importer((p) => import(p))) or pass the exact token the graph uses.`,\n );\n this.name = 'TokenIdentitySplitError';\n }\n}\n","/**\n * Lowercase `test.*` descriptors — immutable frozen values.\n *\n * Descriptors carry NO mutable state (no cursors, no counters, no histories);\n * all mutable invocation state lives in the built environment, so one\n * descriptor value is safe to share across builders and repeated builds.\n */\n\nimport { InvalidDescriptorError } from './errors';\n\nexport const DESCRIPTOR = Symbol.for('noego:testing:descriptor');\n\n/** A raw custom method wrapper: (original) => replacement. NOT auto-watched. */\nexport type RawMethodWrapper = (\n original: (...args: any[]) => any,\n) => (...args: any[]) => any;\n\nexport interface ReturnsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'returns';\n readonly value: unknown;\n}\n\nexport interface ThrowsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'throws';\n readonly error: unknown;\n}\n\nexport interface OriginalDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'original';\n}\n\nexport interface CallsDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'calls';\n readonly script: readonly BehaviorDescriptor[];\n}\n\nexport type BehaviorDescriptor =\n | ReturnsDescriptor\n | ThrowsDescriptor\n | OriginalDescriptor\n | CallsDescriptor;\n\nexport interface WatchDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'watch';\n readonly wrapper?: RawMethodWrapper;\n}\n\nexport interface ExpectationDescriptor {\n readonly [DESCRIPTOR]: true;\n readonly kind: 'expect';\n /** Exact required call count; 0 for never(). */\n readonly expected: number;\n /** Behavior used for allowed calls; undefined = original effective behavior. */\n readonly behavior?: BehaviorDescriptor;\n}\n\n/** Everything installable through .methods({...}). */\nexport type MethodDescriptor =\n | BehaviorDescriptor\n | WatchDescriptor\n | ExpectationDescriptor\n | RawMethodWrapper;\n\nexport function isDescriptor(value: unknown): value is Exclude<MethodDescriptor, RawMethodWrapper> {\n return typeof value === 'object' && value !== null && (value as any)[DESCRIPTOR] === true;\n}\n\nfunction frozen<T extends object>(value: T): T {\n return Object.freeze(value);\n}\n\nfunction assertBehavior(value: unknown, where: string): asserts value is BehaviorDescriptor {\n if (!isDescriptor(value) || !['returns', 'throws', 'original', 'calls'].includes((value as any).kind)) {\n throw new InvalidDescriptorError(\n `${where} requires a behavior descriptor (test.returns/throws/original/calls).`,\n );\n }\n}\n\nexport const test = {\n /** Return the supplied value when the method is called. Auto-watches. */\n returns(value: unknown): ReturnsDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'returns' as const, value });\n },\n\n /** Throw/reject with the supplied error. Auto-watches. */\n throws(error: unknown): ThrowsDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'throws' as const, error });\n },\n\n /** Invoke the original effective method. Auto-watches. */\n original(): OriginalDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'original' as const });\n },\n\n /**\n * Per-invocation behavior script: call 1 uses entry 1, and so on. A call\n * after exhaustion fails immediately. Unused entries do not fail verification.\n */\n calls(script: readonly BehaviorDescriptor[]): CallsDescriptor {\n if (!Array.isArray(script)) {\n throw new InvalidDescriptorError('test.calls() requires an array of behavior descriptors.');\n }\n script.forEach((entry, i) => assertBehavior(entry, `test.calls() entry #${i + 1}`));\n return frozen({ [DESCRIPTOR]: true as const, kind: 'calls' as const, script: Object.freeze([...script]) });\n },\n\n /**\n * Keep original behavior and record calls. With a raw wrapper argument, the\n * wrapper's behavior runs and is recorded.\n */\n watch(wrapper?: RawMethodWrapper): WatchDescriptor {\n if (wrapper !== undefined && typeof wrapper !== 'function') {\n throw new InvalidDescriptorError('test.watch() accepts only a raw wrapper function.');\n }\n return frozen({ [DESCRIPTOR]: true as const, kind: 'watch' as const, wrapper });\n },\n\n /** Require exactly one call; with no behavior, the original runs. */\n once(behavior?: BehaviorDescriptor): ExpectationDescriptor {\n if (behavior !== undefined) assertBehavior(behavior, 'test.once()');\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: 1, behavior });\n },\n\n /** Require exactly `count` calls; with no behavior, the original runs. */\n times(count: number, behavior?: BehaviorDescriptor): ExpectationDescriptor {\n if (!Number.isInteger(count) || count < 0) {\n throw new InvalidDescriptorError(\n `test.times() requires a non-negative integer count, received ${String(count)}.`,\n );\n }\n if (behavior !== undefined) assertBehavior(behavior, 'test.times()');\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: count, behavior });\n },\n\n /** Require zero calls; the first invocation fails and skips the original. */\n never(): ExpectationDescriptor {\n return frozen({ [DESCRIPTOR]: true as const, kind: 'expect' as const, expected: 0 });\n },\n\n /** Read the recorded history for a watched method in one environment. */\n inspect(environment: unknown, token: unknown, method: string): MethodInspection {\n const registry = (environment as any)?.[ENV_REGISTRY];\n if (!registry) {\n throw new InvalidDescriptorError(\n 'test.inspect() requires a built @noego/testing environment as its first argument.',\n );\n }\n return registry.inspect(token, method);\n },\n};\n\nObject.freeze(test);\n\n/** Symbol under which a built environment exposes its watch registry. */\nexport const ENV_REGISTRY = Symbol.for('noego:testing:env-registry');\n\nexport interface RecordedCall {\n /** 1-based invocation index in this environment. */\n readonly index: number;\n readonly args: readonly unknown[];\n /** Present once the call returned (resolved value for async methods). */\n readonly result?: unknown;\n /** Present once the call threw/rejected. */\n readonly error?: unknown;\n /** True while an async outcome is still pending. */\n readonly pending: boolean;\n readonly timestamp: number;\n}\n\nexport interface MethodInspection {\n readonly count: number;\n readonly calls: readonly RecordedCall[];\n}\n","/**\n * Environment-owned method behavior/observation runtime.\n *\n * All mutable state (histories, expectation counters, calls-script cursors)\n * lives here, created fresh at every build(). Descriptors stay immutable.\n */\n\nimport {\n type BehaviorDescriptor,\n type ExpectationDescriptor,\n type MethodDescriptor,\n type MethodInspection,\n type RawMethodWrapper,\n type RecordedCall,\n isDescriptor,\n} from './descriptors';\nimport {\n CallScriptExhaustedError,\n TokenIdentitySplitError,\n ExpectationOverflowError,\n MethodNotCallableError,\n NonObjectMethodTargetError,\n UnwatchedInspectionError,\n VerificationError,\n} from './errors';\n\nconst CONTEXT_WRAPPED = Symbol.for('ioc:context-wrapped');\nconst CONTEXT_OWNER = Symbol.for('ioc:context-owner');\n\nexport function tokenLabel(token: unknown): string {\n if (typeof token === 'function') return (token as { name?: string }).name || '[anonymous class]';\n if (typeof token === 'symbol') return String(token);\n return String(token);\n}\n\ninterface MutableCall {\n index: number;\n args: readonly unknown[];\n result?: unknown;\n error?: unknown;\n pending: boolean;\n timestamp: number;\n}\n\nexport class MethodState {\n readonly calls: MutableCall[] = [];\n /** Actual invocation count (includes the call currently executing). */\n actual = 0;\n /** Cursor into a test.calls() script. */\n scriptCursor = 0;\n\n constructor(\n readonly tokenName: string,\n readonly method: string,\n readonly descriptor: Exclude<MethodDescriptor, RawMethodWrapper>,\n ) {}\n\n get expectation(): ExpectationDescriptor | undefined {\n return this.descriptor.kind === 'expect' ? this.descriptor : undefined;\n }\n\n inspection(): MethodInspection {\n return {\n count: this.calls.length,\n calls: this.calls.map((c) => ({ ...c, args: [...c.args] }) as RecordedCall),\n };\n }\n}\n\n/** One method-config entry: how it was keyed, and its per-method descriptors. */\nexport interface MethodConfigEntry {\n /** Exact token (class/symbol/string) or a name string matched lazily. */\n readonly key: unknown;\n readonly byName: boolean;\n readonly methods: ReadonlyMap<string, MethodDescriptor>;\n}\n\nexport class WatchRegistry {\n /** entry-identity → method → state. Entries share states across instances. */\n private readonly states = new Map<unknown, Map<string, MethodState>>();\n private readonly nameIndex = new Map<string, unknown>();\n private readonly entries: MethodConfigEntry[] = [];\n /** Class-token entries that identity-matched at least one construction. */\n private readonly matchedEntryKeys = new Set<unknown>();\n /** Constructed class tokens that matched NO entry, by display name. */\n private readonly unmatchedConstructedByName = new Map<string, unknown>();\n\n addEntry(entry: MethodConfigEntry): void {\n this.entries.push(entry);\n const byMethod = new Map<string, MethodState>();\n for (const [method, descriptor] of entry.methods) {\n if (typeof descriptor === 'function') continue; // raw wrapper: unwatched, no state\n byMethod.set(method, new MethodState(this.entryLabel(entry), method, descriptor));\n }\n this.states.set(entry.key, byMethod);\n if (entry.byName) this.nameIndex.set(entry.key as string, entry.key);\n else if (typeof entry.key === 'function' && (entry.key as any).name) {\n this.nameIndex.set((entry.key as any).name, entry.key);\n }\n }\n\n private entryLabel(entry: MethodConfigEntry): string {\n return entry.byName ? String(entry.key) : tokenLabel(entry.key);\n }\n\n /** Entries applying to a resolving token (exact identity or name match). */\n matchEntries(token: unknown): MethodConfigEntry[] {\n const name = typeof token === 'function' ? (token as any).name : typeof token === 'string' ? token : undefined;\n const matched = this.entries.filter(\n (entry) => entry.key === token || (entry.byName && name !== undefined && entry.key === name),\n );\n // Split-registry tripwire bookkeeping (spec 04 §17 \"duplicate\n // human-readable token names without identity collision\"): remember which\n // class-token entries genuinely bound, and which constructions bound\n // nothing — verify() cross-references the two by display name.\n if (matched.length) {\n for (const entry of matched) this.matchedEntryKeys.add(entry.key);\n } else if (typeof token === 'function' && name) {\n this.unmatchedConstructedByName.set(name, token);\n }\n return matched;\n }\n\n state(entryKey: unknown, method: string): MethodState | undefined {\n return this.states.get(entryKey)?.get(method);\n }\n\n inspect(token: unknown, method: string): MethodInspection {\n const label = tokenLabel(token);\n const keys: unknown[] = [token];\n const name = typeof token === 'function' ? (token as any).name : typeof token === 'string' ? token : undefined;\n if (name !== undefined && this.nameIndex.has(name)) keys.push(this.nameIndex.get(name));\n for (const key of keys) {\n const state = this.states.get(key)?.get(method);\n if (state) return state.inspection();\n }\n throw new UnwatchedInspectionError(label, method);\n }\n\n /**\n * Class-token entries that never identity-matched a construction while a\n * DIFFERENT class with the same display name did construct. This is the\n * split-module-registry signature (a test-file class object vs the graph's\n * own load of the same file) — or two genuinely distinct same-named tokens\n * where the configured one never resolved. Either way the configured\n * behavior silently did not apply, which must be loud.\n */\n private identitySplits(): { name: string; entryToken: unknown }[] {\n const splits: { name: string; entryToken: unknown }[] = [];\n for (const entry of this.entries) {\n if (entry.byName || typeof entry.key !== 'function') continue;\n if (this.matchedEntryKeys.has(entry.key)) continue;\n const name = (entry.key as { name?: string }).name;\n if (!name) continue;\n const constructed = this.unmatchedConstructedByName.get(name);\n if (constructed !== undefined && constructed !== entry.key) {\n splits.push({ name, entryToken: entry.key });\n }\n }\n return splits;\n }\n\n /** Repeatable snapshot check of all exact expectations. */\n verify(): void {\n const splits = this.identitySplits();\n if (splits.length) {\n throw new TokenIdentitySplitError(splits.map((split) => split.name));\n }\n const failures: { token: string; method: string; expected: number; actual: number }[] = [];\n for (const byMethod of this.states.values()) {\n for (const state of byMethod.values()) {\n const expectation = state.expectation;\n if (!expectation) continue;\n if (state.actual !== expectation.expected) {\n failures.push({\n token: state.tokenName,\n method: state.method,\n expected: expectation.expected,\n actual: state.actual,\n });\n }\n }\n }\n if (failures.length) throw new VerificationError(failures);\n }\n}\n\nfunction isPromiseLike(value: unknown): value is Promise<unknown> {\n return !!value && typeof (value as any).then === 'function';\n}\n\nfunction recordOutcome(call: MutableCall, outcome: unknown, threw: boolean): unknown {\n if (!threw && isPromiseLike(outcome)) {\n call.pending = true;\n outcome.then(\n (value) => {\n call.result = value;\n call.pending = false;\n },\n (error) => {\n call.error = error;\n call.pending = false;\n },\n );\n return outcome;\n }\n call.pending = false;\n if (threw) call.error = outcome;\n else call.result = outcome;\n return outcome;\n}\n\n/**\n * Build the ioc instance decorator for one environment.\n *\n * Identity-stable (WeakMap), preserves sync/async call shape and `this`\n * binding, forwards the ioc context symbols by delegating to the underlying\n * (context-wrapped) target for everything unconfigured.\n */\nexport function createMethodDecorator(registry: WatchRegistry): (instance: any, token: any) => any {\n const wrappers = new WeakMap<object, any>();\n\n return function decorate(instance: any, token: any): any {\n const entries = registry.matchEntries(token);\n if (entries.length === 0) return instance;\n\n if (instance === null || (typeof instance !== 'object' && typeof instance !== 'function')) {\n throw new NonObjectMethodTargetError(tokenLabel(token));\n }\n\n if (wrappers.has(instance)) return wrappers.get(instance);\n\n // Effective per-method config: entries merge in write order, LWW per method\n const effective = new Map<string, { entryKey: unknown; descriptor: MethodDescriptor }>();\n for (const entry of entries) {\n for (const [method, descriptor] of entry.methods) {\n effective.set(method, { entryKey: entry.key, descriptor });\n }\n }\n\n // Validate configured methods exist and are callable\n for (const method of effective.keys()) {\n if (typeof instance[method] !== 'function') {\n throw new MethodNotCallableError(tokenLabel(token), method);\n }\n }\n\n const methodCache = new Map<string, (...args: any[]) => any>();\n\n const proxy = new Proxy(instance, {\n get(target, prop, receiver) {\n if (typeof prop === 'string' && effective.has(prop)) {\n let wrapped = methodCache.get(prop);\n if (!wrapped) {\n const { entryKey, descriptor } = effective.get(prop)!;\n wrapped = buildMethodWrapper(target, prop, descriptor, registry.state(entryKey, prop));\n methodCache.set(prop, wrapped);\n }\n return wrapped;\n }\n // Everything else (including ioc context symbols) delegates to the\n // underlying — usually context-wrapped — target.\n if (prop === CONTEXT_WRAPPED || prop === CONTEXT_OWNER) return (target as any)[prop];\n return Reflect.get(target, prop, receiver);\n },\n });\n\n wrappers.set(instance, proxy);\n return proxy;\n };\n}\n\nfunction buildMethodWrapper(\n target: any,\n method: string,\n descriptor: MethodDescriptor,\n state: MethodState | undefined,\n): (...args: any[]) => any {\n // The original effective method, read through the underlying target so the\n // ioc context proxy still owns context entry for real invocations.\n const callOriginal = (self: any, args: any[]) => {\n const fn = target[method];\n return fn.apply(self === undefined ? target : self, args);\n };\n\n // Raw custom wrapper: installed as-is, NOT watched, no recording.\n if (typeof descriptor === 'function') {\n const replacement = descriptor((...args: any[]) => callOriginal(target, args));\n return function (this: any, ...args: any[]) {\n return replacement.apply(this, args);\n };\n }\n\n if (!isDescriptor(descriptor)) {\n // Should be unreachable: builder validates descriptors on write.\n throw new TypeError(`Invalid method descriptor for ${method}`);\n }\n\n return function (this: any, ...args: any[]) {\n if (!state) throw new TypeError(`Missing method state for ${method}`);\n\n const expectation = state.expectation;\n const attempted = state.actual + 1;\n\n // Overflow fails immediately and never runs behavior/original\n if (expectation && attempted > expectation.expected) {\n state.actual = attempted;\n throw new ExpectationOverflowError(state.tokenName, method, expectation.expected, attempted);\n }\n\n state.actual = attempted;\n const call: MutableCall = {\n index: attempted,\n args: [...args],\n pending: false,\n timestamp: Date.now(),\n };\n state.calls.push(call);\n\n // Effective behavior for this invocation\n let behavior: BehaviorDescriptor | 'original-effective' | RawMethodWrapper;\n const base =\n descriptor.kind === 'expect'\n ? (descriptor.behavior ?? 'original-effective')\n : descriptor.kind === 'watch'\n ? (descriptor.wrapper ?? 'original-effective')\n : descriptor;\n\n if (base !== 'original-effective' && typeof base !== 'function' && base !== undefined && base.kind === 'calls') {\n if (state.scriptCursor >= base.script.length) {\n throw new CallScriptExhaustedError(state.tokenName, method, base.script.length, attempted);\n }\n behavior = base.script[state.scriptCursor]!;\n state.scriptCursor += 1;\n } else {\n behavior = base;\n }\n\n try {\n let outcome: unknown;\n if (behavior === 'original-effective') {\n outcome = callOriginal(this, args);\n } else if (typeof behavior === 'function') {\n // test.watch(rawWrapper): wrapper behavior runs and is recorded\n outcome = behavior((...inner: any[]) => callOriginal(this, inner)).apply(this, args);\n } else if (behavior.kind === 'returns') {\n outcome = behavior.value;\n } else if (behavior.kind === 'throws') {\n throw behavior.error;\n } else if (behavior.kind === 'original') {\n outcome = callOriginal(this, args);\n } else {\n throw new TypeError(`Nested test.calls() scripts are not supported (${method}).`);\n }\n return recordOutcome(call, outcome, false);\n } catch (error) {\n recordOutcome(call, error, true);\n throw error;\n }\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noego/testing",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Canonical NoEgo shared testing owner: testIoc real-IoC composition and the lowercase test.* method behavior/watch/expectation language",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,17 +30,16 @@
30
30
  "publishConfig": {
31
31
  "access": "public"
32
32
  },
33
- "dependencies": {},
34
33
  "devDependencies": {
34
+ "@noego/ioc": "^0.6.1",
35
35
  "@types/jest": "^29.5.14",
36
36
  "@types/node": "^20.10.4",
37
37
  "jest": "^29.7.0",
38
+ "reflect-metadata": "^0.2.2",
38
39
  "ts-jest": "^29.3.2",
39
40
  "ts-node": "^10.9.2",
40
41
  "tsup": "^8.5.0",
41
- "typescript": "^5.8.3",
42
- "@noego/ioc": "file:../ioc",
43
- "reflect-metadata": "^0.2.2"
42
+ "typescript": "^5.8.3"
44
43
  },
45
44
  "peerDependencies": {
46
45
  "@noego/ioc": ">=0.5.0"