@navios/core 0.8.0 → 0.9.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/CHANGELOG.md +47 -0
- package/lib/{index-BDNl7j1G.d.cts → index-D9MNh6Tx.d.mts} +36 -13
- package/lib/index-D9MNh6Tx.d.mts.map +1 -0
- package/lib/{index-BoP0cWT6.d.mts → index-Db1d3cwD.d.cts} +36 -13
- package/lib/index-Db1d3cwD.d.cts.map +1 -0
- package/lib/index.cjs +2 -2
- package/lib/index.d.cts +2 -2
- package/lib/index.d.mts +2 -2
- package/lib/index.mjs +2 -2
- package/lib/legacy-compat/index.cjs +1 -1
- package/lib/legacy-compat/index.cjs.map +1 -1
- package/lib/legacy-compat/index.d.cts +3 -3
- package/lib/legacy-compat/index.d.cts.map +1 -1
- package/lib/legacy-compat/index.d.mts +3 -3
- package/lib/legacy-compat/index.d.mts.map +1 -1
- package/lib/legacy-compat/index.mjs +1 -1
- package/lib/legacy-compat/index.mjs.map +1 -1
- package/lib/{src-B6eISODM.cjs → src-BRPtJ9fG.cjs} +12 -9
- package/lib/src-BRPtJ9fG.cjs.map +1 -0
- package/lib/{src-gBAChVRL.mjs → src-Bo23RIo-.mjs} +13 -10
- package/lib/src-Bo23RIo-.mjs.map +1 -0
- package/lib/testing/index.cjs +346 -29
- package/lib/testing/index.cjs.map +1 -1
- package/lib/testing/index.d.cts +299 -63
- package/lib/testing/index.d.cts.map +1 -1
- package/lib/testing/index.d.mts +299 -63
- package/lib/testing/index.d.mts.map +1 -1
- package/lib/testing/index.mjs +347 -31
- package/lib/testing/index.mjs.map +1 -1
- package/lib/{use-guards.decorator-COR-9mZY.cjs → use-guards.decorator-Bs8oDHOi.cjs} +13 -9
- package/lib/use-guards.decorator-Bs8oDHOi.cjs.map +1 -0
- package/lib/{use-guards.decorator-CUww54Nt.mjs → use-guards.decorator-CzVXuLkz.mjs} +12 -8
- package/lib/use-guards.decorator-CzVXuLkz.mjs.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/controller-resolver.spec.mts +19 -13
- package/src/__tests__/testing-module.spec.mts +459 -0
- package/src/__tests__/unit-testing-module.spec.mts +424 -0
- package/src/decorators/controller.decorator.mts +19 -2
- package/src/decorators/module.decorator.mts +23 -5
- package/src/legacy-compat/__type-tests__/legacy-decorators.spec-d.mts +2 -6
- package/src/legacy-compat/decorators/multipart.decorator.mts +4 -4
- package/src/legacy-compat/decorators/stream.decorator.mts +4 -4
- package/src/navios.application.mts +9 -9
- package/src/navios.environment.mts +3 -1
- package/src/navios.factory.mts +9 -27
- package/src/services/instance-resolver.service.mts +8 -7
- package/src/services/module-loader.service.mts +3 -2
- package/src/testing/index.mts +1 -0
- package/src/testing/testing-module.mts +255 -93
- package/src/testing/unit-testing-module.mts +298 -0
- package/lib/index-BDNl7j1G.d.cts.map +0 -1
- package/lib/index-BoP0cWT6.d.mts.map +0 -1
- package/lib/src-B6eISODM.cjs.map +0 -1
- package/lib/src-gBAChVRL.mjs.map +0 -1
- package/lib/use-guards.decorator-COR-9mZY.cjs.map +0 -1
- package/lib/use-guards.decorator-CUww54Nt.mjs.map +0 -1
package/src/navios.factory.mts
CHANGED
|
@@ -4,13 +4,10 @@ import type {
|
|
|
4
4
|
InjectionToken,
|
|
5
5
|
} from '@navios/di'
|
|
6
6
|
|
|
7
|
-
import { Container
|
|
7
|
+
import { Container } from '@navios/di'
|
|
8
8
|
|
|
9
9
|
import type { NaviosModule } from './interfaces/index.mjs'
|
|
10
|
-
import type {
|
|
11
|
-
NaviosApplicationContextOptions,
|
|
12
|
-
NaviosApplicationOptions,
|
|
13
|
-
} from './navios.application.mjs'
|
|
10
|
+
import type { NaviosApplicationOptions } from './navios.application.mjs'
|
|
14
11
|
|
|
15
12
|
import { ConsoleLogger, isNil, LoggerOutput } from './logger/index.mjs'
|
|
16
13
|
import { NaviosApplication } from './navios.application.mjs'
|
|
@@ -83,7 +80,7 @@ export class NaviosFactory {
|
|
|
83
80
|
adapter: [],
|
|
84
81
|
},
|
|
85
82
|
) {
|
|
86
|
-
const container = options.container ?? new Container()
|
|
83
|
+
const container = options.container ?? new Container(options.registry)
|
|
87
84
|
|
|
88
85
|
// Set request ID flag early, before any adapters are registered
|
|
89
86
|
if (options.enableRequestId === true) {
|
|
@@ -91,15 +88,7 @@ export class NaviosFactory {
|
|
|
91
88
|
}
|
|
92
89
|
|
|
93
90
|
// Store options in container for DI access by adapters
|
|
94
|
-
container
|
|
95
|
-
.getServiceLocator()
|
|
96
|
-
.getManager()
|
|
97
|
-
.storeCreatedHolder(
|
|
98
|
-
NaviosOptionsToken.toString(),
|
|
99
|
-
options,
|
|
100
|
-
InjectableType.Class,
|
|
101
|
-
InjectableScope.Singleton,
|
|
102
|
-
)
|
|
91
|
+
container.addInstance(NaviosOptionsToken, options)
|
|
103
92
|
|
|
104
93
|
await this.registerLoggerConfiguration(container, options)
|
|
105
94
|
const adapters = Array.isArray(options.adapter)
|
|
@@ -128,28 +117,21 @@ export class NaviosFactory {
|
|
|
128
117
|
|
|
129
118
|
private static async registerLoggerConfiguration(
|
|
130
119
|
container: Container,
|
|
131
|
-
options:
|
|
120
|
+
options: NaviosApplicationOptions,
|
|
132
121
|
) {
|
|
133
122
|
const { logger } = options
|
|
134
|
-
if (Array.isArray(logger) || isNil(logger)) {
|
|
123
|
+
if (Array.isArray(logger) || isNil(logger) || options.enableRequestId) {
|
|
135
124
|
const loggerInstance = (await container.get(
|
|
136
125
|
LoggerOutput,
|
|
137
126
|
)) as ConsoleLogger
|
|
138
127
|
loggerInstance?.setup({
|
|
139
|
-
logLevels: logger,
|
|
128
|
+
logLevels: Array.isArray(logger) ? logger : undefined,
|
|
129
|
+
requestId: options.enableRequestId ?? false,
|
|
140
130
|
})
|
|
141
131
|
return
|
|
142
132
|
}
|
|
143
133
|
if ((logger as boolean) !== true && !isNil(logger)) {
|
|
144
|
-
container
|
|
145
|
-
.getServiceLocator()
|
|
146
|
-
.getManager()
|
|
147
|
-
.storeCreatedHolder(
|
|
148
|
-
LoggerOutput.toString(),
|
|
149
|
-
logger,
|
|
150
|
-
InjectableType.Class,
|
|
151
|
-
InjectableScope.Singleton,
|
|
152
|
-
)
|
|
134
|
+
container.addInstance(LoggerOutput, logger)
|
|
153
135
|
}
|
|
154
136
|
}
|
|
155
137
|
}
|
|
@@ -110,16 +110,13 @@ export class InstanceResolverService {
|
|
|
110
110
|
// Class has request-scoped dependencies, update its scope to Request
|
|
111
111
|
// so it will be resolved per-request from the scoped container
|
|
112
112
|
const token = getInjectableToken(classType)
|
|
113
|
-
this.container
|
|
114
|
-
.getRegistry()
|
|
115
|
-
.updateScope(token, InjectableScope.Request)
|
|
113
|
+
this.container.getRegistry().updateScope(token, InjectableScope.Request)
|
|
116
114
|
}
|
|
117
115
|
|
|
118
116
|
return {
|
|
119
117
|
cached: cachedInstance !== null,
|
|
120
118
|
instance: cachedInstance,
|
|
121
|
-
resolve: (scoped: ScopedContainer) =>
|
|
122
|
-
scoped.get(classType) as Promise<T>,
|
|
119
|
+
resolve: (scoped: ScopedContainer) => scoped.get(classType) as Promise<T>,
|
|
123
120
|
}
|
|
124
121
|
}
|
|
125
122
|
|
|
@@ -133,7 +130,9 @@ export class InstanceResolverService {
|
|
|
133
130
|
* @param classTypes - The classes to resolve
|
|
134
131
|
* @returns A resolution result containing either all cached instances or resolver function
|
|
135
132
|
*/
|
|
136
|
-
async resolveMany<T>(
|
|
133
|
+
async resolveMany<T>(
|
|
134
|
+
classTypes: ClassType[],
|
|
135
|
+
): Promise<MultiInstanceResolution<T>> {
|
|
137
136
|
if (classTypes.length === 0) {
|
|
138
137
|
return {
|
|
139
138
|
cached: true,
|
|
@@ -170,7 +169,9 @@ export class InstanceResolverService {
|
|
|
170
169
|
instances: cachedInstances,
|
|
171
170
|
classTypes,
|
|
172
171
|
resolve: (scoped: ScopedContainer) =>
|
|
173
|
-
Promise.all(
|
|
172
|
+
Promise.all(
|
|
173
|
+
classTypes.map((classType) => scoped.get(classType) as Promise<T>),
|
|
174
|
+
),
|
|
174
175
|
}
|
|
175
176
|
}
|
|
176
177
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ClassType, ClassTypeWithInstance } from '@navios/di'
|
|
2
2
|
|
|
3
|
-
import { Container, inject, Injectable } from '@navios/di'
|
|
3
|
+
import { Container, getInjectableToken, inject, Injectable } from '@navios/di'
|
|
4
4
|
|
|
5
5
|
import type { NaviosModule } from '../interfaces/index.mjs'
|
|
6
6
|
import type { ModuleMetadata } from '../metadata/index.mjs'
|
|
@@ -135,7 +135,8 @@ export class ModuleLoaderService {
|
|
|
135
135
|
if (parentMetadata) {
|
|
136
136
|
this.mergeMetadata(metadata, parentMetadata)
|
|
137
137
|
}
|
|
138
|
-
const
|
|
138
|
+
const moduleToken = getInjectableToken(module)
|
|
139
|
+
const moduleName = moduleToken.id
|
|
139
140
|
if (this.modulesMetadata.has(moduleName)) {
|
|
140
141
|
return
|
|
141
142
|
}
|
package/src/testing/index.mts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type {
|
|
2
|
+
ClassType,
|
|
3
|
+
ClassTypeWithInstance,
|
|
4
|
+
InjectionToken,
|
|
5
|
+
ScopedContainer,
|
|
6
|
+
} from '@navios/di'
|
|
4
7
|
|
|
5
8
|
import { TestContainer } from '@navios/di/testing'
|
|
6
9
|
|
|
10
|
+
import type { NaviosModule } from '../interfaces/index.mjs'
|
|
11
|
+
import type { NaviosApplicationOptions } from '../navios.application.mjs'
|
|
12
|
+
|
|
7
13
|
import { NaviosApplication } from '../navios.application.mjs'
|
|
8
14
|
import { NaviosFactory } from '../navios.factory.mjs'
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* Configuration for overriding a provider in the testing module.
|
|
12
|
-
*
|
|
18
|
+
*
|
|
13
19
|
* @typeParam T - The type of the provider being overridden
|
|
14
20
|
*/
|
|
15
21
|
export interface TestingModuleOverride<T = any> {
|
|
@@ -29,68 +35,139 @@ export interface TestingModuleOverride<T = any> {
|
|
|
29
35
|
|
|
30
36
|
/**
|
|
31
37
|
* Options for creating a testing module.
|
|
32
|
-
*
|
|
38
|
+
*
|
|
33
39
|
* Extends NaviosApplicationOptions but excludes the container option,
|
|
34
40
|
* as TestingModule manages its own TestContainer.
|
|
35
41
|
*/
|
|
36
|
-
export interface TestingModuleOptions
|
|
37
|
-
|
|
42
|
+
export interface TestingModuleOptions extends Omit<
|
|
43
|
+
NaviosApplicationOptions,
|
|
44
|
+
'container'
|
|
45
|
+
> {
|
|
38
46
|
/**
|
|
39
47
|
* Initial provider overrides to apply when creating the testing module.
|
|
40
|
-
*
|
|
48
|
+
*
|
|
41
49
|
* You can also use `overrideProvider()` method for a fluent API.
|
|
42
50
|
*/
|
|
43
51
|
overrides?: TestingModuleOverride[]
|
|
52
|
+
/**
|
|
53
|
+
* Container to use for the testing module.
|
|
54
|
+
* If not provided, a new TestContainer will be created.
|
|
55
|
+
*/
|
|
56
|
+
container?: TestContainer
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
/**
|
|
47
60
|
* A testing-optimized wrapper around NaviosApplication.
|
|
48
61
|
* Provides utilities for setting up test environments with mock dependencies.
|
|
62
|
+
*
|
|
63
|
+
* When `init()` is called, a request scope is automatically started.
|
|
64
|
+
* This means `get()` calls will resolve request-scoped services correctly,
|
|
65
|
+
* simulating a real HTTP request context.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const module = await TestingModule.create(AppModule)
|
|
70
|
+
* .overrideProvider(DatabaseService)
|
|
71
|
+
* .useValue(mockDatabase)
|
|
72
|
+
* .init()
|
|
73
|
+
*
|
|
74
|
+
* const userService = await module.get(UserService)
|
|
75
|
+
* // ... run tests ...
|
|
76
|
+
*
|
|
77
|
+
* await module.close()
|
|
78
|
+
* ```
|
|
49
79
|
*/
|
|
50
80
|
export class TestingModule {
|
|
51
81
|
private app: NaviosApplication | null = null
|
|
82
|
+
private scopedContainer: ScopedContainer | null = null
|
|
83
|
+
private requestId = `test-request-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
52
84
|
|
|
53
|
-
constructor(
|
|
85
|
+
private constructor(
|
|
54
86
|
private readonly appModule: ClassTypeWithInstance<NaviosModule>,
|
|
55
87
|
private readonly container: TestContainer,
|
|
56
88
|
private readonly options: TestingModuleOptions,
|
|
57
89
|
) {}
|
|
58
90
|
|
|
59
91
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
92
|
+
* Creates a new TestingModule for the given app module.
|
|
93
|
+
* This is the main entry point for setting up integration tests.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const module = await TestingModule.create(AppModule)
|
|
98
|
+
* .overrideProvider(DatabaseService)
|
|
99
|
+
* .useValue(mockDatabase)
|
|
100
|
+
* .init()
|
|
101
|
+
* ```
|
|
62
102
|
*/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
103
|
+
static create(
|
|
104
|
+
appModule: ClassTypeWithInstance<NaviosModule>,
|
|
105
|
+
options: TestingModuleOptions = { adapter: [] },
|
|
106
|
+
): TestingModule {
|
|
107
|
+
const container =
|
|
108
|
+
options.container ??
|
|
109
|
+
new TestContainer({
|
|
110
|
+
parentRegistry: options.registry,
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// Apply initial overrides if provided
|
|
114
|
+
if (options.overrides) {
|
|
115
|
+
for (const override of options.overrides) {
|
|
116
|
+
if (override.useValue !== undefined) {
|
|
117
|
+
container.bind(override.token as any).toValue(override.useValue)
|
|
118
|
+
} else if (override.useClass) {
|
|
119
|
+
container.bind(override.token as any).toClass(override.useClass)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return new TestingModule(appModule, container, options)
|
|
69
125
|
}
|
|
70
126
|
|
|
71
127
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
128
|
+
* Compiles the testing module without initializing it.
|
|
129
|
+
* Call this if you need to access the app before initialization.
|
|
130
|
+
*
|
|
131
|
+
* @returns this for chaining
|
|
74
132
|
*/
|
|
75
|
-
async
|
|
133
|
+
async compile(): Promise<this> {
|
|
76
134
|
if (!this.app) {
|
|
77
|
-
await this.
|
|
135
|
+
this.app = await NaviosFactory.create(this.appModule, {
|
|
136
|
+
...this.options,
|
|
137
|
+
container: this.container,
|
|
138
|
+
})
|
|
78
139
|
}
|
|
79
|
-
|
|
80
|
-
return this.app!
|
|
140
|
+
return this
|
|
81
141
|
}
|
|
82
142
|
|
|
83
143
|
/**
|
|
84
|
-
*
|
|
144
|
+
* Initializes the application and starts a request scope.
|
|
145
|
+
*
|
|
146
|
+
* This is equivalent to calling `compile()` followed by `app.init()`,
|
|
147
|
+
* plus starting a request context for proper request-scoped service resolution.
|
|
148
|
+
*
|
|
149
|
+
* @returns this for chaining
|
|
85
150
|
*/
|
|
86
|
-
|
|
87
|
-
|
|
151
|
+
async init(): Promise<this> {
|
|
152
|
+
if (!this.app) {
|
|
153
|
+
await this.compile()
|
|
154
|
+
}
|
|
155
|
+
await this.app!.init()
|
|
156
|
+
|
|
157
|
+
// Begin a request scope so get() can resolve request-scoped services
|
|
158
|
+
this.scopedContainer = this.container.beginRequest(this.requestId, {
|
|
159
|
+
testingModule: true,
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
return this
|
|
88
163
|
}
|
|
89
164
|
|
|
90
165
|
/**
|
|
91
|
-
* Gets the compiled application.
|
|
166
|
+
* Gets the compiled application.
|
|
167
|
+
*
|
|
168
|
+
* @throws Error if the module has not been compiled yet
|
|
92
169
|
*/
|
|
93
|
-
|
|
170
|
+
getApp(): NaviosApplication {
|
|
94
171
|
if (!this.app) {
|
|
95
172
|
throw new Error(
|
|
96
173
|
'TestingModule not compiled. Call compile() or init() first.',
|
|
@@ -100,7 +177,28 @@ export class TestingModule {
|
|
|
100
177
|
}
|
|
101
178
|
|
|
102
179
|
/**
|
|
103
|
-
*
|
|
180
|
+
* Gets the underlying TestContainer for direct manipulation.
|
|
181
|
+
*/
|
|
182
|
+
getContainer(): TestContainer {
|
|
183
|
+
return this.container
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Gets the scoped container for the current test request.
|
|
188
|
+
* Only available after calling `init()`.
|
|
189
|
+
*
|
|
190
|
+
* @throws Error if init() has not been called
|
|
191
|
+
*/
|
|
192
|
+
getScopedContainer(): ScopedContainer {
|
|
193
|
+
if (!this.scopedContainer) {
|
|
194
|
+
throw new Error('No scoped container available. Call init() first.')
|
|
195
|
+
}
|
|
196
|
+
return this.scopedContainer
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Override a provider with a mock value or class.
|
|
201
|
+
* Must be called before `compile()` or `init()`.
|
|
104
202
|
*/
|
|
105
203
|
overrideProvider<T>(token: ClassType | InjectionToken<T, any>): {
|
|
106
204
|
useValue: (value: T) => TestingModule
|
|
@@ -120,112 +218,176 @@ export class TestingModule {
|
|
|
120
218
|
|
|
121
219
|
/**
|
|
122
220
|
* Gets an instance from the container.
|
|
221
|
+
*
|
|
222
|
+
* If `init()` has been called, this uses the scoped container
|
|
223
|
+
* which properly resolves request-scoped services.
|
|
224
|
+
*
|
|
225
|
+
* If only `compile()` was called, this uses the root container
|
|
226
|
+
* and request-scoped services will throw.
|
|
123
227
|
*/
|
|
124
|
-
async get<T>(
|
|
228
|
+
async get<T>(
|
|
229
|
+
token: ClassTypeWithInstance<T> | InjectionToken<T, any>,
|
|
230
|
+
): Promise<T> {
|
|
231
|
+
// Use scoped container if available (after init)
|
|
232
|
+
if (this.scopedContainer) {
|
|
233
|
+
return this.scopedContainer.get(token as any)
|
|
234
|
+
}
|
|
235
|
+
// Fall back to root container (after compile only)
|
|
125
236
|
return this.container.get(token as any)
|
|
126
237
|
}
|
|
127
238
|
|
|
128
239
|
/**
|
|
129
|
-
* Disposes the testing module and cleans up resources.
|
|
240
|
+
* Disposes the testing module and cleans up all resources.
|
|
241
|
+
*
|
|
242
|
+
* This will:
|
|
243
|
+
* 1. End the request scope (if started)
|
|
244
|
+
* 2. Close the application (if initialized)
|
|
245
|
+
* 3. Dispose the container
|
|
130
246
|
*/
|
|
131
247
|
async close(): Promise<void> {
|
|
248
|
+
// End the request scope first
|
|
249
|
+
if (this.scopedContainer) {
|
|
250
|
+
await this.scopedContainer.endRequest()
|
|
251
|
+
this.scopedContainer = null
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Close the app
|
|
132
255
|
if (this.app) {
|
|
133
256
|
await this.app.close()
|
|
257
|
+
this.app = null
|
|
134
258
|
}
|
|
259
|
+
|
|
260
|
+
// Dispose the container
|
|
135
261
|
await this.container.dispose()
|
|
136
262
|
}
|
|
137
|
-
}
|
|
138
263
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
*/
|
|
144
|
-
export interface TestingModuleBuilder {
|
|
264
|
+
// ===========================================================================
|
|
265
|
+
// ASSERTION HELPERS (delegated to TestContainer)
|
|
266
|
+
// ===========================================================================
|
|
267
|
+
|
|
145
268
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* @param token - The injection token or class to override
|
|
149
|
-
* @returns An object with `useValue` and `useClass` methods for chaining
|
|
150
|
-
*
|
|
151
|
-
* @example
|
|
152
|
-
* ```typescript
|
|
153
|
-
* const testingModule = await createTestingModule(AppModule)
|
|
154
|
-
* .overrideProvider(DatabaseService)
|
|
155
|
-
* .useValue(mockDatabaseService)
|
|
156
|
-
* .compile()
|
|
157
|
-
* ```
|
|
269
|
+
* Asserts that a service has been resolved at least once.
|
|
158
270
|
*/
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
useClass: (target: ClassType) => TestingModuleBuilder
|
|
271
|
+
expectResolved(token: ClassType | InjectionToken<any, any>): void {
|
|
272
|
+
this.container.expectResolved(token)
|
|
162
273
|
}
|
|
163
274
|
|
|
164
275
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* This creates the application instance but does not initialize it.
|
|
168
|
-
* Call `init()` if you need the application to be fully initialized.
|
|
276
|
+
* Asserts that a service has NOT been resolved.
|
|
169
277
|
*/
|
|
170
|
-
|
|
278
|
+
expectNotResolved(token: ClassType | InjectionToken<any, any>): void {
|
|
279
|
+
this.container.expectNotResolved(token)
|
|
280
|
+
}
|
|
171
281
|
|
|
172
282
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* This is equivalent to calling `compile()` followed by `app.init()`.
|
|
283
|
+
* Asserts that a service is registered as singleton scope.
|
|
176
284
|
*/
|
|
177
|
-
|
|
285
|
+
expectSingleton(token: ClassType | InjectionToken<any, any>): void {
|
|
286
|
+
this.container.expectSingleton(token)
|
|
287
|
+
}
|
|
178
288
|
|
|
179
289
|
/**
|
|
180
|
-
*
|
|
290
|
+
* Asserts that a service is registered as transient scope.
|
|
181
291
|
*/
|
|
182
|
-
|
|
292
|
+
expectTransient(token: ClassType | InjectionToken<any, any>): void {
|
|
293
|
+
this.container.expectTransient(token)
|
|
294
|
+
}
|
|
183
295
|
|
|
184
296
|
/**
|
|
185
|
-
*
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
297
|
+
* Asserts that a service is registered as request scope.
|
|
298
|
+
*/
|
|
299
|
+
expectRequestScoped(token: ClassType | InjectionToken<any, any>): void {
|
|
300
|
+
this.container.expectRequestScoped(token)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Asserts that a method was called on a service.
|
|
305
|
+
* Note: You must use `recordMethodCall()` in your mocks for this to work.
|
|
306
|
+
*/
|
|
307
|
+
expectCalled(
|
|
308
|
+
token: ClassType | InjectionToken<any, any>,
|
|
309
|
+
method: string,
|
|
310
|
+
): void {
|
|
311
|
+
this.container.expectCalled(token, method)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Asserts that a method was called with specific arguments.
|
|
316
|
+
* Note: You must use `recordMethodCall()` in your mocks for this to work.
|
|
317
|
+
*/
|
|
318
|
+
expectCalledWith(
|
|
319
|
+
token: ClassType | InjectionToken<any, any>,
|
|
320
|
+
method: string,
|
|
321
|
+
expectedArgs: unknown[],
|
|
322
|
+
): void {
|
|
323
|
+
this.container.expectCalledWith(token, method, expectedArgs)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Asserts that a method was called a specific number of times.
|
|
328
|
+
* Note: You must use `recordMethodCall()` in your mocks for this to work.
|
|
329
|
+
*/
|
|
330
|
+
expectCallCount(
|
|
331
|
+
token: ClassType | InjectionToken<any, any>,
|
|
332
|
+
method: string,
|
|
333
|
+
count: number,
|
|
334
|
+
): void {
|
|
335
|
+
this.container.expectCallCount(token, method, count)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Records a method call for tracking.
|
|
340
|
+
* Call this from your mock implementations to enable call assertions.
|
|
341
|
+
*/
|
|
342
|
+
recordMethodCall(
|
|
343
|
+
token: ClassType | InjectionToken<any, any>,
|
|
344
|
+
method: string,
|
|
345
|
+
args: unknown[],
|
|
346
|
+
result?: unknown,
|
|
347
|
+
error?: Error,
|
|
348
|
+
): void {
|
|
349
|
+
this.container.recordMethodCall(token, method, args, result, error)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Gets all recorded method calls for a service.
|
|
190
354
|
*/
|
|
191
|
-
|
|
355
|
+
getMethodCalls(token: ClassType | InjectionToken<any, any>) {
|
|
356
|
+
return this.container.getMethodCalls(token)
|
|
357
|
+
}
|
|
192
358
|
|
|
193
359
|
/**
|
|
194
|
-
*
|
|
360
|
+
* Gets the dependency graph for debugging or snapshot testing.
|
|
195
361
|
*/
|
|
196
|
-
|
|
362
|
+
getDependencyGraph() {
|
|
363
|
+
return this.container.getDependencyGraph()
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Gets a simplified dependency graph showing only token relationships.
|
|
368
|
+
*/
|
|
369
|
+
getSimplifiedDependencyGraph() {
|
|
370
|
+
return this.container.getSimplifiedDependencyGraph()
|
|
371
|
+
}
|
|
197
372
|
}
|
|
198
373
|
|
|
199
374
|
/**
|
|
200
375
|
* Creates a testing module for the given app module.
|
|
201
|
-
*
|
|
376
|
+
*
|
|
377
|
+
* @deprecated Use `TestingModule.create()` instead.
|
|
202
378
|
*
|
|
203
379
|
* @example
|
|
204
380
|
* ```typescript
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
* .compile()
|
|
381
|
+
* // Old way (deprecated)
|
|
382
|
+
* const module = createTestingModule(AppModule)
|
|
383
|
+
*
|
|
384
|
+
* // New way
|
|
385
|
+
* const module = TestingModule.create(AppModule)
|
|
211
386
|
* ```
|
|
212
387
|
*/
|
|
213
388
|
export function createTestingModule(
|
|
214
389
|
appModule: ClassTypeWithInstance<NaviosModule>,
|
|
215
390
|
options: TestingModuleOptions = { adapter: [] },
|
|
216
391
|
): TestingModule {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
// Apply initial overrides if provided
|
|
220
|
-
if (options.overrides) {
|
|
221
|
-
for (const override of options.overrides) {
|
|
222
|
-
if (override.useValue !== undefined) {
|
|
223
|
-
container.bind(override.token as any).toValue(override.useValue)
|
|
224
|
-
} else if (override.useClass) {
|
|
225
|
-
container.bind(override.token as any).toClass(override.useClass)
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return new TestingModule(appModule, container, options)
|
|
392
|
+
return TestingModule.create(appModule, options)
|
|
231
393
|
}
|