{"version":3,"file":"index.cjs","names":["Container","InjectableScope","InjectableType","BoundInjectionToken","globalRegistry","Registry","getInjectableToken","defaultInjectors","TestContainer","testRegistry","methodCalls","Map","lifecycleEvents","instanceCounts","boundTokens","Set","options","parentRegistry","logger","bind","token","realToken","resolveToken","tokenId","id","toValue","value","add","registerValueBinding","toClass","cls","registerClassBinding","toFactory","factory","registerFactoryBinding","clear","dispose","expectResolved","storage","getStorage","names","getAllNames","found","some","name","includes","Error","toString","expectNotResolved","expectSingleton","registry","getRegistry","has","record","get","scope","Singleton","expectTransient","Transient","expectRequestScoped","Request","expectSameInstance","instance1","instance2","expectDifferentInstances","expectInitialized","events","initialized","e","event","expectDestroyed","destroyed","expectNotDestroyed","recordMethodCall","method","args","result","error","calls","push","timestamp","Date","now","set","recordLifecycleEvent","instanceName","count","expectCalled","c","expectCalledWith","expectedArgs","argsMatch","JSON","stringify","expectCallCount","actualCount","filter","length","getMethodCalls","getServiceStats","instanceCount","clearMethodCalls","getDependencyGraph","nodes","rootTokens","forEach","holder","tokenMatch","match","dependencies","Array","from","deps","dependents","findDependents","getSimplifiedDependencyGraph","graph","dep","depTokenMatch","depTokenId","key","Object","keys","sort","ValueHolder","create","Factory","nameResolver","getNameResolver","generateInstanceName","undefined","storeInstance","Class","FactoryWrapper","actual","expected","every","arg","index","exp","Container","InjectableScope","InjectableType","DIError","BoundInjectionToken","InjectionToken","Registry","getInjectableToken","defaultInjectors","createTrackingProxy","target","tokenId","methodCalls","Proxy","get","obj","prop","value","Reflect","args","calls","record","method","timestamp","Date","now","result","apply","undefined","Promise","then","res","push","set","catch","err","error","createAutoMockProxy","_","Error","UnitTestContainer","testRegistry","Map","lifecycleEvents","instanceCounts","registeredTokenIds","Set","autoMockedTokenIds","allowUnregistered","options","logger","provider","providers","registerProvider","enableAutoMocking","disableAutoMocking","token","isBoundToken","id","realToken","resolveToken","isRegistered","has","factoryNotFound","toString","idToCheck","add","instance","trackingId","clear","dispose","expectResolved","storage","getStorage","names","getAllNames","found","some","name","includes","expectNotResolved","expectAutoMocked","expectNotAutoMocked","recordLifecycleEvent","event","instanceName","events","count","expectInitialized","initialized","e","expectDestroyed","destroyed","expectNotDestroyed","expectCalled","c","expectNotCalled","expectCalledWith","expectedArgs","argsMatch","filter","actualArgs","map","JSON","stringify","join","expectCallCount","actualCount","length","getMethodCalls","getServiceStats","instanceCount","clearMethodCalls","getRegisteredTokenIds","getAutoMockedTokenIds","create","providerToken","useValue","registerValueBinding","useClass","registerClassBinding","useFactory","registerFactoryBinding","Singleton","Class","ValueHolder","Factory","nameResolver","getNameResolver","generateInstanceName","storeInstance","cls","factory","FactoryWrapper","actual","expected","every","arg","index","exp"],"sources":["../../src/testing/test-container.mts","../../src/testing/unit-test-container.mts"],"sourcesContent":["import type {\n  BindingBuilder,\n  DependencyGraph,\n  DependencyNode,\n  LifecycleRecord,\n  MethodCallRecord,\n  MockServiceStats,\n  TestContainerOptions,\n} from './types.mjs'\n\nimport { Container } from '../container/container.mjs'\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport {\n  BoundInjectionToken,\n  InjectionToken,\n} from '../token/injection-token.mjs'\nimport { globalRegistry, Registry } from '../token/registry.mjs'\nimport { getInjectableToken } from '../utils/get-injectable-token.mjs'\nimport { defaultInjectors } from '../utils/index.mjs'\n\ntype AnyToken =\n  | InjectionToken<any, any>\n  | BoundInjectionToken<any, any>\n  | (new (...args: any[]) => any)\n\n/**\n * TestContainer extends Container with testing utilities.\n *\n * Provides simple value/class binding for integration/e2e tests,\n * plus assertion helpers and dependency graph inspection.\n *\n * @example\n * ```ts\n * const container = new TestContainer()\n *\n * // Bind mock values\n * container.bind(DatabaseToken).toValue(mockDatabase)\n * container.bind(UserService).toClass(MockUserService)\n *\n * // Use container normally\n * const service = await container.get(MyService)\n *\n * // Assert on container state\n * container.expectResolved(MyService)\n * container.expectSingleton(MyService)\n * ```\n */\nexport class TestContainer extends Container {\n  private readonly testRegistry: Registry\n  private readonly methodCalls = new Map<string, MethodCallRecord[]>()\n  private readonly lifecycleEvents = new Map<string, LifecycleRecord[]>()\n  private readonly instanceCounts = new Map<string, number>()\n  private readonly boundTokens = new Set<string>()\n\n  /**\n   * Creates a new TestContainer.\n   *\n   * @param options - Configuration options\n   * @param options.parentRegistry - Parent registry. Defaults to globalRegistry.\n   *   Pass `null` for a completely isolated container.\n   * @param options.logger - Optional logger for debugging.\n   *\n   * @example\n   * ```ts\n   * // Uses globalRegistry as parent (default)\n   * const container = new TestContainer()\n   *\n   * // Isolated container (no access to @Injectable classes)\n   * const isolated = new TestContainer({ parentRegistry: null })\n   *\n   * // Custom parent registry\n   * const custom = new TestContainer({ parentRegistry: myRegistry })\n   * ```\n   */\n  constructor(options: TestContainerOptions = {}) {\n    const { parentRegistry = globalRegistry, logger = null } = options\n    const testRegistry = parentRegistry\n      ? new Registry(parentRegistry)\n      : new Registry()\n    super(testRegistry, logger, defaultInjectors)\n    this.testRegistry = testRegistry\n  }\n\n  // ============================================================================\n  // BINDING API\n  // ============================================================================\n\n  /**\n   * Creates a binding builder for the given token.\n   *\n   * @example\n   * ```ts\n   * container.bind(UserService).toValue(mockUserService)\n   * container.bind(DatabaseToken).toClass(MockDatabase)\n   * container.bind(ConfigToken).toFactory(() => ({ apiKey: 'test' }))\n   * container.bind(BOUND_CONFIG_TOKEN).toValue(overrideValue)\n   * ```\n   */\n  bind<T>(\n    token:\n      | InjectionToken<T, any>\n      | BoundInjectionToken<T, any>\n      | (new (...args: any[]) => T),\n  ): BindingBuilder<T> {\n    const realToken = this.resolveToken(token)\n    const tokenId = realToken.id\n\n    return {\n      toValue: (value: T) => {\n        this.boundTokens.add(tokenId)\n        this.registerValueBinding(realToken, value)\n      },\n      toClass: <C extends new (...args: any[]) => T>(cls: C) => {\n        this.boundTokens.add(tokenId)\n        this.registerClassBinding(realToken, cls)\n      },\n      toFactory: (factory: () => T | Promise<T>) => {\n        this.boundTokens.add(tokenId)\n        this.registerFactoryBinding(realToken, factory)\n      },\n    }\n  }\n\n  /**\n   * Clears all bindings and resets container state.\n   */\n  async clear(): Promise<void> {\n    await this.dispose()\n    this.methodCalls.clear()\n    this.lifecycleEvents.clear()\n    this.instanceCounts.clear()\n    this.boundTokens.clear()\n  }\n\n  // ============================================================================\n  // ASSERTION HELPERS\n  // ============================================================================\n\n  /**\n   * Asserts that a service has been resolved at least once.\n   */\n  expectResolved(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const storage = this.getStorage()\n    const names = storage.getAllNames()\n    const found = names.some((name) => name.includes(realToken.id))\n\n    if (!found) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be resolved, but it was not`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service has NOT been resolved.\n   */\n  expectNotResolved(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const storage = this.getStorage()\n    const names = storage.getAllNames()\n    const found = names.some((name) => name.includes(realToken.id))\n\n    if (found) {\n      throw new Error(\n        `Expected ${realToken.toString()} to NOT be resolved, but it was`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service is registered as singleton scope.\n   */\n  expectSingleton(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const registry = this.getRegistry()\n\n    if (!registry.has(realToken)) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be registered, but it was not`,\n      )\n    }\n\n    const record = registry.get(realToken)\n    if (record.scope !== InjectableScope.Singleton) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be Singleton scope, but it was ${record.scope}`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service is registered as transient scope.\n   */\n  expectTransient(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const registry = this.getRegistry()\n\n    if (!registry.has(realToken)) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be registered, but it was not`,\n      )\n    }\n\n    const record = registry.get(realToken)\n    if (record.scope !== InjectableScope.Transient) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be Transient scope, but it was ${record.scope}`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service is registered as request scope.\n   */\n  expectRequestScoped(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const registry = this.getRegistry()\n\n    if (!registry.has(realToken)) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be registered, but it was not`,\n      )\n    }\n\n    const record = registry.get(realToken)\n    if (record.scope !== InjectableScope.Request) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be Request scope, but it was ${record.scope}`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that two service resolutions return the same instance.\n   */\n  async expectSameInstance(token: AnyToken): Promise<void> {\n    const instance1 = await this.get(token as any)\n    const instance2 = await this.get(token as any)\n\n    if (instance1 !== instance2) {\n      const realToken = this.resolveToken(token)\n      throw new Error(\n        `Expected ${realToken.toString()} to return same instance, but got different instances`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that two service resolutions return different instances.\n   */\n  async expectDifferentInstances(token: AnyToken): Promise<void> {\n    const instance1 = await this.get(token as any)\n    const instance2 = await this.get(token as any)\n\n    if (instance1 === instance2) {\n      const realToken = this.resolveToken(token)\n      throw new Error(\n        `Expected ${realToken.toString()} to return different instances, but got same instance`,\n      )\n    }\n  }\n\n  // ============================================================================\n  // LIFECYCLE ASSERTIONS\n  // ============================================================================\n\n  /**\n   * Asserts that a service's onServiceInit was called.\n   */\n  expectInitialized(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const events = this.lifecycleEvents.get(realToken.id) || []\n    const initialized = events.some((e) => e.event === 'initialized')\n\n    if (!initialized) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be initialized, but onServiceInit was not called`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service's onServiceDestroy was called.\n   */\n  expectDestroyed(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const events = this.lifecycleEvents.get(realToken.id) || []\n    const destroyed = events.some((e) => e.event === 'destroyed')\n\n    if (!destroyed) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be destroyed, but onServiceDestroy was not called`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service has NOT been destroyed.\n   */\n  expectNotDestroyed(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const events = this.lifecycleEvents.get(realToken.id) || []\n    const destroyed = events.some((e) => e.event === 'destroyed')\n\n    if (destroyed) {\n      throw new Error(\n        `Expected ${realToken.toString()} to NOT be destroyed, but onServiceDestroy was called`,\n      )\n    }\n  }\n\n  // ============================================================================\n  // CALL TRACKING\n  // ============================================================================\n\n  /**\n   * Records a method call for tracking.\n   * Call this from your mock implementations.\n   */\n  recordMethodCall(\n    token: AnyToken,\n    method: string,\n    args: unknown[],\n    result?: unknown,\n    error?: Error,\n  ): void {\n    const realToken = this.resolveToken(token)\n    const calls = this.methodCalls.get(realToken.id) || []\n    calls.push({\n      method,\n      args,\n      timestamp: Date.now(),\n      result,\n      error,\n    })\n    this.methodCalls.set(realToken.id, calls)\n  }\n\n  /**\n   * Records a lifecycle event for tracking.\n   */\n  recordLifecycleEvent(\n    token: AnyToken,\n    event: 'created' | 'initialized' | 'destroyed',\n    instanceName: string,\n  ): void {\n    const realToken = this.resolveToken(token)\n    const events = this.lifecycleEvents.get(realToken.id) || []\n    events.push({\n      event,\n      timestamp: Date.now(),\n      instanceName,\n    })\n    this.lifecycleEvents.set(realToken.id, events)\n\n    if (event === 'created') {\n      const count = this.instanceCounts.get(realToken.id) || 0\n      this.instanceCounts.set(realToken.id, count + 1)\n    }\n  }\n\n  /**\n   * Asserts that a method was called on a service.\n   */\n  expectCalled(token: AnyToken, method: string): void {\n    const realToken = this.resolveToken(token)\n    const calls = this.methodCalls.get(realToken.id) || []\n    const found = calls.some((c) => c.method === method)\n\n    if (!found) {\n      throw new Error(\n        `Expected ${realToken.toString()}.${method}() to be called, but it was not`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a method was called with specific arguments.\n   */\n  expectCalledWith(\n    token: AnyToken,\n    method: string,\n    expectedArgs: unknown[],\n  ): void {\n    const realToken = this.resolveToken(token)\n    const calls = this.methodCalls.get(realToken.id) || []\n    const found = calls.some(\n      (c) => c.method === method && this.argsMatch(c.args, expectedArgs),\n    )\n\n    if (!found) {\n      throw new Error(\n        `Expected ${realToken.toString()}.${method}() to be called with ${JSON.stringify(expectedArgs)}, but it was not`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a method was called a specific number of times.\n   */\n  expectCallCount(token: AnyToken, method: string, count: number): void {\n    const realToken = this.resolveToken(token)\n    const calls = this.methodCalls.get(realToken.id) || []\n    const actualCount = calls.filter((c) => c.method === method).length\n\n    if (actualCount !== count) {\n      throw new Error(\n        `Expected ${realToken.toString()}.${method}() to be called ${count} times, but was called ${actualCount} times`,\n      )\n    }\n  }\n\n  /**\n   * Gets all recorded method calls for a service.\n   */\n  getMethodCalls(token: AnyToken): MethodCallRecord[] {\n    const realToken = this.resolveToken(token)\n    return this.methodCalls.get(realToken.id) || []\n  }\n\n  /**\n   * Gets statistics about a mocked service.\n   */\n  getServiceStats(token: AnyToken): MockServiceStats {\n    const realToken = this.resolveToken(token)\n    return {\n      instanceCount: this.instanceCounts.get(realToken.id) || 0,\n      methodCalls: this.methodCalls.get(realToken.id) || [],\n      lifecycleEvents: this.lifecycleEvents.get(realToken.id) || [],\n    }\n  }\n\n  /**\n   * Clears all recorded method calls.\n   */\n  clearMethodCalls(): void {\n    this.methodCalls.clear()\n  }\n\n  // ============================================================================\n  // DEPENDENCY GRAPH\n  // ============================================================================\n\n  /**\n   * Gets the dependency graph for snapshot testing.\n   * Returns a serializable structure that can be used with vitest snapshots.\n   */\n  getDependencyGraph(): DependencyGraph {\n    const storage = this.getStorage()\n    const nodes: Record<string, DependencyNode> = {}\n    const rootTokens: string[] = []\n\n    storage.forEach((name, holder) => {\n      const tokenMatch = name.match(/^([^:]+)/)\n      const tokenId = tokenMatch ? tokenMatch[1] : name\n\n      nodes[name] = {\n        token: tokenId,\n        instanceName: name,\n        scope: holder.scope,\n        dependencies: Array.from(holder.deps),\n        dependents: storage.findDependents(name),\n      }\n\n      // Root tokens have no dependents\n      if (storage.findDependents(name).length === 0) {\n        rootTokens.push(name)\n      }\n    })\n\n    return { nodes, rootTokens }\n  }\n\n  /**\n   * Gets a simplified dependency graph showing only token relationships.\n   * Useful for cleaner snapshot comparisons.\n   */\n  getSimplifiedDependencyGraph(): Record<string, string[]> {\n    const storage = this.getStorage()\n    const graph: Record<string, string[]> = {}\n\n    storage.forEach((name, holder) => {\n      const tokenMatch = name.match(/^([^:]+)/)\n      const tokenId = tokenMatch ? tokenMatch[1] : name\n\n      if (!graph[tokenId]) {\n        graph[tokenId] = []\n      }\n\n      for (const dep of holder.deps) {\n        const depTokenMatch = dep.match(/^([^:]+)/)\n        const depTokenId = depTokenMatch ? depTokenMatch[1] : dep\n        if (!graph[tokenId].includes(depTokenId)) {\n          graph[tokenId].push(depTokenId)\n        }\n      }\n    })\n\n    // Sort for consistent snapshots\n    for (const key of Object.keys(graph)) {\n      graph[key].sort()\n    }\n\n    return graph\n  }\n\n  // ============================================================================\n  // INTERNAL HELPERS\n  // ============================================================================\n\n  private resolveToken(token: AnyToken): InjectionToken<any, any> {\n    if (typeof token === 'function') {\n      return getInjectableToken(token)\n    }\n    if (token instanceof BoundInjectionToken) {\n      return token.token\n    }\n    return token\n  }\n\n  private registerValueBinding<T>(\n    token: InjectionToken<T, any>,\n    value: T,\n  ): void {\n    // Create a simple class that returns the value\n    const ValueHolder = class {\n      create(): T {\n        return value\n      }\n    }\n\n    this.testRegistry.set(\n      token,\n      InjectableScope.Singleton,\n      ValueHolder,\n      InjectableType.Factory,\n      1000, // Higher priority for test overrides\n    )\n\n    // Store the instance directly\n    const nameResolver = this.getNameResolver()\n    const instanceName = nameResolver.generateInstanceName(\n      token,\n      undefined,\n      undefined,\n      InjectableScope.Singleton,\n    )\n    this.getStorage().storeInstance(instanceName, value)\n    this.recordLifecycleEvent(token, 'created', instanceName)\n  }\n\n  private registerClassBinding<T>(\n    token: InjectionToken<T, any>,\n    cls: new (...args: any[]) => T,\n  ): void {\n    this.testRegistry.set(\n      token,\n      InjectableScope.Singleton,\n      cls,\n      InjectableType.Class,\n      1000, // Higher priority for test overrides\n    )\n  }\n\n  private registerFactoryBinding<T>(\n    token: InjectionToken<T, any>,\n    factory: () => T | Promise<T>,\n  ): void {\n    // Create a factory class wrapper\n    const FactoryWrapper = class {\n      static factory = factory\n      async create(): Promise<T> {\n        return await factory()\n      }\n    }\n\n    this.testRegistry.set(\n      token,\n      InjectableScope.Singleton,\n      FactoryWrapper,\n      InjectableType.Factory,\n      1000, // Higher priority for test overrides\n    )\n  }\n\n  private argsMatch(actual: unknown[], expected: unknown[]): boolean {\n    if (actual.length !== expected.length) {\n      return false\n    }\n    return actual.every((arg, index) => {\n      const exp = expected[index]\n      if (typeof exp === 'object' && exp !== null) {\n        return JSON.stringify(arg) === JSON.stringify(exp)\n      }\n      return arg === exp\n    })\n  }\n}\n","import type {\n  LifecycleRecord,\n  MethodCallRecord,\n  MockServiceStats,\n  ProviderConfig,\n  UnitTestContainerOptions,\n} from './types.mjs'\n\nimport { Container } from '../container/container.mjs'\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport { DIError } from '../errors/index.mjs'\nimport {\n  BoundInjectionToken,\n  InjectionToken,\n} from '../token/injection-token.mjs'\nimport { Registry } from '../token/registry.mjs'\nimport { getInjectableToken } from '../utils/get-injectable-token.mjs'\nimport { defaultInjectors } from '../utils/index.mjs'\n\ntype AnyToken =\n  | InjectionToken<any, any>\n  | BoundInjectionToken<any, any>\n  | (new (...args: any[]) => any)\n\n/**\n * Creates a tracking proxy that records method calls.\n */\nfunction createTrackingProxy<T extends object>(\n  target: T,\n  tokenId: string,\n  methodCalls: Map<string, MethodCallRecord[]>,\n): T {\n  return new Proxy(target, {\n    get(obj, prop) {\n      const value = Reflect.get(obj, prop)\n\n      if (typeof value === 'function' && typeof prop === 'string') {\n        return function (this: unknown, ...args: unknown[]) {\n          const calls = methodCalls.get(tokenId) || []\n          const record: MethodCallRecord = {\n            method: prop,\n            args,\n            timestamp: Date.now(),\n          }\n\n          try {\n            const result = value.apply(this === undefined ? obj : this, args)\n\n            if (result instanceof Promise) {\n              return result\n                .then((res) => {\n                  record.result = res\n                  calls.push(record)\n                  methodCalls.set(tokenId, calls)\n                  return res\n                })\n                .catch((err) => {\n                  record.error = err\n                  calls.push(record)\n                  methodCalls.set(tokenId, calls)\n                  throw err\n                })\n            }\n\n            record.result = result\n            calls.push(record)\n            methodCalls.set(tokenId, calls)\n            return result\n          } catch (err) {\n            record.error = err as Error\n            calls.push(record)\n            methodCalls.set(tokenId, calls)\n            throw err\n          }\n        }\n      }\n\n      return value\n    },\n  })\n}\n\n/**\n * Creates an auto-mock proxy that throws on method access.\n */\nfunction createAutoMockProxy(tokenId: string): object {\n  return new Proxy(\n    {},\n    {\n      get(_, prop) {\n        if (prop === 'then' || prop === 'catch' || prop === 'finally') {\n          return undefined\n        }\n        if (typeof prop === 'symbol') {\n          return undefined\n        }\n        throw new Error(\n          `[UnitTestContainer] Attempted to access '${prop}' on auto-mocked service '${tokenId}'. ` +\n            `This service was not provided in the providers list. ` +\n            `Add it to providers or use allowUnregistered: false to catch this earlier.`,\n        )\n      },\n    },\n  )\n}\n\n/**\n * UnitTestContainer for isolated unit testing.\n *\n * Only services explicitly listed in `providers` can be resolved.\n * All method calls are automatically tracked via proxies.\n * Unregistered dependencies throw by default, or can be auto-mocked.\n *\n * @example\n * ```ts\n * const container = new UnitTestContainer({\n *   providers: [\n *     { token: UserService, useClass: MockUserService },\n *     { token: ConfigToken, useValue: { apiUrl: 'test' } },\n *   ],\n * })\n *\n * const service = await container.get(UserService)\n *\n * // All method calls are automatically tracked\n * await service.findUser('123')\n *\n * container.expectCalled(UserService, 'findUser')\n * container.expectCalledWith(UserService, 'findUser', ['123'])\n * ```\n */\nexport class UnitTestContainer extends Container {\n  private readonly testRegistry: Registry\n  private readonly methodCalls = new Map<string, MethodCallRecord[]>()\n  private readonly lifecycleEvents = new Map<string, LifecycleRecord[]>()\n  private readonly instanceCounts = new Map<string, number>()\n  private readonly registeredTokenIds = new Set<string>()\n  private readonly autoMockedTokenIds = new Set<string>()\n  private allowUnregistered: boolean\n\n  constructor(options: UnitTestContainerOptions) {\n    const testRegistry = new Registry()\n    super(testRegistry, options.logger ?? null, defaultInjectors)\n    this.testRegistry = testRegistry\n    this.allowUnregistered = options.allowUnregistered ?? false\n\n    // Register all providers\n    for (const provider of options.providers) {\n      this.registerProvider(provider)\n    }\n  }\n\n  /**\n   * Enables auto-mocking for unregistered dependencies.\n   * Call this to switch from strict mode to auto-mock mode.\n   */\n  enableAutoMocking(): this {\n    this.allowUnregistered = true\n    return this\n  }\n\n  /**\n   * Disables auto-mocking (strict mode).\n   * Unregistered dependencies will throw.\n   */\n  disableAutoMocking(): this {\n    this.allowUnregistered = false\n    return this\n  }\n\n  /**\n   * Override get to wrap instances in tracking proxies.\n   */\n  override async get(token: any, args?: unknown): Promise<any> {\n    // Check if token is a BoundInjectionToken and if it's registered\n    const isBoundToken = token instanceof BoundInjectionToken\n    const tokenId = isBoundToken ? token.id : undefined\n    const realToken = this.resolveToken(token)\n\n    // Check if this is a registered provider (check both bound token ID and real token ID)\n    const isRegistered =\n      (tokenId && this.registeredTokenIds.has(tokenId)) ||\n      this.registeredTokenIds.has(realToken.id)\n\n    if (!isRegistered) {\n      if (!this.allowUnregistered) {\n        throw DIError.factoryNotFound(\n          `${realToken.toString()} is not in the providers list. ` +\n            `Add it to providers or enable allowUnregistered.`,\n        )\n      }\n\n      // Auto-mock unregistered dependency\n      const idToCheck = tokenId || realToken.id\n      if (!this.autoMockedTokenIds.has(idToCheck)) {\n        this.autoMockedTokenIds.add(idToCheck)\n      }\n\n      return createAutoMockProxy(idToCheck)\n    }\n\n    const instance = await super.get(token, args)\n\n    // Wrap in tracking proxy if it's an object\n    const trackingId = tokenId || realToken.id\n    if (instance && typeof instance === 'object') {\n      return createTrackingProxy(instance, trackingId, this.methodCalls)\n    }\n\n    return instance\n  }\n\n  /**\n   * Clears all state and disposes the container.\n   */\n  async clear(): Promise<void> {\n    await this.dispose()\n    this.methodCalls.clear()\n    this.lifecycleEvents.clear()\n    this.instanceCounts.clear()\n    this.autoMockedTokenIds.clear()\n  }\n\n  // ============================================================================\n  // ASSERTION HELPERS\n  // ============================================================================\n\n  /**\n   * Asserts that a service has been resolved at least once.\n   */\n  expectResolved(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const storage = this.getStorage()\n    const names = storage.getAllNames()\n    const found = names.some((name) => name.includes(realToken.id))\n\n    if (!found) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be resolved, but it was not`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service has NOT been resolved.\n   */\n  expectNotResolved(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const storage = this.getStorage()\n    const names = storage.getAllNames()\n    const found = names.some((name) => name.includes(realToken.id))\n\n    if (found) {\n      throw new Error(\n        `Expected ${realToken.toString()} to NOT be resolved, but it was`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service was auto-mocked (not in providers list).\n   */\n  expectAutoMocked(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n\n    if (!this.autoMockedTokenIds.has(realToken.id)) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be auto-mocked, but it was not. ` +\n          `Either it's in the providers list or hasn't been resolved.`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service was NOT auto-mocked (is in providers list).\n   */\n  expectNotAutoMocked(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n\n    if (this.autoMockedTokenIds.has(realToken.id)) {\n      throw new Error(\n        `Expected ${realToken.toString()} to NOT be auto-mocked, but it was.`,\n      )\n    }\n  }\n\n  // ============================================================================\n  // LIFECYCLE ASSERTIONS\n  // ============================================================================\n\n  /**\n   * Records a lifecycle event for tracking.\n   */\n  recordLifecycleEvent(\n    token: AnyToken,\n    event: 'created' | 'initialized' | 'destroyed',\n    instanceName: string,\n  ): void {\n    const realToken = this.resolveToken(token)\n    const events = this.lifecycleEvents.get(realToken.id) || []\n    events.push({\n      event,\n      timestamp: Date.now(),\n      instanceName,\n    })\n    this.lifecycleEvents.set(realToken.id, events)\n\n    if (event === 'created') {\n      const count = this.instanceCounts.get(realToken.id) || 0\n      this.instanceCounts.set(realToken.id, count + 1)\n    }\n  }\n\n  /**\n   * Asserts that a service's onServiceInit was called.\n   */\n  expectInitialized(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const events = this.lifecycleEvents.get(realToken.id) || []\n    const initialized = events.some((e) => e.event === 'initialized')\n\n    if (!initialized) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be initialized, but onServiceInit was not called`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service's onServiceDestroy was called.\n   */\n  expectDestroyed(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const events = this.lifecycleEvents.get(realToken.id) || []\n    const destroyed = events.some((e) => e.event === 'destroyed')\n\n    if (!destroyed) {\n      throw new Error(\n        `Expected ${realToken.toString()} to be destroyed, but onServiceDestroy was not called`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a service has NOT been destroyed.\n   */\n  expectNotDestroyed(token: AnyToken): void {\n    const realToken = this.resolveToken(token)\n    const events = this.lifecycleEvents.get(realToken.id) || []\n    const destroyed = events.some((e) => e.event === 'destroyed')\n\n    if (destroyed) {\n      throw new Error(\n        `Expected ${realToken.toString()} to NOT be destroyed, but onServiceDestroy was called`,\n      )\n    }\n  }\n\n  // ============================================================================\n  // CALL TRACKING (AUTO-TRACKED VIA PROXY)\n  // ============================================================================\n\n  /**\n   * Asserts that a method was called on a service.\n   */\n  expectCalled(token: AnyToken, method: string): void {\n    const realToken = this.resolveToken(token)\n    const calls = this.methodCalls.get(realToken.id) || []\n    const found = calls.some((c) => c.method === method)\n\n    if (!found) {\n      throw new Error(\n        `Expected ${realToken.toString()}.${method}() to be called, but it was not`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a method was NOT called on a service.\n   */\n  expectNotCalled(token: AnyToken, method: string): void {\n    const realToken = this.resolveToken(token)\n    const calls = this.methodCalls.get(realToken.id) || []\n    const found = calls.some((c) => c.method === method)\n\n    if (found) {\n      throw new Error(\n        `Expected ${realToken.toString()}.${method}() to NOT be called, but it was`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a method was called with specific arguments.\n   */\n  expectCalledWith(\n    token: AnyToken,\n    method: string,\n    expectedArgs: unknown[],\n  ): void {\n    const realToken = this.resolveToken(token)\n    const calls = this.methodCalls.get(realToken.id) || []\n    const found = calls.some(\n      (c) => c.method === method && this.argsMatch(c.args, expectedArgs),\n    )\n\n    if (!found) {\n      const methodCalls = calls.filter((c) => c.method === method)\n      const actualArgs = methodCalls\n        .map((c) => JSON.stringify(c.args))\n        .join(', ')\n      throw new Error(\n        `Expected ${realToken.toString()}.${method}() to be called with ${JSON.stringify(expectedArgs)}. ` +\n          `Actual calls: [${actualArgs}]`,\n      )\n    }\n  }\n\n  /**\n   * Asserts that a method was called a specific number of times.\n   */\n  expectCallCount(token: AnyToken, method: string, count: number): void {\n    const realToken = this.resolveToken(token)\n    const calls = this.methodCalls.get(realToken.id) || []\n    const actualCount = calls.filter((c) => c.method === method).length\n\n    if (actualCount !== count) {\n      throw new Error(\n        `Expected ${realToken.toString()}.${method}() to be called ${count} times, but was called ${actualCount} times`,\n      )\n    }\n  }\n\n  /**\n   * Gets all recorded method calls for a service.\n   */\n  getMethodCalls(token: AnyToken): MethodCallRecord[] {\n    const realToken = this.resolveToken(token)\n    return this.methodCalls.get(realToken.id) || []\n  }\n\n  /**\n   * Gets statistics about a service.\n   */\n  getServiceStats(token: AnyToken): MockServiceStats {\n    const realToken = this.resolveToken(token)\n    return {\n      instanceCount: this.instanceCounts.get(realToken.id) || 0,\n      methodCalls: this.methodCalls.get(realToken.id) || [],\n      lifecycleEvents: this.lifecycleEvents.get(realToken.id) || [],\n    }\n  }\n\n  /**\n   * Clears all recorded method calls.\n   */\n  clearMethodCalls(): void {\n    this.methodCalls.clear()\n  }\n\n  /**\n   * Gets list of all registered provider token IDs.\n   */\n  getRegisteredTokenIds(): ReadonlySet<string> {\n    return this.registeredTokenIds\n  }\n\n  /**\n   * Gets list of all auto-mocked token IDs.\n   */\n  getAutoMockedTokenIds(): ReadonlySet<string> {\n    return this.autoMockedTokenIds\n  }\n\n  // ============================================================================\n  // INTERNAL HELPERS\n  // ============================================================================\n\n  private resolveToken(token: AnyToken): InjectionToken<any, any> {\n    if (typeof token === 'function') {\n      try {\n        return getInjectableToken(token)\n      } catch {\n        // Class doesn't have @Injectable, create a token for it\n        return InjectionToken.create(token)\n      }\n    }\n    if (token instanceof BoundInjectionToken) {\n      return token.token\n    }\n    return token\n  }\n\n  private registerProvider<T>(provider: ProviderConfig<T>): void {\n    const providerToken = provider.token as AnyToken\n    const realToken = this.resolveToken(providerToken)\n\n    // Track both the real token ID and the bound token ID if it's a bound token\n    this.registeredTokenIds.add(realToken.id)\n    if (providerToken instanceof BoundInjectionToken) {\n      this.registeredTokenIds.add(providerToken.id)\n    }\n\n    if (provider.useValue !== undefined) {\n      this.registerValueBinding(realToken, provider.useValue)\n    } else if (provider.useClass) {\n      this.registerClassBinding(realToken, provider.useClass)\n    } else if (provider.useFactory) {\n      this.registerFactoryBinding(realToken, provider.useFactory)\n    } else {\n      // Just the token - register as itself\n      if (typeof provider.token === 'function') {\n        this.testRegistry.set(\n          realToken,\n          InjectableScope.Singleton,\n          provider.token,\n          InjectableType.Class,\n          1000, // Higher priority for test overrides\n        )\n      } else if (providerToken instanceof BoundInjectionToken) {\n        // If it's a bound token without override, register the bound value\n        this.registerValueBinding(realToken, providerToken.value)\n      }\n    }\n  }\n\n  private registerValueBinding<T>(\n    token: InjectionToken<T, any>,\n    value: T,\n  ): void {\n    const ValueHolder = class {\n      create(): T {\n        return value\n      }\n    }\n\n    this.testRegistry.set(\n      token,\n      InjectableScope.Singleton,\n      ValueHolder,\n      InjectableType.Factory,\n      1000, // Higher priority for test overrides\n    )\n\n    const nameResolver = this.getNameResolver()\n    const instanceName = nameResolver.generateInstanceName(\n      token,\n      undefined,\n      undefined,\n      InjectableScope.Singleton,\n    )\n    this.getStorage().storeInstance(instanceName, value)\n    this.recordLifecycleEvent(token, 'created', instanceName)\n  }\n\n  private registerClassBinding<T>(\n    token: InjectionToken<T, any>,\n    cls: new (...args: any[]) => T,\n  ): void {\n    this.testRegistry.set(\n      token,\n      InjectableScope.Singleton,\n      cls,\n      InjectableType.Class,\n      1000, // Higher priority for test overrides\n    )\n  }\n\n  private registerFactoryBinding<T>(\n    token: InjectionToken<T, any>,\n    factory: () => T | Promise<T>,\n  ): void {\n    const FactoryWrapper = class {\n      static factory = factory\n      async create(): Promise<T> {\n        return await factory()\n      }\n    }\n\n    this.testRegistry.set(\n      token,\n      InjectableScope.Singleton,\n      FactoryWrapper,\n      InjectableType.Factory,\n      1000, // Higher priority for test overrides\n    )\n  }\n\n  private argsMatch(actual: unknown[], expected: unknown[]): boolean {\n    if (actual.length !== expected.length) {\n      return false\n    }\n    return actual.every((arg, index) => {\n      const exp = expected[index]\n      if (typeof exp === 'object' && exp !== null) {\n        return JSON.stringify(arg) === JSON.stringify(exp)\n      }\n      return arg === exp\n    })\n  }\n}\n"],"mappings":"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"}