refactor(testing): testBedSetup + testBedSetupContainer
MODIFY
packages/core/src/+internal/utils/http.util.ts
packages/core/src/+internal/utils/http.util.ts
import { AddressInfo } from 'net';
import { pipe } from 'fp-ts/lib/pipeable';
-import { IO } from 'fp-ts/lib/IO';
+import { Task } from 'fp-ts/lib/Task';
import { toUndefined } from 'fp-ts/lib/Option';
import { HttpRequest, HttpServer } from '../../http/http.interface';
import { getHead } from './array.util';
@@ -12,8 +12,8 @@ export const getHeaderValueHead = <T extends string = string>(key: string) => (r
: header as T;
};
-export const closeServer = (server: HttpServer): IO<Promise<void>> => () =>
- new Promise((res, rej) =>
+export const closeServer = (server: HttpServer): Task<void> =>
+ () => new Promise((res, rej) =>
server.close(err => err ? rej(err) : res()));
export const getServerAddress = (server: HttpServer): { host: string; port: number } => {

MODIFY
packages/testing/src/testBed/testBed.interface.ts
packages/testing/src/testBed/testBed.interface.ts
-import { IO } from 'fp-ts/lib/IO';
+import { Task } from 'fp-ts/lib/Task';
import { ContextProvider, BoundDependency } from '@marblejs/core';
export enum TestBedType {
@@ -10,7 +10,7 @@ export enum TestBedType {
export interface TestBed {
type: TestBedType;
ask: ContextProvider;
- finish: IO<Promise<void>>;
+ finish: Task<void>;
}
export type TestBedFactory<T> = (dependencies?: BoundDependency<any>[]) => Promise<T>

MODIFY
packages/testing/src/testBed/testBedContainer.interface.ts
packages/testing/src/testBed/testBedContainer.interface.ts
-import { IO } from 'fp-ts/lib/IO';
+import { Task } from 'fp-ts/lib/Task';
import { ContextToken } from '@marblejs/core';
import { TestBed } from './testBed.interface';
@@ -12,6 +12,6 @@ export interface TestBedContainerConfig {
}
export interface TestBedContainer {
- cleanup: IO<Promise<void>>;
- register: (instance: TestBed) => void;
+ cleanup: Task<void>;
+ register: <T extends TestBed>(instance: T) => Task<T>;
}

MODIFY
packages/testing/src/testBed/testBedContainer.ts
packages/testing/src/testBed/testBedContainer.ts
+import * as T from 'fp-ts/lib/Task';
import * as O from 'fp-ts/lib/Option';
+import * as A from 'fp-ts/lib/Array';
import { pipe } from 'fp-ts/lib/pipeable';
import { EventBusClientToken } from '@marblejs/messaging';
import { TestBed } from './testBed.interface';
@@ -17,26 +19,31 @@ export const createTestBedContainer = (config?: TestBedContainerConfig): TestBed
...config?.cleanups ?? [],
];
- const register = (testBed: TestBed) => {
+ const register = <T extends TestBed>(testBed: T): T.Task<T> => {
instances.push(testBed);
+ return T.of(testBed);
}
- const cleanupDependency = (testBed: TestBed) => (dependencyCleanup: DependencyCleanup<any>): Promise<void> =>
- pipe(
+ const cleanupDependency = (testBed: TestBed) => (dependencyCleanup: DependencyCleanup<any>): T.Task<void> => pipe(
testBed.ask(dependencyCleanup.token),
O.map(dependencyCleanup.cleanup),
- O.getOrElse(() => Promise.resolve()),
+ O.fold(() => T.of(undefined), res => () => res),
);
- const cleanupInstance = async (testBed: TestBed): Promise<void> => {
- await Promise.all(registeredCleanups.map(cleanupDependency(testBed)))
- await testBed.finish();
- }
+ const cleanupInstance = (testBed: TestBed): T.Task<void> => pipe(
+ A.array.map(registeredCleanups, cleanupDependency(testBed)),
+ A.array.sequence(T.task),
+ T.chain(_ => testBed.finish),
+ );
- const cleanup = async (): Promise<void> => {
- await Promise.all(instances.map(cleanupInstance));
+ const cleanup: T.Task<void> = () => pipe(
+ A.array.map(instances, cleanupInstance),
+ A.array.sequence(T.task),
+ T.chain(_ => {
instances = [];
- }
+ return T.of(undefined);
+ }),
+ )();
return { cleanup, register };
};

MODIFY
packages/testing/src/testBed/testBedSetup.interface.ts
packages/testing/src/testBed/testBedSetup.interface.ts
-import { IO } from 'fp-ts/lib/IO';
+import { Task } from 'fp-ts/lib/Task';
import { BoundDependency } from '@marblejs/core';
import { DependencyCleanup } from './testBedContainer.interface';
import { TestBed, TestBedFactory } from './testBed.interface';
@@ -11,5 +11,5 @@ export interface TestBedSetupConfig<T extends TestBed> {
export interface TestBedSetup<T extends TestBed> {
useTestBed: TestBedFactory<T>;
- cleanup: IO<Promise<void>>;
+ cleanup: Task<void>;
}

MODIFY
packages/testing/src/testBed/testBedSetup.ts
packages/testing/src/testBed/testBedSetup.ts
import { BoundDependency } from '@marblejs/core';
+import * as T from 'fp-ts/lib/Task';
+import { pipe } from 'fp-ts/lib/pipeable';
import { TestBedSetupConfig, TestBedSetup } from './testBedSetup.interface';
import { createTestBedContainer } from './testBedContainer';
import { TestBed } from './testBed.interface';
@@ -8,22 +10,19 @@ type CreateTestBedSetup = <T extends TestBed>
(prependDependencies?: readonly BoundDependency<any>[]) =>
TestBedSetup<T>
-export const createTestBedSetup: CreateTestBedSetup = config => (prependDependencies = []) => {
- const { dependencies: defaultDependencies = [], cleanups = [] } = config;
+export const createTestBedSetup: CreateTestBedSetup = config => prependDependencies => {
+ const { dependencies: defaultDependencies, cleanups = [] } = config;
const { cleanup, register } = createTestBedContainer({ cleanups });
- const useTestBed = async (dependencies: BoundDependency<any>[] = []) => {
- const testBed = await config.testBed([
- ...defaultDependencies,
- ...prependDependencies,
+ const useTestBed = async (dependencies: BoundDependency<any>[] = []) => pipe(
+ () => config.testBed([
+ ...defaultDependencies ?? [],
+ ...prependDependencies ?? [],
...dependencies
- ]);
-
- register(testBed);
-
- return testBed;
- };
+ ]),
+ T.chain(register),
+ )();
return {
useTestBed,

refactor(testing): testBedSetup + testBedSetupContainer