@znight/testing 0.3.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.mjs +10 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/extensions.ts +20 -6
package/dist/index.mjs
CHANGED
|
@@ -663,7 +663,7 @@ function readConfigClasses(metadata) {
|
|
|
663
663
|
}
|
|
664
664
|
/**
|
|
665
665
|
* Tokens an HTTP application needs at boot: controllers (`extensions.http.controllers[].token`) and
|
|
666
|
-
* the guards and
|
|
666
|
+
* the guards, interceptors and parameter resolvers (RFC 0010) they and their routes reference.
|
|
667
667
|
*/
|
|
668
668
|
function readHttpRoots(metadata) {
|
|
669
669
|
const roots = [];
|
|
@@ -671,14 +671,18 @@ function readHttpRoots(metadata) {
|
|
|
671
671
|
if (!isRecord(controller)) continue;
|
|
672
672
|
if (typeof controller["token"] === "string") roots.push(controller["token"]);
|
|
673
673
|
roots.push(...tokensOf(controller["guards"]), ...tokensOf(controller["interceptors"]));
|
|
674
|
-
for (const route of arrayOf(controller["routes"])) if (isRecord(route)) roots.push(...tokensOf(route["guards"]), ...tokensOf(route["interceptors"]));
|
|
674
|
+
for (const route of arrayOf(controller["routes"])) if (isRecord(route)) roots.push(...tokensOf(route["guards"]), ...tokensOf(route["interceptors"]), ...tokensOf(route["paramResolvers"]));
|
|
675
675
|
}
|
|
676
676
|
return roots;
|
|
677
677
|
}
|
|
678
|
-
/** Message consumers (`extensions.messaging.consumers[].token`). */
|
|
678
|
+
/** Message consumers (`extensions.messaging.consumers[].token`) and their parameter resolvers (RFC 0010). */
|
|
679
679
|
function readMessagingRoots(metadata) {
|
|
680
680
|
const roots = [];
|
|
681
|
-
for (const consumer of arrayOf(extension(metadata, "messaging")?.["consumers"]))
|
|
681
|
+
for (const consumer of arrayOf(extension(metadata, "messaging")?.["consumers"])) {
|
|
682
|
+
if (!isRecord(consumer)) continue;
|
|
683
|
+
if (typeof consumer["token"] === "string") roots.push(consumer["token"]);
|
|
684
|
+
for (const handler of arrayOf(consumer["handlers"])) if (isRecord(handler)) roots.push(...tokensOf(handler["paramResolvers"]));
|
|
685
|
+
}
|
|
682
686
|
return roots;
|
|
683
687
|
}
|
|
684
688
|
/** Hosts of scheduled jobs (`extensions.schedule.jobs[].token`), disabled jobs included (they can be triggered). */
|
|
@@ -690,7 +694,7 @@ function readScheduleRoots(metadata) {
|
|
|
690
694
|
/**
|
|
691
695
|
* Tokens a GraphQL application needs at boot (`extensions.graphql`, RFC 0005 §7.1): for every field
|
|
692
696
|
* of an object type bound to a resolver (`types[kind: 'object'].fields[].resolver`), the resolver
|
|
693
|
-
* token, its guard tokens
|
|
697
|
+
* token, its guard tokens, the loader tokens its method injects and its parameter resolvers (RFC 0010).
|
|
694
698
|
*/
|
|
695
699
|
function readGraphQLRoots(metadata) {
|
|
696
700
|
const roots = [];
|
|
@@ -700,7 +704,7 @@ function readGraphQLRoots(metadata) {
|
|
|
700
704
|
const resolver = isRecord(field) ? field["resolver"] : void 0;
|
|
701
705
|
if (!isRecord(resolver)) continue;
|
|
702
706
|
if (typeof resolver["token"] === "string") roots.push(resolver["token"]);
|
|
703
|
-
roots.push(...tokensOf(resolver["guards"]), ...tokensOf(resolver["loaders"]));
|
|
707
|
+
roots.push(...tokensOf(resolver["guards"]), ...tokensOf(resolver["loaders"]), ...tokensOf(resolver["paramResolvers"]));
|
|
704
708
|
}
|
|
705
709
|
}
|
|
706
710
|
return roots;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["isObjectLike"],"sources":["../src/utils.ts","../src/define-metadata.ts","../src/spy.ts","../src/mock-fn.ts","../src/mock.ts","../src/overrides.ts","../src/extensions.ts","../src/metadata-index.ts","../src/test-app.ts","../src/config.ts","../src/mock-registry.ts","../src/testbed-builder.ts","../src/testbed.ts"],"sourcesContent":["/** Internal helpers. */\n\n/**\n * Materialises a `Map`, an iterable of `[key, value]` pairs or a record into an array of pairs (an\n * iterable such as a generator can only be read once).\n */\nexport function entriesOf<K, V>(\n values: Iterable<readonly [K, V]> | Readonly<Record<string, V>>,\n): (readonly [K | string, V])[] {\n if (typeof (values as Partial<Iterable<unknown>>)[Symbol.iterator] === 'function') {\n const entries: (readonly [K, V])[] = []\n for (const entry of values as Iterable<readonly [K, V]>) {\n if (!Array.isArray(entry) || entry.length !== 2) {\n throw new TypeError('[znight] Expected [key, value] pairs (a Map, an array of pairs or a record)')\n }\n entries.push(entry)\n }\n return entries\n }\n return Object.entries(values as Readonly<Record<string, V>>)\n}\n\n/** Whether `value` is a promise-like object (has a callable `then`). */\nexport function isThenable(value: unknown): value is PromiseLike<unknown> {\n return (\n value !== null &&\n (typeof value === 'object' || typeof value === 'function') &&\n typeof (value as { then?: unknown }).then === 'function'\n )\n}\n\n/** Describes a provider key (class, token...) for messages. */\nexport function describeKey(key: unknown): string {\n if (typeof key === 'function') return `class ${(key as { name?: string }).name || '<anonymous>'}`\n if (typeof key === 'string') return `\"${key}\"`\n return String(key)\n}\n","import type {\n ClassKey,\n DependencyRef,\n ExternalDefinition,\n MethodInterception,\n ProviderClass,\n ProviderDefinition,\n ProviderFactory,\n Scope,\n SourceLocation,\n Token,\n ZnightExtensionsMetadata,\n ZnightMetadata,\n} from '@znight/core'\n\nimport { describeToken, ErrorCode, isProviderDefinition, METADATA_VERSION, ZnightError } from '@znight/core'\n\nimport { entriesOf } from './utils.ts'\n\n/** Options of {@link createMetadata}. */\nexport interface CreateMetadataOptions {\n readonly aliases?: Readonly<Record<Token, Token>>\n /** Externals, as tokens or full definitions (`{ token, scope, providedBy }`). */\n readonly externals?: readonly (Token | ExternalDefinition)[]\n readonly extensions?: ZnightExtensionsMetadata\n /** Default: a deterministic topological order (dependencies first, declaration order otherwise). */\n readonly resolutionOrder?: readonly Token[]\n}\n\n/**\n * Hand-written metadata with the exact shape the compiler generates (version, resolution order...),\n * for tests that do not run the compiler (plugins, libraries, edge cases).\n *\n * ```ts\n * const metadata = createMetadata({\n * 'src/clock.ts#Clock': { scope: 'singleton', class: Clock, deps: [], factory: () => new Clock() },\n * })\n * ```\n *\n * @throws ZnightError ZNIGHT005 for a malformed provider definition.\n */\nexport function createMetadata(\n providers: Readonly<Record<Token, ProviderDefinition>>,\n options: CreateMetadataOptions = {},\n): ZnightMetadata {\n if (providers === null || typeof providers !== 'object') {\n throw new TypeError('[znight] createMetadata() expects a record of provider definitions')\n }\n for (const [token, definition] of Object.entries(providers)) {\n if (!isProviderDefinition(definition)) {\n throw new ZnightError(\n ErrorCode.InvalidDecorator,\n `Invalid provider definition for ${describeToken(token)}: expected { scope, deps, factory }`,\n )\n }\n }\n const externals = options.externals?.map(external =>\n typeof external === 'string' ? ({ token: external } satisfies ExternalDefinition) : external,\n )\n return {\n version: METADATA_VERSION,\n providers,\n resolutionOrder: options.resolutionOrder ?? topologicalOrder(providers),\n ...(options.aliases === undefined ? {} : { aliases: options.aliases }),\n ...(externals === undefined ? {} : { externals }),\n ...(options.extensions === undefined ? {} : { extensions: options.extensions }),\n }\n}\n\n/** A provider class or a token, in {@link defineTestMetadata}. */\nexport type TestKey = Token | ProviderClass | ClassKey\n\n/** A dependency in {@link defineTestMetadata}: like `DependencyRef`, with classes allowed in place of tokens. */\nexport type TestDependency =\n | TestKey\n | { readonly token: TestKey; readonly optional: true }\n | { readonly multi: readonly TestKey[] }\n | { readonly lazy: TestKey }\n\n/** A provider in {@link defineTestMetadata}. */\nexport interface TestProvider<T = unknown> {\n /** Default: `test#<ClassName>` (see `tokenPrefix`). Required without `class`. */\n readonly token?: Token\n readonly class?: ProviderClass<T>\n /** Default: `'singleton'`. */\n readonly scope?: Scope\n /** Constructor (or factory) dependencies, in parameter order. */\n readonly deps?: readonly TestDependency[]\n /** Default: `deps => new Class(...deps)`. Required without `class`. */\n readonly factory?: ProviderFactory<T>\n readonly async?: boolean\n readonly interceptors?: Readonly<Record<string, MethodInterception>>\n readonly dispose?: string\n /** `@Named` qualifier. */\n readonly name?: string\n readonly primary?: boolean\n readonly source?: SourceLocation\n}\n\n/** Input of {@link defineTestMetadata}. */\nexport interface TestMetadataSpec {\n /** Providers: classes (no dependency) or {@link TestProvider}s. */\n readonly providers?: readonly (TestProvider | ProviderClass)[]\n /** Alias → provider pairs (`[UserRepository, PgUserRepository]`), or a record of tokens. */\n readonly aliases?: Iterable<readonly [TestKey, TestKey]> | Readonly<Record<Token, TestKey>>\n readonly externals?: readonly (Token | ExternalDefinition)[]\n /** Feature metadata (`http`, `messaging`, `config`), tokens written with {@link testToken}. */\n readonly extensions?: ZnightExtensionsMetadata\n readonly resolutionOrder?: readonly Token[]\n /** Prefix of the tokens derived from class names. Default: `'test'` (`test#UserService`). */\n readonly tokenPrefix?: string\n}\n\nconst DEFAULT_PREFIX = 'test'\n\n/** The token {@link defineTestMetadata} derives from a class: `<prefix>#<ClassName>`. */\nexport function testToken(cls: ProviderClass | ClassKey, prefix: string = DEFAULT_PREFIX): Token {\n const name = typeof cls === 'function' ? (cls as { name?: unknown }).name : undefined\n if (typeof name !== 'string' || name === '') {\n throw new TypeError('[znight] testToken(): expected a named class')\n }\n return `${prefix}#${name}`\n}\n\n/**\n * Class-first hand-written metadata: tokens are derived from class names (`test#UserService`),\n * dependencies may be classes, factories default to `new Class(...deps)` and the resolution order\n * is computed.\n *\n * ```ts\n * const metadata = defineTestMetadata({\n * providers: [\n * PgUserRepository,\n * { class: UserService, deps: [PgUserRepository, '@znight/observability#Logger'] },\n * ],\n * aliases: [[UserRepository, PgUserRepository]],\n * externals: ['@znight/observability#Logger'],\n * })\n * ```\n *\n * @throws ZnightError ZNIGHT004 for duplicate tokens; TypeError for a provider without class nor\n * token/factory.\n */\nexport function defineTestMetadata(spec: TestMetadataSpec = {}): ZnightMetadata {\n const prefix = spec.tokenPrefix ?? DEFAULT_PREFIX\n const providers = (spec.providers ?? []).map(entry =>\n typeof entry === 'function' ? ({ class: entry } satisfies TestProvider) : entry,\n )\n const classTokens = new Map<unknown, Token>()\n const tokens = providers.map(provider => {\n if (provider === null || typeof provider !== 'object') {\n throw new TypeError(\n '[znight] defineTestMetadata(): a provider must be a class or { class?, token?, deps?, factory? }',\n )\n }\n const token = provider.token ?? (provider.class === undefined ? undefined : testToken(provider.class, prefix))\n if (token === undefined) throw new TypeError('[znight] defineTestMetadata(): a provider needs a class or a token')\n if (provider.class !== undefined && !classTokens.has(provider.class)) classTokens.set(provider.class, token)\n return token\n })\n const toToken = (key: TestKey): Token => {\n if (typeof key === 'string') return key\n return classTokens.get(key) ?? testToken(key, prefix)\n }\n\n const definitions = new Map<Token, ProviderDefinition>()\n providers.forEach((provider, position) => {\n const token = tokens[position] as Token\n if (definitions.has(token)) {\n throw new ZnightError(\n ErrorCode.DuplicateProvider,\n `defineTestMetadata(): duplicate provider ${describeToken(token)}`,\n {\n hints: ['Give one of them an explicit token'],\n },\n )\n }\n definitions.set(token, toDefinition(token, provider, toToken))\n })\n\n let aliases: Record<Token, Token> | undefined\n if (spec.aliases !== undefined) {\n const pairs = entriesOf<TestKey, TestKey>(spec.aliases).map(([alias, target]): [Token, Token] => [\n toToken(alias),\n toToken(target),\n ])\n aliases = Object.fromEntries(pairs)\n }\n return createMetadata(Object.fromEntries(definitions), {\n ...(aliases === undefined ? {} : { aliases }),\n ...(spec.externals === undefined ? {} : { externals: spec.externals }),\n ...(spec.extensions === undefined ? {} : { extensions: spec.extensions }),\n ...(spec.resolutionOrder === undefined ? {} : { resolutionOrder: spec.resolutionOrder }),\n })\n}\n\nfunction toDefinition(token: Token, provider: TestProvider, toToken: (key: TestKey) => Token): ProviderDefinition {\n const cls = provider.class\n let factory = provider.factory\n if (factory === undefined) {\n if (cls === undefined) throw new TypeError(`[znight] defineTestMetadata(): ${token} needs a class or a factory`)\n const constructible = cls as unknown as new (...args: unknown[]) => unknown\n factory = (deps: unknown[]) => new constructible(...deps)\n }\n const deps = (provider.deps ?? []).map(dep => toDependency(dep, toToken))\n return {\n scope: provider.scope ?? 'singleton',\n deps,\n factory,\n ...(cls === undefined ? {} : { class: cls }),\n ...(provider.async === undefined ? {} : { async: provider.async }),\n ...(provider.interceptors === undefined ? {} : { interceptors: provider.interceptors }),\n ...(provider.dispose === undefined ? {} : { dispose: provider.dispose }),\n ...(provider.name === undefined ? {} : { name: provider.name }),\n ...(provider.primary === undefined ? {} : { primary: provider.primary }),\n ...(provider.source === undefined ? {} : { source: provider.source }),\n }\n}\n\nfunction toDependency(dep: TestDependency, toToken: (key: TestKey) => Token): DependencyRef {\n if (typeof dep === 'string' || typeof dep === 'function') return toToken(dep)\n if (dep !== null && typeof dep === 'object') {\n if ('multi' in dep && Array.isArray(dep.multi)) return { multi: dep.multi.map(toToken) }\n if ('lazy' in dep && dep.lazy !== undefined) return { lazy: toToken(dep.lazy) }\n if ('token' in dep && dep.optional === true) return { token: toToken(dep.token), optional: true }\n if ('prototype' in dep) return toToken(dep as ClassKey)\n }\n throw new TypeError(`[znight] defineTestMetadata(): invalid dependency ${String(dep)}`)\n}\n\n/** Hard dependencies of a definition (lazy ones excluded: they never constrain the order). */\nfunction hardDependencies(definition: ProviderDefinition): Token[] {\n const tokens: Token[] = []\n for (const ref of definition.deps) {\n if (typeof ref === 'string') tokens.push(ref)\n else if ('multi' in ref) tokens.push(...ref.multi)\n else if ('token' in ref) tokens.push(ref.token)\n }\n return tokens\n}\n\n/** Deterministic topological order (dependencies first). Cycles are left for the container to report. */\nfunction topologicalOrder(providers: Readonly<Record<Token, ProviderDefinition>>): Token[] {\n const order: Token[] = []\n const state = new Map<Token, 'visiting' | 'done'>()\n const visit = (token: Token): void => {\n if (state.has(token) || !Object.hasOwn(providers, token)) return\n state.set(token, 'visiting')\n for (const dep of hardDependencies(providers[token] as ProviderDefinition)) visit(dep)\n state.set(token, 'done')\n order.push(token)\n }\n for (const token of Object.keys(providers)) visit(token)\n return order\n}\n","import type { AnyFunction, MockFunction, UntypedFunction } from './types.ts'\n\ntype Implementation = (this: unknown, ...args: unknown[]) => unknown\n\ninterface MutableResult {\n type: 'return' | 'throw' | 'incomplete'\n value: unknown\n}\n\ninterface MutableState {\n readonly calls: unknown[][]\n readonly results: MutableResult[]\n readonly instances: unknown[]\n readonly contexts: unknown[]\n readonly invocationCallOrder: number[]\n readonly lastCall: unknown[] | undefined\n}\n\ninterface SpyInternals {\n name: string\n implementation: Implementation | undefined\n readonly initial: Implementation | undefined\n readonly once: Implementation[]\n readonly state: MutableState\n}\n\nconst DEFAULT_NAME = 'spy'\n\n/** Global call counter shared by every built-in spy (`mock.invocationCallOrder`). */\nlet callOrder = 0\n\nconst internalsBySpy = new WeakMap<object, SpyInternals>()\n\nfunction internalsOf(spy: unknown): SpyInternals {\n const internals = typeof spy === 'function' ? internalsBySpy.get(spy) : undefined\n if (internals === undefined) throw new TypeError('[znight] Not a spy created by createSpy()')\n return internals\n}\n\nfunction createState(): MutableState {\n const calls: unknown[][] = []\n return {\n calls,\n results: [],\n instances: [],\n contexts: [],\n invocationCallOrder: [],\n get lastCall(): unknown[] | undefined {\n return calls[calls.length - 1]\n },\n }\n}\n\nfunction clearState(state: MutableState): void {\n state.calls.length = 0\n state.results.length = 0\n state.instances.length = 0\n state.contexts.length = 0\n state.invocationCallOrder.length = 0\n}\n\nfunction isObjectLike(value: unknown): boolean {\n return value !== null && (typeof value === 'object' || typeof value === 'function')\n}\n\nfunction invoke(internals: SpyInternals, self: unknown, args: unknown[], isNew: boolean): unknown {\n const state = internals.state\n state.calls.push(args)\n state.contexts.push(self)\n state.instances.push(self)\n state.invocationCallOrder.push(++callOrder)\n const result: MutableResult = { type: 'incomplete', value: undefined }\n state.results.push(result)\n const implementation = internals.once.shift() ?? internals.implementation\n try {\n const value = implementation === undefined ? undefined : implementation.apply(self, args)\n const returned = isNew && !isObjectLike(value) ? self : value\n result.type = 'return'\n result.value = returned\n return returned\n } catch (error) {\n result.type = 'throw'\n result.value = error\n throw error\n }\n}\n\nfunction returning(value: unknown): Implementation {\n return () => value\n}\n\nfunction resolving(value: unknown): Implementation {\n return () => Promise.resolve(value)\n}\n\nfunction rejecting(error: unknown): Implementation {\n return () => Promise.reject(error)\n}\n\nfunction returnThis(this: unknown): unknown {\n return this\n}\n\n/** Methods shared by every built-in spy (the prototype of the spy functions). */\nconst spyPrototype: object = Object.create(Function.prototype, {\n _isMockFunction: { value: true },\n mock: {\n get(this: unknown): MutableState {\n return internalsOf(this).state\n },\n },\n mockImplementation: {\n value(this: unknown, implementation: Implementation): unknown {\n internalsOf(this).implementation = implementation\n return this\n },\n },\n mockImplementationOnce: {\n value(this: unknown, implementation: Implementation): unknown {\n internalsOf(this).once.push(implementation)\n return this\n },\n },\n mockReturnValue: {\n value(this: unknown, value: unknown): unknown {\n internalsOf(this).implementation = returning(value)\n return this\n },\n },\n mockReturnValueOnce: {\n value(this: unknown, value: unknown): unknown {\n internalsOf(this).once.push(returning(value))\n return this\n },\n },\n mockResolvedValue: {\n value(this: unknown, value: unknown): unknown {\n internalsOf(this).implementation = resolving(value)\n return this\n },\n },\n mockResolvedValueOnce: {\n value(this: unknown, value: unknown): unknown {\n internalsOf(this).once.push(resolving(value))\n return this\n },\n },\n mockRejectedValue: {\n value(this: unknown, error: unknown): unknown {\n internalsOf(this).implementation = rejecting(error)\n return this\n },\n },\n mockRejectedValueOnce: {\n value(this: unknown, error: unknown): unknown {\n internalsOf(this).once.push(rejecting(error))\n return this\n },\n },\n mockReturnThis: {\n value(this: unknown): unknown {\n internalsOf(this).implementation = returnThis\n return this\n },\n },\n mockName: {\n value(this: unknown, name: string): unknown {\n internalsOf(this).name = String(name)\n return this\n },\n },\n getMockName: {\n value(this: unknown): string {\n return internalsOf(this).name\n },\n },\n getMockImplementation: {\n value(this: unknown): Implementation | undefined {\n return internalsOf(this).implementation\n },\n },\n mockClear: {\n value(this: unknown): unknown {\n clearState(internalsOf(this).state)\n return this\n },\n },\n mockReset: {\n value(this: unknown): unknown {\n const internals = internalsOf(this)\n clearState(internals.state)\n internals.once.length = 0\n internals.implementation = internals.initial\n return this\n },\n },\n mockRestore: {\n value(this: unknown): void {\n const internals = internalsOf(this)\n clearState(internals.state)\n internals.once.length = 0\n internals.implementation = internals.initial\n },\n },\n})\n\n/**\n * Creates the built-in, dependency-free, Jest-compatible spy. It records `mock.calls`,\n * `mock.results`, `mock.instances`, `mock.contexts`, `mock.invocationCallOrder` and `mock.lastCall`,\n * supports `mockReturnValue(Once)`, `mockResolvedValue(Once)`, `mockRejectedValue(Once)`,\n * `mockImplementation(Once)`, `mockReturnThis`, `mockName`, `mockClear`, `mockReset` and\n * `mockRestore`, and is recognised by Jest's and Vitest's `expect` (`_isMockFunction`).\n *\n * `mockReset()` restores the implementation given to `createSpy()` (Vitest semantics).\n *\n * ```ts\n * const find = createSpy((id: string) => ({ id }))\n * find.mockReturnValueOnce({ id: 'x' })\n * find('1')\n * find.mock.calls // [['1']]\n * ```\n */\nexport function createSpy<F extends AnyFunction = UntypedFunction>(implementation?: F): MockFunction<F> {\n if (implementation !== undefined && typeof implementation !== 'function') {\n throw new TypeError('[znight] createSpy() expects a function implementation')\n }\n const initial = implementation as Implementation | undefined\n const internals: SpyInternals = {\n name: DEFAULT_NAME,\n implementation: initial,\n initial,\n once: [],\n state: createState(),\n }\n const spy = function (this: unknown, ...args: unknown[]): unknown {\n return invoke(internals, this, args, new.target !== undefined)\n }\n Object.setPrototypeOf(spy, spyPrototype)\n internalsBySpy.set(spy, internals)\n return spy as unknown as MockFunction<F>\n}\n\n/** Whether `value` is a spy created by {@link createSpy}. */\nexport function isBuiltinSpy(value: unknown): boolean {\n return typeof value === 'function' && internalsBySpy.has(value)\n}\n","import type { MockFnFactory, MockFnOption } from './types.ts'\n\nimport { createRequire } from 'node:module'\n\nimport { createSpy } from './spy.ts'\n\n/** Where the spy factory used by mocks comes from. */\nexport type MockFnSource = 'custom' | 'vitest' | 'jest' | 'bun' | 'builtin'\n\n/** A spy factory and its origin (see {@link resolveMockFn}). */\nexport interface ResolvedMockFn {\n readonly source: MockFnSource\n readonly create: MockFnFactory\n}\n\nconst BUILTIN: ResolvedMockFn = Object.freeze({ source: 'builtin', create: createSpy as MockFnFactory })\n\nlet defaultOption: MockFnOption = 'auto'\n/** `mock` of `bun:test`: `undefined` until probed, `null` when unavailable. */\nlet bunMock: MockFnFactory | null | undefined\n\nfunction assertOption(option: unknown, where: string): asserts option is MockFnOption {\n if (typeof option === 'function' || option === 'auto' || option === 'builtin') return\n throw new TypeError(`[znight] ${where}: mockFn must be 'auto', 'builtin' or a function such as vi.fn`)\n}\n\n/**\n * Sets the spy factory used when `mockFn` is not passed explicitly (e.g. in a Vitest setup file:\n * `setDefaultMockFn(vi.fn)`). Without argument, restores auto-detection.\n */\nexport function setDefaultMockFn(option: MockFnOption = 'auto'): void {\n assertOption(option, 'setDefaultMockFn()')\n defaultOption = option\n}\n\n/**\n * Resolves a {@link MockFnOption} (default: the option set with {@link setDefaultMockFn}, `'auto'`\n * initially) to a spy factory.\n */\nexport function resolveMockFn(option?: MockFnOption): ResolvedMockFn {\n const effective = option ?? defaultOption\n assertOption(effective, 'resolveMockFn()')\n if (typeof effective === 'function') return { source: 'custom', create: effective }\n if (effective === 'builtin') return BUILTIN\n return detectMockFn()\n}\n\n/**\n * Auto-detects the spy factory of the running test framework: Vitest (`globalThis.vi.fn`, with\n * `globals: true`), Jest (`globalThis.jest.fn`), `bun:test` (`mock`, loaded only when running on\n * Bun), otherwise the built-in spy ({@link createSpy}).\n */\nexport function detectMockFn(): ResolvedMockFn {\n const scope = globalThis as { vi?: { fn?: unknown }; jest?: { fn?: unknown } }\n const vitest = scope.vi?.fn\n if (typeof vitest === 'function') return { source: 'vitest', create: vitest as MockFnFactory }\n const jest = scope.jest?.fn\n if (typeof jest === 'function') return { source: 'jest', create: jest as MockFnFactory }\n const bun = loadBunMock()\n if (bun !== undefined) return { source: 'bun', create: bun }\n return BUILTIN\n}\n\n/** Whether the code runs on Bun. */\nexport function isBunRuntime(): boolean {\n return typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'\n}\n\nfunction loadBunMock(): MockFnFactory | undefined {\n bunMock ??= isBunRuntime() ? requireBunMock() : null\n return bunMock ?? undefined\n}\n\nfunction requireBunMock(): MockFnFactory | null {\n try {\n // non-literal specifier: bundlers and Vite never try to resolve `bun:test`\n const specifier = ['bun', 'test'].join(':')\n const bunTest = createRequire(import.meta.url)(specifier) as { mock?: unknown }\n return typeof bunTest.mock === 'function' ? (bunTest.mock as MockFnFactory) : null\n } catch {\n return null\n }\n}\n","import type { ClassKey } from '@znight/core'\nimport type { AnyFunction, DeepMock, Mocked, MockFnFactory, MockFnOption } from './types.ts'\n\nimport { resolveMockFn } from './mock-fn.ts'\n\n/** Options of {@link createMock}. */\nexport interface CreateMockOptions {\n /**\n * Name of the mock, used to name its spies in assertion messages (`UserRepository.findById`).\n * Default: the class name, or `mock`.\n */\n readonly name?: string\n /**\n * When `true`, calling an unconfigured method returns a deep mock (the same one for every call)\n * instead of `undefined`, so fluent APIs work: `db.select().from('users')`. Default: `false`.\n */\n readonly deep?: boolean\n /** Spy implementation. Default: auto-detected (see `MockFnOption`). */\n readonly mockFn?: MockFnOption\n}\n\n/** Shared state of a mock and every spy created under it. */\ninterface MockTree {\n readonly create: MockFnFactory\n readonly deep: boolean\n readonly spies: SpyRecord[]\n}\n\ninterface SpyRecord {\n readonly spy: SpyLike\n readonly implementation: AnyFunction | undefined\n}\n\ninterface SpyLike {\n (...args: unknown[]): unknown\n mockName?: (name: string) => unknown\n mockClear?: () => unknown\n mockReset?: () => unknown\n mockImplementation?: (implementation: AnyFunction) => unknown\n}\n\n/**\n * Property names never auto-mocked (they read as `undefined` unless set explicitly). Libraries probe\n * them to detect promises (`then`), JSON values (`toJSON`), asymmetric matchers (`asymmetricMatch`),\n * React elements (`$$typeof`), DOM nodes (`nodeType`, `tagName`), ES module namespaces\n * (`__esModule`) or mock functions (`_isMockFunction`). Names starting with `@@` (Immutable.js\n * sentinels) are reserved too. Symbol-keyed properties are never auto-mocked.\n */\nconst RESERVED: ReadonlySet<string> = new Set([\n 'then',\n 'toJSON',\n 'asymmetricMatch',\n '$$typeof',\n 'nodeType',\n 'tagName',\n '__esModule',\n '_isMockFunction',\n])\n\nconst TREE: unique symbol = Symbol('znight.mock')\n\nconst mocks = new WeakSet<object>()\n\nfunction isReserved(key: string): boolean {\n return RESERVED.has(key) || key.startsWith('@@')\n}\n\n/**\n * Creates a deep auto-mock.\n *\n * - Every property read returns a spy (`MockFunction`), created on first access and then stable.\n * Spies are deep too: `mock.pool.query.mockResolvedValue(rows)`.\n * - Unconfigured spies return `undefined` (or a deep mock with `{ deep: true }`).\n * - The mock is **not thenable** and inert for serialisers: `then`, `toJSON`, `asymmetricMatch`,\n * `$$typeof`, `Symbol.toPrimitive`... read as `undefined`, so `await mock`, `JSON.stringify(mock)`\n * and `expect(...).toEqual(mock)` behave.\n * - Assigned properties win: `mock.enabled = false`.\n * - With a class, the mock inherits its prototype (`instanceof` works) and getters read as\n * `undefined` instead of a (truthy) spy.\n * - Functions of `partial` become spies with that implementation; other values are set as is.\n *\n * ```ts\n * const repository = createMock(UserRepository, { findById: async id => ({ id }) })\n * const logger = createMock<Logger>()\n * logger.info('hello')\n * expect(logger.info).toHaveBeenCalledWith('hello')\n * ```\n */\nexport function createMock<T>(cls: ClassKey<T>, partial?: Partial<T>, options?: CreateMockOptions): Mocked<T>\nexport function createMock<T = never>(\n partial?: Partial<T>,\n options?: CreateMockOptions,\n): [T] extends [never] ? DeepMock : Mocked<T>\nexport function createMock(first?: unknown, second?: unknown, third?: unknown): unknown {\n if (typeof first === 'function') {\n return mockObject(first as ClassKey<unknown>, second as object | undefined, third as CreateMockOptions | undefined)\n }\n return mockObject(undefined, first as object | undefined, second as CreateMockOptions | undefined)\n}\n\n/** {@link createMock} with an optional class (internal). */\nexport function mockObject(\n cls: ClassKey<unknown> | undefined,\n partial: object | undefined,\n options: CreateMockOptions = {},\n): object {\n if (partial !== undefined && (partial === null || typeof partial !== 'object')) {\n throw new TypeError('[znight] createMock(): the partial implementation must be an object')\n }\n const tree: MockTree = {\n create: resolveMockFn(options.mockFn).create,\n deep: options.deep === true,\n spies: [],\n }\n const className = typeof cls === 'function' ? (cls as { name?: unknown }).name : undefined\n const name = options.name ?? (typeof className === 'string' && className !== '' ? className : 'mock')\n return createNode(name, tree, cls, partial)\n}\n\n/** Whether `value` is a mock (or one of its spies) created by {@link createMock}. */\nexport function isMock(value: unknown): boolean {\n return value !== null && (typeof value === 'object' || typeof value === 'function') && mocks.has(value)\n}\n\n/** Forgets the calls recorded by every spy of `mock` (`mockClear()`); implementations are kept. */\nexport function clearMock(mock: object): void {\n for (const { spy } of treeOf(mock, 'clearMock').spies) spy.mockClear?.()\n}\n\n/**\n * Resets every spy of `mock` to its initial state: recorded calls and programmed implementations\n * are forgotten, implementations given to {@link createMock} (and deep returns) are restored.\n */\nexport function resetMock(mock: object): void {\n for (const { spy, implementation } of treeOf(mock, 'resetMock').spies) {\n spy.mockReset?.()\n if (implementation !== undefined) spy.mockImplementation?.(implementation)\n }\n}\n\nfunction treeOf(mock: object, where: string): MockTree {\n const tree = isMock(mock) ? (mock as { [TREE]?: MockTree })[TREE] : undefined\n if (tree === undefined) throw new TypeError(`[znight] ${where}(): expected a mock created by createMock()`)\n return tree\n}\n\n/** An object mock (the root of a mock, or the value returned by a deep spy). */\nfunction createNode(\n name: string,\n tree: MockTree,\n cls: ClassKey<unknown> | undefined,\n partial: object | undefined,\n): object {\n const target: Record<PropertyKey, unknown> = Object.create(\n typeof cls === 'function' && isObjectLike(cls.prototype) ? (cls.prototype as object) : Object.prototype,\n )\n const accessors = typeof cls === 'function' ? accessorKeys(cls.prototype) : undefined\n const children = new Map<string, unknown>()\n if (partial !== undefined) {\n for (const key of Reflect.ownKeys(partial)) {\n const value = (partial as Record<PropertyKey, unknown>)[key]\n if (typeof key === 'string' && typeof value === 'function') {\n children.set(key, createSpyNode(`${name}.${key}`, tree, value as AnyFunction))\n } else {\n defineValue(target, key, value)\n }\n }\n }\n const proxy: object = new Proxy(target, {\n get(object, key, receiver): unknown {\n if (typeof key === 'symbol') {\n if (key === TREE) return tree\n return Object.hasOwn(object, key) ? object[key] : undefined\n }\n if (Object.hasOwn(object, key)) return object[key]\n if (key === 'constructor') return Reflect.get(object, key, receiver)\n if (isReserved(key)) return undefined\n if (Object.hasOwn(Object.prototype, key)) return Reflect.get(Object.prototype, key, receiver)\n if (accessors?.has(key) === true) return undefined\n let child = children.get(key)\n if (child === undefined) {\n child = createSpyNode(`${name}.${key}`, tree, undefined)\n children.set(key, child)\n }\n return child\n },\n set(object, key, value): boolean {\n defineValue(object, key, value)\n return true\n },\n deleteProperty(object, key): boolean {\n if (typeof key === 'string') children.delete(key)\n return Reflect.deleteProperty(object, key)\n },\n })\n mocks.add(proxy)\n return proxy\n}\n\n/** A spy whose unknown properties are deep spies (`spy.nested.method`). */\nfunction createSpyNode(path: string, tree: MockTree, implementation: AnyFunction | undefined): SpyLike {\n const effective = implementation ?? (tree.deep ? deepReturn(path, tree) : undefined)\n const spy = tree.create(effective) as SpyLike\n if (typeof spy !== 'function') {\n throw new TypeError(`[znight] The mockFn factory returned ${typeof spy} instead of a function`)\n }\n if (typeof spy.mockName === 'function') spy.mockName(path)\n makeDeep(spy, path, tree)\n tree.spies.push({ spy, implementation: effective })\n mocks.add(spy)\n return spy\n}\n\n/** The implementation of a deep spy: returns the same deep mock on every call. */\nfunction deepReturn(path: string, tree: MockTree): AnyFunction {\n let result: object | undefined\n return () => {\n result ??= createNode(`${path}()`, tree, undefined, undefined)\n return result\n }\n}\n\n/**\n * Inserts a proxy between `spy` and its prototype: reading a property the spy does not have (own or\n * inherited) creates a child spy. The spy itself stays a genuine spy of its framework, which\n * `bun:test`'s `expect` requires (it rejects proxies).\n */\nfunction makeDeep(spy: SpyLike, path: string, tree: MockTree): void {\n const original: unknown = Object.getPrototypeOf(spy)\n if (!isObjectLike(original)) return\n const children = new Map<string, SpyLike>()\n const prototype = new Proxy(original as object, {\n get(object, key, receiver): unknown {\n if (typeof key === 'symbol' || key in object || isReserved(key)) return Reflect.get(object, key, receiver)\n let child = children.get(key)\n if (child === undefined) {\n child = createSpyNode(`${path}.${key}`, tree, undefined)\n children.set(key, child)\n }\n return child\n },\n })\n try {\n Object.setPrototypeOf(spy, prototype)\n } catch {\n // a frozen or exotic spy: it keeps working, without deep members\n }\n}\n\nfunction defineValue(object: object, key: PropertyKey, value: unknown): void {\n Object.defineProperty(object, key, { value, writable: true, enumerable: true, configurable: true })\n}\n\n/** Names of the accessors (getters/setters) declared along a prototype chain, `Object.prototype` excluded. */\nfunction accessorKeys(prototype: unknown): ReadonlySet<string> {\n const keys = new Set<string>()\n let current: unknown = prototype\n while (isObjectLike(current) && current !== Object.prototype && current !== Function.prototype) {\n for (const key of Object.getOwnPropertyNames(current)) {\n const descriptor = Object.getOwnPropertyDescriptor(current, key)\n if (descriptor !== undefined && (descriptor.get !== undefined || descriptor.set !== undefined)) keys.add(key)\n }\n current = Object.getPrototypeOf(current)\n }\n return keys\n}\n\nfunction isObjectLike(value: unknown): value is object {\n return value !== null && (typeof value === 'object' || typeof value === 'function')\n}\n","import type { DependencyRef, ProviderDefinition, ProviderFactory, ProviderKey, Scope } from '@znight/core'\n\n/** A typed `[key, value]` entry for `overrides` / `providers` / `provide`. */\nexport type OverrideEntry<T = unknown> = readonly [ProviderKey<T>, T]\n\n/** A `[key, definition]` entry replacing a provider with a factory. */\nexport type OverrideDefinitionEntry<T = unknown> = readonly [ProviderKey<T>, ProviderDefinition<T>]\n\n/**\n * A type-checked override: the value must match the type designated by the class or typed token.\n *\n * ```ts\n * await TestApp.create({ metadata, overrides: [override(UserRepository, new InMemoryUserRepository())] })\n * ```\n */\nexport function override<T>(key: ProviderKey<T>, value: NoInfer<T>): OverrideEntry<T> {\n return [key, value]\n}\n\n/** Options of {@link overrideFactory}. */\nexport interface OverrideFactoryOptions {\n /** Tokens resolved and passed to the factory, in order. Default: none. */\n readonly deps?: readonly DependencyRef[]\n /** Default: `'singleton'`. */\n readonly scope?: Scope\n /** Set when the factory returns a promise (singletons only). */\n readonly async?: boolean\n /** Method called when the instance is disposed. */\n readonly dispose?: string\n}\n\n/**\n * Replaces a provider with a factory whose dependencies are resolved by the container (or, in\n * `TestBed`, like the target's dependencies).\n *\n * ```ts\n * overrideFactory(UserRepository, ([db]) => new InMemoryUserRepository(db), { deps: ['src/db.ts#Database'] })\n * ```\n */\nexport function overrideFactory<T>(\n key: ProviderKey<T>,\n factory: ProviderFactory<NoInfer<T>>,\n options: OverrideFactoryOptions = {},\n): OverrideDefinitionEntry<T> {\n if (typeof factory !== 'function') throw new TypeError('[znight] overrideFactory() expects a factory function')\n const definition: ProviderDefinition<T> = {\n scope: options.scope ?? 'singleton',\n deps: options.deps ?? [],\n factory,\n ...(options.async === undefined ? {} : { async: options.async }),\n ...(options.dispose === undefined ? {} : { dispose: options.dispose }),\n }\n return [key, definition]\n}\n","/**\n * Structural readers of the feature metadata (`metadata.extensions`). `@znight/testing` depends on\n * no feature package: it reads the documented shapes (architecture §9, RFC 0005 §7.1 for\n * `extensions.graphql`) defensively and ignores malformed entries.\n */\nimport type { Token, ZnightMetadata } from '@znight/core'\n\n/** A configuration class (`metadata.extensions.config.configs[]`), as far as tests need it. */\nexport interface ConfigClassInfo {\n readonly token: Token\n readonly prefix: string | undefined\n readonly fields: readonly ConfigFieldInfo[]\n}\n\n/** A field of a configuration class. */\nexport interface ConfigFieldInfo {\n readonly property: string\n readonly env: string | undefined\n /** Config type (`'string'`, `'number'`, `'url'`...), `undefined` when absent from the metadata. */\n readonly type: string | undefined\n /** Whether the field declares a default value (`@Default`; initializers are not in the metadata). */\n readonly hasDefault: boolean\n readonly default: unknown\n readonly required: boolean\n}\n\ntype Loose = Readonly<Record<string, unknown>>\n\nfunction isRecord(value: unknown): value is Loose {\n return value !== null && typeof value === 'object'\n}\n\nfunction arrayOf(value: unknown): readonly unknown[] {\n return Array.isArray(value) ? value : []\n}\n\nfunction extension(metadata: ZnightMetadata, name: string): Loose | undefined {\n if (!isRecord(metadata)) return undefined\n const extensions: unknown = metadata.extensions\n if (!isRecord(extensions)) return undefined\n const value = extensions[name]\n return isRecord(value) ? value : undefined\n}\n\nfunction tokensOf(value: unknown): Token[] {\n return arrayOf(value).filter((token): token is Token => typeof token === 'string')\n}\n\n/** Configuration classes declared by `@znight/config` (`extensions.config.configs`), by token. */\nexport function readConfigClasses(metadata: ZnightMetadata): Map<Token, ConfigClassInfo> {\n const result = new Map<Token, ConfigClassInfo>()\n for (const entry of arrayOf(extension(metadata, 'config')?.['configs'])) {\n if (!isRecord(entry) || typeof entry['token'] !== 'string') continue\n const fields: ConfigFieldInfo[] = []\n for (const field of arrayOf(entry['fields'])) {\n if (!isRecord(field) || typeof field['property'] !== 'string') continue\n fields.push({\n property: field['property'],\n env: typeof field['env'] === 'string' ? field['env'] : undefined,\n type: typeof field['type'] === 'string' ? field['type'] : undefined,\n hasDefault: Object.hasOwn(field, 'default') && field['default'] !== undefined,\n default: field['default'],\n required: field['required'] === true,\n })\n }\n const prefix = entry['prefix']\n result.set(entry['token'], {\n token: entry['token'],\n prefix: typeof prefix === 'string' && prefix !== '' ? prefix : undefined,\n fields,\n })\n }\n return result\n}\n\n/**\n * Tokens an HTTP application needs at boot: controllers (`extensions.http.controllers[].token`) and\n * the guards and interceptors they and their routes reference.\n */\nexport function readHttpRoots(metadata: ZnightMetadata): Token[] {\n const roots: Token[] = []\n for (const controller of arrayOf(extension(metadata, 'http')?.['controllers'])) {\n if (!isRecord(controller)) continue\n if (typeof controller['token'] === 'string') roots.push(controller['token'])\n roots.push(...tokensOf(controller['guards']), ...tokensOf(controller['interceptors']))\n for (const route of arrayOf(controller['routes'])) {\n if (isRecord(route)) roots.push(...tokensOf(route['guards']), ...tokensOf(route['interceptors']))\n }\n }\n return roots\n}\n\n/** Message consumers (`extensions.messaging.consumers[].token`). */\nexport function readMessagingRoots(metadata: ZnightMetadata): Token[] {\n const roots: Token[] = []\n for (const consumer of arrayOf(extension(metadata, 'messaging')?.['consumers'])) {\n if (isRecord(consumer) && typeof consumer['token'] === 'string') roots.push(consumer['token'])\n }\n return roots\n}\n\n/** Hosts of scheduled jobs (`extensions.schedule.jobs[].token`), disabled jobs included (they can be triggered). */\nexport function readScheduleRoots(metadata: ZnightMetadata): Token[] {\n const roots: Token[] = []\n for (const job of arrayOf(extension(metadata, 'schedule')?.['jobs'])) {\n if (isRecord(job) && typeof job['token'] === 'string') roots.push(job['token'])\n }\n return roots\n}\n\n/**\n * Tokens a GraphQL application needs at boot (`extensions.graphql`, RFC 0005 §7.1): for every field\n * of an object type bound to a resolver (`types[kind: 'object'].fields[].resolver`), the resolver\n * token, its guard tokens and the loader tokens its method injects.\n */\nexport function readGraphQLRoots(metadata: ZnightMetadata): Token[] {\n const roots: Token[] = []\n for (const type of arrayOf(extension(metadata, 'graphql')?.['types'])) {\n if (!isRecord(type) || type['kind'] !== 'object') continue\n for (const field of arrayOf(type['fields'])) {\n const resolver = isRecord(field) ? field['resolver'] : undefined\n if (!isRecord(resolver)) continue\n if (typeof resolver['token'] === 'string') roots.push(resolver['token'])\n roots.push(...tokensOf(resolver['guards']), ...tokensOf(resolver['loaders']))\n }\n }\n return roots\n}\n","import type { ExternalDefinition, ProviderClass, ProviderDefinition, Token, ZnightMetadata } from '@znight/core'\n\nimport { describeToken, displayName, ErrorCode, METADATA_VERSION, ZnightError } from '@znight/core'\n\n/**\n * Read-only index over compiled metadata: provider definitions, aliases, externals and the key\n * lookups shared by `TestBed`, `mocks.get()` and the testing helpers (class, token, alias or display\n * name → canonical token). Internal.\n */\nexport class MetadataIndex {\n readonly metadata: ZnightMetadata\n readonly #providers = new Map<Token, ProviderDefinition>()\n readonly #aliases = new Map<Token, Token>()\n readonly #externals = new Map<Token, ExternalDefinition>()\n\n constructor(metadata: ZnightMetadata) {\n assertMetadata(metadata)\n this.metadata = metadata\n for (const [token, definition] of Object.entries(metadata.providers)) this.#providers.set(token, definition)\n for (const [alias, target] of Object.entries(metadata.aliases ?? {})) this.#aliases.set(alias, target)\n for (const external of metadata.externals ?? []) {\n if (typeof external?.token === 'string') this.#externals.set(external.token, external)\n }\n }\n\n /** Every provider token, in declaration order. */\n providerTokens(): IterableIterator<Token> {\n return this.#providers.keys()\n }\n\n definition(token: Token): ProviderDefinition | undefined {\n return this.#providers.get(token)\n }\n\n isProvider(token: Token): boolean {\n return this.#providers.has(token)\n }\n\n external(token: Token): ExternalDefinition | undefined {\n return this.#externals.get(token)\n }\n\n /** Whether `token` is a provider, an alias or an external of the metadata. */\n isKnown(token: Token): boolean {\n return this.#providers.has(token) || this.#aliases.has(token) || this.#externals.has(token)\n }\n\n /** Provider, alias and external tokens. */\n knownTokens(): Set<Token> {\n return new Set([...this.#providers.keys(), ...this.#aliases.keys(), ...this.#externals.keys()])\n }\n\n /** The class of a provider, when it is a class provider. */\n classOf(token: Token): ProviderClass | undefined {\n return this.#providers.get(token)?.class\n }\n\n /** Follows aliases (cycle-guarded) until a provider token; returns `token` itself otherwise. */\n canonical(token: Token): Token {\n let current = token\n const seen = new Set<Token>()\n while (!this.#providers.has(current) && this.#aliases.has(current) && !seen.has(current)) {\n seen.add(current)\n current = this.#aliases.get(current) as Token\n }\n return current\n }\n\n /** Alias entries (alias → target), for filtering and display. */\n aliases(): IterableIterator<[Token, Token]> {\n return this.#aliases.entries()\n }\n\n /**\n * Finds the canonical token designated by `key` among `universe`:\n * - a string: a token of `universe`, an alias resolving into it, or a unique display name\n * (`'UserService'`) of a token or alias;\n * - a class: the token whose provider class is `key`, else the unique token whose class extends\n * it, else a unique display name equal to the class name (externals, interfaces).\n *\n * @throws ZnightError ZNIGHT008 when a display name is ambiguous.\n */\n find(key: unknown, universe: ReadonlySet<Token>): Token | undefined {\n if (typeof key === 'string') {\n if (universe.has(key)) return key\n const canonical = this.canonical(key)\n if (universe.has(canonical)) return canonical\n return this.#findByName(key, universe, undefined)\n }\n if (typeof key !== 'function') return undefined\n const cls = key as ProviderClass\n const exact = [...universe].filter(token => this.classOf(token) === cls)\n if (exact.length > 0) return exact[0]\n const derived = [...universe].filter(token => extendsClass(this.classOf(token), cls))\n if (derived.length === 1) return derived[0]\n if (derived.length > 1) throw ambiguousError(cls.name, derived)\n const name = cls.name\n return typeof name === 'string' && name !== '' ? this.#findByName(name, universe, cls) : undefined\n }\n\n #findByName(name: string, universe: ReadonlySet<Token>, cls: ProviderClass | undefined): Token | undefined {\n // an alias and its provider designate the same thing: matches are compared by canonical token\n const matches = new Set<Token>()\n const add = (token: Token): void => {\n const canonical = this.canonical(token)\n if (universe.has(canonical)) matches.add(canonical)\n else if (universe.has(token)) matches.add(token)\n }\n for (const token of universe) if (displayName(token) === name) add(token)\n for (const [alias] of this.#aliases) if (displayName(alias) === name) add(alias)\n const candidates = [...matches].filter(token => {\n if (cls === undefined) return true\n const own = this.classOf(token)\n return own === undefined || own === cls || extendsClass(own, cls)\n })\n if (candidates.length === 1) return candidates[0]\n if (candidates.length > 1) throw ambiguousError(name, candidates)\n return undefined\n }\n}\n\nfunction extendsClass(candidate: ProviderClass | undefined, base: ProviderClass): boolean {\n if (candidate === undefined || candidate === base) return false\n const prototype: unknown = base.prototype\n return typeof prototype === 'object' && prototype !== null && candidate.prototype instanceof base\n}\n\nfunction ambiguousError(name: string, tokens: readonly Token[]): ZnightError {\n return new ZnightError(\n ErrorCode.AmbiguousInjection,\n `\"${name}\" is ambiguous: it matches ${tokens.map(describeToken).join(', ')}`,\n { hints: ['Use the full token (or the class) instead of the display name'] },\n )\n}\n\nfunction assertMetadata(metadata: ZnightMetadata): void {\n if (\n metadata === null ||\n typeof metadata !== 'object' ||\n metadata.providers === null ||\n typeof metadata.providers !== 'object'\n ) {\n throw new ZnightError(\n ErrorCode.MissingProvider,\n 'No compiled metadata: expected the generated __ZNIGHT_METADATA__',\n {\n hints: [\n 'Pass { metadata: __ZNIGHT_METADATA__ } imported from src/.znight/container.generated.ts',\n 'Generate it before running tests: `znight generate`, the Bun preload `@znight/compiler/bun` or the Vite plugin under Vitest',\n ],\n },\n )\n }\n if (metadata.version !== METADATA_VERSION) {\n throw new ZnightError(\n ErrorCode.VersionMismatch,\n `Unsupported metadata version ${String(metadata.version)} (expected ${METADATA_VERSION})`,\n { hints: ['Regenerate the metadata with the @znight/compiler version matching @znight/testing'] },\n )\n }\n}\n","import type {\n ClassKey,\n Container,\n CoreLogger,\n Plugin,\n PluginRootsContext,\n ProviderClass,\n ProviderKey,\n ProviderValues,\n ShutdownOptions,\n Token,\n TypedToken,\n ZnightMetadata,\n} from '@znight/core'\n\nimport { Application, createConsoleLogger, ErrorCode, ZnightError } from '@znight/core'\n\nimport { readGraphQLRoots, readHttpRoots, readMessagingRoots, readScheduleRoots } from './extensions.ts'\nimport { MetadataIndex } from './metadata-index.ts'\nimport { entriesOf } from './utils.ts'\n\n/** Name of the HTTP plugin `TestApp.inject()` delegates to (`HttpPlugin.configure()` from `@znight/http`). */\nexport const HTTP_PLUGIN_NAME = 'http'\n\n/** An in-memory HTTP request for {@link TestApp.inject}. */\nexport interface InjectRequest {\n /** HTTP method. Default: `GET`. */\n readonly method?: string\n /** Path, with an optional query string (`/users?page=2`). */\n readonly url: string\n readonly headers?: Readonly<Record<string, string>>\n /**\n * Request body, encoded by the HTTP plugin: a string or bytes are sent as is (`text/plain` /\n * `application/octet-stream` without `content-type` header), a `FormData` as\n * `multipart/form-data` (files included: uploads), a `Blob` / `File` with its type, anything else\n * as JSON (`application/json`).\n */\n readonly body?: unknown\n /** Query parameters added to those of `url`. */\n readonly query?: Readonly<Record<string, string | readonly string[]>>\n /**\n * Request cookies (name → value), sent by the HTTP plugin in a `cookie` header, after any `cookie`\n * header of `headers`. Values are encoded like the cookies the plugin sets, so a value read from\n * `response.cookies` can be sent back as is (signed values included).\n */\n readonly cookies?: Readonly<Record<string, string>>\n /**\n * Cookies the HTTP plugin signs with its current secret (`cookies.secrets[0]`) and merges into\n * `cookies` before dispatch: the way to send a valid `@SignedCookie`.\n */\n readonly signedCookies?: Readonly<Record<string, string>>\n}\n\n/**\n * A parsed `Set-Cookie` header of an {@link InjectResponse}: the shape of `SetCookieInfo` from\n * `@znight/http`.\n */\nexport interface SetCookieInfo {\n readonly name: string\n /** Decoded value (a signed cookie: `<value>.<signature>`). */\n readonly value: string\n /** The `Set-Cookie` header line. */\n readonly raw: string\n readonly expires?: Date\n readonly maxAge?: number\n readonly domain?: string\n readonly path?: string\n readonly secure: boolean\n readonly httpOnly: boolean\n readonly sameSite?: 'strict' | 'lax' | 'none'\n readonly partitioned: boolean\n readonly priority?: 'low' | 'medium' | 'high'\n}\n\n/** The response of {@link TestApp.inject}. */\nexport interface InjectResponse {\n readonly status: number\n /** Response headers (lower-cased names). */\n readonly headers: Readonly<Record<string, string | readonly string[] | undefined>>\n /** The body decoded as UTF-8. */\n readonly body: string\n /** The raw body bytes (downloads, binary responses). */\n readonly bytes: Uint8Array\n /** The `set-cookie` headers parsed, by cookie name (the last one wins); `{}` without any. */\n readonly cookies: Readonly<Record<string, SetCookieInfo>>\n /** The body parsed as JSON. */\n json<T = unknown>(): T\n}\n\n/**\n * What the `inject()` of the HTTP plugin resolves with: an {@link InjectResponse} whose `bytes` and\n * `cookies` may be absent (`TestApp.inject()` then encodes `body` as UTF-8 and returns no cookies).\n */\nexport type HttpInjectResult = Omit<InjectResponse, 'bytes' | 'cookies'> & {\n readonly bytes?: Uint8Array\n readonly cookies?: Readonly<Record<string, SetCookieInfo>>\n}\n\n/**\n * What `TestApp.inject()` expects from the plugin named `'http'`: an in-memory dispatch (no socket).\n * `HttpPlugin` from `@znight/http` implements it.\n */\nexport interface HttpInjector {\n inject(request: InjectRequest & { readonly method: string }): Promise<HttpInjectResult>\n}\n\n/** A request for {@link TestApp.injectStream} / {@link TestApp.injectSse}: an {@link InjectRequest} that can be aborted. */\nexport interface InjectStreamRequest extends InjectRequest {\n /** Aborting it disconnects the client (like cancelling the response body). */\n readonly signal?: AbortSignal\n}\n\n/**\n * The response of {@link TestApp.injectStream}: available at the headers, the body read as it is\n * produced. Cancelling `body` disconnects the client. The shape of `InjectStreamResponse` from\n * `@znight/http`.\n */\nexport interface InjectStreamResponse {\n readonly status: number\n readonly headers: Readonly<Record<string, string | readonly string[] | undefined>>\n readonly cookies: Readonly<Record<string, SetCookieInfo>>\n readonly body: ReadableStream<Uint8Array>\n}\n\n/** An event of an event stream (`SseMessage` of `@znight/http`). */\nexport interface SseMessage {\n /** Event type: `message` by default. */\n readonly event: string\n readonly data: string\n /** The last event id at dispatch time. */\n readonly id: string\n json<T = unknown>(): T\n}\n\n/**\n * The response of {@link TestApp.injectSse}: an event stream read in memory like `EventSource`\n * would (`InjectSseResponse` of `@znight/http`).\n */\nexport interface InjectSseResponse extends AsyncIterable<SseMessage>, AsyncDisposable {\n readonly status: number\n readonly headers: Readonly<Record<string, string | readonly string[] | undefined>>\n readonly cookies: Readonly<Record<string, SetCookieInfo>>\n /** `''` for an event stream; otherwise the whole body (an error, a 204...). */\n readonly body: string\n json<T = unknown>(): T\n /** The next event (comments skipped). Rejects on timeout (default 2 000 ms) or when the stream ended. */\n next(options?: { readonly timeoutMs?: number }): Promise<SseMessage>\n take(count: number, options?: { readonly timeoutMs?: number }): Promise<SseMessage[]>\n /** Comments received so far (heartbeats are `''`). */\n readonly comments: readonly string[]\n /** What a browser would send as `Last-Event-ID`. */\n readonly lastEventId: string\n /** The last `retry` received. */\n readonly retry: number | undefined\n /** Resolves when the server ends the stream. */\n readonly done: Promise<void>\n /** Disconnects (the server sees a client disconnect). Idempotent. */\n close(): Promise<void>\n /** Reconnects like `EventSource`: the same request plus `last-event-id`. */\n reconnect(): Promise<InjectSseResponse>\n}\n\n/**\n * What `TestApp.injectStream()` / `injectSse()` expect from the plugin named `'http'`\n * (`HttpPlugin` of `@znight/http` ≥ 0.1.0, the release that ships streaming).\n */\nexport interface HttpStreamInjector {\n injectStream(request: InjectStreamRequest & { readonly method: string }): Promise<InjectStreamResponse>\n injectSse(request: InjectStreamRequest & { readonly method: string }): Promise<InjectSseResponse>\n}\n\n/**\n * A plugin implementing the optional `initRoots(context)` member of `Plugin` (`@znight/core`), read\n * by `TestApp.create()`: the providers the plugin needs at boot although the metadata does not make\n * them entry points, i.e. classes or tokens given in its options (`HttpPlugin.configure({ guards,\n * interceptors, exceptionMappers })`) or derived from its metadata section (`context.metadata`).\n * `TestApp` adds them to the providers instantiated at boot (see {@link TestAppOptions.only}), so\n * that their async dependencies exist when the plugin resolves them: an async factory cannot run on\n * demand.\n *\n * Called once per `TestApp.create()`, before the application is created. Keys that are not\n * providers of the metadata are ignored (the plugin reports them itself).\n */\nexport type PluginInitRoots = Required<Pick<Plugin, 'initRoots'>>\n\n/** Options of {@link TestApp.create}. */\nexport interface TestAppOptions {\n /** The generated metadata (`__ZNIGHT_METADATA__`). */\n readonly metadata: ZnightMetadata\n readonly plugins?: readonly Plugin[]\n /** Values supplied by the application (externals, configuration...), as in `Application.create`. */\n readonly providers?: ProviderValues\n /**\n * Replacements applied last, with the highest precedence: values or provider definitions\n * (`{ scope, deps, factory }`), keyed by class or token. Overridden providers are instantiated.\n */\n readonly overrides?: ProviderValues\n /**\n * Which providers are instantiated at boot (with their dependency closure, plus the overrides and\n * the providers the plugins resolve at bootstrap, see {@link PluginInitRoots}: global guards,\n * interceptors and exception mappers of `HttpPlugin`):\n * - default: the entry points of the metadata, i.e. the HTTP controllers (with their guards and\n * interceptors), the message consumers and the hosts of scheduled jobs, or every provider when\n * there is none;\n * - `'all'`: every provider;\n * - a list of classes or tokens.\n *\n * Other providers are created on first use (synchronous factories only: list a provider here\n * when it, or one of its dependencies, has an async factory).\n */\n readonly only?: readonly ProviderKey[] | 'all'\n /** Application logger. Default: a console logger writing warnings and errors. */\n readonly logger?: CoreLogger\n /** Run `app.start()` (plugins `onStart`: listen, subscribe...). Default: `true`. */\n readonly start?: boolean\n /** Shutdown timeouts. Signal handlers are always disabled. */\n readonly shutdown?: Omit<ShutdownOptions, 'signals' | 'process'>\n}\n\n/**\n * End-to-end harness: a started {@link Application} without signal handlers, overrides applied last\n * and only what the tested entry points need instantiated.\n *\n * ```ts\n * await using app = await TestApp.create({\n * metadata: __ZNIGHT_METADATA__,\n * plugins: [HttpPlugin.configure({ adapter: fastify() })],\n * overrides: [[UserRepository, fakeRepository]],\n * })\n * const response = await app.inject({ method: 'GET', url: '/users/1' })\n * expect(response.status).toBe(200)\n * expect(response.json()).toEqual({ id: '1' })\n * ```\n */\nexport class TestApp implements AsyncDisposable {\n /** The application under test. */\n readonly app: Application\n #closed = false\n\n private constructor(app: Application) {\n this.app = app\n }\n\n /**\n * Creates and (by default) starts the application.\n *\n * Plugins are used as configured: give the servers they start a free port or none in tests\n * (`HttpPlugin.configure({ port: 0 })`, `ObservabilityPlugin.configure({ metrics: { server: false } })`);\n * a start failing on a port already in use (`EADDRINUSE`) gets a hint saying so.\n *\n * @throws the error of `Application.create()` / `app.start()` (everything is rolled back).\n */\n static async create(options: TestAppOptions): Promise<TestApp> {\n if (options === null || typeof options !== 'object') {\n throw new TypeError('[znight] TestApp.create({ metadata }) requires options with the generated metadata')\n }\n const index = new MetadataIndex(options.metadata)\n const providers = resolveKeys(options.providers, index)\n const overrides = resolveKeys(options.overrides, index)\n const init = initOptions(options, index, overrides)\n try {\n const app = await Application.create({\n metadata: options.metadata,\n plugins: options.plugins ?? [],\n ...(providers === undefined ? {} : { providers }),\n ...(overrides === undefined ? {} : { overrides }),\n logger: options.logger ?? createConsoleLogger({ level: 'warn' }),\n shutdown: { ...options.shutdown, signals: false },\n init,\n })\n if (options.start !== false) await app.start()\n return new TestApp(app)\n } catch (error) {\n addHints(error, init.only !== undefined)\n throw error\n }\n }\n\n /** The application container. */\n get container(): Container {\n return this.app.container\n }\n\n /** Shortcut for `app.container.get(key)`. */\n get<T>(key: ProviderClass<T>): T\n get<T>(key: ClassKey<T>): T\n get<T = unknown>(key: TypedToken<T>): T\n get(key: ProviderKey): unknown {\n return this.app.container.get(key as TypedToken<unknown>)\n }\n\n /**\n * Dispatches a request in memory through the HTTP plugin (`HttpPlugin`): routing, guards,\n * interceptors, validation, serialisation, without opening a socket. Send uploads as a\n * `FormData` body; read downloads from `response.bytes`. Send cookies with `cookies` (and\n * `signedCookies`), read those the response sets from `response.cookies`.\n *\n * @throws ZnightError ZNIGHT001 when the application has no HTTP plugin, ZNIGHT021 once closed.\n */\n inject(request: InjectRequest): Promise<InjectResponse> {\n try {\n if (this.#closed) {\n throw new ZnightError(ErrorCode.LifecycleFailed, 'TestApp.inject(): the application is closed')\n }\n if (request === null || typeof request !== 'object' || typeof request.url !== 'string') {\n throw new TypeError(\n '[znight] TestApp.inject() expects { method?, url, headers?, body?, query?, cookies?, signedCookies? }',\n )\n }\n const plugin = this.app.getPlugin<Plugin & Partial<HttpInjector>>(HTTP_PLUGIN_NAME)\n if (plugin === undefined || typeof plugin.inject !== 'function') {\n throw new ZnightError(ErrorCode.MissingProvider, 'TestApp.inject() requires the HTTP plugin', {\n hints: ['Add HttpPlugin.configure({ adapter }) from @znight/http to TestApp.create({ plugins })'],\n })\n }\n const method = (request.method ?? 'GET').toUpperCase()\n return Promise.resolve(plugin.inject({ ...request, method })).then(complete)\n } catch (error) {\n return Promise.reject(error)\n }\n }\n\n /**\n * Dispatches a request in memory and resolves at the response headers; the body is read as it is\n * produced (`response.body`). Cancelling the body (or aborting `signal`) disconnects the client.\n *\n * @throws ZnightError ZNIGHT001 when the HTTP plugin does not support streaming, ZNIGHT021 once closed.\n */\n injectStream(request: InjectStreamRequest): Promise<InjectStreamResponse> {\n return this.#stream('injectStream', request)\n }\n\n /**\n * Opens an event stream (Server-Sent Events) in memory and reads it like `EventSource`:\n *\n * ```ts\n * await using stream = await app.injectSse({ url: '/orders/o-1/events' })\n * const event = await stream.next() // rejects after 2 000 ms\n * expect(event.json()).toMatchObject({ status: 'paid' })\n * const resumed = await stream.reconnect() // last-event-id, like EventSource\n * ```\n *\n * Leaving the `await using` block (or `close()`) disconnects: the server sees `ctx.signal` abort.\n *\n * @throws ZnightError ZNIGHT001 when the HTTP plugin does not support event streams, ZNIGHT021 once closed.\n */\n injectSse(request: InjectStreamRequest): Promise<InjectSseResponse> {\n return this.#stream('injectSse', request)\n }\n\n #stream<K extends keyof HttpStreamInjector>(\n method: K,\n request: InjectStreamRequest,\n ): ReturnType<HttpStreamInjector[K]> {\n try {\n if (this.#closed) {\n throw new ZnightError(ErrorCode.LifecycleFailed, `TestApp.${method}(): the application is closed`)\n }\n if (request === null || typeof request !== 'object' || typeof request.url !== 'string') {\n throw new TypeError(\n `[znight] TestApp.${method}() expects { method?, url, headers?, body?, query?, cookies?, signedCookies?, signal? }`,\n )\n }\n const plugin = this.app.getPlugin<Plugin & Partial<HttpStreamInjector>>(HTTP_PLUGIN_NAME)\n const dispatch = plugin?.[method] as\n | ((this: unknown, request: InjectStreamRequest & { readonly method: string }) => unknown)\n | undefined\n if (typeof dispatch !== 'function') {\n throw new ZnightError(\n ErrorCode.MissingProvider,\n `TestApp.${method}() requires the HTTP plugin with streaming support`,\n {\n hints: [\n plugin === undefined\n ? 'Add HttpPlugin.configure({ adapter }) from @znight/http to TestApp.create({ plugins })'\n : `The plugin named 'http' does not implement ${method}(): register HttpPlugin.configure({ adapter }) from @znight/http ≥ 0.1.0 (the same release as @znight/testing)`,\n ],\n },\n )\n }\n const sent = { ...request, method: (request.method ?? 'GET').toUpperCase() }\n return Promise.resolve(dispatch.call(plugin, sent)) as ReturnType<HttpStreamInjector[K]>\n } catch (error) {\n return Promise.reject(error) as ReturnType<HttpStreamInjector[K]>\n }\n }\n\n /** Stops the application (idempotent): plugins `onStop`, providers `onStop` and disposal, plugins `onDispose`. */\n close(): Promise<void> {\n this.#closed = true\n return this.app.stop()\n }\n\n /** {@link close}, for `await using app = await TestApp.create(...)`. */\n [Symbol.asyncDispose](): Promise<void> {\n return this.close()\n }\n}\n\nconst ENCODER = new TextEncoder()\n\nconst NO_COOKIES: Readonly<Record<string, SetCookieInfo>> = Object.freeze({})\n\n/**\n * The plugin response, as is when it is complete; otherwise with `bytes` derived from `body` and\n * no `cookies` when the plugin did not provide them.\n */\nfunction complete(response: HttpInjectResult): InjectResponse {\n const hasBytes = response.bytes instanceof Uint8Array\n const hasCookies = response.cookies !== null && typeof response.cookies === 'object'\n if (hasBytes && hasCookies) return response as InjectResponse\n return {\n status: response.status,\n headers: response.headers,\n body: response.body,\n bytes: hasBytes ? (response.bytes as Uint8Array) : ENCODER.encode(response.body),\n cookies: hasCookies ? (response.cookies as Readonly<Record<string, SetCookieInfo>>) : NO_COOKIES,\n json: <T = unknown>(): T => response.json<T>(),\n }\n}\n\ntype Entries = readonly (readonly [ProviderKey, unknown])[]\n\n/**\n * Materialises `providers`/`overrides` and maps string keys that are not tokens of the metadata to\n * the token they designate (alias or unique display name: `'UserRepository'`), like `TestBed` does.\n * Unknown strings are kept (tokens registered at runtime by plugins); classes are resolved by the\n * container.\n */\nfunction resolveKeys(values: ProviderValues | undefined, index: MetadataIndex): Entries | undefined {\n if (values === undefined) return undefined\n const known = index.knownTokens()\n return entriesOf<ProviderKey, unknown>(values).map(([key, value]): readonly [ProviderKey, unknown] => {\n if (typeof key !== 'string' || known.has(key)) return [key, value]\n return [index.find(key, known) ?? key, value]\n })\n}\n\nfunction initOptions(\n options: TestAppOptions,\n index: MetadataIndex,\n overrides: Entries | undefined,\n): { readonly only?: readonly ProviderKey[] } {\n const only = options.only\n if (only === 'all') return {}\n let roots: readonly ProviderKey[]\n if (only === undefined) {\n const metadata = options.metadata\n roots = [\n ...readHttpRoots(metadata),\n ...readMessagingRoots(metadata),\n ...readScheduleRoots(metadata),\n ...readGraphQLRoots(metadata),\n ].filter(token => index.isProvider(token))\n // plugin roots complete the entry points; they never restrict the boot by themselves\n if (roots.length === 0) return {}\n } else {\n if (!Array.isArray(only)) throw new TypeError(\"[znight] TestApp.create(): only must be 'all' or an array of keys\")\n roots = only\n }\n const extra = (overrides ?? []).map(([key]) => key)\n const plugins = pluginRoots(options.plugins ?? [], { metadata: options.metadata }, index)\n return { only: unique([...roots, ...plugins, ...extra]) }\n}\n\n/**\n * Providers the plugins need at boot (`Plugin.initRoots()`, {@link PluginInitRoots}), as provider\n * tokens of the metadata. Other keys (classes without provider, unknown or ambiguous names) are\n * left to the plugin, which reports them with its own message.\n */\nfunction pluginRoots(plugins: readonly Plugin[], context: PluginRootsContext, index: MetadataIndex): Token[] {\n const providers = new Set(index.providerTokens())\n const roots: Token[] = []\n const frozen: PluginRootsContext = Object.freeze({ metadata: context.metadata })\n for (const plugin of plugins) {\n const initRoots = (plugin as Partial<PluginInitRoots> | null | undefined)?.initRoots\n if (typeof initRoots !== 'function') continue\n const keys: unknown = initRoots.call(plugin, frozen)\n if (!Array.isArray(keys)) {\n throw new TypeError(\n `[znight] TestApp.create(): initRoots() of the plugin \"${String(plugin.name)}\" must return an array of classes or tokens`,\n )\n }\n for (const key of keys) {\n const token = findProvider(key, providers, index)\n if (token !== undefined) roots.push(token)\n }\n }\n return roots\n}\n\nfunction findProvider(key: unknown, providers: ReadonlySet<Token>, index: MetadataIndex): Token | undefined {\n try {\n return index.find(key, providers)\n } catch {\n return undefined // ambiguous display name\n }\n}\n\nconst ONLY_HINT = \"With TestApp: list it in TestApp.create({ only: [...] }) (or pass only: 'all') to create it at boot\"\n\n/** Hint added to start failures caused by a port already in use (`EADDRINUSE`). */\nconst PORT_IN_USE_HINT =\n 'With TestApp, servers need no fixed port (inject() sends requests in memory): configure HttpPlugin with { port: 0 } and ObservabilityPlugin with { metrics: { server: false } } (or server: { port: 0 }) in tests'\n\ninterface ErrorLike {\n readonly code?: unknown\n readonly hints?: unknown\n readonly cause?: unknown\n}\n\n/**\n * Adds TestApp hints to a failed `TestApp.create()`, along the `cause` chain:\n * - the TestApp form of the container hint to \"cannot create on demand: its factory is async\"\n * errors (ZNIGHT015, hint `init({ only })`) of a restricted boot, which `TestApp` exposes as its\n * `only` option;\n * - when a server could not listen because its port is taken (`EADDRINUSE`: a fixed port, such as\n * the default `9464` of the observability metrics server, shared by test files running in\n * parallel or by `znight dev`), the options giving it a free port or none, on the outermost error\n * carrying hints (the `ZnightError` the application wraps plugin failures in).\n */\nfunction addHints(error: unknown, restricted: boolean): void {\n const chain: (object & ErrorLike)[] = []\n let current = error\n while (current !== null && typeof current === 'object' && !chain.includes(current)) {\n chain.push(current)\n current = (current as ErrorLike).cause\n }\n if (restricted) {\n for (const item of chain) {\n if (\n item.code === ErrorCode.InstantiationFailed &&\n Array.isArray(item.hints) &&\n item.hints.some(hint => typeof hint === 'string' && hint.includes('init({ only })'))\n ) {\n addHint(item, ONLY_HINT)\n }\n }\n }\n if (chain.some(item => item.code === 'EADDRINUSE')) {\n const outermost = chain.find(item => Array.isArray(item.hints))\n if (outermost !== undefined) addHint(outermost, PORT_IN_USE_HINT)\n }\n}\n\nfunction addHint(error: object & ErrorLike, hint: string): void {\n const hints = error.hints as readonly unknown[]\n // `hints` is a plain own property of ZnightError; a frozen error is left as is\n if (!hints.includes(hint)) Reflect.set(error, 'hints', [...hints, hint])\n}\n\nfunction unique<T>(values: readonly T[]): T[] {\n return [...new Set(values)]\n}\n","import type { ProviderClass, ProviderKey, Token } from '@znight/core'\nimport type { ConfigClassInfo } from './extensions.ts'\nimport type { MetadataIndex } from './metadata-index.ts'\n\nimport { displayName, ErrorCode, InstantiationError, ZnightError } from '@znight/core'\n\nimport { describeKey, entriesOf } from './utils.ts'\n\n/** Property values of one configuration class (`{ port: 8080 }`). */\nexport type ConfigProperties = Readonly<Record<string, unknown>>\n\n/**\n * Configuration values by configuration class, for `TestBed.create(..., { config })`: a record keyed\n * by token, display name or `@Config` prefix, or `[ConfigClass, values]` pairs.\n *\n * ```ts\n * config: { DatabaseConfig: { host: 'db.test' } }\n * config: { database: { host: 'db.test' } } // @Config('database')\n * config: [[DatabaseConfig, { host: 'db.test' }]]\n * ```\n */\nexport type ConfigValues =\n | Iterable<readonly [ProviderKey, ConfigProperties]>\n | Readonly<Record<string, ConfigProperties>>\n\n/**\n * Resolves {@link ConfigValues} to per-token values, validating class keys and property names.\n *\n * @throws ZnightError ZNIGHT012 for an unknown configuration class or property.\n */\nexport function normalizeConfigValues(\n values: ConfigValues | undefined,\n index: MetadataIndex,\n configs: ReadonlyMap<Token, ConfigClassInfo>,\n): Map<Token, Record<string, unknown>> {\n const result = new Map<Token, Record<string, unknown>>()\n if (values === undefined) return result\n const universe = new Set(configs.keys())\n for (const [key, properties] of entriesOf<ProviderKey, ConfigProperties>(values)) {\n const token = index.find(key, universe) ?? findByPrefix(key, configs)\n if (token === undefined) {\n const available = [...configs.values()].map(describeConfig)\n throw new ZnightError(ErrorCode.InvalidConfig, `config: ${describeKey(key)} is not a configuration class`, {\n hints: [\n available.length === 0\n ? 'The metadata declares no configuration class (extensions.config.configs)'\n : `Configuration classes: ${available.join(', ')}`,\n ],\n })\n }\n const info = configs.get(token) as ConfigClassInfo\n if (properties === null || typeof properties !== 'object') {\n throw new ZnightError(ErrorCode.InvalidConfig, `config: the values of ${displayName(token)} must be an object`)\n }\n const known = new Set(info.fields.map(field => field.property))\n for (const property of Object.keys(properties)) {\n if (!known.has(property)) {\n throw new ZnightError(\n ErrorCode.InvalidConfig,\n `config: ${displayName(token)} has no configuration property \"${property}\"`,\n { hints: [`Properties: ${[...known].join(', ') || '(none)'}`] },\n )\n }\n }\n result.set(token, { ...result.get(token), ...properties })\n }\n return result\n}\n\n/**\n * Builds a real configuration instance like `@znight/config` without any source would:\n * `new ConfigClass()` (field initializers run), then the declared `@Default` values (which win over\n * initializers, as at runtime, converted to the field type, see {@link convertDefault}), then\n * `values` (as given). Required fields without value stay `undefined`.\n */\nexport function buildConfigInstance(\n info: ConfigClassInfo,\n cls: ProviderClass | undefined,\n values: Readonly<Record<string, unknown>> | undefined,\n): object {\n let instance: Record<string, unknown>\n try {\n instance =\n cls === undefined ? {} : (new (cls as unknown as new () => Record<string, unknown>)() as Record<string, unknown>)\n } catch (error) {\n throw new InstantiationError(info.token, [info.token], error)\n }\n for (const field of info.fields) {\n if (values !== undefined && Object.hasOwn(values, field.property)) {\n instance[field.property] = values[field.property]\n } else if (field.hasDefault) {\n instance[field.property] = convertDefault(field.default, field.type)\n }\n }\n return instance\n}\n\nfunction findByPrefix(key: unknown, configs: ReadonlyMap<Token, ConfigClassInfo>): Token | undefined {\n if (typeof key !== 'string') return undefined\n const matches = [...configs.values()].filter(info => info.prefix === key)\n return matches.length === 1 ? matches[0]?.token : undefined\n}\n\nfunction describeConfig(info: ConfigClassInfo): string {\n const name = displayName(info.token)\n return info.prefix === undefined ? name : `${name} (prefix \"${info.prefix}\")`\n}\n\nconst INVALID: unique symbol = Symbol('invalid')\n/** Strict decimal numbers, as accepted by `@znight/config` (`42`, `-1.5`, `1e3`; not `0x10`). */\nconst DECIMAL = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/\nconst TRUE = new Set(['true', '1', 'yes', 'on'])\nconst FALSE = new Set(['false', '0', 'no', 'off'])\n\n/**\n * A declared default converted to the field type the way `@znight/config` converts it at runtime\n * (`loadConfig`), so the instance has the same shape in tests as in the application: `'8080'` → `8080`\n * (`number`), `'yes'` → `true`, `'a, b'` → `['a', 'b']` (lists), an absolute URL string → a `URL`\n * (`url`), a JSON string → its value (`json`). `@znight/testing` does not depend on `@znight/config`,\n * hence this small mirror of its coercion rules. A value that does not convert (the compiler already\n * rejects invalid defaults) or an unknown type is kept as is (copied).\n */\nexport function convertDefault(value: unknown, type: string | undefined): unknown {\n const converted = convert(value, type)\n return converted === INVALID ? copy(value) : converted\n}\n\nfunction convert(value: unknown, type: string | undefined): unknown {\n switch (type) {\n case 'string':\n return toText(value)\n case 'number':\n return toNumber(value)\n case 'boolean':\n return toBoolean(value)\n case 'string[]':\n return toList(value, toText)\n case 'number[]':\n return toList(value, toNumber)\n case 'url':\n return toUrl(value)\n case 'json':\n return toJson(value)\n default:\n return INVALID\n }\n}\n\nfunction toText(value: unknown): unknown {\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value)\n return INVALID\n}\n\nfunction toNumber(value: unknown): unknown {\n if (typeof value === 'number') return Number.isFinite(value) ? value : INVALID\n if (typeof value !== 'string' || !DECIMAL.test(value.trim())) return INVALID\n const number = Number(value.trim())\n return Number.isFinite(number) ? number : INVALID\n}\n\nfunction toBoolean(value: unknown): unknown {\n if (typeof value === 'boolean') return value\n if (value === 1 || value === 0) return value === 1\n if (typeof value !== 'string') return INVALID\n const text = value.trim().toLowerCase()\n if (TRUE.has(text)) return true\n return FALSE.has(text) ? false : INVALID\n}\n\nfunction toList(value: unknown, item: (value: unknown) => unknown): unknown {\n let items: readonly unknown[]\n if (Array.isArray(value)) {\n items = value\n } else if (typeof value === 'string') {\n items = value\n .split(',')\n .map(part => part.trim())\n .filter(part => part !== '')\n } else {\n return INVALID\n }\n const result: unknown[] = []\n for (const entry of items) {\n const converted = item(entry)\n if (converted === INVALID) return INVALID\n result.push(converted)\n }\n return result\n}\n\nfunction toUrl(value: unknown): unknown {\n if (value instanceof URL) return new URL(value.href)\n return typeof value === 'string' && URL.canParse(value.trim()) ? new URL(value.trim()) : INVALID\n}\n\nfunction toJson(value: unknown): unknown {\n if (typeof value !== 'string') return copy(value)\n try {\n return JSON.parse(value) as unknown\n } catch {\n return INVALID\n }\n}\n\n/** Defaults are static values: copy them so that tests never share mutable defaults. */\nfunction copy(value: unknown): unknown {\n if (value === null || typeof value !== 'object') return value\n try {\n return structuredClone(value)\n } catch {\n return value\n }\n}\n","import type { ClassKey, Token, TypedToken } from '@znight/core'\nimport type { MetadataIndex } from './metadata-index.ts'\nimport type { DeepMock, Mocked } from './types.ts'\n\nimport { describeToken, displayName, ErrorCode, ZnightError } from '@znight/core'\n\nimport { clearMock, resetMock } from './mock.ts'\nimport { describeKey } from './utils.ts'\n\n/**\n * The auto-mocks of a `TestBed`, looked up by class, token, alias or display name.\n *\n * ```ts\n * const { instance, mocks } = await TestBed.create(UserService, { metadata })\n * mocks.get(UserRepository).findById.mockResolvedValue(user) // typed\n * mocks.get('Logger').info // untyped deep mock\n * ```\n */\nexport interface MockRegistry {\n /**\n * The auto-mock injected for `key`: a class (typed result), a token, an alias (interface, base\n * class) or a unique display name (`'UserRepository'`).\n *\n * @throws ZnightError ZNIGHT001 when no auto-mock matches (the message says why: provided value,\n * configuration class, optional dependency...), ZNIGHT008 when a display name is ambiguous.\n */\n get<T>(key: ClassKey<T>): Mocked<T>\n get<T = never>(key: TypedToken<T>): [T] extends [never] ? DeepMock : Mocked<T>\n /** Whether an auto-mock matches `key`. */\n has(key: ClassKey | Token): boolean\n /** Tokens of the auto-mocked dependencies, in injection order. */\n tokens(): Token[]\n /** `mockClear()` on every spy of every auto-mock (recorded calls are forgotten). */\n clearAll(): void\n /** Resets every auto-mock to its initial state (calls and programmed behaviours are forgotten). */\n resetAll(): void\n}\n\n/** Why a dependency was not auto-mocked (used in error messages). */\nexport type InjectionKind = 'provided' | 'override' | 'config' | 'optional' | 'interceptor' | 'real'\n\nconst REASONS: Readonly<Record<InjectionKind, string>> = {\n provided: 'its value was passed with `provide`',\n override: 'it was replaced with `overrides`',\n config: 'it is a configuration class (a real instance is injected; set values with `config`)',\n optional: 'it is an optional dependency (`undefined` is injected unless provided)',\n interceptor: 'it is an interceptor (not applied unless `aop: \"real\"`)',\n real: 'it was built for real (aop: \"real\")',\n}\n\n/** Default {@link MockRegistry} implementation (internal). */\nexport class TestMocks implements MockRegistry {\n readonly #mocks: ReadonlyMap<Token, object>\n readonly #others: ReadonlyMap<Token, InjectionKind>\n readonly #index: MetadataIndex\n readonly #owner: Token\n\n constructor(\n mocks: ReadonlyMap<Token, object>,\n others: ReadonlyMap<Token, InjectionKind>,\n index: MetadataIndex,\n owner: Token,\n ) {\n this.#mocks = mocks\n this.#others = others\n this.#index = index\n this.#owner = owner\n }\n\n get<T>(key: ClassKey<T>): Mocked<T>\n get<T = never>(key: TypedToken<T>): [T] extends [never] ? DeepMock : Mocked<T>\n get(key: unknown): unknown {\n const token = this.#index.find(key, new Set(this.#mocks.keys()))\n if (token !== undefined) return this.#mocks.get(token)\n throw this.#notMockedError(key)\n }\n\n has(key: ClassKey | Token): boolean {\n return this.#index.find(key, new Set(this.#mocks.keys())) !== undefined\n }\n\n tokens(): Token[] {\n return [...this.#mocks.keys()]\n }\n\n clearAll(): void {\n for (const mock of this.#mocks.values()) clearMock(mock)\n }\n\n resetAll(): void {\n for (const mock of this.#mocks.values()) resetMock(mock)\n }\n\n #notMockedError(key: unknown): ZnightError {\n const owner = displayName(this.#owner)\n let other: Token | undefined\n try {\n other = this.#index.find(key, new Set(this.#others.keys()))\n } catch {\n other = undefined\n }\n if (other !== undefined) {\n const kind = this.#others.get(other) as InjectionKind\n return new ZnightError(ErrorCode.MissingProvider, `${describeToken(other)} is not mocked: ${REASONS[kind]}`)\n }\n const mocked = [...this.#mocks.keys()].map(displayName)\n return new ZnightError(\n ErrorCode.MissingProvider,\n `No mock for ${describeKey(key)}: it is not a direct dependency of ${owner}`,\n {\n hints: [\n mocked.length === 0 ? `${owner} has no auto-mocked dependency` : `Auto-mocked: ${mocked.join(', ')}`,\n 'TestBed only mocks direct dependencies; regenerate the metadata if the constructor changed',\n ],\n },\n )\n }\n}\n","import type { DependencyRef, ProviderDefinition, ProviderValues, Token, ZnightMetadata } from '@znight/core'\nimport type { ConfigClassInfo } from './extensions.ts'\nimport type { AopMode, TestBedOptions, TestBedResult } from './testbed.ts'\nimport type { MockFnFactory } from './types.ts'\n\nimport {\n applyInterceptors,\n Container,\n describeToken,\n displayName,\n ErrorCode,\n formatPath,\n InstantiationError,\n isProviderDefinition,\n METADATA_VERSION,\n ZnightError,\n} from '@znight/core'\n\nimport { buildConfigInstance, normalizeConfigValues } from './config.ts'\nimport { readConfigClasses } from './extensions.ts'\nimport { MetadataIndex } from './metadata-index.ts'\nimport { mockObject } from './mock.ts'\nimport { resolveMockFn } from './mock-fn.ts'\nimport { type InjectionKind, TestMocks } from './mock-registry.ts'\nimport { describeKey, entriesOf, isThenable } from './utils.ts'\n\nconst AOP_MODES: ReadonlySet<AopMode | undefined> = new Set([undefined, 'none', 'real'])\n\n/**\n * Builds the target of `TestBed.create()`: resolves keys, injects auto-mocks / provided values /\n * configuration instances, runs the factory and assembles the result container. Internal.\n */\nexport class Builder {\n readonly #index: MetadataIndex\n readonly #options: TestBedOptions\n readonly #mockFn: MockFnFactory\n readonly #configs: ReadonlyMap<Token, ConfigClassInfo>\n readonly #configValues: ReadonlyMap<Token, Record<string, unknown>>\n readonly #provided: ReadonlyMap<Token, unknown>\n readonly #overrides: ReadonlyMap<Token, unknown>\n /** Values injected into the target (and into built dependencies), by canonical token. */\n readonly #values = new Map<Token, unknown>()\n /** Real interceptors (aop: 'real'), by canonical token. */\n readonly #interceptors = new Map<Token, unknown>()\n readonly #kinds = new Map<Token, InjectionKind>()\n readonly #mocks = new Map<Token, object>()\n /** Providers being built (cycle guard). */\n readonly #building = new Set<Token>()\n #known: Set<Token> | undefined\n\n constructor(options: TestBedOptions) {\n if (options === null || typeof options !== 'object') {\n throw new TypeError('[znight] TestBed.create(target, { metadata }) requires options with the generated metadata')\n }\n if (!AOP_MODES.has(options.aop)) {\n throw new TypeError(`[znight] TestBed.create(): aop must be 'none' or 'real', got ${String(options.aop)}`)\n }\n this.#options = options\n this.#index = new MetadataIndex(options.metadata)\n this.#mockFn = resolveMockFn(options.mockFn).create\n this.#configs = readConfigClasses(options.metadata)\n this.#configValues = normalizeConfigValues(options.config, this.#index, this.#configs)\n this.#provided = this.#normalize(options.provide, 'provide')\n this.#overrides = this.#normalize(options.overrides, 'overrides')\n }\n\n async build(target: unknown): Promise<TestBedResult<unknown>> {\n const token = this.#resolveTarget(target)\n let definition = this.#index.definition(token) as ProviderDefinition\n if (this.#overrides.has(token)) {\n const replacement = this.#overrides.get(token)\n if (!isProviderDefinition(replacement)) {\n throw new ZnightError(\n ErrorCode.InvalidDecorator,\n `overrides: the target ${displayName(token)} can only be replaced by a provider definition { scope, deps, factory }`,\n )\n }\n definition = replacement\n }\n const instance = await this.#construct(token, definition, [token])\n const container = await this.#createContainer(token, definition, instance)\n const others = new Map(this.#kinds)\n return {\n instance,\n mocks: new TestMocks(this.#mocks, others, this.#index, token),\n container,\n }\n }\n\n // -----------------------------------------------------------------------------------------------\n // Keys\n // -----------------------------------------------------------------------------------------------\n\n #resolveTarget(target: unknown): Token {\n const token = this.#index.find(target, new Set(this.#index.providerTokens()))\n if (token !== undefined) return token\n throw new ZnightError(\n ErrorCode.MissingProvider,\n `TestBed: ${describeKey(target)} is not a provider of the metadata`,\n {\n hints: [\n 'Check that the class is decorated (@Injectable(), @Controller()...) and exported',\n 'Regenerate the metadata before running tests: `znight generate`, the Bun preload `@znight/compiler/bun` or the Vite plugin',\n ],\n },\n )\n }\n\n /** Every token a `provide`/`overrides` key may designate (canonical). */\n #knownTokens(): Set<Token> {\n if (this.#known !== undefined) return this.#known\n const index = this.#index\n const known = new Set<Token>()\n const add = (token: unknown): void => {\n if (typeof token === 'string') known.add(index.canonical(token))\n }\n for (const token of index.providerTokens()) {\n known.add(token)\n for (const ref of (index.definition(token) as ProviderDefinition).deps) {\n for (const dep of tokensOfRef(ref)) add(dep)\n }\n }\n for (const external of index.metadata.externals ?? []) add(external?.token)\n for (const [alias] of index.aliases()) add(alias)\n this.#known = known\n return known\n }\n\n #normalize(values: ProviderValues | undefined, option: 'provide' | 'overrides'): Map<Token, unknown> {\n const result = new Map<Token, unknown>()\n if (values === undefined) return result\n const known = this.#knownTokens()\n for (const [key, value] of entriesOf<unknown, unknown>(values)) {\n const token = this.#index.find(key, known)\n if (token === undefined) {\n throw new ZnightError(\n ErrorCode.MissingProvider,\n `${option}: ${describeKey(key)} matches no provider, external or dependency of the metadata`,\n { hints: ['Use a class, a token, an alias or a unique display name (e.g. \"UserRepository\")'] },\n )\n }\n if (result.has(token)) {\n throw new ZnightError(ErrorCode.DuplicateProvider, `${option}: several values for ${describeToken(token)}`)\n }\n result.set(token, value)\n }\n return result\n }\n\n #isExplicit(token: Token): boolean {\n const canonical = this.#index.canonical(token)\n return this.#overrides.has(canonical) || this.#provided.has(canonical)\n }\n\n // -----------------------------------------------------------------------------------------------\n // Construction\n // -----------------------------------------------------------------------------------------------\n\n async #construct(token: Token, definition: ProviderDefinition, path: readonly Token[]): Promise<unknown> {\n if (this.#building.has(token)) {\n throw new ZnightError(ErrorCode.CircularDependency, `Circular dependency: ${formatPath([...path])}`)\n }\n this.#building.add(token)\n try {\n const interceptorDeps = interceptorIndices(definition)\n const deps: unknown[] = new Array(definition.deps.length)\n for (let index = 0; index < definition.deps.length; index++) {\n const ref = definition.deps[index] as DependencyRef\n if (!interceptorDeps.has(index)) deps[index] = await this.#resolve(ref, path)\n else if (this.#options.aop === 'real') deps[index] = await this.#interceptor(ref, path)\n else for (const dep of tokensOfRef(ref)) this.#record(this.#index.canonical(dep), 'interceptor')\n }\n let instance: unknown\n try {\n instance = definition.factory(deps)\n if (isThenable(instance)) instance = await instance\n } catch (error) {\n throw new InstantiationError(token, path, error, definition.source)\n }\n if (this.#options.aop === 'real' && definition.interceptors !== undefined) {\n try {\n applyInterceptors(instance as object, definition.interceptors, deps, displayName(token))\n } catch (error) {\n throw new InstantiationError(token, path, error, definition.source)\n }\n }\n return instance\n } finally {\n this.#building.delete(token)\n }\n }\n\n async #resolve(ref: DependencyRef, path: readonly Token[]): Promise<unknown> {\n if (typeof ref === 'string') return this.#value(ref, path)\n if (ref !== null && typeof ref === 'object') {\n if ('multi' in ref && Array.isArray(ref.multi)) {\n const values: unknown[] = []\n for (const token of ref.multi as readonly Token[]) {\n if (this.#isExplicit(token)) values.push(await this.#value(token, path))\n }\n return values\n }\n if ('lazy' in ref && typeof ref.lazy === 'string') {\n const value = await this.#value(ref.lazy, path)\n return { get: (): unknown => value }\n }\n if ('token' in ref && typeof ref.token === 'string') {\n if (this.#isExplicit(ref.token)) return this.#value(ref.token, path)\n this.#record(this.#index.canonical(ref.token), 'optional')\n return undefined\n }\n }\n throw new ZnightError(\n ErrorCode.InvalidDecorator,\n `Invalid dependency of ${displayName(path[path.length - 1] as Token)}: ${safeJson(ref)}`,\n { hints: ['Expected a token, { token, optional: true }, { multi: [...] } or { lazy: token }'] },\n )\n }\n\n /** The value injected for `token` (cached: the same dependency always gets the same value). */\n async #value(token: Token, path: readonly Token[]): Promise<unknown> {\n const canonical = this.#index.canonical(token)\n if (this.#values.has(canonical)) return this.#values.get(canonical)\n let value: unknown\n if (this.#overrides.has(canonical)) {\n value = await this.#explicit(canonical, this.#overrides.get(canonical), path)\n this.#record(canonical, 'override')\n } else if (this.#provided.has(canonical)) {\n value = this.#provided.get(canonical)\n this.#record(canonical, 'provided')\n } else if (this.#configs.has(canonical)) {\n const info = this.#configs.get(canonical) as ConfigClassInfo\n value = buildConfigInstance(info, this.#index.classOf(canonical), this.#configValues.get(canonical))\n this.#record(canonical, 'config')\n } else {\n value = this.#autoMock(canonical, path)\n }\n this.#values.set(canonical, value)\n return value\n }\n\n /** An override (a value, or a definition built with its dependencies resolved like the target's). */\n #explicit(token: Token, value: unknown, path: readonly Token[]): Promise<unknown> | unknown {\n return isProviderDefinition(value) ? this.#construct(token, value, [...path, token]) : value\n }\n\n #autoMock(token: Token, path: readonly Token[]): object {\n const definition = this.#index.definition(token)\n if (definition !== undefined && definition.class === undefined && definition.name !== undefined) {\n throw qualifiedValueError(token, definition.name, path)\n }\n const mock = mockObject(definition?.class, undefined, {\n name: displayName(token),\n deep: this.#options.deep === true,\n mockFn: this.#mockFn,\n })\n this.#mocks.set(token, mock)\n this.#kinds.delete(token)\n return mock\n }\n\n /** A real interceptor (aop: 'real'): explicit value, or built from its compiled definition. */\n async #interceptor(ref: DependencyRef, path: readonly Token[]): Promise<unknown> {\n if (typeof ref !== 'string') return this.#resolve(ref, path)\n const token = this.#index.canonical(ref)\n if (this.#interceptors.has(token)) return this.#interceptors.get(token)\n let value: unknown\n if (this.#overrides.has(token)) {\n value = await this.#explicit(token, this.#overrides.get(token), path)\n this.#record(token, 'override')\n } else if (this.#provided.has(token)) {\n value = this.#provided.get(token)\n this.#record(token, 'provided')\n } else {\n const definition = this.#index.definition(token)\n if (definition === undefined) {\n const providedBy = this.#index.external(token)?.providedBy\n throw new ZnightError(\n ErrorCode.MissingProvider,\n `aop: 'real' needs the interceptor ${describeToken(token)}, supplied at runtime by ${providedBy ?? 'a plugin'}`,\n { hints: [`Pass an instance: provide: [[${JSON.stringify(token)}, interceptor]]`] },\n )\n }\n value = await this.#construct(token, definition, [...path, token])\n this.#record(token, 'real')\n }\n this.#interceptors.set(token, value)\n return value\n }\n\n #record(token: Token, kind: InjectionKind): void {\n if (!this.#mocks.has(token)) this.#kinds.set(token, kind)\n }\n\n // -----------------------------------------------------------------------------------------------\n // Result container\n // -----------------------------------------------------------------------------------------------\n\n async #createContainer(target: Token, definition: ProviderDefinition, instance: unknown): Promise<Container> {\n const bound = new Map<Token, unknown>([[target, instance]])\n for (const [token, value] of this.#values) if (value !== undefined && !bound.has(token)) bound.set(token, value)\n for (const [token, value] of this.#interceptors) {\n if (value !== undefined && !bound.has(token)) bound.set(token, value)\n }\n const providers = [...bound.keys()].map((token): [Token, ProviderDefinition] => {\n const cls = token === target ? (definition.class ?? this.#index.classOf(token)) : this.#index.classOf(token)\n // placeholder definitions: they register the classes for lookups, the values are bound below\n return [\n token,\n { scope: 'singleton', deps: [], factory: () => undefined, ...(cls === undefined ? {} : { class: cls }) },\n ]\n })\n const aliases: [Token, Token][] = []\n for (const [alias] of this.#index.aliases()) {\n const canonical = this.#index.canonical(alias)\n if (bound.has(canonical) && !bound.has(alias)) aliases.push([alias, canonical])\n }\n const metadata: ZnightMetadata = {\n version: METADATA_VERSION,\n providers: Object.fromEntries(providers),\n resolutionOrder: [...bound.keys()],\n aliases: Object.fromEntries(aliases),\n }\n const container = Container.create(metadata)\n for (const [token, value] of bound) container.provide(token, value)\n await container.init()\n return container\n }\n}\n\n/** Indices of `definition.deps` used only by interceptor chains. */\nfunction interceptorIndices(definition: ProviderDefinition): Set<number> {\n const indices = new Set<number>()\n for (const interception of Object.values(definition.interceptors ?? {})) {\n for (const binding of interception.chain) indices.add(binding.dep)\n }\n return indices\n}\n\nfunction tokensOfRef(ref: DependencyRef): readonly Token[] {\n if (typeof ref === 'string') return [ref]\n if (ref === null || typeof ref !== 'object') return []\n if ('multi' in ref && Array.isArray(ref.multi)) return ref.multi\n if ('lazy' in ref && typeof ref.lazy === 'string') return [ref.lazy]\n if ('token' in ref && typeof ref.token === 'string') return [ref.token]\n return []\n}\n\nfunction qualifiedValueError(token: Token, name: string, path: readonly Token[]): ZnightError {\n const owner = displayName(path[path.length - 1] as Token)\n const key = displayName(token)\n return new ZnightError(\n ErrorCode.MissingProvider,\n `TestBed cannot auto-mock ${describeToken(token)}, the value named \"${name}\" injected into ${owner}: ` +\n 'qualified values may be primitives, provide one',\n { hints: [`TestBed.create(${owner}, { metadata, provide: { ${JSON.stringify(key)}: value } })`] },\n )\n}\n\nfunction safeJson(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n","import type { ClassKey, Container, ProviderClass, ProviderValues, TypedToken, ZnightMetadata } from '@znight/core'\nimport type { ConfigValues } from './config.ts'\nimport type { MockRegistry } from './mock-registry.ts'\nimport type { MockFnOption } from './types.ts'\n\nimport { Builder } from './testbed-builder.ts'\n\n/**\n * How `@Intercept` interceptors of the target are handled:\n * - `'none'` (default): interceptors are neither instantiated nor applied, the target's methods are\n * the plain ones;\n * - `'real'`: interceptors are built (their own dependencies auto-mocked) or taken from\n * `provide`/`overrides`, and applied like the container does.\n */\nexport type AopMode = 'none' | 'real'\n\n/** Options of {@link TestBed.create}. */\nexport interface TestBedOptions {\n /** The generated metadata (`__ZNIGHT_METADATA__`). */\n readonly metadata: ZnightMetadata\n /**\n * Values injected instead of auto-mocks, keyed by class, token, alias or display name. Required\n * for qualified values (`@Inject('dbUrl')`, `@Provides({ name })` without a class) such as\n * primitives; also used for optional dependencies and members of multi dependencies.\n */\n readonly provide?: ProviderValues\n /**\n * Like `provide`, but a value shaped like a provider definition (`{ scope, deps, factory }`) is\n * built with its factory, its own dependencies being resolved like the target's (auto-mocked...).\n * A definition keyed by the target replaces the target's factory. Wins over `provide`.\n */\n readonly overrides?: ProviderValues\n /** Values of configuration classes (real instances are injected for `@Config` classes). */\n readonly config?: ConfigValues\n /** Spy implementation of the auto-mocks. Default: auto-detected. */\n readonly mockFn?: MockFnOption\n /** Auto-mocks return deep mocks from unconfigured methods instead of `undefined`. Default: `false`. */\n readonly deep?: boolean\n /** Interceptors handling, see {@link AopMode}. Default: `'none'`. */\n readonly aop?: AopMode\n}\n\n/** What {@link TestBed.create} returns. */\nexport interface TestBedResult<T> {\n /** The target, built with its real (generated) factory. */\n readonly instance: T\n /** The auto-mocks injected into the target. */\n readonly mocks: MockRegistry\n /**\n * A container holding the target and everything injected into it (auto-mocks, provided values,\n * configuration instances), for code that resolves dependencies itself.\n */\n readonly container: Container\n}\n\n/**\n * Unit-test harness: builds one provider with its real factory and auto-mocks its **direct**\n * dependencies, by kind:\n *\n * | Dependency | Injected |\n * | -------------------------------------------- | --------------------------------------------------- |\n * | class / interface / `@Provides` / external | deep auto-mock |\n * | configuration class (`@Config`) | real instance: defaults + `config` values |\n * | qualified value (`@Inject('x')`, primitives) | the `provide` value (an error otherwise) |\n * | optional (`@Optional()`, `T \\| undefined`) | `undefined` (or the `provide` value) |\n * | multi (`T[]`) | `[]` (or the provided members) |\n * | `Lazy<T>` | `{ get: () => mock }` |\n * | interceptor (`@Intercept`) | nothing, not applied (unless `aop: 'real'`) |\n *\n * ```ts\n * const { instance, mocks } = await TestBed.create(UserService, { metadata: __ZNIGHT_METADATA__ })\n * mocks.get(UserRepository).findById.mockResolvedValue({ id: '1' })\n * await instance.findById('1')\n * expect(mocks.get(UserRepository).findById).toHaveBeenCalledWith('1')\n * ```\n */\nexport class TestBed {\n private constructor() {\n // static API only\n }\n\n /**\n * Builds `target` (a class, token, alias or display name of a provider of `options.metadata`).\n *\n * @throws ZnightError ZNIGHT001 (unknown target, qualified dependency without value), ZNIGHT012\n * (invalid `config`), ZNIGHT015 (the factory failed).\n */\n static create<T>(target: ProviderClass<T> | ClassKey<T>, options: TestBedOptions): Promise<TestBedResult<T>>\n static create<T = unknown>(target: TypedToken<T>, options: TestBedOptions): Promise<TestBedResult<T>>\n static create(target: unknown, options: TestBedOptions): Promise<TestBedResult<unknown>> {\n try {\n return new Builder(options).build(target)\n } catch (error) {\n return Promise.reject(error)\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["isObjectLike"],"sources":["../src/utils.ts","../src/define-metadata.ts","../src/spy.ts","../src/mock-fn.ts","../src/mock.ts","../src/overrides.ts","../src/extensions.ts","../src/metadata-index.ts","../src/test-app.ts","../src/config.ts","../src/mock-registry.ts","../src/testbed-builder.ts","../src/testbed.ts"],"sourcesContent":["/** Internal helpers. */\n\n/**\n * Materialises a `Map`, an iterable of `[key, value]` pairs or a record into an array of pairs (an\n * iterable such as a generator can only be read once).\n */\nexport function entriesOf<K, V>(\n values: Iterable<readonly [K, V]> | Readonly<Record<string, V>>,\n): (readonly [K | string, V])[] {\n if (typeof (values as Partial<Iterable<unknown>>)[Symbol.iterator] === 'function') {\n const entries: (readonly [K, V])[] = []\n for (const entry of values as Iterable<readonly [K, V]>) {\n if (!Array.isArray(entry) || entry.length !== 2) {\n throw new TypeError('[znight] Expected [key, value] pairs (a Map, an array of pairs or a record)')\n }\n entries.push(entry)\n }\n return entries\n }\n return Object.entries(values as Readonly<Record<string, V>>)\n}\n\n/** Whether `value` is a promise-like object (has a callable `then`). */\nexport function isThenable(value: unknown): value is PromiseLike<unknown> {\n return (\n value !== null &&\n (typeof value === 'object' || typeof value === 'function') &&\n typeof (value as { then?: unknown }).then === 'function'\n )\n}\n\n/** Describes a provider key (class, token...) for messages. */\nexport function describeKey(key: unknown): string {\n if (typeof key === 'function') return `class ${(key as { name?: string }).name || '<anonymous>'}`\n if (typeof key === 'string') return `\"${key}\"`\n return String(key)\n}\n","import type {\n ClassKey,\n DependencyRef,\n ExternalDefinition,\n MethodInterception,\n ProviderClass,\n ProviderDefinition,\n ProviderFactory,\n Scope,\n SourceLocation,\n Token,\n ZnightExtensionsMetadata,\n ZnightMetadata,\n} from '@znight/core'\n\nimport { describeToken, ErrorCode, isProviderDefinition, METADATA_VERSION, ZnightError } from '@znight/core'\n\nimport { entriesOf } from './utils.ts'\n\n/** Options of {@link createMetadata}. */\nexport interface CreateMetadataOptions {\n readonly aliases?: Readonly<Record<Token, Token>>\n /** Externals, as tokens or full definitions (`{ token, scope, providedBy }`). */\n readonly externals?: readonly (Token | ExternalDefinition)[]\n readonly extensions?: ZnightExtensionsMetadata\n /** Default: a deterministic topological order (dependencies first, declaration order otherwise). */\n readonly resolutionOrder?: readonly Token[]\n}\n\n/**\n * Hand-written metadata with the exact shape the compiler generates (version, resolution order...),\n * for tests that do not run the compiler (plugins, libraries, edge cases).\n *\n * ```ts\n * const metadata = createMetadata({\n * 'src/clock.ts#Clock': { scope: 'singleton', class: Clock, deps: [], factory: () => new Clock() },\n * })\n * ```\n *\n * @throws ZnightError ZNIGHT005 for a malformed provider definition.\n */\nexport function createMetadata(\n providers: Readonly<Record<Token, ProviderDefinition>>,\n options: CreateMetadataOptions = {},\n): ZnightMetadata {\n if (providers === null || typeof providers !== 'object') {\n throw new TypeError('[znight] createMetadata() expects a record of provider definitions')\n }\n for (const [token, definition] of Object.entries(providers)) {\n if (!isProviderDefinition(definition)) {\n throw new ZnightError(\n ErrorCode.InvalidDecorator,\n `Invalid provider definition for ${describeToken(token)}: expected { scope, deps, factory }`,\n )\n }\n }\n const externals = options.externals?.map(external =>\n typeof external === 'string' ? ({ token: external } satisfies ExternalDefinition) : external,\n )\n return {\n version: METADATA_VERSION,\n providers,\n resolutionOrder: options.resolutionOrder ?? topologicalOrder(providers),\n ...(options.aliases === undefined ? {} : { aliases: options.aliases }),\n ...(externals === undefined ? {} : { externals }),\n ...(options.extensions === undefined ? {} : { extensions: options.extensions }),\n }\n}\n\n/** A provider class or a token, in {@link defineTestMetadata}. */\nexport type TestKey = Token | ProviderClass | ClassKey\n\n/** A dependency in {@link defineTestMetadata}: like `DependencyRef`, with classes allowed in place of tokens. */\nexport type TestDependency =\n | TestKey\n | { readonly token: TestKey; readonly optional: true }\n | { readonly multi: readonly TestKey[] }\n | { readonly lazy: TestKey }\n\n/** A provider in {@link defineTestMetadata}. */\nexport interface TestProvider<T = unknown> {\n /** Default: `test#<ClassName>` (see `tokenPrefix`). Required without `class`. */\n readonly token?: Token\n readonly class?: ProviderClass<T>\n /** Default: `'singleton'`. */\n readonly scope?: Scope\n /** Constructor (or factory) dependencies, in parameter order. */\n readonly deps?: readonly TestDependency[]\n /** Default: `deps => new Class(...deps)`. Required without `class`. */\n readonly factory?: ProviderFactory<T>\n readonly async?: boolean\n readonly interceptors?: Readonly<Record<string, MethodInterception>>\n readonly dispose?: string\n /** `@Named` qualifier. */\n readonly name?: string\n readonly primary?: boolean\n readonly source?: SourceLocation\n}\n\n/** Input of {@link defineTestMetadata}. */\nexport interface TestMetadataSpec {\n /** Providers: classes (no dependency) or {@link TestProvider}s. */\n readonly providers?: readonly (TestProvider | ProviderClass)[]\n /** Alias → provider pairs (`[UserRepository, PgUserRepository]`), or a record of tokens. */\n readonly aliases?: Iterable<readonly [TestKey, TestKey]> | Readonly<Record<Token, TestKey>>\n readonly externals?: readonly (Token | ExternalDefinition)[]\n /** Feature metadata (`http`, `messaging`, `config`), tokens written with {@link testToken}. */\n readonly extensions?: ZnightExtensionsMetadata\n readonly resolutionOrder?: readonly Token[]\n /** Prefix of the tokens derived from class names. Default: `'test'` (`test#UserService`). */\n readonly tokenPrefix?: string\n}\n\nconst DEFAULT_PREFIX = 'test'\n\n/** The token {@link defineTestMetadata} derives from a class: `<prefix>#<ClassName>`. */\nexport function testToken(cls: ProviderClass | ClassKey, prefix: string = DEFAULT_PREFIX): Token {\n const name = typeof cls === 'function' ? (cls as { name?: unknown }).name : undefined\n if (typeof name !== 'string' || name === '') {\n throw new TypeError('[znight] testToken(): expected a named class')\n }\n return `${prefix}#${name}`\n}\n\n/**\n * Class-first hand-written metadata: tokens are derived from class names (`test#UserService`),\n * dependencies may be classes, factories default to `new Class(...deps)` and the resolution order\n * is computed.\n *\n * ```ts\n * const metadata = defineTestMetadata({\n * providers: [\n * PgUserRepository,\n * { class: UserService, deps: [PgUserRepository, '@znight/observability#Logger'] },\n * ],\n * aliases: [[UserRepository, PgUserRepository]],\n * externals: ['@znight/observability#Logger'],\n * })\n * ```\n *\n * @throws ZnightError ZNIGHT004 for duplicate tokens; TypeError for a provider without class nor\n * token/factory.\n */\nexport function defineTestMetadata(spec: TestMetadataSpec = {}): ZnightMetadata {\n const prefix = spec.tokenPrefix ?? DEFAULT_PREFIX\n const providers = (spec.providers ?? []).map(entry =>\n typeof entry === 'function' ? ({ class: entry } satisfies TestProvider) : entry,\n )\n const classTokens = new Map<unknown, Token>()\n const tokens = providers.map(provider => {\n if (provider === null || typeof provider !== 'object') {\n throw new TypeError(\n '[znight] defineTestMetadata(): a provider must be a class or { class?, token?, deps?, factory? }',\n )\n }\n const token = provider.token ?? (provider.class === undefined ? undefined : testToken(provider.class, prefix))\n if (token === undefined) throw new TypeError('[znight] defineTestMetadata(): a provider needs a class or a token')\n if (provider.class !== undefined && !classTokens.has(provider.class)) classTokens.set(provider.class, token)\n return token\n })\n const toToken = (key: TestKey): Token => {\n if (typeof key === 'string') return key\n return classTokens.get(key) ?? testToken(key, prefix)\n }\n\n const definitions = new Map<Token, ProviderDefinition>()\n providers.forEach((provider, position) => {\n const token = tokens[position] as Token\n if (definitions.has(token)) {\n throw new ZnightError(\n ErrorCode.DuplicateProvider,\n `defineTestMetadata(): duplicate provider ${describeToken(token)}`,\n {\n hints: ['Give one of them an explicit token'],\n },\n )\n }\n definitions.set(token, toDefinition(token, provider, toToken))\n })\n\n let aliases: Record<Token, Token> | undefined\n if (spec.aliases !== undefined) {\n const pairs = entriesOf<TestKey, TestKey>(spec.aliases).map(([alias, target]): [Token, Token] => [\n toToken(alias),\n toToken(target),\n ])\n aliases = Object.fromEntries(pairs)\n }\n return createMetadata(Object.fromEntries(definitions), {\n ...(aliases === undefined ? {} : { aliases }),\n ...(spec.externals === undefined ? {} : { externals: spec.externals }),\n ...(spec.extensions === undefined ? {} : { extensions: spec.extensions }),\n ...(spec.resolutionOrder === undefined ? {} : { resolutionOrder: spec.resolutionOrder }),\n })\n}\n\nfunction toDefinition(token: Token, provider: TestProvider, toToken: (key: TestKey) => Token): ProviderDefinition {\n const cls = provider.class\n let factory = provider.factory\n if (factory === undefined) {\n if (cls === undefined) throw new TypeError(`[znight] defineTestMetadata(): ${token} needs a class or a factory`)\n const constructible = cls as unknown as new (...args: unknown[]) => unknown\n factory = (deps: unknown[]) => new constructible(...deps)\n }\n const deps = (provider.deps ?? []).map(dep => toDependency(dep, toToken))\n return {\n scope: provider.scope ?? 'singleton',\n deps,\n factory,\n ...(cls === undefined ? {} : { class: cls }),\n ...(provider.async === undefined ? {} : { async: provider.async }),\n ...(provider.interceptors === undefined ? {} : { interceptors: provider.interceptors }),\n ...(provider.dispose === undefined ? {} : { dispose: provider.dispose }),\n ...(provider.name === undefined ? {} : { name: provider.name }),\n ...(provider.primary === undefined ? {} : { primary: provider.primary }),\n ...(provider.source === undefined ? {} : { source: provider.source }),\n }\n}\n\nfunction toDependency(dep: TestDependency, toToken: (key: TestKey) => Token): DependencyRef {\n if (typeof dep === 'string' || typeof dep === 'function') return toToken(dep)\n if (dep !== null && typeof dep === 'object') {\n if ('multi' in dep && Array.isArray(dep.multi)) return { multi: dep.multi.map(toToken) }\n if ('lazy' in dep && dep.lazy !== undefined) return { lazy: toToken(dep.lazy) }\n if ('token' in dep && dep.optional === true) return { token: toToken(dep.token), optional: true }\n if ('prototype' in dep) return toToken(dep as ClassKey)\n }\n throw new TypeError(`[znight] defineTestMetadata(): invalid dependency ${String(dep)}`)\n}\n\n/** Hard dependencies of a definition (lazy ones excluded: they never constrain the order). */\nfunction hardDependencies(definition: ProviderDefinition): Token[] {\n const tokens: Token[] = []\n for (const ref of definition.deps) {\n if (typeof ref === 'string') tokens.push(ref)\n else if ('multi' in ref) tokens.push(...ref.multi)\n else if ('token' in ref) tokens.push(ref.token)\n }\n return tokens\n}\n\n/** Deterministic topological order (dependencies first). Cycles are left for the container to report. */\nfunction topologicalOrder(providers: Readonly<Record<Token, ProviderDefinition>>): Token[] {\n const order: Token[] = []\n const state = new Map<Token, 'visiting' | 'done'>()\n const visit = (token: Token): void => {\n if (state.has(token) || !Object.hasOwn(providers, token)) return\n state.set(token, 'visiting')\n for (const dep of hardDependencies(providers[token] as ProviderDefinition)) visit(dep)\n state.set(token, 'done')\n order.push(token)\n }\n for (const token of Object.keys(providers)) visit(token)\n return order\n}\n","import type { AnyFunction, MockFunction, UntypedFunction } from './types.ts'\n\ntype Implementation = (this: unknown, ...args: unknown[]) => unknown\n\ninterface MutableResult {\n type: 'return' | 'throw' | 'incomplete'\n value: unknown\n}\n\ninterface MutableState {\n readonly calls: unknown[][]\n readonly results: MutableResult[]\n readonly instances: unknown[]\n readonly contexts: unknown[]\n readonly invocationCallOrder: number[]\n readonly lastCall: unknown[] | undefined\n}\n\ninterface SpyInternals {\n name: string\n implementation: Implementation | undefined\n readonly initial: Implementation | undefined\n readonly once: Implementation[]\n readonly state: MutableState\n}\n\nconst DEFAULT_NAME = 'spy'\n\n/** Global call counter shared by every built-in spy (`mock.invocationCallOrder`). */\nlet callOrder = 0\n\nconst internalsBySpy = new WeakMap<object, SpyInternals>()\n\nfunction internalsOf(spy: unknown): SpyInternals {\n const internals = typeof spy === 'function' ? internalsBySpy.get(spy) : undefined\n if (internals === undefined) throw new TypeError('[znight] Not a spy created by createSpy()')\n return internals\n}\n\nfunction createState(): MutableState {\n const calls: unknown[][] = []\n return {\n calls,\n results: [],\n instances: [],\n contexts: [],\n invocationCallOrder: [],\n get lastCall(): unknown[] | undefined {\n return calls[calls.length - 1]\n },\n }\n}\n\nfunction clearState(state: MutableState): void {\n state.calls.length = 0\n state.results.length = 0\n state.instances.length = 0\n state.contexts.length = 0\n state.invocationCallOrder.length = 0\n}\n\nfunction isObjectLike(value: unknown): boolean {\n return value !== null && (typeof value === 'object' || typeof value === 'function')\n}\n\nfunction invoke(internals: SpyInternals, self: unknown, args: unknown[], isNew: boolean): unknown {\n const state = internals.state\n state.calls.push(args)\n state.contexts.push(self)\n state.instances.push(self)\n state.invocationCallOrder.push(++callOrder)\n const result: MutableResult = { type: 'incomplete', value: undefined }\n state.results.push(result)\n const implementation = internals.once.shift() ?? internals.implementation\n try {\n const value = implementation === undefined ? undefined : implementation.apply(self, args)\n const returned = isNew && !isObjectLike(value) ? self : value\n result.type = 'return'\n result.value = returned\n return returned\n } catch (error) {\n result.type = 'throw'\n result.value = error\n throw error\n }\n}\n\nfunction returning(value: unknown): Implementation {\n return () => value\n}\n\nfunction resolving(value: unknown): Implementation {\n return () => Promise.resolve(value)\n}\n\nfunction rejecting(error: unknown): Implementation {\n return () => Promise.reject(error)\n}\n\nfunction returnThis(this: unknown): unknown {\n return this\n}\n\n/** Methods shared by every built-in spy (the prototype of the spy functions). */\nconst spyPrototype: object = Object.create(Function.prototype, {\n _isMockFunction: { value: true },\n mock: {\n get(this: unknown): MutableState {\n return internalsOf(this).state\n },\n },\n mockImplementation: {\n value(this: unknown, implementation: Implementation): unknown {\n internalsOf(this).implementation = implementation\n return this\n },\n },\n mockImplementationOnce: {\n value(this: unknown, implementation: Implementation): unknown {\n internalsOf(this).once.push(implementation)\n return this\n },\n },\n mockReturnValue: {\n value(this: unknown, value: unknown): unknown {\n internalsOf(this).implementation = returning(value)\n return this\n },\n },\n mockReturnValueOnce: {\n value(this: unknown, value: unknown): unknown {\n internalsOf(this).once.push(returning(value))\n return this\n },\n },\n mockResolvedValue: {\n value(this: unknown, value: unknown): unknown {\n internalsOf(this).implementation = resolving(value)\n return this\n },\n },\n mockResolvedValueOnce: {\n value(this: unknown, value: unknown): unknown {\n internalsOf(this).once.push(resolving(value))\n return this\n },\n },\n mockRejectedValue: {\n value(this: unknown, error: unknown): unknown {\n internalsOf(this).implementation = rejecting(error)\n return this\n },\n },\n mockRejectedValueOnce: {\n value(this: unknown, error: unknown): unknown {\n internalsOf(this).once.push(rejecting(error))\n return this\n },\n },\n mockReturnThis: {\n value(this: unknown): unknown {\n internalsOf(this).implementation = returnThis\n return this\n },\n },\n mockName: {\n value(this: unknown, name: string): unknown {\n internalsOf(this).name = String(name)\n return this\n },\n },\n getMockName: {\n value(this: unknown): string {\n return internalsOf(this).name\n },\n },\n getMockImplementation: {\n value(this: unknown): Implementation | undefined {\n return internalsOf(this).implementation\n },\n },\n mockClear: {\n value(this: unknown): unknown {\n clearState(internalsOf(this).state)\n return this\n },\n },\n mockReset: {\n value(this: unknown): unknown {\n const internals = internalsOf(this)\n clearState(internals.state)\n internals.once.length = 0\n internals.implementation = internals.initial\n return this\n },\n },\n mockRestore: {\n value(this: unknown): void {\n const internals = internalsOf(this)\n clearState(internals.state)\n internals.once.length = 0\n internals.implementation = internals.initial\n },\n },\n})\n\n/**\n * Creates the built-in, dependency-free, Jest-compatible spy. It records `mock.calls`,\n * `mock.results`, `mock.instances`, `mock.contexts`, `mock.invocationCallOrder` and `mock.lastCall`,\n * supports `mockReturnValue(Once)`, `mockResolvedValue(Once)`, `mockRejectedValue(Once)`,\n * `mockImplementation(Once)`, `mockReturnThis`, `mockName`, `mockClear`, `mockReset` and\n * `mockRestore`, and is recognised by Jest's and Vitest's `expect` (`_isMockFunction`).\n *\n * `mockReset()` restores the implementation given to `createSpy()` (Vitest semantics).\n *\n * ```ts\n * const find = createSpy((id: string) => ({ id }))\n * find.mockReturnValueOnce({ id: 'x' })\n * find('1')\n * find.mock.calls // [['1']]\n * ```\n */\nexport function createSpy<F extends AnyFunction = UntypedFunction>(implementation?: F): MockFunction<F> {\n if (implementation !== undefined && typeof implementation !== 'function') {\n throw new TypeError('[znight] createSpy() expects a function implementation')\n }\n const initial = implementation as Implementation | undefined\n const internals: SpyInternals = {\n name: DEFAULT_NAME,\n implementation: initial,\n initial,\n once: [],\n state: createState(),\n }\n const spy = function (this: unknown, ...args: unknown[]): unknown {\n return invoke(internals, this, args, new.target !== undefined)\n }\n Object.setPrototypeOf(spy, spyPrototype)\n internalsBySpy.set(spy, internals)\n return spy as unknown as MockFunction<F>\n}\n\n/** Whether `value` is a spy created by {@link createSpy}. */\nexport function isBuiltinSpy(value: unknown): boolean {\n return typeof value === 'function' && internalsBySpy.has(value)\n}\n","import type { MockFnFactory, MockFnOption } from './types.ts'\n\nimport { createRequire } from 'node:module'\n\nimport { createSpy } from './spy.ts'\n\n/** Where the spy factory used by mocks comes from. */\nexport type MockFnSource = 'custom' | 'vitest' | 'jest' | 'bun' | 'builtin'\n\n/** A spy factory and its origin (see {@link resolveMockFn}). */\nexport interface ResolvedMockFn {\n readonly source: MockFnSource\n readonly create: MockFnFactory\n}\n\nconst BUILTIN: ResolvedMockFn = Object.freeze({ source: 'builtin', create: createSpy as MockFnFactory })\n\nlet defaultOption: MockFnOption = 'auto'\n/** `mock` of `bun:test`: `undefined` until probed, `null` when unavailable. */\nlet bunMock: MockFnFactory | null | undefined\n\nfunction assertOption(option: unknown, where: string): asserts option is MockFnOption {\n if (typeof option === 'function' || option === 'auto' || option === 'builtin') return\n throw new TypeError(`[znight] ${where}: mockFn must be 'auto', 'builtin' or a function such as vi.fn`)\n}\n\n/**\n * Sets the spy factory used when `mockFn` is not passed explicitly (e.g. in a Vitest setup file:\n * `setDefaultMockFn(vi.fn)`). Without argument, restores auto-detection.\n */\nexport function setDefaultMockFn(option: MockFnOption = 'auto'): void {\n assertOption(option, 'setDefaultMockFn()')\n defaultOption = option\n}\n\n/**\n * Resolves a {@link MockFnOption} (default: the option set with {@link setDefaultMockFn}, `'auto'`\n * initially) to a spy factory.\n */\nexport function resolveMockFn(option?: MockFnOption): ResolvedMockFn {\n const effective = option ?? defaultOption\n assertOption(effective, 'resolveMockFn()')\n if (typeof effective === 'function') return { source: 'custom', create: effective }\n if (effective === 'builtin') return BUILTIN\n return detectMockFn()\n}\n\n/**\n * Auto-detects the spy factory of the running test framework: Vitest (`globalThis.vi.fn`, with\n * `globals: true`), Jest (`globalThis.jest.fn`), `bun:test` (`mock`, loaded only when running on\n * Bun), otherwise the built-in spy ({@link createSpy}).\n */\nexport function detectMockFn(): ResolvedMockFn {\n const scope = globalThis as { vi?: { fn?: unknown }; jest?: { fn?: unknown } }\n const vitest = scope.vi?.fn\n if (typeof vitest === 'function') return { source: 'vitest', create: vitest as MockFnFactory }\n const jest = scope.jest?.fn\n if (typeof jest === 'function') return { source: 'jest', create: jest as MockFnFactory }\n const bun = loadBunMock()\n if (bun !== undefined) return { source: 'bun', create: bun }\n return BUILTIN\n}\n\n/** Whether the code runs on Bun. */\nexport function isBunRuntime(): boolean {\n return typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined'\n}\n\nfunction loadBunMock(): MockFnFactory | undefined {\n bunMock ??= isBunRuntime() ? requireBunMock() : null\n return bunMock ?? undefined\n}\n\nfunction requireBunMock(): MockFnFactory | null {\n try {\n // non-literal specifier: bundlers and Vite never try to resolve `bun:test`\n const specifier = ['bun', 'test'].join(':')\n const bunTest = createRequire(import.meta.url)(specifier) as { mock?: unknown }\n return typeof bunTest.mock === 'function' ? (bunTest.mock as MockFnFactory) : null\n } catch {\n return null\n }\n}\n","import type { ClassKey } from '@znight/core'\nimport type { AnyFunction, DeepMock, Mocked, MockFnFactory, MockFnOption } from './types.ts'\n\nimport { resolveMockFn } from './mock-fn.ts'\n\n/** Options of {@link createMock}. */\nexport interface CreateMockOptions {\n /**\n * Name of the mock, used to name its spies in assertion messages (`UserRepository.findById`).\n * Default: the class name, or `mock`.\n */\n readonly name?: string\n /**\n * When `true`, calling an unconfigured method returns a deep mock (the same one for every call)\n * instead of `undefined`, so fluent APIs work: `db.select().from('users')`. Default: `false`.\n */\n readonly deep?: boolean\n /** Spy implementation. Default: auto-detected (see `MockFnOption`). */\n readonly mockFn?: MockFnOption\n}\n\n/** Shared state of a mock and every spy created under it. */\ninterface MockTree {\n readonly create: MockFnFactory\n readonly deep: boolean\n readonly spies: SpyRecord[]\n}\n\ninterface SpyRecord {\n readonly spy: SpyLike\n readonly implementation: AnyFunction | undefined\n}\n\ninterface SpyLike {\n (...args: unknown[]): unknown\n mockName?: (name: string) => unknown\n mockClear?: () => unknown\n mockReset?: () => unknown\n mockImplementation?: (implementation: AnyFunction) => unknown\n}\n\n/**\n * Property names never auto-mocked (they read as `undefined` unless set explicitly). Libraries probe\n * them to detect promises (`then`), JSON values (`toJSON`), asymmetric matchers (`asymmetricMatch`),\n * React elements (`$$typeof`), DOM nodes (`nodeType`, `tagName`), ES module namespaces\n * (`__esModule`) or mock functions (`_isMockFunction`). Names starting with `@@` (Immutable.js\n * sentinels) are reserved too. Symbol-keyed properties are never auto-mocked.\n */\nconst RESERVED: ReadonlySet<string> = new Set([\n 'then',\n 'toJSON',\n 'asymmetricMatch',\n '$$typeof',\n 'nodeType',\n 'tagName',\n '__esModule',\n '_isMockFunction',\n])\n\nconst TREE: unique symbol = Symbol('znight.mock')\n\nconst mocks = new WeakSet<object>()\n\nfunction isReserved(key: string): boolean {\n return RESERVED.has(key) || key.startsWith('@@')\n}\n\n/**\n * Creates a deep auto-mock.\n *\n * - Every property read returns a spy (`MockFunction`), created on first access and then stable.\n * Spies are deep too: `mock.pool.query.mockResolvedValue(rows)`.\n * - Unconfigured spies return `undefined` (or a deep mock with `{ deep: true }`).\n * - The mock is **not thenable** and inert for serialisers: `then`, `toJSON`, `asymmetricMatch`,\n * `$$typeof`, `Symbol.toPrimitive`... read as `undefined`, so `await mock`, `JSON.stringify(mock)`\n * and `expect(...).toEqual(mock)` behave.\n * - Assigned properties win: `mock.enabled = false`.\n * - With a class, the mock inherits its prototype (`instanceof` works) and getters read as\n * `undefined` instead of a (truthy) spy.\n * - Functions of `partial` become spies with that implementation; other values are set as is.\n *\n * ```ts\n * const repository = createMock(UserRepository, { findById: async id => ({ id }) })\n * const logger = createMock<Logger>()\n * logger.info('hello')\n * expect(logger.info).toHaveBeenCalledWith('hello')\n * ```\n */\nexport function createMock<T>(cls: ClassKey<T>, partial?: Partial<T>, options?: CreateMockOptions): Mocked<T>\nexport function createMock<T = never>(\n partial?: Partial<T>,\n options?: CreateMockOptions,\n): [T] extends [never] ? DeepMock : Mocked<T>\nexport function createMock(first?: unknown, second?: unknown, third?: unknown): unknown {\n if (typeof first === 'function') {\n return mockObject(first as ClassKey<unknown>, second as object | undefined, third as CreateMockOptions | undefined)\n }\n return mockObject(undefined, first as object | undefined, second as CreateMockOptions | undefined)\n}\n\n/** {@link createMock} with an optional class (internal). */\nexport function mockObject(\n cls: ClassKey<unknown> | undefined,\n partial: object | undefined,\n options: CreateMockOptions = {},\n): object {\n if (partial !== undefined && (partial === null || typeof partial !== 'object')) {\n throw new TypeError('[znight] createMock(): the partial implementation must be an object')\n }\n const tree: MockTree = {\n create: resolveMockFn(options.mockFn).create,\n deep: options.deep === true,\n spies: [],\n }\n const className = typeof cls === 'function' ? (cls as { name?: unknown }).name : undefined\n const name = options.name ?? (typeof className === 'string' && className !== '' ? className : 'mock')\n return createNode(name, tree, cls, partial)\n}\n\n/** Whether `value` is a mock (or one of its spies) created by {@link createMock}. */\nexport function isMock(value: unknown): boolean {\n return value !== null && (typeof value === 'object' || typeof value === 'function') && mocks.has(value)\n}\n\n/** Forgets the calls recorded by every spy of `mock` (`mockClear()`); implementations are kept. */\nexport function clearMock(mock: object): void {\n for (const { spy } of treeOf(mock, 'clearMock').spies) spy.mockClear?.()\n}\n\n/**\n * Resets every spy of `mock` to its initial state: recorded calls and programmed implementations\n * are forgotten, implementations given to {@link createMock} (and deep returns) are restored.\n */\nexport function resetMock(mock: object): void {\n for (const { spy, implementation } of treeOf(mock, 'resetMock').spies) {\n spy.mockReset?.()\n if (implementation !== undefined) spy.mockImplementation?.(implementation)\n }\n}\n\nfunction treeOf(mock: object, where: string): MockTree {\n const tree = isMock(mock) ? (mock as { [TREE]?: MockTree })[TREE] : undefined\n if (tree === undefined) throw new TypeError(`[znight] ${where}(): expected a mock created by createMock()`)\n return tree\n}\n\n/** An object mock (the root of a mock, or the value returned by a deep spy). */\nfunction createNode(\n name: string,\n tree: MockTree,\n cls: ClassKey<unknown> | undefined,\n partial: object | undefined,\n): object {\n const target: Record<PropertyKey, unknown> = Object.create(\n typeof cls === 'function' && isObjectLike(cls.prototype) ? (cls.prototype as object) : Object.prototype,\n )\n const accessors = typeof cls === 'function' ? accessorKeys(cls.prototype) : undefined\n const children = new Map<string, unknown>()\n if (partial !== undefined) {\n for (const key of Reflect.ownKeys(partial)) {\n const value = (partial as Record<PropertyKey, unknown>)[key]\n if (typeof key === 'string' && typeof value === 'function') {\n children.set(key, createSpyNode(`${name}.${key}`, tree, value as AnyFunction))\n } else {\n defineValue(target, key, value)\n }\n }\n }\n const proxy: object = new Proxy(target, {\n get(object, key, receiver): unknown {\n if (typeof key === 'symbol') {\n if (key === TREE) return tree\n return Object.hasOwn(object, key) ? object[key] : undefined\n }\n if (Object.hasOwn(object, key)) return object[key]\n if (key === 'constructor') return Reflect.get(object, key, receiver)\n if (isReserved(key)) return undefined\n if (Object.hasOwn(Object.prototype, key)) return Reflect.get(Object.prototype, key, receiver)\n if (accessors?.has(key) === true) return undefined\n let child = children.get(key)\n if (child === undefined) {\n child = createSpyNode(`${name}.${key}`, tree, undefined)\n children.set(key, child)\n }\n return child\n },\n set(object, key, value): boolean {\n defineValue(object, key, value)\n return true\n },\n deleteProperty(object, key): boolean {\n if (typeof key === 'string') children.delete(key)\n return Reflect.deleteProperty(object, key)\n },\n })\n mocks.add(proxy)\n return proxy\n}\n\n/** A spy whose unknown properties are deep spies (`spy.nested.method`). */\nfunction createSpyNode(path: string, tree: MockTree, implementation: AnyFunction | undefined): SpyLike {\n const effective = implementation ?? (tree.deep ? deepReturn(path, tree) : undefined)\n const spy = tree.create(effective) as SpyLike\n if (typeof spy !== 'function') {\n throw new TypeError(`[znight] The mockFn factory returned ${typeof spy} instead of a function`)\n }\n if (typeof spy.mockName === 'function') spy.mockName(path)\n makeDeep(spy, path, tree)\n tree.spies.push({ spy, implementation: effective })\n mocks.add(spy)\n return spy\n}\n\n/** The implementation of a deep spy: returns the same deep mock on every call. */\nfunction deepReturn(path: string, tree: MockTree): AnyFunction {\n let result: object | undefined\n return () => {\n result ??= createNode(`${path}()`, tree, undefined, undefined)\n return result\n }\n}\n\n/**\n * Inserts a proxy between `spy` and its prototype: reading a property the spy does not have (own or\n * inherited) creates a child spy. The spy itself stays a genuine spy of its framework, which\n * `bun:test`'s `expect` requires (it rejects proxies).\n */\nfunction makeDeep(spy: SpyLike, path: string, tree: MockTree): void {\n const original: unknown = Object.getPrototypeOf(spy)\n if (!isObjectLike(original)) return\n const children = new Map<string, SpyLike>()\n const prototype = new Proxy(original as object, {\n get(object, key, receiver): unknown {\n if (typeof key === 'symbol' || key in object || isReserved(key)) return Reflect.get(object, key, receiver)\n let child = children.get(key)\n if (child === undefined) {\n child = createSpyNode(`${path}.${key}`, tree, undefined)\n children.set(key, child)\n }\n return child\n },\n })\n try {\n Object.setPrototypeOf(spy, prototype)\n } catch {\n // a frozen or exotic spy: it keeps working, without deep members\n }\n}\n\nfunction defineValue(object: object, key: PropertyKey, value: unknown): void {\n Object.defineProperty(object, key, { value, writable: true, enumerable: true, configurable: true })\n}\n\n/** Names of the accessors (getters/setters) declared along a prototype chain, `Object.prototype` excluded. */\nfunction accessorKeys(prototype: unknown): ReadonlySet<string> {\n const keys = new Set<string>()\n let current: unknown = prototype\n while (isObjectLike(current) && current !== Object.prototype && current !== Function.prototype) {\n for (const key of Object.getOwnPropertyNames(current)) {\n const descriptor = Object.getOwnPropertyDescriptor(current, key)\n if (descriptor !== undefined && (descriptor.get !== undefined || descriptor.set !== undefined)) keys.add(key)\n }\n current = Object.getPrototypeOf(current)\n }\n return keys\n}\n\nfunction isObjectLike(value: unknown): value is object {\n return value !== null && (typeof value === 'object' || typeof value === 'function')\n}\n","import type { DependencyRef, ProviderDefinition, ProviderFactory, ProviderKey, Scope } from '@znight/core'\n\n/** A typed `[key, value]` entry for `overrides` / `providers` / `provide`. */\nexport type OverrideEntry<T = unknown> = readonly [ProviderKey<T>, T]\n\n/** A `[key, definition]` entry replacing a provider with a factory. */\nexport type OverrideDefinitionEntry<T = unknown> = readonly [ProviderKey<T>, ProviderDefinition<T>]\n\n/**\n * A type-checked override: the value must match the type designated by the class or typed token.\n *\n * ```ts\n * await TestApp.create({ metadata, overrides: [override(UserRepository, new InMemoryUserRepository())] })\n * ```\n */\nexport function override<T>(key: ProviderKey<T>, value: NoInfer<T>): OverrideEntry<T> {\n return [key, value]\n}\n\n/** Options of {@link overrideFactory}. */\nexport interface OverrideFactoryOptions {\n /** Tokens resolved and passed to the factory, in order. Default: none. */\n readonly deps?: readonly DependencyRef[]\n /** Default: `'singleton'`. */\n readonly scope?: Scope\n /** Set when the factory returns a promise (singletons only). */\n readonly async?: boolean\n /** Method called when the instance is disposed. */\n readonly dispose?: string\n}\n\n/**\n * Replaces a provider with a factory whose dependencies are resolved by the container (or, in\n * `TestBed`, like the target's dependencies).\n *\n * ```ts\n * overrideFactory(UserRepository, ([db]) => new InMemoryUserRepository(db), { deps: ['src/db.ts#Database'] })\n * ```\n */\nexport function overrideFactory<T>(\n key: ProviderKey<T>,\n factory: ProviderFactory<NoInfer<T>>,\n options: OverrideFactoryOptions = {},\n): OverrideDefinitionEntry<T> {\n if (typeof factory !== 'function') throw new TypeError('[znight] overrideFactory() expects a factory function')\n const definition: ProviderDefinition<T> = {\n scope: options.scope ?? 'singleton',\n deps: options.deps ?? [],\n factory,\n ...(options.async === undefined ? {} : { async: options.async }),\n ...(options.dispose === undefined ? {} : { dispose: options.dispose }),\n }\n return [key, definition]\n}\n","/**\n * Structural readers of the feature metadata (`metadata.extensions`). `@znight/testing` depends on\n * no feature package: it reads the documented shapes (architecture §9, RFC 0005 §7.1 for\n * `extensions.graphql`) defensively and ignores malformed entries.\n */\nimport type { Token, ZnightMetadata } from '@znight/core'\n\n/** A configuration class (`metadata.extensions.config.configs[]`), as far as tests need it. */\nexport interface ConfigClassInfo {\n readonly token: Token\n readonly prefix: string | undefined\n readonly fields: readonly ConfigFieldInfo[]\n}\n\n/** A field of a configuration class. */\nexport interface ConfigFieldInfo {\n readonly property: string\n readonly env: string | undefined\n /** Config type (`'string'`, `'number'`, `'url'`...), `undefined` when absent from the metadata. */\n readonly type: string | undefined\n /** Whether the field declares a default value (`@Default`; initializers are not in the metadata). */\n readonly hasDefault: boolean\n readonly default: unknown\n readonly required: boolean\n}\n\ntype Loose = Readonly<Record<string, unknown>>\n\nfunction isRecord(value: unknown): value is Loose {\n return value !== null && typeof value === 'object'\n}\n\nfunction arrayOf(value: unknown): readonly unknown[] {\n return Array.isArray(value) ? value : []\n}\n\nfunction extension(metadata: ZnightMetadata, name: string): Loose | undefined {\n if (!isRecord(metadata)) return undefined\n const extensions: unknown = metadata.extensions\n if (!isRecord(extensions)) return undefined\n const value = extensions[name]\n return isRecord(value) ? value : undefined\n}\n\nfunction tokensOf(value: unknown): Token[] {\n return arrayOf(value).filter((token): token is Token => typeof token === 'string')\n}\n\n/** Configuration classes declared by `@znight/config` (`extensions.config.configs`), by token. */\nexport function readConfigClasses(metadata: ZnightMetadata): Map<Token, ConfigClassInfo> {\n const result = new Map<Token, ConfigClassInfo>()\n for (const entry of arrayOf(extension(metadata, 'config')?.['configs'])) {\n if (!isRecord(entry) || typeof entry['token'] !== 'string') continue\n const fields: ConfigFieldInfo[] = []\n for (const field of arrayOf(entry['fields'])) {\n if (!isRecord(field) || typeof field['property'] !== 'string') continue\n fields.push({\n property: field['property'],\n env: typeof field['env'] === 'string' ? field['env'] : undefined,\n type: typeof field['type'] === 'string' ? field['type'] : undefined,\n hasDefault: Object.hasOwn(field, 'default') && field['default'] !== undefined,\n default: field['default'],\n required: field['required'] === true,\n })\n }\n const prefix = entry['prefix']\n result.set(entry['token'], {\n token: entry['token'],\n prefix: typeof prefix === 'string' && prefix !== '' ? prefix : undefined,\n fields,\n })\n }\n return result\n}\n\n/**\n * Tokens an HTTP application needs at boot: controllers (`extensions.http.controllers[].token`) and\n * the guards, interceptors and parameter resolvers (RFC 0010) they and their routes reference.\n */\nexport function readHttpRoots(metadata: ZnightMetadata): Token[] {\n const roots: Token[] = []\n for (const controller of arrayOf(extension(metadata, 'http')?.['controllers'])) {\n if (!isRecord(controller)) continue\n if (typeof controller['token'] === 'string') roots.push(controller['token'])\n roots.push(...tokensOf(controller['guards']), ...tokensOf(controller['interceptors']))\n for (const route of arrayOf(controller['routes'])) {\n if (isRecord(route)) {\n roots.push(\n ...tokensOf(route['guards']),\n ...tokensOf(route['interceptors']),\n ...tokensOf(route['paramResolvers']),\n )\n }\n }\n }\n return roots\n}\n\n/** Message consumers (`extensions.messaging.consumers[].token`) and their parameter resolvers (RFC 0010). */\nexport function readMessagingRoots(metadata: ZnightMetadata): Token[] {\n const roots: Token[] = []\n for (const consumer of arrayOf(extension(metadata, 'messaging')?.['consumers'])) {\n if (!isRecord(consumer)) continue\n if (typeof consumer['token'] === 'string') roots.push(consumer['token'])\n for (const handler of arrayOf(consumer['handlers'])) {\n if (isRecord(handler)) roots.push(...tokensOf(handler['paramResolvers']))\n }\n }\n return roots\n}\n\n/** Hosts of scheduled jobs (`extensions.schedule.jobs[].token`), disabled jobs included (they can be triggered). */\nexport function readScheduleRoots(metadata: ZnightMetadata): Token[] {\n const roots: Token[] = []\n for (const job of arrayOf(extension(metadata, 'schedule')?.['jobs'])) {\n if (isRecord(job) && typeof job['token'] === 'string') roots.push(job['token'])\n }\n return roots\n}\n\n/**\n * Tokens a GraphQL application needs at boot (`extensions.graphql`, RFC 0005 §7.1): for every field\n * of an object type bound to a resolver (`types[kind: 'object'].fields[].resolver`), the resolver\n * token, its guard tokens, the loader tokens its method injects and its parameter resolvers (RFC 0010).\n */\nexport function readGraphQLRoots(metadata: ZnightMetadata): Token[] {\n const roots: Token[] = []\n for (const type of arrayOf(extension(metadata, 'graphql')?.['types'])) {\n if (!isRecord(type) || type['kind'] !== 'object') continue\n for (const field of arrayOf(type['fields'])) {\n const resolver = isRecord(field) ? field['resolver'] : undefined\n if (!isRecord(resolver)) continue\n if (typeof resolver['token'] === 'string') roots.push(resolver['token'])\n roots.push(\n ...tokensOf(resolver['guards']),\n ...tokensOf(resolver['loaders']),\n ...tokensOf(resolver['paramResolvers']),\n )\n }\n }\n return roots\n}\n","import type { ExternalDefinition, ProviderClass, ProviderDefinition, Token, ZnightMetadata } from '@znight/core'\n\nimport { describeToken, displayName, ErrorCode, METADATA_VERSION, ZnightError } from '@znight/core'\n\n/**\n * Read-only index over compiled metadata: provider definitions, aliases, externals and the key\n * lookups shared by `TestBed`, `mocks.get()` and the testing helpers (class, token, alias or display\n * name → canonical token). Internal.\n */\nexport class MetadataIndex {\n readonly metadata: ZnightMetadata\n readonly #providers = new Map<Token, ProviderDefinition>()\n readonly #aliases = new Map<Token, Token>()\n readonly #externals = new Map<Token, ExternalDefinition>()\n\n constructor(metadata: ZnightMetadata) {\n assertMetadata(metadata)\n this.metadata = metadata\n for (const [token, definition] of Object.entries(metadata.providers)) this.#providers.set(token, definition)\n for (const [alias, target] of Object.entries(metadata.aliases ?? {})) this.#aliases.set(alias, target)\n for (const external of metadata.externals ?? []) {\n if (typeof external?.token === 'string') this.#externals.set(external.token, external)\n }\n }\n\n /** Every provider token, in declaration order. */\n providerTokens(): IterableIterator<Token> {\n return this.#providers.keys()\n }\n\n definition(token: Token): ProviderDefinition | undefined {\n return this.#providers.get(token)\n }\n\n isProvider(token: Token): boolean {\n return this.#providers.has(token)\n }\n\n external(token: Token): ExternalDefinition | undefined {\n return this.#externals.get(token)\n }\n\n /** Whether `token` is a provider, an alias or an external of the metadata. */\n isKnown(token: Token): boolean {\n return this.#providers.has(token) || this.#aliases.has(token) || this.#externals.has(token)\n }\n\n /** Provider, alias and external tokens. */\n knownTokens(): Set<Token> {\n return new Set([...this.#providers.keys(), ...this.#aliases.keys(), ...this.#externals.keys()])\n }\n\n /** The class of a provider, when it is a class provider. */\n classOf(token: Token): ProviderClass | undefined {\n return this.#providers.get(token)?.class\n }\n\n /** Follows aliases (cycle-guarded) until a provider token; returns `token` itself otherwise. */\n canonical(token: Token): Token {\n let current = token\n const seen = new Set<Token>()\n while (!this.#providers.has(current) && this.#aliases.has(current) && !seen.has(current)) {\n seen.add(current)\n current = this.#aliases.get(current) as Token\n }\n return current\n }\n\n /** Alias entries (alias → target), for filtering and display. */\n aliases(): IterableIterator<[Token, Token]> {\n return this.#aliases.entries()\n }\n\n /**\n * Finds the canonical token designated by `key` among `universe`:\n * - a string: a token of `universe`, an alias resolving into it, or a unique display name\n * (`'UserService'`) of a token or alias;\n * - a class: the token whose provider class is `key`, else the unique token whose class extends\n * it, else a unique display name equal to the class name (externals, interfaces).\n *\n * @throws ZnightError ZNIGHT008 when a display name is ambiguous.\n */\n find(key: unknown, universe: ReadonlySet<Token>): Token | undefined {\n if (typeof key === 'string') {\n if (universe.has(key)) return key\n const canonical = this.canonical(key)\n if (universe.has(canonical)) return canonical\n return this.#findByName(key, universe, undefined)\n }\n if (typeof key !== 'function') return undefined\n const cls = key as ProviderClass\n const exact = [...universe].filter(token => this.classOf(token) === cls)\n if (exact.length > 0) return exact[0]\n const derived = [...universe].filter(token => extendsClass(this.classOf(token), cls))\n if (derived.length === 1) return derived[0]\n if (derived.length > 1) throw ambiguousError(cls.name, derived)\n const name = cls.name\n return typeof name === 'string' && name !== '' ? this.#findByName(name, universe, cls) : undefined\n }\n\n #findByName(name: string, universe: ReadonlySet<Token>, cls: ProviderClass | undefined): Token | undefined {\n // an alias and its provider designate the same thing: matches are compared by canonical token\n const matches = new Set<Token>()\n const add = (token: Token): void => {\n const canonical = this.canonical(token)\n if (universe.has(canonical)) matches.add(canonical)\n else if (universe.has(token)) matches.add(token)\n }\n for (const token of universe) if (displayName(token) === name) add(token)\n for (const [alias] of this.#aliases) if (displayName(alias) === name) add(alias)\n const candidates = [...matches].filter(token => {\n if (cls === undefined) return true\n const own = this.classOf(token)\n return own === undefined || own === cls || extendsClass(own, cls)\n })\n if (candidates.length === 1) return candidates[0]\n if (candidates.length > 1) throw ambiguousError(name, candidates)\n return undefined\n }\n}\n\nfunction extendsClass(candidate: ProviderClass | undefined, base: ProviderClass): boolean {\n if (candidate === undefined || candidate === base) return false\n const prototype: unknown = base.prototype\n return typeof prototype === 'object' && prototype !== null && candidate.prototype instanceof base\n}\n\nfunction ambiguousError(name: string, tokens: readonly Token[]): ZnightError {\n return new ZnightError(\n ErrorCode.AmbiguousInjection,\n `\"${name}\" is ambiguous: it matches ${tokens.map(describeToken).join(', ')}`,\n { hints: ['Use the full token (or the class) instead of the display name'] },\n )\n}\n\nfunction assertMetadata(metadata: ZnightMetadata): void {\n if (\n metadata === null ||\n typeof metadata !== 'object' ||\n metadata.providers === null ||\n typeof metadata.providers !== 'object'\n ) {\n throw new ZnightError(\n ErrorCode.MissingProvider,\n 'No compiled metadata: expected the generated __ZNIGHT_METADATA__',\n {\n hints: [\n 'Pass { metadata: __ZNIGHT_METADATA__ } imported from src/.znight/container.generated.ts',\n 'Generate it before running tests: `znight generate`, the Bun preload `@znight/compiler/bun` or the Vite plugin under Vitest',\n ],\n },\n )\n }\n if (metadata.version !== METADATA_VERSION) {\n throw new ZnightError(\n ErrorCode.VersionMismatch,\n `Unsupported metadata version ${String(metadata.version)} (expected ${METADATA_VERSION})`,\n { hints: ['Regenerate the metadata with the @znight/compiler version matching @znight/testing'] },\n )\n }\n}\n","import type {\n ClassKey,\n Container,\n CoreLogger,\n Plugin,\n PluginRootsContext,\n ProviderClass,\n ProviderKey,\n ProviderValues,\n ShutdownOptions,\n Token,\n TypedToken,\n ZnightMetadata,\n} from '@znight/core'\n\nimport { Application, createConsoleLogger, ErrorCode, ZnightError } from '@znight/core'\n\nimport { readGraphQLRoots, readHttpRoots, readMessagingRoots, readScheduleRoots } from './extensions.ts'\nimport { MetadataIndex } from './metadata-index.ts'\nimport { entriesOf } from './utils.ts'\n\n/** Name of the HTTP plugin `TestApp.inject()` delegates to (`HttpPlugin.configure()` from `@znight/http`). */\nexport const HTTP_PLUGIN_NAME = 'http'\n\n/** An in-memory HTTP request for {@link TestApp.inject}. */\nexport interface InjectRequest {\n /** HTTP method. Default: `GET`. */\n readonly method?: string\n /** Path, with an optional query string (`/users?page=2`). */\n readonly url: string\n readonly headers?: Readonly<Record<string, string>>\n /**\n * Request body, encoded by the HTTP plugin: a string or bytes are sent as is (`text/plain` /\n * `application/octet-stream` without `content-type` header), a `FormData` as\n * `multipart/form-data` (files included: uploads), a `Blob` / `File` with its type, anything else\n * as JSON (`application/json`).\n */\n readonly body?: unknown\n /** Query parameters added to those of `url`. */\n readonly query?: Readonly<Record<string, string | readonly string[]>>\n /**\n * Request cookies (name → value), sent by the HTTP plugin in a `cookie` header, after any `cookie`\n * header of `headers`. Values are encoded like the cookies the plugin sets, so a value read from\n * `response.cookies` can be sent back as is (signed values included).\n */\n readonly cookies?: Readonly<Record<string, string>>\n /**\n * Cookies the HTTP plugin signs with its current secret (`cookies.secrets[0]`) and merges into\n * `cookies` before dispatch: the way to send a valid `@SignedCookie`.\n */\n readonly signedCookies?: Readonly<Record<string, string>>\n}\n\n/**\n * A parsed `Set-Cookie` header of an {@link InjectResponse}: the shape of `SetCookieInfo` from\n * `@znight/http`.\n */\nexport interface SetCookieInfo {\n readonly name: string\n /** Decoded value (a signed cookie: `<value>.<signature>`). */\n readonly value: string\n /** The `Set-Cookie` header line. */\n readonly raw: string\n readonly expires?: Date\n readonly maxAge?: number\n readonly domain?: string\n readonly path?: string\n readonly secure: boolean\n readonly httpOnly: boolean\n readonly sameSite?: 'strict' | 'lax' | 'none'\n readonly partitioned: boolean\n readonly priority?: 'low' | 'medium' | 'high'\n}\n\n/** The response of {@link TestApp.inject}. */\nexport interface InjectResponse {\n readonly status: number\n /** Response headers (lower-cased names). */\n readonly headers: Readonly<Record<string, string | readonly string[] | undefined>>\n /** The body decoded as UTF-8. */\n readonly body: string\n /** The raw body bytes (downloads, binary responses). */\n readonly bytes: Uint8Array\n /** The `set-cookie` headers parsed, by cookie name (the last one wins); `{}` without any. */\n readonly cookies: Readonly<Record<string, SetCookieInfo>>\n /** The body parsed as JSON. */\n json<T = unknown>(): T\n}\n\n/**\n * What the `inject()` of the HTTP plugin resolves with: an {@link InjectResponse} whose `bytes` and\n * `cookies` may be absent (`TestApp.inject()` then encodes `body` as UTF-8 and returns no cookies).\n */\nexport type HttpInjectResult = Omit<InjectResponse, 'bytes' | 'cookies'> & {\n readonly bytes?: Uint8Array\n readonly cookies?: Readonly<Record<string, SetCookieInfo>>\n}\n\n/**\n * What `TestApp.inject()` expects from the plugin named `'http'`: an in-memory dispatch (no socket).\n * `HttpPlugin` from `@znight/http` implements it.\n */\nexport interface HttpInjector {\n inject(request: InjectRequest & { readonly method: string }): Promise<HttpInjectResult>\n}\n\n/** A request for {@link TestApp.injectStream} / {@link TestApp.injectSse}: an {@link InjectRequest} that can be aborted. */\nexport interface InjectStreamRequest extends InjectRequest {\n /** Aborting it disconnects the client (like cancelling the response body). */\n readonly signal?: AbortSignal\n}\n\n/**\n * The response of {@link TestApp.injectStream}: available at the headers, the body read as it is\n * produced. Cancelling `body` disconnects the client. The shape of `InjectStreamResponse` from\n * `@znight/http`.\n */\nexport interface InjectStreamResponse {\n readonly status: number\n readonly headers: Readonly<Record<string, string | readonly string[] | undefined>>\n readonly cookies: Readonly<Record<string, SetCookieInfo>>\n readonly body: ReadableStream<Uint8Array>\n}\n\n/** An event of an event stream (`SseMessage` of `@znight/http`). */\nexport interface SseMessage {\n /** Event type: `message` by default. */\n readonly event: string\n readonly data: string\n /** The last event id at dispatch time. */\n readonly id: string\n json<T = unknown>(): T\n}\n\n/**\n * The response of {@link TestApp.injectSse}: an event stream read in memory like `EventSource`\n * would (`InjectSseResponse` of `@znight/http`).\n */\nexport interface InjectSseResponse extends AsyncIterable<SseMessage>, AsyncDisposable {\n readonly status: number\n readonly headers: Readonly<Record<string, string | readonly string[] | undefined>>\n readonly cookies: Readonly<Record<string, SetCookieInfo>>\n /** `''` for an event stream; otherwise the whole body (an error, a 204...). */\n readonly body: string\n json<T = unknown>(): T\n /** The next event (comments skipped). Rejects on timeout (default 2 000 ms) or when the stream ended. */\n next(options?: { readonly timeoutMs?: number }): Promise<SseMessage>\n take(count: number, options?: { readonly timeoutMs?: number }): Promise<SseMessage[]>\n /** Comments received so far (heartbeats are `''`). */\n readonly comments: readonly string[]\n /** What a browser would send as `Last-Event-ID`. */\n readonly lastEventId: string\n /** The last `retry` received. */\n readonly retry: number | undefined\n /** Resolves when the server ends the stream. */\n readonly done: Promise<void>\n /** Disconnects (the server sees a client disconnect). Idempotent. */\n close(): Promise<void>\n /** Reconnects like `EventSource`: the same request plus `last-event-id`. */\n reconnect(): Promise<InjectSseResponse>\n}\n\n/**\n * What `TestApp.injectStream()` / `injectSse()` expect from the plugin named `'http'`\n * (`HttpPlugin` of `@znight/http` ≥ 0.1.0, the release that ships streaming).\n */\nexport interface HttpStreamInjector {\n injectStream(request: InjectStreamRequest & { readonly method: string }): Promise<InjectStreamResponse>\n injectSse(request: InjectStreamRequest & { readonly method: string }): Promise<InjectSseResponse>\n}\n\n/**\n * A plugin implementing the optional `initRoots(context)` member of `Plugin` (`@znight/core`), read\n * by `TestApp.create()`: the providers the plugin needs at boot although the metadata does not make\n * them entry points, i.e. classes or tokens given in its options (`HttpPlugin.configure({ guards,\n * interceptors, exceptionMappers })`) or derived from its metadata section (`context.metadata`).\n * `TestApp` adds them to the providers instantiated at boot (see {@link TestAppOptions.only}), so\n * that their async dependencies exist when the plugin resolves them: an async factory cannot run on\n * demand.\n *\n * Called once per `TestApp.create()`, before the application is created. Keys that are not\n * providers of the metadata are ignored (the plugin reports them itself).\n */\nexport type PluginInitRoots = Required<Pick<Plugin, 'initRoots'>>\n\n/** Options of {@link TestApp.create}. */\nexport interface TestAppOptions {\n /** The generated metadata (`__ZNIGHT_METADATA__`). */\n readonly metadata: ZnightMetadata\n readonly plugins?: readonly Plugin[]\n /** Values supplied by the application (externals, configuration...), as in `Application.create`. */\n readonly providers?: ProviderValues\n /**\n * Replacements applied last, with the highest precedence: values or provider definitions\n * (`{ scope, deps, factory }`), keyed by class or token. Overridden providers are instantiated.\n */\n readonly overrides?: ProviderValues\n /**\n * Which providers are instantiated at boot (with their dependency closure, plus the overrides and\n * the providers the plugins resolve at bootstrap, see {@link PluginInitRoots}: global guards,\n * interceptors and exception mappers of `HttpPlugin`):\n * - default: the entry points of the metadata, i.e. the HTTP controllers (with their guards and\n * interceptors), the message consumers and the hosts of scheduled jobs, or every provider when\n * there is none;\n * - `'all'`: every provider;\n * - a list of classes or tokens.\n *\n * Other providers are created on first use (synchronous factories only: list a provider here\n * when it, or one of its dependencies, has an async factory).\n */\n readonly only?: readonly ProviderKey[] | 'all'\n /** Application logger. Default: a console logger writing warnings and errors. */\n readonly logger?: CoreLogger\n /** Run `app.start()` (plugins `onStart`: listen, subscribe...). Default: `true`. */\n readonly start?: boolean\n /** Shutdown timeouts. Signal handlers are always disabled. */\n readonly shutdown?: Omit<ShutdownOptions, 'signals' | 'process'>\n}\n\n/**\n * End-to-end harness: a started {@link Application} without signal handlers, overrides applied last\n * and only what the tested entry points need instantiated.\n *\n * ```ts\n * await using app = await TestApp.create({\n * metadata: __ZNIGHT_METADATA__,\n * plugins: [HttpPlugin.configure({ adapter: fastify() })],\n * overrides: [[UserRepository, fakeRepository]],\n * })\n * const response = await app.inject({ method: 'GET', url: '/users/1' })\n * expect(response.status).toBe(200)\n * expect(response.json()).toEqual({ id: '1' })\n * ```\n */\nexport class TestApp implements AsyncDisposable {\n /** The application under test. */\n readonly app: Application\n #closed = false\n\n private constructor(app: Application) {\n this.app = app\n }\n\n /**\n * Creates and (by default) starts the application.\n *\n * Plugins are used as configured: give the servers they start a free port or none in tests\n * (`HttpPlugin.configure({ port: 0 })`, `ObservabilityPlugin.configure({ metrics: { server: false } })`);\n * a start failing on a port already in use (`EADDRINUSE`) gets a hint saying so.\n *\n * @throws the error of `Application.create()` / `app.start()` (everything is rolled back).\n */\n static async create(options: TestAppOptions): Promise<TestApp> {\n if (options === null || typeof options !== 'object') {\n throw new TypeError('[znight] TestApp.create({ metadata }) requires options with the generated metadata')\n }\n const index = new MetadataIndex(options.metadata)\n const providers = resolveKeys(options.providers, index)\n const overrides = resolveKeys(options.overrides, index)\n const init = initOptions(options, index, overrides)\n try {\n const app = await Application.create({\n metadata: options.metadata,\n plugins: options.plugins ?? [],\n ...(providers === undefined ? {} : { providers }),\n ...(overrides === undefined ? {} : { overrides }),\n logger: options.logger ?? createConsoleLogger({ level: 'warn' }),\n shutdown: { ...options.shutdown, signals: false },\n init,\n })\n if (options.start !== false) await app.start()\n return new TestApp(app)\n } catch (error) {\n addHints(error, init.only !== undefined)\n throw error\n }\n }\n\n /** The application container. */\n get container(): Container {\n return this.app.container\n }\n\n /** Shortcut for `app.container.get(key)`. */\n get<T>(key: ProviderClass<T>): T\n get<T>(key: ClassKey<T>): T\n get<T = unknown>(key: TypedToken<T>): T\n get(key: ProviderKey): unknown {\n return this.app.container.get(key as TypedToken<unknown>)\n }\n\n /**\n * Dispatches a request in memory through the HTTP plugin (`HttpPlugin`): routing, guards,\n * interceptors, validation, serialisation, without opening a socket. Send uploads as a\n * `FormData` body; read downloads from `response.bytes`. Send cookies with `cookies` (and\n * `signedCookies`), read those the response sets from `response.cookies`.\n *\n * @throws ZnightError ZNIGHT001 when the application has no HTTP plugin, ZNIGHT021 once closed.\n */\n inject(request: InjectRequest): Promise<InjectResponse> {\n try {\n if (this.#closed) {\n throw new ZnightError(ErrorCode.LifecycleFailed, 'TestApp.inject(): the application is closed')\n }\n if (request === null || typeof request !== 'object' || typeof request.url !== 'string') {\n throw new TypeError(\n '[znight] TestApp.inject() expects { method?, url, headers?, body?, query?, cookies?, signedCookies? }',\n )\n }\n const plugin = this.app.getPlugin<Plugin & Partial<HttpInjector>>(HTTP_PLUGIN_NAME)\n if (plugin === undefined || typeof plugin.inject !== 'function') {\n throw new ZnightError(ErrorCode.MissingProvider, 'TestApp.inject() requires the HTTP plugin', {\n hints: ['Add HttpPlugin.configure({ adapter }) from @znight/http to TestApp.create({ plugins })'],\n })\n }\n const method = (request.method ?? 'GET').toUpperCase()\n return Promise.resolve(plugin.inject({ ...request, method })).then(complete)\n } catch (error) {\n return Promise.reject(error)\n }\n }\n\n /**\n * Dispatches a request in memory and resolves at the response headers; the body is read as it is\n * produced (`response.body`). Cancelling the body (or aborting `signal`) disconnects the client.\n *\n * @throws ZnightError ZNIGHT001 when the HTTP plugin does not support streaming, ZNIGHT021 once closed.\n */\n injectStream(request: InjectStreamRequest): Promise<InjectStreamResponse> {\n return this.#stream('injectStream', request)\n }\n\n /**\n * Opens an event stream (Server-Sent Events) in memory and reads it like `EventSource`:\n *\n * ```ts\n * await using stream = await app.injectSse({ url: '/orders/o-1/events' })\n * const event = await stream.next() // rejects after 2 000 ms\n * expect(event.json()).toMatchObject({ status: 'paid' })\n * const resumed = await stream.reconnect() // last-event-id, like EventSource\n * ```\n *\n * Leaving the `await using` block (or `close()`) disconnects: the server sees `ctx.signal` abort.\n *\n * @throws ZnightError ZNIGHT001 when the HTTP plugin does not support event streams, ZNIGHT021 once closed.\n */\n injectSse(request: InjectStreamRequest): Promise<InjectSseResponse> {\n return this.#stream('injectSse', request)\n }\n\n #stream<K extends keyof HttpStreamInjector>(\n method: K,\n request: InjectStreamRequest,\n ): ReturnType<HttpStreamInjector[K]> {\n try {\n if (this.#closed) {\n throw new ZnightError(ErrorCode.LifecycleFailed, `TestApp.${method}(): the application is closed`)\n }\n if (request === null || typeof request !== 'object' || typeof request.url !== 'string') {\n throw new TypeError(\n `[znight] TestApp.${method}() expects { method?, url, headers?, body?, query?, cookies?, signedCookies?, signal? }`,\n )\n }\n const plugin = this.app.getPlugin<Plugin & Partial<HttpStreamInjector>>(HTTP_PLUGIN_NAME)\n const dispatch = plugin?.[method] as\n | ((this: unknown, request: InjectStreamRequest & { readonly method: string }) => unknown)\n | undefined\n if (typeof dispatch !== 'function') {\n throw new ZnightError(\n ErrorCode.MissingProvider,\n `TestApp.${method}() requires the HTTP plugin with streaming support`,\n {\n hints: [\n plugin === undefined\n ? 'Add HttpPlugin.configure({ adapter }) from @znight/http to TestApp.create({ plugins })'\n : `The plugin named 'http' does not implement ${method}(): register HttpPlugin.configure({ adapter }) from @znight/http ≥ 0.1.0 (the same release as @znight/testing)`,\n ],\n },\n )\n }\n const sent = { ...request, method: (request.method ?? 'GET').toUpperCase() }\n return Promise.resolve(dispatch.call(plugin, sent)) as ReturnType<HttpStreamInjector[K]>\n } catch (error) {\n return Promise.reject(error) as ReturnType<HttpStreamInjector[K]>\n }\n }\n\n /** Stops the application (idempotent): plugins `onStop`, providers `onStop` and disposal, plugins `onDispose`. */\n close(): Promise<void> {\n this.#closed = true\n return this.app.stop()\n }\n\n /** {@link close}, for `await using app = await TestApp.create(...)`. */\n [Symbol.asyncDispose](): Promise<void> {\n return this.close()\n }\n}\n\nconst ENCODER = new TextEncoder()\n\nconst NO_COOKIES: Readonly<Record<string, SetCookieInfo>> = Object.freeze({})\n\n/**\n * The plugin response, as is when it is complete; otherwise with `bytes` derived from `body` and\n * no `cookies` when the plugin did not provide them.\n */\nfunction complete(response: HttpInjectResult): InjectResponse {\n const hasBytes = response.bytes instanceof Uint8Array\n const hasCookies = response.cookies !== null && typeof response.cookies === 'object'\n if (hasBytes && hasCookies) return response as InjectResponse\n return {\n status: response.status,\n headers: response.headers,\n body: response.body,\n bytes: hasBytes ? (response.bytes as Uint8Array) : ENCODER.encode(response.body),\n cookies: hasCookies ? (response.cookies as Readonly<Record<string, SetCookieInfo>>) : NO_COOKIES,\n json: <T = unknown>(): T => response.json<T>(),\n }\n}\n\ntype Entries = readonly (readonly [ProviderKey, unknown])[]\n\n/**\n * Materialises `providers`/`overrides` and maps string keys that are not tokens of the metadata to\n * the token they designate (alias or unique display name: `'UserRepository'`), like `TestBed` does.\n * Unknown strings are kept (tokens registered at runtime by plugins); classes are resolved by the\n * container.\n */\nfunction resolveKeys(values: ProviderValues | undefined, index: MetadataIndex): Entries | undefined {\n if (values === undefined) return undefined\n const known = index.knownTokens()\n return entriesOf<ProviderKey, unknown>(values).map(([key, value]): readonly [ProviderKey, unknown] => {\n if (typeof key !== 'string' || known.has(key)) return [key, value]\n return [index.find(key, known) ?? key, value]\n })\n}\n\nfunction initOptions(\n options: TestAppOptions,\n index: MetadataIndex,\n overrides: Entries | undefined,\n): { readonly only?: readonly ProviderKey[] } {\n const only = options.only\n if (only === 'all') return {}\n let roots: readonly ProviderKey[]\n if (only === undefined) {\n const metadata = options.metadata\n roots = [\n ...readHttpRoots(metadata),\n ...readMessagingRoots(metadata),\n ...readScheduleRoots(metadata),\n ...readGraphQLRoots(metadata),\n ].filter(token => index.isProvider(token))\n // plugin roots complete the entry points; they never restrict the boot by themselves\n if (roots.length === 0) return {}\n } else {\n if (!Array.isArray(only)) throw new TypeError(\"[znight] TestApp.create(): only must be 'all' or an array of keys\")\n roots = only\n }\n const extra = (overrides ?? []).map(([key]) => key)\n const plugins = pluginRoots(options.plugins ?? [], { metadata: options.metadata }, index)\n return { only: unique([...roots, ...plugins, ...extra]) }\n}\n\n/**\n * Providers the plugins need at boot (`Plugin.initRoots()`, {@link PluginInitRoots}), as provider\n * tokens of the metadata. Other keys (classes without provider, unknown or ambiguous names) are\n * left to the plugin, which reports them with its own message.\n */\nfunction pluginRoots(plugins: readonly Plugin[], context: PluginRootsContext, index: MetadataIndex): Token[] {\n const providers = new Set(index.providerTokens())\n const roots: Token[] = []\n const frozen: PluginRootsContext = Object.freeze({ metadata: context.metadata })\n for (const plugin of plugins) {\n const initRoots = (plugin as Partial<PluginInitRoots> | null | undefined)?.initRoots\n if (typeof initRoots !== 'function') continue\n const keys: unknown = initRoots.call(plugin, frozen)\n if (!Array.isArray(keys)) {\n throw new TypeError(\n `[znight] TestApp.create(): initRoots() of the plugin \"${String(plugin.name)}\" must return an array of classes or tokens`,\n )\n }\n for (const key of keys) {\n const token = findProvider(key, providers, index)\n if (token !== undefined) roots.push(token)\n }\n }\n return roots\n}\n\nfunction findProvider(key: unknown, providers: ReadonlySet<Token>, index: MetadataIndex): Token | undefined {\n try {\n return index.find(key, providers)\n } catch {\n return undefined // ambiguous display name\n }\n}\n\nconst ONLY_HINT = \"With TestApp: list it in TestApp.create({ only: [...] }) (or pass only: 'all') to create it at boot\"\n\n/** Hint added to start failures caused by a port already in use (`EADDRINUSE`). */\nconst PORT_IN_USE_HINT =\n 'With TestApp, servers need no fixed port (inject() sends requests in memory): configure HttpPlugin with { port: 0 } and ObservabilityPlugin with { metrics: { server: false } } (or server: { port: 0 }) in tests'\n\ninterface ErrorLike {\n readonly code?: unknown\n readonly hints?: unknown\n readonly cause?: unknown\n}\n\n/**\n * Adds TestApp hints to a failed `TestApp.create()`, along the `cause` chain:\n * - the TestApp form of the container hint to \"cannot create on demand: its factory is async\"\n * errors (ZNIGHT015, hint `init({ only })`) of a restricted boot, which `TestApp` exposes as its\n * `only` option;\n * - when a server could not listen because its port is taken (`EADDRINUSE`: a fixed port, such as\n * the default `9464` of the observability metrics server, shared by test files running in\n * parallel or by `znight dev`), the options giving it a free port or none, on the outermost error\n * carrying hints (the `ZnightError` the application wraps plugin failures in).\n */\nfunction addHints(error: unknown, restricted: boolean): void {\n const chain: (object & ErrorLike)[] = []\n let current = error\n while (current !== null && typeof current === 'object' && !chain.includes(current)) {\n chain.push(current)\n current = (current as ErrorLike).cause\n }\n if (restricted) {\n for (const item of chain) {\n if (\n item.code === ErrorCode.InstantiationFailed &&\n Array.isArray(item.hints) &&\n item.hints.some(hint => typeof hint === 'string' && hint.includes('init({ only })'))\n ) {\n addHint(item, ONLY_HINT)\n }\n }\n }\n if (chain.some(item => item.code === 'EADDRINUSE')) {\n const outermost = chain.find(item => Array.isArray(item.hints))\n if (outermost !== undefined) addHint(outermost, PORT_IN_USE_HINT)\n }\n}\n\nfunction addHint(error: object & ErrorLike, hint: string): void {\n const hints = error.hints as readonly unknown[]\n // `hints` is a plain own property of ZnightError; a frozen error is left as is\n if (!hints.includes(hint)) Reflect.set(error, 'hints', [...hints, hint])\n}\n\nfunction unique<T>(values: readonly T[]): T[] {\n return [...new Set(values)]\n}\n","import type { ProviderClass, ProviderKey, Token } from '@znight/core'\nimport type { ConfigClassInfo } from './extensions.ts'\nimport type { MetadataIndex } from './metadata-index.ts'\n\nimport { displayName, ErrorCode, InstantiationError, ZnightError } from '@znight/core'\n\nimport { describeKey, entriesOf } from './utils.ts'\n\n/** Property values of one configuration class (`{ port: 8080 }`). */\nexport type ConfigProperties = Readonly<Record<string, unknown>>\n\n/**\n * Configuration values by configuration class, for `TestBed.create(..., { config })`: a record keyed\n * by token, display name or `@Config` prefix, or `[ConfigClass, values]` pairs.\n *\n * ```ts\n * config: { DatabaseConfig: { host: 'db.test' } }\n * config: { database: { host: 'db.test' } } // @Config('database')\n * config: [[DatabaseConfig, { host: 'db.test' }]]\n * ```\n */\nexport type ConfigValues =\n | Iterable<readonly [ProviderKey, ConfigProperties]>\n | Readonly<Record<string, ConfigProperties>>\n\n/**\n * Resolves {@link ConfigValues} to per-token values, validating class keys and property names.\n *\n * @throws ZnightError ZNIGHT012 for an unknown configuration class or property.\n */\nexport function normalizeConfigValues(\n values: ConfigValues | undefined,\n index: MetadataIndex,\n configs: ReadonlyMap<Token, ConfigClassInfo>,\n): Map<Token, Record<string, unknown>> {\n const result = new Map<Token, Record<string, unknown>>()\n if (values === undefined) return result\n const universe = new Set(configs.keys())\n for (const [key, properties] of entriesOf<ProviderKey, ConfigProperties>(values)) {\n const token = index.find(key, universe) ?? findByPrefix(key, configs)\n if (token === undefined) {\n const available = [...configs.values()].map(describeConfig)\n throw new ZnightError(ErrorCode.InvalidConfig, `config: ${describeKey(key)} is not a configuration class`, {\n hints: [\n available.length === 0\n ? 'The metadata declares no configuration class (extensions.config.configs)'\n : `Configuration classes: ${available.join(', ')}`,\n ],\n })\n }\n const info = configs.get(token) as ConfigClassInfo\n if (properties === null || typeof properties !== 'object') {\n throw new ZnightError(ErrorCode.InvalidConfig, `config: the values of ${displayName(token)} must be an object`)\n }\n const known = new Set(info.fields.map(field => field.property))\n for (const property of Object.keys(properties)) {\n if (!known.has(property)) {\n throw new ZnightError(\n ErrorCode.InvalidConfig,\n `config: ${displayName(token)} has no configuration property \"${property}\"`,\n { hints: [`Properties: ${[...known].join(', ') || '(none)'}`] },\n )\n }\n }\n result.set(token, { ...result.get(token), ...properties })\n }\n return result\n}\n\n/**\n * Builds a real configuration instance like `@znight/config` without any source would:\n * `new ConfigClass()` (field initializers run), then the declared `@Default` values (which win over\n * initializers, as at runtime, converted to the field type, see {@link convertDefault}), then\n * `values` (as given). Required fields without value stay `undefined`.\n */\nexport function buildConfigInstance(\n info: ConfigClassInfo,\n cls: ProviderClass | undefined,\n values: Readonly<Record<string, unknown>> | undefined,\n): object {\n let instance: Record<string, unknown>\n try {\n instance =\n cls === undefined ? {} : (new (cls as unknown as new () => Record<string, unknown>)() as Record<string, unknown>)\n } catch (error) {\n throw new InstantiationError(info.token, [info.token], error)\n }\n for (const field of info.fields) {\n if (values !== undefined && Object.hasOwn(values, field.property)) {\n instance[field.property] = values[field.property]\n } else if (field.hasDefault) {\n instance[field.property] = convertDefault(field.default, field.type)\n }\n }\n return instance\n}\n\nfunction findByPrefix(key: unknown, configs: ReadonlyMap<Token, ConfigClassInfo>): Token | undefined {\n if (typeof key !== 'string') return undefined\n const matches = [...configs.values()].filter(info => info.prefix === key)\n return matches.length === 1 ? matches[0]?.token : undefined\n}\n\nfunction describeConfig(info: ConfigClassInfo): string {\n const name = displayName(info.token)\n return info.prefix === undefined ? name : `${name} (prefix \"${info.prefix}\")`\n}\n\nconst INVALID: unique symbol = Symbol('invalid')\n/** Strict decimal numbers, as accepted by `@znight/config` (`42`, `-1.5`, `1e3`; not `0x10`). */\nconst DECIMAL = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/\nconst TRUE = new Set(['true', '1', 'yes', 'on'])\nconst FALSE = new Set(['false', '0', 'no', 'off'])\n\n/**\n * A declared default converted to the field type the way `@znight/config` converts it at runtime\n * (`loadConfig`), so the instance has the same shape in tests as in the application: `'8080'` → `8080`\n * (`number`), `'yes'` → `true`, `'a, b'` → `['a', 'b']` (lists), an absolute URL string → a `URL`\n * (`url`), a JSON string → its value (`json`). `@znight/testing` does not depend on `@znight/config`,\n * hence this small mirror of its coercion rules. A value that does not convert (the compiler already\n * rejects invalid defaults) or an unknown type is kept as is (copied).\n */\nexport function convertDefault(value: unknown, type: string | undefined): unknown {\n const converted = convert(value, type)\n return converted === INVALID ? copy(value) : converted\n}\n\nfunction convert(value: unknown, type: string | undefined): unknown {\n switch (type) {\n case 'string':\n return toText(value)\n case 'number':\n return toNumber(value)\n case 'boolean':\n return toBoolean(value)\n case 'string[]':\n return toList(value, toText)\n case 'number[]':\n return toList(value, toNumber)\n case 'url':\n return toUrl(value)\n case 'json':\n return toJson(value)\n default:\n return INVALID\n }\n}\n\nfunction toText(value: unknown): unknown {\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value)\n return INVALID\n}\n\nfunction toNumber(value: unknown): unknown {\n if (typeof value === 'number') return Number.isFinite(value) ? value : INVALID\n if (typeof value !== 'string' || !DECIMAL.test(value.trim())) return INVALID\n const number = Number(value.trim())\n return Number.isFinite(number) ? number : INVALID\n}\n\nfunction toBoolean(value: unknown): unknown {\n if (typeof value === 'boolean') return value\n if (value === 1 || value === 0) return value === 1\n if (typeof value !== 'string') return INVALID\n const text = value.trim().toLowerCase()\n if (TRUE.has(text)) return true\n return FALSE.has(text) ? false : INVALID\n}\n\nfunction toList(value: unknown, item: (value: unknown) => unknown): unknown {\n let items: readonly unknown[]\n if (Array.isArray(value)) {\n items = value\n } else if (typeof value === 'string') {\n items = value\n .split(',')\n .map(part => part.trim())\n .filter(part => part !== '')\n } else {\n return INVALID\n }\n const result: unknown[] = []\n for (const entry of items) {\n const converted = item(entry)\n if (converted === INVALID) return INVALID\n result.push(converted)\n }\n return result\n}\n\nfunction toUrl(value: unknown): unknown {\n if (value instanceof URL) return new URL(value.href)\n return typeof value === 'string' && URL.canParse(value.trim()) ? new URL(value.trim()) : INVALID\n}\n\nfunction toJson(value: unknown): unknown {\n if (typeof value !== 'string') return copy(value)\n try {\n return JSON.parse(value) as unknown\n } catch {\n return INVALID\n }\n}\n\n/** Defaults are static values: copy them so that tests never share mutable defaults. */\nfunction copy(value: unknown): unknown {\n if (value === null || typeof value !== 'object') return value\n try {\n return structuredClone(value)\n } catch {\n return value\n }\n}\n","import type { ClassKey, Token, TypedToken } from '@znight/core'\nimport type { MetadataIndex } from './metadata-index.ts'\nimport type { DeepMock, Mocked } from './types.ts'\n\nimport { describeToken, displayName, ErrorCode, ZnightError } from '@znight/core'\n\nimport { clearMock, resetMock } from './mock.ts'\nimport { describeKey } from './utils.ts'\n\n/**\n * The auto-mocks of a `TestBed`, looked up by class, token, alias or display name.\n *\n * ```ts\n * const { instance, mocks } = await TestBed.create(UserService, { metadata })\n * mocks.get(UserRepository).findById.mockResolvedValue(user) // typed\n * mocks.get('Logger').info // untyped deep mock\n * ```\n */\nexport interface MockRegistry {\n /**\n * The auto-mock injected for `key`: a class (typed result), a token, an alias (interface, base\n * class) or a unique display name (`'UserRepository'`).\n *\n * @throws ZnightError ZNIGHT001 when no auto-mock matches (the message says why: provided value,\n * configuration class, optional dependency...), ZNIGHT008 when a display name is ambiguous.\n */\n get<T>(key: ClassKey<T>): Mocked<T>\n get<T = never>(key: TypedToken<T>): [T] extends [never] ? DeepMock : Mocked<T>\n /** Whether an auto-mock matches `key`. */\n has(key: ClassKey | Token): boolean\n /** Tokens of the auto-mocked dependencies, in injection order. */\n tokens(): Token[]\n /** `mockClear()` on every spy of every auto-mock (recorded calls are forgotten). */\n clearAll(): void\n /** Resets every auto-mock to its initial state (calls and programmed behaviours are forgotten). */\n resetAll(): void\n}\n\n/** Why a dependency was not auto-mocked (used in error messages). */\nexport type InjectionKind = 'provided' | 'override' | 'config' | 'optional' | 'interceptor' | 'real'\n\nconst REASONS: Readonly<Record<InjectionKind, string>> = {\n provided: 'its value was passed with `provide`',\n override: 'it was replaced with `overrides`',\n config: 'it is a configuration class (a real instance is injected; set values with `config`)',\n optional: 'it is an optional dependency (`undefined` is injected unless provided)',\n interceptor: 'it is an interceptor (not applied unless `aop: \"real\"`)',\n real: 'it was built for real (aop: \"real\")',\n}\n\n/** Default {@link MockRegistry} implementation (internal). */\nexport class TestMocks implements MockRegistry {\n readonly #mocks: ReadonlyMap<Token, object>\n readonly #others: ReadonlyMap<Token, InjectionKind>\n readonly #index: MetadataIndex\n readonly #owner: Token\n\n constructor(\n mocks: ReadonlyMap<Token, object>,\n others: ReadonlyMap<Token, InjectionKind>,\n index: MetadataIndex,\n owner: Token,\n ) {\n this.#mocks = mocks\n this.#others = others\n this.#index = index\n this.#owner = owner\n }\n\n get<T>(key: ClassKey<T>): Mocked<T>\n get<T = never>(key: TypedToken<T>): [T] extends [never] ? DeepMock : Mocked<T>\n get(key: unknown): unknown {\n const token = this.#index.find(key, new Set(this.#mocks.keys()))\n if (token !== undefined) return this.#mocks.get(token)\n throw this.#notMockedError(key)\n }\n\n has(key: ClassKey | Token): boolean {\n return this.#index.find(key, new Set(this.#mocks.keys())) !== undefined\n }\n\n tokens(): Token[] {\n return [...this.#mocks.keys()]\n }\n\n clearAll(): void {\n for (const mock of this.#mocks.values()) clearMock(mock)\n }\n\n resetAll(): void {\n for (const mock of this.#mocks.values()) resetMock(mock)\n }\n\n #notMockedError(key: unknown): ZnightError {\n const owner = displayName(this.#owner)\n let other: Token | undefined\n try {\n other = this.#index.find(key, new Set(this.#others.keys()))\n } catch {\n other = undefined\n }\n if (other !== undefined) {\n const kind = this.#others.get(other) as InjectionKind\n return new ZnightError(ErrorCode.MissingProvider, `${describeToken(other)} is not mocked: ${REASONS[kind]}`)\n }\n const mocked = [...this.#mocks.keys()].map(displayName)\n return new ZnightError(\n ErrorCode.MissingProvider,\n `No mock for ${describeKey(key)}: it is not a direct dependency of ${owner}`,\n {\n hints: [\n mocked.length === 0 ? `${owner} has no auto-mocked dependency` : `Auto-mocked: ${mocked.join(', ')}`,\n 'TestBed only mocks direct dependencies; regenerate the metadata if the constructor changed',\n ],\n },\n )\n }\n}\n","import type { DependencyRef, ProviderDefinition, ProviderValues, Token, ZnightMetadata } from '@znight/core'\nimport type { ConfigClassInfo } from './extensions.ts'\nimport type { AopMode, TestBedOptions, TestBedResult } from './testbed.ts'\nimport type { MockFnFactory } from './types.ts'\n\nimport {\n applyInterceptors,\n Container,\n describeToken,\n displayName,\n ErrorCode,\n formatPath,\n InstantiationError,\n isProviderDefinition,\n METADATA_VERSION,\n ZnightError,\n} from '@znight/core'\n\nimport { buildConfigInstance, normalizeConfigValues } from './config.ts'\nimport { readConfigClasses } from './extensions.ts'\nimport { MetadataIndex } from './metadata-index.ts'\nimport { mockObject } from './mock.ts'\nimport { resolveMockFn } from './mock-fn.ts'\nimport { type InjectionKind, TestMocks } from './mock-registry.ts'\nimport { describeKey, entriesOf, isThenable } from './utils.ts'\n\nconst AOP_MODES: ReadonlySet<AopMode | undefined> = new Set([undefined, 'none', 'real'])\n\n/**\n * Builds the target of `TestBed.create()`: resolves keys, injects auto-mocks / provided values /\n * configuration instances, runs the factory and assembles the result container. Internal.\n */\nexport class Builder {\n readonly #index: MetadataIndex\n readonly #options: TestBedOptions\n readonly #mockFn: MockFnFactory\n readonly #configs: ReadonlyMap<Token, ConfigClassInfo>\n readonly #configValues: ReadonlyMap<Token, Record<string, unknown>>\n readonly #provided: ReadonlyMap<Token, unknown>\n readonly #overrides: ReadonlyMap<Token, unknown>\n /** Values injected into the target (and into built dependencies), by canonical token. */\n readonly #values = new Map<Token, unknown>()\n /** Real interceptors (aop: 'real'), by canonical token. */\n readonly #interceptors = new Map<Token, unknown>()\n readonly #kinds = new Map<Token, InjectionKind>()\n readonly #mocks = new Map<Token, object>()\n /** Providers being built (cycle guard). */\n readonly #building = new Set<Token>()\n #known: Set<Token> | undefined\n\n constructor(options: TestBedOptions) {\n if (options === null || typeof options !== 'object') {\n throw new TypeError('[znight] TestBed.create(target, { metadata }) requires options with the generated metadata')\n }\n if (!AOP_MODES.has(options.aop)) {\n throw new TypeError(`[znight] TestBed.create(): aop must be 'none' or 'real', got ${String(options.aop)}`)\n }\n this.#options = options\n this.#index = new MetadataIndex(options.metadata)\n this.#mockFn = resolveMockFn(options.mockFn).create\n this.#configs = readConfigClasses(options.metadata)\n this.#configValues = normalizeConfigValues(options.config, this.#index, this.#configs)\n this.#provided = this.#normalize(options.provide, 'provide')\n this.#overrides = this.#normalize(options.overrides, 'overrides')\n }\n\n async build(target: unknown): Promise<TestBedResult<unknown>> {\n const token = this.#resolveTarget(target)\n let definition = this.#index.definition(token) as ProviderDefinition\n if (this.#overrides.has(token)) {\n const replacement = this.#overrides.get(token)\n if (!isProviderDefinition(replacement)) {\n throw new ZnightError(\n ErrorCode.InvalidDecorator,\n `overrides: the target ${displayName(token)} can only be replaced by a provider definition { scope, deps, factory }`,\n )\n }\n definition = replacement\n }\n const instance = await this.#construct(token, definition, [token])\n const container = await this.#createContainer(token, definition, instance)\n const others = new Map(this.#kinds)\n return {\n instance,\n mocks: new TestMocks(this.#mocks, others, this.#index, token),\n container,\n }\n }\n\n // -----------------------------------------------------------------------------------------------\n // Keys\n // -----------------------------------------------------------------------------------------------\n\n #resolveTarget(target: unknown): Token {\n const token = this.#index.find(target, new Set(this.#index.providerTokens()))\n if (token !== undefined) return token\n throw new ZnightError(\n ErrorCode.MissingProvider,\n `TestBed: ${describeKey(target)} is not a provider of the metadata`,\n {\n hints: [\n 'Check that the class is decorated (@Injectable(), @Controller()...) and exported',\n 'Regenerate the metadata before running tests: `znight generate`, the Bun preload `@znight/compiler/bun` or the Vite plugin',\n ],\n },\n )\n }\n\n /** Every token a `provide`/`overrides` key may designate (canonical). */\n #knownTokens(): Set<Token> {\n if (this.#known !== undefined) return this.#known\n const index = this.#index\n const known = new Set<Token>()\n const add = (token: unknown): void => {\n if (typeof token === 'string') known.add(index.canonical(token))\n }\n for (const token of index.providerTokens()) {\n known.add(token)\n for (const ref of (index.definition(token) as ProviderDefinition).deps) {\n for (const dep of tokensOfRef(ref)) add(dep)\n }\n }\n for (const external of index.metadata.externals ?? []) add(external?.token)\n for (const [alias] of index.aliases()) add(alias)\n this.#known = known\n return known\n }\n\n #normalize(values: ProviderValues | undefined, option: 'provide' | 'overrides'): Map<Token, unknown> {\n const result = new Map<Token, unknown>()\n if (values === undefined) return result\n const known = this.#knownTokens()\n for (const [key, value] of entriesOf<unknown, unknown>(values)) {\n const token = this.#index.find(key, known)\n if (token === undefined) {\n throw new ZnightError(\n ErrorCode.MissingProvider,\n `${option}: ${describeKey(key)} matches no provider, external or dependency of the metadata`,\n { hints: ['Use a class, a token, an alias or a unique display name (e.g. \"UserRepository\")'] },\n )\n }\n if (result.has(token)) {\n throw new ZnightError(ErrorCode.DuplicateProvider, `${option}: several values for ${describeToken(token)}`)\n }\n result.set(token, value)\n }\n return result\n }\n\n #isExplicit(token: Token): boolean {\n const canonical = this.#index.canonical(token)\n return this.#overrides.has(canonical) || this.#provided.has(canonical)\n }\n\n // -----------------------------------------------------------------------------------------------\n // Construction\n // -----------------------------------------------------------------------------------------------\n\n async #construct(token: Token, definition: ProviderDefinition, path: readonly Token[]): Promise<unknown> {\n if (this.#building.has(token)) {\n throw new ZnightError(ErrorCode.CircularDependency, `Circular dependency: ${formatPath([...path])}`)\n }\n this.#building.add(token)\n try {\n const interceptorDeps = interceptorIndices(definition)\n const deps: unknown[] = new Array(definition.deps.length)\n for (let index = 0; index < definition.deps.length; index++) {\n const ref = definition.deps[index] as DependencyRef\n if (!interceptorDeps.has(index)) deps[index] = await this.#resolve(ref, path)\n else if (this.#options.aop === 'real') deps[index] = await this.#interceptor(ref, path)\n else for (const dep of tokensOfRef(ref)) this.#record(this.#index.canonical(dep), 'interceptor')\n }\n let instance: unknown\n try {\n instance = definition.factory(deps)\n if (isThenable(instance)) instance = await instance\n } catch (error) {\n throw new InstantiationError(token, path, error, definition.source)\n }\n if (this.#options.aop === 'real' && definition.interceptors !== undefined) {\n try {\n applyInterceptors(instance as object, definition.interceptors, deps, displayName(token))\n } catch (error) {\n throw new InstantiationError(token, path, error, definition.source)\n }\n }\n return instance\n } finally {\n this.#building.delete(token)\n }\n }\n\n async #resolve(ref: DependencyRef, path: readonly Token[]): Promise<unknown> {\n if (typeof ref === 'string') return this.#value(ref, path)\n if (ref !== null && typeof ref === 'object') {\n if ('multi' in ref && Array.isArray(ref.multi)) {\n const values: unknown[] = []\n for (const token of ref.multi as readonly Token[]) {\n if (this.#isExplicit(token)) values.push(await this.#value(token, path))\n }\n return values\n }\n if ('lazy' in ref && typeof ref.lazy === 'string') {\n const value = await this.#value(ref.lazy, path)\n return { get: (): unknown => value }\n }\n if ('token' in ref && typeof ref.token === 'string') {\n if (this.#isExplicit(ref.token)) return this.#value(ref.token, path)\n this.#record(this.#index.canonical(ref.token), 'optional')\n return undefined\n }\n }\n throw new ZnightError(\n ErrorCode.InvalidDecorator,\n `Invalid dependency of ${displayName(path[path.length - 1] as Token)}: ${safeJson(ref)}`,\n { hints: ['Expected a token, { token, optional: true }, { multi: [...] } or { lazy: token }'] },\n )\n }\n\n /** The value injected for `token` (cached: the same dependency always gets the same value). */\n async #value(token: Token, path: readonly Token[]): Promise<unknown> {\n const canonical = this.#index.canonical(token)\n if (this.#values.has(canonical)) return this.#values.get(canonical)\n let value: unknown\n if (this.#overrides.has(canonical)) {\n value = await this.#explicit(canonical, this.#overrides.get(canonical), path)\n this.#record(canonical, 'override')\n } else if (this.#provided.has(canonical)) {\n value = this.#provided.get(canonical)\n this.#record(canonical, 'provided')\n } else if (this.#configs.has(canonical)) {\n const info = this.#configs.get(canonical) as ConfigClassInfo\n value = buildConfigInstance(info, this.#index.classOf(canonical), this.#configValues.get(canonical))\n this.#record(canonical, 'config')\n } else {\n value = this.#autoMock(canonical, path)\n }\n this.#values.set(canonical, value)\n return value\n }\n\n /** An override (a value, or a definition built with its dependencies resolved like the target's). */\n #explicit(token: Token, value: unknown, path: readonly Token[]): Promise<unknown> | unknown {\n return isProviderDefinition(value) ? this.#construct(token, value, [...path, token]) : value\n }\n\n #autoMock(token: Token, path: readonly Token[]): object {\n const definition = this.#index.definition(token)\n if (definition !== undefined && definition.class === undefined && definition.name !== undefined) {\n throw qualifiedValueError(token, definition.name, path)\n }\n const mock = mockObject(definition?.class, undefined, {\n name: displayName(token),\n deep: this.#options.deep === true,\n mockFn: this.#mockFn,\n })\n this.#mocks.set(token, mock)\n this.#kinds.delete(token)\n return mock\n }\n\n /** A real interceptor (aop: 'real'): explicit value, or built from its compiled definition. */\n async #interceptor(ref: DependencyRef, path: readonly Token[]): Promise<unknown> {\n if (typeof ref !== 'string') return this.#resolve(ref, path)\n const token = this.#index.canonical(ref)\n if (this.#interceptors.has(token)) return this.#interceptors.get(token)\n let value: unknown\n if (this.#overrides.has(token)) {\n value = await this.#explicit(token, this.#overrides.get(token), path)\n this.#record(token, 'override')\n } else if (this.#provided.has(token)) {\n value = this.#provided.get(token)\n this.#record(token, 'provided')\n } else {\n const definition = this.#index.definition(token)\n if (definition === undefined) {\n const providedBy = this.#index.external(token)?.providedBy\n throw new ZnightError(\n ErrorCode.MissingProvider,\n `aop: 'real' needs the interceptor ${describeToken(token)}, supplied at runtime by ${providedBy ?? 'a plugin'}`,\n { hints: [`Pass an instance: provide: [[${JSON.stringify(token)}, interceptor]]`] },\n )\n }\n value = await this.#construct(token, definition, [...path, token])\n this.#record(token, 'real')\n }\n this.#interceptors.set(token, value)\n return value\n }\n\n #record(token: Token, kind: InjectionKind): void {\n if (!this.#mocks.has(token)) this.#kinds.set(token, kind)\n }\n\n // -----------------------------------------------------------------------------------------------\n // Result container\n // -----------------------------------------------------------------------------------------------\n\n async #createContainer(target: Token, definition: ProviderDefinition, instance: unknown): Promise<Container> {\n const bound = new Map<Token, unknown>([[target, instance]])\n for (const [token, value] of this.#values) if (value !== undefined && !bound.has(token)) bound.set(token, value)\n for (const [token, value] of this.#interceptors) {\n if (value !== undefined && !bound.has(token)) bound.set(token, value)\n }\n const providers = [...bound.keys()].map((token): [Token, ProviderDefinition] => {\n const cls = token === target ? (definition.class ?? this.#index.classOf(token)) : this.#index.classOf(token)\n // placeholder definitions: they register the classes for lookups, the values are bound below\n return [\n token,\n { scope: 'singleton', deps: [], factory: () => undefined, ...(cls === undefined ? {} : { class: cls }) },\n ]\n })\n const aliases: [Token, Token][] = []\n for (const [alias] of this.#index.aliases()) {\n const canonical = this.#index.canonical(alias)\n if (bound.has(canonical) && !bound.has(alias)) aliases.push([alias, canonical])\n }\n const metadata: ZnightMetadata = {\n version: METADATA_VERSION,\n providers: Object.fromEntries(providers),\n resolutionOrder: [...bound.keys()],\n aliases: Object.fromEntries(aliases),\n }\n const container = Container.create(metadata)\n for (const [token, value] of bound) container.provide(token, value)\n await container.init()\n return container\n }\n}\n\n/** Indices of `definition.deps` used only by interceptor chains. */\nfunction interceptorIndices(definition: ProviderDefinition): Set<number> {\n const indices = new Set<number>()\n for (const interception of Object.values(definition.interceptors ?? {})) {\n for (const binding of interception.chain) indices.add(binding.dep)\n }\n return indices\n}\n\nfunction tokensOfRef(ref: DependencyRef): readonly Token[] {\n if (typeof ref === 'string') return [ref]\n if (ref === null || typeof ref !== 'object') return []\n if ('multi' in ref && Array.isArray(ref.multi)) return ref.multi\n if ('lazy' in ref && typeof ref.lazy === 'string') return [ref.lazy]\n if ('token' in ref && typeof ref.token === 'string') return [ref.token]\n return []\n}\n\nfunction qualifiedValueError(token: Token, name: string, path: readonly Token[]): ZnightError {\n const owner = displayName(path[path.length - 1] as Token)\n const key = displayName(token)\n return new ZnightError(\n ErrorCode.MissingProvider,\n `TestBed cannot auto-mock ${describeToken(token)}, the value named \"${name}\" injected into ${owner}: ` +\n 'qualified values may be primitives, provide one',\n { hints: [`TestBed.create(${owner}, { metadata, provide: { ${JSON.stringify(key)}: value } })`] },\n )\n}\n\nfunction safeJson(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n","import type { ClassKey, Container, ProviderClass, ProviderValues, TypedToken, ZnightMetadata } from '@znight/core'\nimport type { ConfigValues } from './config.ts'\nimport type { MockRegistry } from './mock-registry.ts'\nimport type { MockFnOption } from './types.ts'\n\nimport { Builder } from './testbed-builder.ts'\n\n/**\n * How `@Intercept` interceptors of the target are handled:\n * - `'none'` (default): interceptors are neither instantiated nor applied, the target's methods are\n * the plain ones;\n * - `'real'`: interceptors are built (their own dependencies auto-mocked) or taken from\n * `provide`/`overrides`, and applied like the container does.\n */\nexport type AopMode = 'none' | 'real'\n\n/** Options of {@link TestBed.create}. */\nexport interface TestBedOptions {\n /** The generated metadata (`__ZNIGHT_METADATA__`). */\n readonly metadata: ZnightMetadata\n /**\n * Values injected instead of auto-mocks, keyed by class, token, alias or display name. Required\n * for qualified values (`@Inject('dbUrl')`, `@Provides({ name })` without a class) such as\n * primitives; also used for optional dependencies and members of multi dependencies.\n */\n readonly provide?: ProviderValues\n /**\n * Like `provide`, but a value shaped like a provider definition (`{ scope, deps, factory }`) is\n * built with its factory, its own dependencies being resolved like the target's (auto-mocked...).\n * A definition keyed by the target replaces the target's factory. Wins over `provide`.\n */\n readonly overrides?: ProviderValues\n /** Values of configuration classes (real instances are injected for `@Config` classes). */\n readonly config?: ConfigValues\n /** Spy implementation of the auto-mocks. Default: auto-detected. */\n readonly mockFn?: MockFnOption\n /** Auto-mocks return deep mocks from unconfigured methods instead of `undefined`. Default: `false`. */\n readonly deep?: boolean\n /** Interceptors handling, see {@link AopMode}. Default: `'none'`. */\n readonly aop?: AopMode\n}\n\n/** What {@link TestBed.create} returns. */\nexport interface TestBedResult<T> {\n /** The target, built with its real (generated) factory. */\n readonly instance: T\n /** The auto-mocks injected into the target. */\n readonly mocks: MockRegistry\n /**\n * A container holding the target and everything injected into it (auto-mocks, provided values,\n * configuration instances), for code that resolves dependencies itself.\n */\n readonly container: Container\n}\n\n/**\n * Unit-test harness: builds one provider with its real factory and auto-mocks its **direct**\n * dependencies, by kind:\n *\n * | Dependency | Injected |\n * | -------------------------------------------- | --------------------------------------------------- |\n * | class / interface / `@Provides` / external | deep auto-mock |\n * | configuration class (`@Config`) | real instance: defaults + `config` values |\n * | qualified value (`@Inject('x')`, primitives) | the `provide` value (an error otherwise) |\n * | optional (`@Optional()`, `T \\| undefined`) | `undefined` (or the `provide` value) |\n * | multi (`T[]`) | `[]` (or the provided members) |\n * | `Lazy<T>` | `{ get: () => mock }` |\n * | interceptor (`@Intercept`) | nothing, not applied (unless `aop: 'real'`) |\n *\n * ```ts\n * const { instance, mocks } = await TestBed.create(UserService, { metadata: __ZNIGHT_METADATA__ })\n * mocks.get(UserRepository).findById.mockResolvedValue({ id: '1' })\n * await instance.findById('1')\n * expect(mocks.get(UserRepository).findById).toHaveBeenCalledWith('1')\n * ```\n */\nexport class TestBed {\n private constructor() {\n // static API only\n }\n\n /**\n * Builds `target` (a class, token, alias or display name of a provider of `options.metadata`).\n *\n * @throws ZnightError ZNIGHT001 (unknown target, qualified dependency without value), ZNIGHT012\n * (invalid `config`), ZNIGHT015 (the factory failed).\n */\n static create<T>(target: ProviderClass<T> | ClassKey<T>, options: TestBedOptions): Promise<TestBedResult<T>>\n static create<T = unknown>(target: TypedToken<T>, options: TestBedOptions): Promise<TestBedResult<T>>\n static create(target: unknown, options: TestBedOptions): Promise<TestBedResult<unknown>> {\n try {\n return new Builder(options).build(target)\n } catch (error) {\n return Promise.reject(error)\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@znight/testing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Znight testing utilities: TestBed with auto-mocking and TestApp for end-to-end tests",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ugho STEPHAN",
|
|
@@ -46,6 +46,6 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@znight/core": "0.
|
|
49
|
+
"@znight/core": "0.4.0"
|
|
50
50
|
}
|
|
51
51
|
}
|
package/src/extensions.ts
CHANGED
|
@@ -75,7 +75,7 @@ export function readConfigClasses(metadata: ZnightMetadata): Map<Token, ConfigCl
|
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
77
|
* Tokens an HTTP application needs at boot: controllers (`extensions.http.controllers[].token`) and
|
|
78
|
-
* the guards and
|
|
78
|
+
* the guards, interceptors and parameter resolvers (RFC 0010) they and their routes reference.
|
|
79
79
|
*/
|
|
80
80
|
export function readHttpRoots(metadata: ZnightMetadata): Token[] {
|
|
81
81
|
const roots: Token[] = []
|
|
@@ -84,17 +84,27 @@ export function readHttpRoots(metadata: ZnightMetadata): Token[] {
|
|
|
84
84
|
if (typeof controller['token'] === 'string') roots.push(controller['token'])
|
|
85
85
|
roots.push(...tokensOf(controller['guards']), ...tokensOf(controller['interceptors']))
|
|
86
86
|
for (const route of arrayOf(controller['routes'])) {
|
|
87
|
-
if (isRecord(route))
|
|
87
|
+
if (isRecord(route)) {
|
|
88
|
+
roots.push(
|
|
89
|
+
...tokensOf(route['guards']),
|
|
90
|
+
...tokensOf(route['interceptors']),
|
|
91
|
+
...tokensOf(route['paramResolvers']),
|
|
92
|
+
)
|
|
93
|
+
}
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
96
|
return roots
|
|
91
97
|
}
|
|
92
98
|
|
|
93
|
-
/** Message consumers (`extensions.messaging.consumers[].token`). */
|
|
99
|
+
/** Message consumers (`extensions.messaging.consumers[].token`) and their parameter resolvers (RFC 0010). */
|
|
94
100
|
export function readMessagingRoots(metadata: ZnightMetadata): Token[] {
|
|
95
101
|
const roots: Token[] = []
|
|
96
102
|
for (const consumer of arrayOf(extension(metadata, 'messaging')?.['consumers'])) {
|
|
97
|
-
if (isRecord(consumer)
|
|
103
|
+
if (!isRecord(consumer)) continue
|
|
104
|
+
if (typeof consumer['token'] === 'string') roots.push(consumer['token'])
|
|
105
|
+
for (const handler of arrayOf(consumer['handlers'])) {
|
|
106
|
+
if (isRecord(handler)) roots.push(...tokensOf(handler['paramResolvers']))
|
|
107
|
+
}
|
|
98
108
|
}
|
|
99
109
|
return roots
|
|
100
110
|
}
|
|
@@ -111,7 +121,7 @@ export function readScheduleRoots(metadata: ZnightMetadata): Token[] {
|
|
|
111
121
|
/**
|
|
112
122
|
* Tokens a GraphQL application needs at boot (`extensions.graphql`, RFC 0005 §7.1): for every field
|
|
113
123
|
* of an object type bound to a resolver (`types[kind: 'object'].fields[].resolver`), the resolver
|
|
114
|
-
* token, its guard tokens
|
|
124
|
+
* token, its guard tokens, the loader tokens its method injects and its parameter resolvers (RFC 0010).
|
|
115
125
|
*/
|
|
116
126
|
export function readGraphQLRoots(metadata: ZnightMetadata): Token[] {
|
|
117
127
|
const roots: Token[] = []
|
|
@@ -121,7 +131,11 @@ export function readGraphQLRoots(metadata: ZnightMetadata): Token[] {
|
|
|
121
131
|
const resolver = isRecord(field) ? field['resolver'] : undefined
|
|
122
132
|
if (!isRecord(resolver)) continue
|
|
123
133
|
if (typeof resolver['token'] === 'string') roots.push(resolver['token'])
|
|
124
|
-
roots.push(
|
|
134
|
+
roots.push(
|
|
135
|
+
...tokensOf(resolver['guards']),
|
|
136
|
+
...tokensOf(resolver['loaders']),
|
|
137
|
+
...tokensOf(resolver['paramResolvers']),
|
|
138
|
+
)
|
|
125
139
|
}
|
|
126
140
|
}
|
|
127
141
|
return roots
|