diff --git a/.vscode/settings.json b/.vscode/settings.json index 3ed5ae2..da63cc5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,6 @@ "*ui": false, "*ui.*": false }, - "cSpell.words": ["antd", "fileupload", "metadatas", "uuidv"], + "cSpell.words": ["antd", "fileupload", "metadatas", "undici", "uuidv"], "editor.rulers": [100] } diff --git a/server/package.json b/server/package.json index d77916b..a0cd0d3 100644 --- a/server/package.json +++ b/server/package.json @@ -5,9 +5,9 @@ "main": "index.js", "scripts": { "pretest": "tsc", - "test": "ts-node ./build/test/test.js", - "test:watch": "tsc-watch --onSuccess 'ts-node ./build/test/test.js'", - "dev": "tsc-watch --onSuccess 'ts-node ./build/src/main.js'" + "test:unit": "NODE_ENV=unit tsc-watch --onSuccess 'ts-node ./build/test/test.js'", + "test:e2e": "NODE_ENV=e2e tsc-watch --onSuccess 'ts-node ./build/test/test.js'", + "dev": "NODE_ENV=dev tsc-watch --onSuccess 'ts-node ./build/src/main.js'" }, "author": "IDONTSUDO", "devDependencies": { @@ -31,10 +31,10 @@ }, "dependencies": { "@grpc/grpc-js": "^1.9.0", + "axios": "^1.6.2", "babel-register": "^6.26.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", - "concurrently": "^8.2.0", "cors": "^2.8.5", "express": "^4.18.2", "express-fileupload": "^1.4.2", diff --git a/server/src/core/controllers/app.ts b/server/src/core/controllers/app.ts index 40d0c69..05ca80b 100644 --- a/server/src/core/controllers/app.ts +++ b/server/src/core/controllers/app.ts @@ -9,25 +9,46 @@ import fileUpload from "express-fileupload"; import { SetLastActivePipelineToRealTimeServiceScenario } from "../scenarios/set_active_pipeline_to_realtime_service_scenario"; import { CheckAndCreateStaticFilesFolderUseCase } from "../usecases/check_and_create_static_files_folder_usecase"; import { DataBaseConnectUseCase } from "../usecases/database_connect_usecase"; +import { TypedEvent } from "../helpers/typed_event"; -export class App { +export enum ServerStatus { + init = "init", + finished = "finshed", + error = "error", +} +export enum Environment { + DEV = "DEV", + E2E_TEST = "E2E_TEST", +} + +export class App extends TypedEvent { public app: express.Application; public port: number; - public env: string; + public env: Environment; public socketSubscribers: SocketSubscriber[]; public io: Server; + status: ServerStatus; - constructor(routes: Routes[], socketSubscribers: SocketSubscriber[]) { + constructor(routes: Routes[] = [], socketSubscribers: SocketSubscriber[] = [], env = Environment.DEV) { + super(); + this.init(routes, socketSubscribers, env); + } + + public init(routes: Routes[], socketSubscribers: SocketSubscriber[], env: Environment) { this.port = 4001; this.socketSubscribers = socketSubscribers; - this.env = "dev"; + this.env = env; this.app = express(); + this.setServerStatus(ServerStatus.init); + this.loadAppDependencies().then(() => { this.initializeMiddlewares(); this.initializeRoutes(routes); + if (this.status !== ServerStatus.error) { + this.setServerStatus(ServerStatus.finished); + } }); } - public listen() { const httpServer = createServer(this.app); const io = new Server(httpServer, { @@ -49,9 +70,13 @@ export class App { console.info(`🚀 WS ws://localhost:${this.port}`); console.info(`=================================`); }); + this.io = io; } - + setServerStatus(status: ServerStatus) { + this.emit(status); + this.status = status; + } public getServer() { return this.app; } @@ -75,12 +100,19 @@ export class App { }); } - async loadAppDependencies() { - if ((await new DataBaseConnectUseCase().call()).isFailure()) { - console.log("database connect error"); - } - await new CheckAndCreateStaticFilesFolderUseCase().call(); - await new SetLastActivePipelineToRealTimeServiceScenario().call(); + async loadAppDependencies(): Promise { + const dataBaseName = this.env === Environment.E2E_TEST ? "e2e_test" : "dev"; + // TODO(IDONTSUDO):maybe convert it to a class and map it there + const result = await new DataBaseConnectUseCase().call(dataBaseName); + await result.fold( + async (_s) => { + await new CheckAndCreateStaticFilesFolderUseCase().call(); + await new SetLastActivePipelineToRealTimeServiceScenario().call(); + }, + async (_e) => { + this.setServerStatus(ServerStatus.error); + } + ); } static staticFilesStoreDir = () => { diff --git a/server/src/core/controllers/http_controller.ts b/server/src/core/controllers/http_controller.ts index 1e0e6ed..ae3b30d 100644 --- a/server/src/core/controllers/http_controller.ts +++ b/server/src/core/controllers/http_controller.ts @@ -3,7 +3,7 @@ import { Result } from "../helpers/result"; import { Router, Request, Response } from "express"; import { IRouteModel, Routes } from "../interfaces/router"; -export type Method = "all" | "get" | "post" | "put" | "delete" | "patch" | "options" | "head"; +export type HttpMethodType = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "PATCH" | "HEAD"; export type ResponseBase = Promise>; @@ -29,7 +29,7 @@ export abstract class CallbackStrategyWithFileUpload { } interface ISubSetFeatureRouter { - method: Method; + method: HttpMethodType; subUrl: string; fn: | CallbackStrategyWithValidationModel @@ -78,7 +78,7 @@ export class CoreHttpController implements ICoreHttpController { call(): Routes { if (this.subRoutes.isNotEmpty()) { this.subRoutes.map((el) => { - this.router[el.method](this.mainURL + "/" + el.subUrl, async (req, res) => { + this.router[el.method.toLowerCase()](this.mainURL + "/" + el.subUrl, async (req, res) => { if (el.fn instanceof CallbackStrategyWithValidationModel) { // TODO(IDONTSUDO): throw Error("needs to be implimed"); diff --git a/server/src/core/controllers/routes.ts b/server/src/core/controllers/routes.ts new file mode 100644 index 0000000..76e8f90 --- /dev/null +++ b/server/src/core/controllers/routes.ts @@ -0,0 +1,26 @@ +import { NixStoreManagerPresentation } from "../../features/nix_store_manager/nix_store_manager"; +import { PipelinePresentation } from "../../features/pipelines/pipeline_presentation"; +import { ProcessPresentation } from "../../features/process/process_presentation"; +import { ProjectInstancePresentation } from "../../features/project_instance/project_instance_presentation"; +import { ProjectsPresentation } from "../../features/projects/projects_presentation"; +import { RealTimePresentation } from "../../features/realtime/realtime_presentation"; +import { TriggerPresentation } from "../../features/triggers/triggers_presentation"; +import { extensions } from "../extensions/extensions"; +import { Routes } from "../interfaces/router"; + +extensions(); + +export const routersImplementPureCrud = [ + new TriggerPresentation(), + new ProjectsPresentation(), + new ProcessPresentation(), + new PipelinePresentation(), +]; + +export const httpRoutes: Routes[] = [ + new RealTimePresentation(), + new ProjectInstancePresentation(), + new NixStoreManagerPresentation(), +] + .concat(routersImplementPureCrud) + .map((el) => el.call()); diff --git a/server/src/core/extensions/array.ts b/server/src/core/extensions/array.ts index b07130d..f62faa8 100644 --- a/server/src/core/extensions/array.ts +++ b/server/src/core/extensions/array.ts @@ -1,5 +1,10 @@ /* eslint-disable @typescript-eslint/no-this-alias */ export const ArrayExtensions = () => { + if ([].firstElement === undefined) { + Array.prototype.firstElement = function () { + return this[0]; + }; + } if ([].equals === undefined) { // eslint-disable-next-line no-extend-native Array.prototype.equals = function (array, strict = true) { diff --git a/server/src/core/extensions/extensions.ts b/server/src/core/extensions/extensions.ts index ac4adea..14e8907 100644 --- a/server/src/core/extensions/extensions.ts +++ b/server/src/core/extensions/extensions.ts @@ -6,6 +6,7 @@ declare global { // @strict: The parameter is determined whether the arrays must be exactly the same in content and order of this relationship or simply follow the same requirements. equals(array: Array, strict: boolean): boolean; lastElement(): T | undefined; + firstElement(): T | undefined; isEmpty(): boolean; isNotEmpty(): boolean; } diff --git a/server/src/core/helpers/class_validator_mocket.ts b/server/src/core/helpers/class_validator_mocker.ts similarity index 87% rename from server/src/core/helpers/class_validator_mocket.ts rename to server/src/core/helpers/class_validator_mocker.ts index 1f2157b..433d17a 100644 --- a/server/src/core/helpers/class_validator_mocket.ts +++ b/server/src/core/helpers/class_validator_mocker.ts @@ -1,8 +1,8 @@ import { randomBytes, randomInt, randomUUID } from "crypto"; -import { getMetadataStorage, IS_BOOLEAN, IS_MONGO_ID, IS_NUMBER, IS_STRING, IS_UUID } from "class-validator"; +import { getMetadataStorage, IS_ARRAY, IS_BOOLEAN, IS_MONGO_ID, IS_NUMBER, IS_STRING, IS_UUID } from "class-validator"; import { ValidationMetadata } from "class-validator/types/metadata/ValidationMetadata"; -type AvailableTypes = string | number | boolean | undefined; +type AvailableTypes = string | number | boolean | undefined | []; export class ClassValidatorMocker { // eslint-disable-next-line @typescript-eslint/ban-types @@ -16,7 +16,6 @@ export class ClassValidatorMocker { const targetMetadatas = metadataStorage.getTargetValidationMetadatas(constructor, "", false, false); const groupedMetadatas = metadataStorage.groupByPropertyName(targetMetadatas); // nestedValidation - console.log(targetMetadatas); let randomFixture = {} as T; for (const propertyName of Object.keys(groupedMetadatas)) { @@ -40,6 +39,10 @@ export class ClassValidatorMocker { for (const constraint of constraints) { switch (constraint.name) { + case IS_ARRAY: + return []; + case "isEnum": + return Object.keys(metadata.constraints.firstElement()).firstElement(); case IS_MONGO_ID: return this.randomUUID(); case IS_STRING: diff --git a/server/src/core/models/exec_error_model.ts b/server/src/core/models/exec_error_model.ts index e6953c0..bbb9f38 100644 --- a/server/src/core/models/exec_error_model.ts +++ b/server/src/core/models/exec_error_model.ts @@ -1,3 +1,7 @@ +import { extensions } from "../extensions/extensions"; + +extensions(); + export class ExecError extends Error { static isExecError(e: any): ExecError | void { if ("type" in e && "script" in e && "unixTime" in e && "error" in e) { @@ -13,7 +17,7 @@ export class ExecError extends Error { super(...args); this.script = script; this.unixTime = Date.now(); - this.error = args[0]; + this.error = args.firstElement(); } } diff --git a/server/src/core/repository/http_repository.ts b/server/src/core/repository/http_repository.ts new file mode 100644 index 0000000..2603c4a --- /dev/null +++ b/server/src/core/repository/http_repository.ts @@ -0,0 +1,24 @@ +import axios from "axios"; +import { Result } from "../helpers/result"; +import { HttpMethodType } from "../controllers/http_controller"; + +export class HttpRepository { + serverUrl = "http://localhost:4001"; + + constructor(serverURL: string) { + this.serverUrl = serverURL; + } + + async jsonRequest(url: string, method: HttpMethodType, reqBody?: any): Promise> { + try { + const result = await axios(this.serverUrl + url, { method: method, data: reqBody }); + if (result.status !== 200) { + return Result.error(Error("status code" + String(result.status))); + } + return Result.ok(result.data); + } catch (error) { + console.log(error); + return Result.error(error); + } + } +} diff --git a/server/src/core/usecases/database_connect_usecase.ts b/server/src/core/usecases/database_connect_usecase.ts index 1cf7cb9..9b4d3b8 100644 --- a/server/src/core/usecases/database_connect_usecase.ts +++ b/server/src/core/usecases/database_connect_usecase.ts @@ -2,11 +2,13 @@ import mongoose from "mongoose"; import { Result } from "../helpers/result"; export class DataBaseConnectUseCase { - call = async (): Promise> => { + call = async (dataBaseName: string = "test"): Promise> => { try { - await mongoose.connect("mongodb://127.0.0.1:27017/test"); + await mongoose.connect(`mongodb://127.0.0.1:27017/${dataBaseName}`); return Result.ok(); } catch (error) { + console.log(error); + console.log("database connect error"); return Result.error(error as Error); } }; diff --git a/server/src/core/usecases/delete_database_model_usecase.ts b/server/src/core/usecases/delete_database_model_usecase.ts index cfdd296..07dcc51 100644 --- a/server/src/core/usecases/delete_database_model_usecase.ts +++ b/server/src/core/usecases/delete_database_model_usecase.ts @@ -5,12 +5,17 @@ export class DeleteDataBaseModelUseCase { constructor(model) { this.databaseModel = model; } - call = async (id: string): Promise> => { + call = async (id: string): Promise> => { try { - const model = new this.databaseModel({ _id: id }); - await model.deleteOne(); + const model = this.databaseModel as any; - return Result.ok(true); + const result = await model.deleteOne({ _id: id }); + + if (result.deletedCount === 0) { + return Result.error(Error(`the database does not have a collection with this ID:${id}`)); + } + + return Result.ok({ ok: "model delete" }); } catch (error) { return Result.error(error); } diff --git a/server/src/core/usecases/drop_database_usecase.ts b/server/src/core/usecases/drop_database_usecase.ts new file mode 100644 index 0000000..a9a4d6b --- /dev/null +++ b/server/src/core/usecases/drop_database_usecase.ts @@ -0,0 +1,7 @@ +import mongoose from "mongoose"; + +export class DropDataBaseUseCase { + call = async () => { + await mongoose.connection.dropDatabase(); + }; +} diff --git a/server/src/core/usecases/exit_app_usecase.ts b/server/src/core/usecases/exit_app_usecase.ts new file mode 100644 index 0000000..2a7498a --- /dev/null +++ b/server/src/core/usecases/exit_app_usecase.ts @@ -0,0 +1,5 @@ +export class ExitAppUseCase { + call = () => { + process.exit(); + }; +} diff --git a/server/src/core/usecases/read_database_model_usecase.ts b/server/src/core/usecases/read_database_model_usecase.ts index 6786b80..1de0ab6 100644 --- a/server/src/core/usecases/read_database_model_usecase.ts +++ b/server/src/core/usecases/read_database_model_usecase.ts @@ -1,5 +1,4 @@ - -import { Result } from "../helper/result"; +import { Result } from "../helpers/result"; export class ReadByIdDataBaseModelUseCase { databaseModel: D; diff --git a/server/src/features/nix_store_manager/nix_store_manager.ts b/server/src/features/nix_store_manager/nix_store_manager.ts index dc5067b..145bfd5 100644 --- a/server/src/features/nix_store_manager/nix_store_manager.ts +++ b/server/src/features/nix_store_manager/nix_store_manager.ts @@ -35,7 +35,7 @@ class GetNixStorePackagesUseCase extends CallbackStrategyWithEmpty { const promise = new Promise((resolve, _reject) => { stackService.on((e) => { - const iteration = e[0]; + const iteration = e.firstElement(); if (iteration.result instanceof ExecutorResult) { const nixPackage = iteration.result.data; resolve(nixPackage.split("\n").filter((e) => e.hasNoPattern(".drv"))); diff --git a/server/src/features/pipelines/pipeline_model.ts b/server/src/features/pipelines/pipeline_model.ts index 3409dd0..6491ed3 100644 --- a/server/src/features/pipelines/pipeline_model.ts +++ b/server/src/features/pipelines/pipeline_model.ts @@ -1,11 +1,8 @@ import { IsMongoId, IsEnum } from "class-validator"; import { Schema, model } from "mongoose"; -import { StackGenerateType } from "../../core/model/process_model"; -import { - TriggerModel, - triggerSchema, -} from "../triggers/trigger_model"; +import { TriggerModel, triggerSchema } from "../triggers/trigger_model"; import { schemaProcess } from "../process/process_model"; +import { StackGenerateType } from "../../core/models/process_model"; export const PipelineSchema = new Schema({ process: { @@ -27,10 +24,7 @@ export const PipelineSchema = new Schema({ export const schemaPipeline = "Pipeline"; -export const PipelineDBModel = model( - schemaPipeline, - PipelineSchema -); +export const PipelineDBModel = model(schemaPipeline, PipelineSchema); export class PipelineModel { @IsMongoId() diff --git a/server/src/features/process/process_model.ts b/server/src/features/process/process_model.ts index df48590..a8105c1 100644 --- a/server/src/features/process/process_model.ts +++ b/server/src/features/process/process_model.ts @@ -1,16 +1,7 @@ -import { - IsString, - IsOptional, - IsEnum, - IsNumber, - IsBoolean, -} from "class-validator"; +import { IsString, IsOptional, IsEnum, IsNumber, IsBoolean } from "class-validator"; import { Schema, model } from "mongoose"; -import { - IProcess, - IssueType, -} from "../../core/model/process_model"; -import { EXEC_TYPE } from "../../core/model/exec_error_model"; +import { IProcess, IssueType } from "../../core/models/process_model"; +import { EXEC_TYPE } from "../../core/models/exec_error_model"; export const ProcessSchema = new Schema({ type: { @@ -61,9 +52,8 @@ export class ProcessModel implements IProcess { @IsOptional() @IsNumber() public timeout?: number; - + @IsOptional() @IsString() public commit?: string; } - \ No newline at end of file diff --git a/server/src/features/project_instance/project_instance_presentation.ts b/server/src/features/project_instance/project_instance_presentation.ts index f8962c4..77040a8 100644 --- a/server/src/features/project_instance/project_instance_presentation.ts +++ b/server/src/features/project_instance/project_instance_presentation.ts @@ -18,7 +18,7 @@ export class ProjectInstancePresentation extends CrudController< super.subRoutes = [ { - method: "post", + method: "POST", subUrl: "upload", fn: new UploadCadFileToProjectScenario(), }, diff --git a/server/src/main.ts b/server/src/main.ts index 9f6f0fa..3b91a44 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -1,28 +1,12 @@ import "reflect-metadata"; import { App } from "./core/controllers/app"; import { SocketSubscriber } from "./core/controllers/socket_controller"; -import { Routes } from "./core/interfaces/router"; -import { TriggerPresentation } from "./features/triggers/triggers_presentation"; -import { ProjectsPresentation } from "./features/projects/projects_presentation"; -import { PipelinePresentation } from "./features/pipelines/pipeline_presentation"; -import { ProcessPresentation } from "./features/process/process_presentation"; -import { RealTimePresentation, pipelineRealTimeService } from "./features/realtime/realtime_presentation"; import { extensions } from "./core/extensions/extensions"; -import { ProjectInstancePresentation } from "./features/project_instance/project_instance_presentation"; -import { NixStoreManagerPresentation } from "./features/nix_store_manager/nix_store_manager"; +import { httpRoutes } from "./core/controllers/routes"; +import { pipelineRealTimeService } from "./features/realtime/realtime_presentation"; extensions(); -export const httpRoutes: Routes[] = [ - new TriggerPresentation(), - new ProjectsPresentation(), - new ProcessPresentation(), - new PipelinePresentation(), - new RealTimePresentation(), - new ProjectInstancePresentation(), - new NixStoreManagerPresentation(), -].map((el) => el.call()); - const socketSubscribers = [new SocketSubscriber(pipelineRealTimeService, "realtime")]; new App(httpRoutes, socketSubscribers).listen(); diff --git a/server/test/controllers/crud_controller_test.ts b/server/test/controllers/crud_controller_test.ts new file mode 100644 index 0000000..23b074a --- /dev/null +++ b/server/test/controllers/crud_controller_test.ts @@ -0,0 +1,49 @@ +import { CrudController } from "../../src/core/controllers/crud_controller"; +import { ClassValidatorMocker } from "../../src/core/helpers/class_validator_mocker"; +import { HttpRepository } from "../../src/core/repository/http_repository"; + +function instanceOfObjectAndHaveId(s: any): string { + if (s instanceof Object && "id" in s) { + return s.id; + } + if (s instanceof Object && "_id" in s) { + return s._id; + } + throw Error(`${s} is not instance object or not have property _id`); +} + +export class CrudControllerTest { + controllerTest: CrudController; + httpRepository: HttpRepository; + + constructor(port: number, controller: CrudController) { + this.controllerTest = controller; + this.httpRepository = new HttpRepository(`http://localhost:${port}`); + } + + async call() { + let result = false; + const mockModel = ClassValidatorMocker.create(this.controllerTest.validationModel); + const postRequestBody = await this.httpRepository.jsonRequest(this.controllerTest.mainURL, "POST", mockModel); + + await postRequestBody.map(async (s) => { + const id = instanceOfObjectAndHaveId(s); + const getRequestBody = await this.httpRepository.jsonRequest(this.controllerTest.mainURL, "GET"); + await getRequestBody.map(async (el) => { + if (el instanceof Array) { + const firstElement = el.firstElement(); + const mockModelUpdate = ClassValidatorMocker.create(this.controllerTest.validationModel); + Object.assign(firstElement, mockModelUpdate); + delete firstElement.__v; + const putReqBody = await this.httpRepository.jsonRequest(this.controllerTest.mainURL, "PUT", firstElement); + await putReqBody.map(async () => { + (await this.httpRepository.jsonRequest(this.controllerTest.mainURL + "?id=" + id, "DELETE")).map(() => { + result = true; + }); + }); + } + }); + }); + return result; + } +} diff --git a/server/test/core/test_core.ts b/server/test/core/test_core.ts index ec115b2..f3424ff 100644 --- a/server/test/core/test_core.ts +++ b/server/test/core/test_core.ts @@ -2,9 +2,12 @@ import mongoose from "mongoose"; import { delay } from "../../src/core/helpers/delay"; import { Result } from "../../src/core/helpers/result"; import { TypedEvent } from "../../src/core/helpers/typed_event"; +import { DropDataBaseUseCase } from "../../src/core/usecases/drop_database_usecase"; +import { ExitAppUseCase } from "../../src/core/usecases/exit_app_usecase"; export const before = async () => { - await mongoose.connection.dropDatabase(); + new DropDataBaseUseCase().call(); + new ExitAppUseCase().call(); }; export class TestCore { diff --git a/server/test/helper/class_validator_mocker_test.ts b/server/test/helper/class_validator_mocker_test.ts deleted file mode 100644 index b468fd3..0000000 --- a/server/test/helper/class_validator_mocker_test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Type } from "class-transformer"; -import { ClassValidatorMocker } from "../../src/core/helpers/class_validator_mocket"; -import { IsString, IsNumber, IsBoolean, IsUUID, IsMongoId, ValidateNested } from "class-validator"; - -class Foo {} -class MyClass { - @ValidateNested() - @Type(() => Foo) - model: Foo; - - @IsNumber() - numberProperty: number; - - @IsBoolean() - booleanProperty: boolean; - - @IsUUID() - uuidProperty: string; -} - -const myClassDataMock = ClassValidatorMocker.create(MyClass); - -export const mainTest = () => { - console.log(myClassDataMock); -}; diff --git a/server/test/test.ts b/server/test/test.ts index 2311c1d..1bbe197 100644 --- a/server/test/test.ts +++ b/server/test/test.ts @@ -13,10 +13,12 @@ import { ReadDataBaseModelUseCaseTest } from "./usecases/read_database_model_use import { UpdateDataBaseModelUseCaseTest } from "./usecases/update_database_model_usecase"; import { PaginationDataBaseModelUseCaseTest } from "./usecases/pagination_database_model_usecase_test"; import { extensions } from "../src/core/extensions/extensions"; +import { CrudControllerTest } from "./controllers/crud_controller_test"; +import { TriggerPresentation } from "../src/features/triggers/triggers_presentation"; +import { App, Environment, ServerStatus } from "../src/core/controllers/app"; +import { httpRoutes } from "../src/core/controllers/routes"; import { DataBaseConnectUseCase } from "../src/core/usecases/database_connect_usecase"; -extensions(); - const testCore = TestCore.instance; export const dirname__: string = dirname(__filename); export const assert = testCore.assert; @@ -33,13 +35,13 @@ const init = async () => { await new DataBaseConnectUseCase().call(); }; -const test = async () => { +const unitTest = async () => { + await init(); await new ExecutorProgramServiceTest(dirname__).test(); await new FilesChangerTest(dirname__).test(); await new StackServiceTest(dirname__ + "/context/").test(); await new TriggerServiceTest().test(); await new CreateDataBaseModelUseCaseTest().test(); - await new CreateDataBaseModelUseCaseTest().test(); await new DeleteDataBaseModelUseCaseTest().test(); await new ReadDataBaseModelUseCaseTest().test(); @@ -48,11 +50,35 @@ const test = async () => { for await (const usecase of tests) { testCore.assert(await new usecase().test(), usecase.name); } - +}; +const presentationCrudControllers = [new TriggerPresentation()]; +const e2eTest = async () => { + const app = new App(httpRoutes, [], Environment.E2E_TEST); + app.listen(); + await new Promise((resolve, reject) => { + app.on(async (e) => { + if (e === ServerStatus.finished) { + for await (const el of presentationCrudControllers) { + testCore.assert(await new CrudControllerTest(app.port, el).call(), el.constructor.name); + } + resolve(e); + } + if (e === ServerStatus.error) { + console.log(e); + reject(e); + } + }); + }); }; const main = async () => { - await init(); - await test(); + extensions(); + if (process.env.NODE_ENV === "unit") { + await unitTest(); + } + + if (process.env.NODE_ENV === "e2e") { + await e2eTest(); + } await testCore.testResult(); };