@fluojs/testing 1.0.0-beta.1 → 1.0.0-beta.2
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/README.ko.md +13 -0
- package/README.md +13 -0
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +29 -11
- package/dist/portability/http-adapter-portability.d.ts +6 -0
- package/dist/portability/http-adapter-portability.d.ts.map +1 -1
- package/dist/portability/http-adapter-portability.js +155 -20
- package/package.json +8 -8
package/README.ko.md
CHANGED
|
@@ -65,6 +65,19 @@ const module = await createTestingModule({ rootModule: AppModule })
|
|
|
65
65
|
.compile();
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
### `overrideModule()` 사용 시 모듈 identity 보존
|
|
69
|
+
|
|
70
|
+
`createTestingModule({ rootModule })`에는 명시적인 루트 모듈이 필요합니다. 그래야 테스트가 프로덕션 bootstrap과 같은 모듈 그래프 형태를 컴파일합니다. `overrideModule(source, replacement)`로 import된 모듈을 교체해도, 컴파일된 testing module은 provider 해석에 replacement import를 사용하면서 원래 `rootModule`과 컴파일된 `modules[].type` identity를 보존합니다. 따라서 diagnostics, graph assertion, module introspection 헬퍼는 테스트 전용 synthetic wrapper 클래스가 아니라 사용자가 작성한 애플리케이션 모듈 클래스에 계속 연결됩니다.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
const module = await createTestingModule({ rootModule: AppModule })
|
|
74
|
+
.overrideModule(StripeModule, FakeStripeModule)
|
|
75
|
+
.compile();
|
|
76
|
+
|
|
77
|
+
expect(module.rootModule).toBe(AppModule);
|
|
78
|
+
expect(module.modules.some((compiledModule) => compiledModule.type === BillingModule)).toBe(true);
|
|
79
|
+
```
|
|
80
|
+
|
|
68
81
|
### HTTP 통합 테스트
|
|
69
82
|
|
|
70
83
|
```typescript
|
package/README.md
CHANGED
|
@@ -63,6 +63,19 @@ const module = await createTestingModule({ rootModule: AppModule })
|
|
|
63
63
|
.compile();
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
### Preserve module identity with `overrideModule()`
|
|
67
|
+
|
|
68
|
+
`createTestingModule({ rootModule })` requires an explicit root module so tests compile the same module graph shape that production bootstrap uses. When `overrideModule(source, replacement)` swaps imported modules, the compiled testing module preserves the original `rootModule` and compiled `modules[].type` identities while using the replacement imports for provider resolution. This keeps diagnostics, graph assertions, and module-introspection helpers tied to the application module classes you authored instead of synthetic test-only wrapper classes.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const module = await createTestingModule({ rootModule: AppModule })
|
|
72
|
+
.overrideModule(StripeModule, FakeStripeModule)
|
|
73
|
+
.compile();
|
|
74
|
+
|
|
75
|
+
expect(module.rootModule).toBe(AppModule);
|
|
76
|
+
expect(module.modules.some((compiledModule) => compiledModule.type === BillingModule)).toBe(true);
|
|
77
|
+
```
|
|
78
|
+
|
|
66
79
|
### Request-level tests with `createTestApp()`
|
|
67
80
|
|
|
68
81
|
```ts
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,SAAS,EAId,KAAK,QAAQ,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAqC,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMrF,OAAO,KAAK,EAA2B,oBAAoB,EAAE,oBAAoB,EAAoB,MAAM,YAAY,CAAC;AAExH;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,UAAU,GAAG,QAAQ,EAAE,CAQzE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,EAAE,CAQ5E;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,EAAE,CAQzE;
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,SAAS,EAId,KAAK,QAAQ,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAqC,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMrF,OAAO,KAAK,EAA2B,oBAAoB,EAAE,oBAAoB,EAAoB,MAAM,YAAY,CAAC;AAExH;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,UAAU,GAAG,QAAQ,EAAE,CAQzE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,EAAE,CAQ5E;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,EAAE,CAQzE;AAubD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,oBAAoB,CAEvF;AAED;;GAEG;AACH,eAAO,MAAM,IAAI;;CAEhB,CAAC"}
|
package/dist/module.js
CHANGED
|
@@ -250,6 +250,7 @@ class DefaultOverrideProviderBuilder {
|
|
|
250
250
|
class DefaultTestingModuleBuilder {
|
|
251
251
|
overrides = [];
|
|
252
252
|
moduleReplacements = new Map();
|
|
253
|
+
originalModuleDefinitions = new Map();
|
|
253
254
|
constructor(options) {
|
|
254
255
|
this.options = options;
|
|
255
256
|
}
|
|
@@ -308,15 +309,22 @@ class DefaultTestingModuleBuilder {
|
|
|
308
309
|
return this.createTestingModuleRef(bootstrapped);
|
|
309
310
|
}
|
|
310
311
|
bootstrapTestingModule() {
|
|
311
|
-
const
|
|
312
|
-
const bootstrapped = bootstrapModule(rootModule, {
|
|
313
|
-
providers: this.options.providers
|
|
314
|
-
});
|
|
312
|
+
const bootstrapped = this.bootstrapWithPatchedModuleImports();
|
|
315
313
|
if (this.overrides.length > 0) {
|
|
316
314
|
bootstrapped.container.override(...this.overrides);
|
|
317
315
|
}
|
|
318
316
|
return bootstrapped;
|
|
319
317
|
}
|
|
318
|
+
bootstrapWithPatchedModuleImports() {
|
|
319
|
+
try {
|
|
320
|
+
const rootModule = this._applyModuleReplacements(this.options.rootModule);
|
|
321
|
+
return bootstrapModule(rootModule, {
|
|
322
|
+
providers: this.options.providers
|
|
323
|
+
});
|
|
324
|
+
} finally {
|
|
325
|
+
this.restorePatchedModuleImports();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
320
328
|
createTestingModuleRef(bootstrapped) {
|
|
321
329
|
const dispatcher = createTestingDispatcher(bootstrapped);
|
|
322
330
|
const getSync = createSyncResolver(bootstrapped.container);
|
|
@@ -367,17 +375,27 @@ class DefaultTestingModuleBuilder {
|
|
|
367
375
|
if (!hasChange) {
|
|
368
376
|
return module;
|
|
369
377
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
defineModule(patchedModule, {
|
|
373
|
-
...metadata,
|
|
374
|
-
imports: rewrittenImports
|
|
375
|
-
});
|
|
376
|
-
return patchedModule;
|
|
378
|
+
this.patchModuleImports(module, metadata, rewrittenImports);
|
|
379
|
+
return module;
|
|
377
380
|
}
|
|
378
381
|
rewriteModuleImports(imports) {
|
|
379
382
|
return imports.map(moduleImport => this._applyModuleReplacements(moduleImport));
|
|
380
383
|
}
|
|
384
|
+
patchModuleImports(module, metadata, imports) {
|
|
385
|
+
if (!this.originalModuleDefinitions.has(module)) {
|
|
386
|
+
this.originalModuleDefinitions.set(module, metadata);
|
|
387
|
+
}
|
|
388
|
+
defineModule(module, {
|
|
389
|
+
...metadata,
|
|
390
|
+
imports
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
restorePatchedModuleImports() {
|
|
394
|
+
for (const [module, metadata] of this.originalModuleDefinitions) {
|
|
395
|
+
defineModule(module, metadata);
|
|
396
|
+
}
|
|
397
|
+
this.originalModuleDefinitions.clear();
|
|
398
|
+
}
|
|
381
399
|
}
|
|
382
400
|
|
|
383
401
|
/**
|
|
@@ -61,7 +61,13 @@ export declare class HttpAdapterPortabilityHarness<TBootstrapOptions extends obj
|
|
|
61
61
|
assertPreservesMalformedCookieValues(): Promise<void>;
|
|
62
62
|
assertPreservesRawBodyForJsonAndText(): Promise<void>;
|
|
63
63
|
assertExcludesRawBodyForMultipart(): Promise<void>;
|
|
64
|
+
assertDefaultsMultipartTotalLimitToMaxBodySize(): Promise<void>;
|
|
64
65
|
assertSupportsSseStreaming(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Asserts that adapter stream backpressure waiters settle when the response
|
|
68
|
+
* closes before a `drain` event is emitted.
|
|
69
|
+
*/
|
|
70
|
+
assertSettlesStreamDrainWaitOnClose(): Promise<void>;
|
|
65
71
|
assertReportsConfiguredHostInStartupLogs(): Promise<void>;
|
|
66
72
|
assertReportsHttpsStartupUrl(https: {
|
|
67
73
|
cert: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-adapter-portability.d.ts","sourceRoot":"","sources":["../../src/portability/http-adapter-portability.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,gBAAgB;QACxB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;QACvB,OAAO,CAAC,EAAE,UAAU,CAAC;KACtB;CACF;AAED,KAAK,OAAO,GAAG;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,oCAAoC,CACnD,iBAAiB,SAAS,MAAM,EAChC,WAAW,SAAS,MAAM,EAC1B,IAAI,SAAS,OAAO,GAAG,OAAO;IAE9B;;;;;;OAMG;IACH,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjF;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;OAMG;IACH,GAAG,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE;AAuDD;;;;;;;GAOG;AACH,qBAAa,6BAA6B,CACxC,iBAAiB,SAAS,MAAM,EAChC,WAAW,SAAS,MAAM,EAC1B,IAAI,SAAS,OAAO,GAAG,OAAO;IAOlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC;;;;OAIG;gBAC0B,OAAO,EAAE,oCAAoC,CAAC,iBAAiB,EAAE,WAAW,EAAE,IAAI,CAAC;IAEhH;;;OAGG;IACG,oCAAoC,IAAI,OAAO,CAAC,IAAI,CAAC;IA+CrD,oCAAoC,IAAI,OAAO,CAAC,IAAI,CAAC;IA8DrD,iCAAiC,IAAI,OAAO,CAAC,IAAI,CAAC;IA8ClD,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"http-adapter-portability.d.ts","sourceRoot":"","sources":["../../src/portability/http-adapter-portability.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,gBAAgB;QACxB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;QACvB,OAAO,CAAC,EAAE,UAAU,CAAC;KACtB;CACF;AAED,KAAK,OAAO,GAAG;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,oCAAoC,CACnD,iBAAiB,SAAS,MAAM,EAChC,WAAW,SAAS,MAAM,EAC1B,IAAI,SAAS,OAAO,GAAG,OAAO;IAE9B;;;;;;OAMG;IACH,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjF;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;OAMG;IACH,GAAG,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE;AAuDD;;;;;;;GAOG;AACH,qBAAa,6BAA6B,CACxC,iBAAiB,SAAS,MAAM,EAChC,WAAW,SAAS,MAAM,EAC1B,IAAI,SAAS,OAAO,GAAG,OAAO;IAOlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC;;;;OAIG;gBAC0B,OAAO,EAAE,oCAAoC,CAAC,iBAAiB,EAAE,WAAW,EAAE,IAAI,CAAC;IAEhH;;;OAGG;IACG,oCAAoC,IAAI,OAAO,CAAC,IAAI,CAAC;IA+CrD,oCAAoC,IAAI,OAAO,CAAC,IAAI,CAAC;IA8DrD,iCAAiC,IAAI,OAAO,CAAC,IAAI,CAAC;IA8ClD,8CAA8C,IAAI,OAAO,CAAC,IAAI,CAAC;IAwD/D,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDjD;;;OAGG;IACG,mCAAmC,IAAI,OAAO,CAAC,IAAI,CAAC;IAqDpD,wCAAwC,IAAI,OAAO,CAAC,IAAI,CAAC;IAuDzD,4BAA4B,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAuDjF,8CAA8C,IAAI,OAAO,CAAC,IAAI,CAAC;CA2CtE;AAED;;;;;;;;GAQG;AACH,wBAAgB,mCAAmC,CACjD,iBAAiB,SAAS,MAAM,EAChC,WAAW,SAAS,MAAM,EAC1B,IAAI,SAAS,OAAO,GAAG,OAAO,EAE9B,OAAO,EAAE,oCAAoC,CAAC,iBAAiB,EAAE,WAAW,EAAE,IAAI,CAAC,GAClF,6BAA6B,CAAC,iBAAiB,EAAE,WAAW,EAAE,IAAI,CAAC,CAErE"}
|
|
@@ -272,18 +272,76 @@ export class HttpAdapterPortabilityHarness {
|
|
|
272
272
|
await closeSilently(app);
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
|
-
async
|
|
275
|
+
async assertDefaultsMultipartTotalLimitToMaxBodySize() {
|
|
276
276
|
let _initProto4, _initClass4;
|
|
277
|
+
let _UploadController2;
|
|
278
|
+
class UploadController {
|
|
279
|
+
static {
|
|
280
|
+
({
|
|
281
|
+
e: [_initProto4],
|
|
282
|
+
c: [_UploadController2, _initClass4]
|
|
283
|
+
} = _applyDecs(this, [Controller('/uploads')], [[Post('/'), 2, "upload"]]));
|
|
284
|
+
}
|
|
285
|
+
constructor() {
|
|
286
|
+
_initProto4(this);
|
|
287
|
+
}
|
|
288
|
+
upload(_input, context) {
|
|
289
|
+
return {
|
|
290
|
+
body: context.request.body,
|
|
291
|
+
fileCount: context.request.files?.length ?? 0
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
static {
|
|
295
|
+
_initClass4();
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
class AppModule {}
|
|
299
|
+
defineModule(AppModule, {
|
|
300
|
+
controllers: [_UploadController2]
|
|
301
|
+
});
|
|
302
|
+
const port = await findAvailablePort();
|
|
303
|
+
const app = await this.options.bootstrap(AppModule, {
|
|
304
|
+
cors: false,
|
|
305
|
+
maxBodySize: 8,
|
|
306
|
+
multipart: {
|
|
307
|
+
maxFileSize: 1024
|
|
308
|
+
},
|
|
309
|
+
port
|
|
310
|
+
});
|
|
311
|
+
await app.listen();
|
|
312
|
+
try {
|
|
313
|
+
const form = new FormData();
|
|
314
|
+
form.set('name', 'Ada');
|
|
315
|
+
form.set('payload', new Blob(['12345678'], {
|
|
316
|
+
type: 'text/plain'
|
|
317
|
+
}), 'payload.txt');
|
|
318
|
+
const response = await fetch(`http://127.0.0.1:${String(port)}/uploads`, {
|
|
319
|
+
body: form,
|
|
320
|
+
method: 'POST'
|
|
321
|
+
});
|
|
322
|
+
if (response.status !== 413) {
|
|
323
|
+
throw new Error(`${this.options.name} adapter did not default multipart.maxTotalSize to maxBodySize.`);
|
|
324
|
+
}
|
|
325
|
+
const body = await response.json();
|
|
326
|
+
if (typeof body !== 'object' || body === null || body.error?.code !== 'PAYLOAD_TOO_LARGE') {
|
|
327
|
+
throw new Error(`${this.options.name} adapter changed multipart limit error semantics.`);
|
|
328
|
+
}
|
|
329
|
+
} finally {
|
|
330
|
+
await closeSilently(app);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
async assertSupportsSseStreaming() {
|
|
334
|
+
let _initProto5, _initClass5;
|
|
277
335
|
let _EventsController;
|
|
278
336
|
class EventsController {
|
|
279
337
|
static {
|
|
280
338
|
({
|
|
281
|
-
e: [
|
|
282
|
-
c: [_EventsController,
|
|
339
|
+
e: [_initProto5],
|
|
340
|
+
c: [_EventsController, _initClass5]
|
|
283
341
|
} = _applyDecs(this, [Controller('/events')], [[Get('/'), 2, "stream"]]));
|
|
284
342
|
}
|
|
285
343
|
constructor() {
|
|
286
|
-
|
|
344
|
+
_initProto5(this);
|
|
287
345
|
}
|
|
288
346
|
stream(_input, context) {
|
|
289
347
|
const stream = new SseResponse(context);
|
|
@@ -300,7 +358,7 @@ export class HttpAdapterPortabilityHarness {
|
|
|
300
358
|
return stream;
|
|
301
359
|
}
|
|
302
360
|
static {
|
|
303
|
-
|
|
361
|
+
_initClass5();
|
|
304
362
|
}
|
|
305
363
|
}
|
|
306
364
|
class AppModule {}
|
|
@@ -334,8 +392,72 @@ export class HttpAdapterPortabilityHarness {
|
|
|
334
392
|
await closeSilently(app);
|
|
335
393
|
}
|
|
336
394
|
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Asserts that adapter stream backpressure waiters settle when the response
|
|
398
|
+
* closes before a `drain` event is emitted.
|
|
399
|
+
*/
|
|
400
|
+
async assertSettlesStreamDrainWaitOnClose() {
|
|
401
|
+
let _initProto6, _initClass6;
|
|
402
|
+
const adapterName = this.options.name;
|
|
403
|
+
let resolveDrainWait;
|
|
404
|
+
const drainWaitSettled = new Promise(resolve => {
|
|
405
|
+
resolveDrainWait = resolve;
|
|
406
|
+
});
|
|
407
|
+
let _EventsController2;
|
|
408
|
+
class EventsController {
|
|
409
|
+
static {
|
|
410
|
+
({
|
|
411
|
+
e: [_initProto6],
|
|
412
|
+
c: [_EventsController2, _initClass6]
|
|
413
|
+
} = _applyDecs(this, [Controller('/events')], [[Get('/'), 2, "stream"]]));
|
|
414
|
+
}
|
|
415
|
+
constructor() {
|
|
416
|
+
_initProto6(this);
|
|
417
|
+
}
|
|
418
|
+
async stream(_input, context) {
|
|
419
|
+
const stream = new SseResponse(context);
|
|
420
|
+
const responseStream = context.response.stream;
|
|
421
|
+
if (!responseStream?.waitForDrain) {
|
|
422
|
+
throw new Error(`${adapterName} adapter did not expose response.stream.waitForDrain().`);
|
|
423
|
+
}
|
|
424
|
+
const drainWait = responseStream.waitForDrain();
|
|
425
|
+
stream.close();
|
|
426
|
+
await drainWait;
|
|
427
|
+
resolveDrainWait();
|
|
428
|
+
return stream;
|
|
429
|
+
}
|
|
430
|
+
static {
|
|
431
|
+
_initClass6();
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
class AppModule {}
|
|
435
|
+
defineModule(AppModule, {
|
|
436
|
+
controllers: [_EventsController2]
|
|
437
|
+
});
|
|
438
|
+
const port = await findAvailablePort();
|
|
439
|
+
const app = await this.options.bootstrap(AppModule, {
|
|
440
|
+
cors: false,
|
|
441
|
+
port
|
|
442
|
+
});
|
|
443
|
+
await app.listen();
|
|
444
|
+
try {
|
|
445
|
+
const response = await fetch(`http://127.0.0.1:${String(port)}/events`, {
|
|
446
|
+
headers: {
|
|
447
|
+
accept: 'text/event-stream'
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
if (response.status !== 200) {
|
|
451
|
+
throw new Error(`${this.options.name} adapter changed closed stream response status semantics.`);
|
|
452
|
+
}
|
|
453
|
+
await response.text();
|
|
454
|
+
await withTimeout(drainWaitSettled, 2_000, `${this.options.name} adapter left response.stream.waitForDrain() pending after close.`);
|
|
455
|
+
} finally {
|
|
456
|
+
await closeSilently(app);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
337
459
|
async assertReportsConfiguredHostInStartupLogs() {
|
|
338
|
-
let
|
|
460
|
+
let _initProto7, _initClass7;
|
|
339
461
|
const loggerEvents = [];
|
|
340
462
|
const logger = {
|
|
341
463
|
debug() {},
|
|
@@ -351,12 +473,12 @@ export class HttpAdapterPortabilityHarness {
|
|
|
351
473
|
class HealthController {
|
|
352
474
|
static {
|
|
353
475
|
({
|
|
354
|
-
e: [
|
|
355
|
-
c: [_HealthController,
|
|
476
|
+
e: [_initProto7],
|
|
477
|
+
c: [_HealthController, _initClass7]
|
|
356
478
|
} = _applyDecs(this, [Controller('/health')], [[Get('/'), 2, "getHealth"]]));
|
|
357
479
|
}
|
|
358
480
|
constructor() {
|
|
359
|
-
|
|
481
|
+
_initProto7(this);
|
|
360
482
|
}
|
|
361
483
|
getHealth() {
|
|
362
484
|
return {
|
|
@@ -364,7 +486,7 @@ export class HttpAdapterPortabilityHarness {
|
|
|
364
486
|
};
|
|
365
487
|
}
|
|
366
488
|
static {
|
|
367
|
-
|
|
489
|
+
_initClass7();
|
|
368
490
|
}
|
|
369
491
|
}
|
|
370
492
|
class AppModule {}
|
|
@@ -398,7 +520,7 @@ export class HttpAdapterPortabilityHarness {
|
|
|
398
520
|
}
|
|
399
521
|
}
|
|
400
522
|
async assertReportsHttpsStartupUrl(https) {
|
|
401
|
-
let
|
|
523
|
+
let _initProto8, _initClass8;
|
|
402
524
|
const loggerEvents = [];
|
|
403
525
|
const logger = {
|
|
404
526
|
debug() {},
|
|
@@ -414,12 +536,12 @@ export class HttpAdapterPortabilityHarness {
|
|
|
414
536
|
class HealthController {
|
|
415
537
|
static {
|
|
416
538
|
({
|
|
417
|
-
e: [
|
|
418
|
-
c: [_HealthController2,
|
|
539
|
+
e: [_initProto8],
|
|
540
|
+
c: [_HealthController2, _initClass8]
|
|
419
541
|
} = _applyDecs(this, [Controller('/health')], [[Get('/'), 2, "getHealth"]]));
|
|
420
542
|
}
|
|
421
543
|
constructor() {
|
|
422
|
-
|
|
544
|
+
_initProto8(this);
|
|
423
545
|
}
|
|
424
546
|
getHealth() {
|
|
425
547
|
return {
|
|
@@ -427,7 +549,7 @@ export class HttpAdapterPortabilityHarness {
|
|
|
427
549
|
};
|
|
428
550
|
}
|
|
429
551
|
static {
|
|
430
|
-
|
|
552
|
+
_initClass8();
|
|
431
553
|
}
|
|
432
554
|
}
|
|
433
555
|
class AppModule {}
|
|
@@ -461,7 +583,7 @@ export class HttpAdapterPortabilityHarness {
|
|
|
461
583
|
}
|
|
462
584
|
}
|
|
463
585
|
async assertRemovesShutdownSignalListenersAfterClose() {
|
|
464
|
-
let
|
|
586
|
+
let _initProto9, _initClass9;
|
|
465
587
|
const logger = {
|
|
466
588
|
debug() {},
|
|
467
589
|
error() {},
|
|
@@ -472,12 +594,12 @@ export class HttpAdapterPortabilityHarness {
|
|
|
472
594
|
class HealthController {
|
|
473
595
|
static {
|
|
474
596
|
({
|
|
475
|
-
e: [
|
|
476
|
-
c: [_HealthController3,
|
|
597
|
+
e: [_initProto9],
|
|
598
|
+
c: [_HealthController3, _initClass9]
|
|
477
599
|
} = _applyDecs(this, [Controller('/health')], [[Get('/'), 2, "getHealth"]]));
|
|
478
600
|
}
|
|
479
601
|
constructor() {
|
|
480
|
-
|
|
602
|
+
_initProto9(this);
|
|
481
603
|
}
|
|
482
604
|
getHealth() {
|
|
483
605
|
return {
|
|
@@ -485,7 +607,7 @@ export class HttpAdapterPortabilityHarness {
|
|
|
485
607
|
};
|
|
486
608
|
}
|
|
487
609
|
static {
|
|
488
|
-
|
|
610
|
+
_initClass9();
|
|
489
611
|
}
|
|
490
612
|
}
|
|
491
613
|
class AppModule {}
|
|
@@ -525,4 +647,17 @@ export class HttpAdapterPortabilityHarness {
|
|
|
525
647
|
*/
|
|
526
648
|
export function createHttpAdapterPortabilityHarness(options) {
|
|
527
649
|
return new HttpAdapterPortabilityHarness(options);
|
|
650
|
+
}
|
|
651
|
+
function withTimeout(promise, timeoutMs, message) {
|
|
652
|
+
let timeout;
|
|
653
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
654
|
+
timeout = setTimeout(() => {
|
|
655
|
+
reject(new Error(message));
|
|
656
|
+
}, timeoutMs);
|
|
657
|
+
});
|
|
658
|
+
return Promise.race([promise, timeoutPromise]).finally(() => {
|
|
659
|
+
if (timeout !== undefined) {
|
|
660
|
+
clearTimeout(timeout);
|
|
661
|
+
}
|
|
662
|
+
});
|
|
528
663
|
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"override",
|
|
10
10
|
"module-builder"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.0.0-beta.
|
|
12
|
+
"version": "1.0.0-beta.2",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -76,11 +76,11 @@
|
|
|
76
76
|
"dist"
|
|
77
77
|
],
|
|
78
78
|
"dependencies": {
|
|
79
|
-
"@fluojs/
|
|
80
|
-
"@fluojs/core": "^1.0.0-beta.1",
|
|
79
|
+
"@fluojs/config": "^1.0.0-beta.2",
|
|
81
80
|
"@fluojs/http": "^1.0.0-beta.1",
|
|
82
|
-
"@fluojs/
|
|
83
|
-
"@fluojs/
|
|
81
|
+
"@fluojs/di": "^1.0.0-beta.2",
|
|
82
|
+
"@fluojs/runtime": "^1.0.0-beta.2",
|
|
83
|
+
"@fluojs/core": "^1.0.0-beta.1"
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
86
|
"@babel/core": ">=7.0.0",
|
|
@@ -88,9 +88,9 @@
|
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"vitest": "^3.2.4",
|
|
91
|
-
"@fluojs/platform-nodejs": "^1.0.0-beta.
|
|
92
|
-
"@fluojs/platform-
|
|
93
|
-
"@fluojs/platform-
|
|
91
|
+
"@fluojs/platform-nodejs": "^1.0.0-beta.2",
|
|
92
|
+
"@fluojs/platform-express": "^1.0.0-beta.2",
|
|
93
|
+
"@fluojs/platform-fastify": "^1.0.0-beta.3"
|
|
94
94
|
},
|
|
95
95
|
"scripts": {
|
|
96
96
|
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|