From b65b104099982bc4788540165f74ab107c051c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 19:19:31 +0200 Subject: [PATCH 01/13] project exists middleware --- src/server/middleware/project-scenario-exists.ts | 14 ++++++++++++++ src/server/queries/projects.ts | 2 +- src/server/routes/item.ts | 15 +++++++++++++++ src/server/routes/label.ts | 4 ++++ src/server/routes/scenario.ts | 12 ++++++++++++ 5 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/server/middleware/project-scenario-exists.ts diff --git a/src/server/middleware/project-scenario-exists.ts b/src/server/middleware/project-scenario-exists.ts new file mode 100644 index 00000000..4cffdce0 --- /dev/null +++ b/src/server/middleware/project-scenario-exists.ts @@ -0,0 +1,14 @@ +import { IGetUserAuthInfoRequest } from "./request.model" +import { NextFunction, Response } from "express" +import { db } from "../../db/db" +import * as boom from "boom" +import { findProjectId } from "../queries/projects" + +export const projectExistsMiddleware = async (req: IGetUserAuthInfoRequest, res: Response, next: NextFunction) => { + + const { projectName } = req.params + const project = await db.oneOrNone(findProjectId(projectName)) + if (!project) { + return next(boom.notFound("Project not found")) + } +} diff --git a/src/server/queries/projects.ts b/src/server/queries/projects.ts index a43bc527..054fe0f4 100644 --- a/src/server/queries/projects.ts +++ b/src/server/queries/projects.ts @@ -18,7 +18,7 @@ export const createNewProject = projectName => { export const findProjectId = projectName => { return { name: "find-project-id", - text: "SELECT id FROM jtl.projects WHERE project_name = $1 AND", + text: "SELECT id FROM jtl.projects WHERE project_name = $1", values: [projectName], } } diff --git a/src/server/routes/item.ts b/src/server/routes/item.ts index 90493f6d..d958a48e 100644 --- a/src/server/routes/item.ts +++ b/src/server/routes/item.ts @@ -33,6 +33,7 @@ import { getItemChartSettingsController } from "../controllers/item/get-item-cha import { AllowedRoles, authorizationMiddleware } from "../middleware/authorization-middleware" import { authenticationMiddleware } from "../middleware/authentication-middleware" import { getRequestStatsExportController } from "../controllers/item/get-request-stats-export-controller" +import { projectExistsMiddleware } from "../middleware/project-scenario-exists" export class ItemsRoutes { @@ -44,12 +45,14 @@ export class ItemsRoutes { authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(scenarioParamsSchema), queryParamsValidator(querySchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => getItemsController(req, res))) .post( authenticationMiddleware, authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(newItemParamSchema), + projectExistsMiddleware, createItemController) app.route("/api/projects/:projectName/scenarios/:scenarioName/items/start-async") @@ -58,6 +61,7 @@ export class ItemsRoutes { authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), bodySchemaValidator(newAsyncItemStartBodySchema), paramsSchemaValidator(newItemParamSchema), + projectExistsMiddleware, createItemAsyncController) app.route("/api/projects/:projectName/scenarios/:scenarioName/items/:itemId") @@ -66,6 +70,7 @@ export class ItemsRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => getItemController(req, res))) .put( @@ -73,12 +78,14 @@ export class ItemsRoutes { authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), bodySchemaValidator(updateItemBodySchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response, next: NextFunction) => updateItemController(req, res, next))) .delete( authenticationMiddleware, authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => deleteItemController(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/items/:itemId/request-stats-export") @@ -86,6 +93,7 @@ export class ItemsRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => getRequestStatsExportController(req, res))) @@ -95,6 +103,7 @@ export class ItemsRoutes { authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), bodySchemaValidator(stopItemAsyncBodySchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => stopItemAsyncController(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/items/:itemId/share-tokens") @@ -102,12 +111,14 @@ export class ItemsRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => getItemLinksController(req, res))) .post( authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => createItemLinkController(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/items/:itemId/share-tokens/:tokenId") @@ -115,6 +126,7 @@ export class ItemsRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(shareTokenSchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => deleteItemShareTokenController(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/processing-items") @@ -123,6 +135,7 @@ export class ItemsRoutes { authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(scenarioParamsSchema), queryParamsValidator(environmentQuerySchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => getProcessingItemsController(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/items/:itemId/custom-chart-settings") @@ -131,12 +144,14 @@ export class ItemsRoutes { authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), bodySchemaValidator(upsertUserItemChartSettings), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => upsertItemChartSettingsController(req, res)) ) .get( authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => getItemChartSettingsController(req, res))) } } diff --git a/src/server/routes/label.ts b/src/server/routes/label.ts index 2a078ff8..4defc4ac 100644 --- a/src/server/routes/label.ts +++ b/src/server/routes/label.ts @@ -8,6 +8,7 @@ import { getLabelVirtualUsersController } from "../controllers/label/get-label-v import { getLabelErrorsController } from "../controllers/label/get-label-errors-controller" import { AllowedRoles, authorizationMiddleware } from "../middleware/authorization-middleware" import { authenticationMiddleware } from "../middleware/authentication-middleware" +import { projectExistsMiddleware } from "../middleware/project-scenario-exists" export class LabelRoutes { @@ -19,6 +20,7 @@ export class LabelRoutes { authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(labelParamSchema), queryParamsValidator(labelQuerySchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => getLabelTrendController(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/items/:itemId/label/:label/virtual-users") @@ -27,6 +29,7 @@ export class LabelRoutes { authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(labelParamSchema), queryParamsValidator(labelQuerySchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response, next: NextFunction) => getLabelVirtualUsersController(req, res, next))) @@ -35,6 +38,7 @@ export class LabelRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(labelParamSchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => getLabelErrorsController(req, res))) } } diff --git a/src/server/routes/scenario.ts b/src/server/routes/scenario.ts index f6259a6a..82a9e6fa 100644 --- a/src/server/routes/scenario.ts +++ b/src/server/routes/scenario.ts @@ -28,6 +28,7 @@ import { AllowedRoles, authorizationMiddleware } from "../middleware/authorizati import { IGetUserAuthInfoRequest } from "../middleware/request.model" import { postScenarioTrendsSettings } from "../controllers/scenario/trends/update-scenario-trends-settings-controller" import { getScenarioEnvironmentController } from "../controllers/scenario/get-scenario-environment-controller" +import {projectExistsMiddleware} from "../middleware/project-scenario-exists"; export class ScenarioRoutes { @@ -38,6 +39,7 @@ export class ScenarioRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(projectNameParam), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => getScenariosController(req, res))) .post( @@ -45,6 +47,7 @@ export class ScenarioRoutes { authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(projectNameParam), bodySchemaValidator(scenarioSchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response, next: NextFunction) => createScenarioController(req, res, next))) @@ -53,6 +56,7 @@ export class ScenarioRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => getScenarioController(req, res)) ) @@ -61,12 +65,14 @@ export class ScenarioRoutes { authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), bodySchemaValidator(updateScenarioSchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => updateScenarioController(req, res))) .delete( authenticationMiddleware, authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => deleteScenarioController(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/notifications") @@ -74,6 +80,7 @@ export class ScenarioRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => getScenarioNotificationsController(req, res))) .post( @@ -81,6 +88,7 @@ export class ScenarioRoutes { authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), bodySchemaValidator(scenarioNotificationBodySchema), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => createScenarioNotificationController(req, res))) @@ -89,6 +97,7 @@ export class ScenarioRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramSchemaNotification), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => deleteScenarioNotificationController(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/trends") @@ -97,6 +106,7 @@ export class ScenarioRoutes { authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), queryParamsValidator(environmentQuerySchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => getScenarioTrendsController(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/trends/settings") @@ -105,6 +115,7 @@ export class ScenarioRoutes { authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), bodySchemaValidator(scenarioTrendsSettings), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => postScenarioTrendsSettings(req, res))) app.route("/api/projects/:projectName/scenarios/:scenarioName/environment") @@ -112,6 +123,7 @@ export class ScenarioRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(paramsSchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => getScenarioEnvironmentController(req, res))) } } From ca3b46b635bc29c8ada9ac62a7f79e7e04fc895b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 19:23:44 +0200 Subject: [PATCH 02/13] linter fixes --- src/server/routes/scenario.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/routes/scenario.ts b/src/server/routes/scenario.ts index 82a9e6fa..95bb0b22 100644 --- a/src/server/routes/scenario.ts +++ b/src/server/routes/scenario.ts @@ -28,7 +28,7 @@ import { AllowedRoles, authorizationMiddleware } from "../middleware/authorizati import { IGetUserAuthInfoRequest } from "../middleware/request.model" import { postScenarioTrendsSettings } from "../controllers/scenario/trends/update-scenario-trends-settings-controller" import { getScenarioEnvironmentController } from "../controllers/scenario/get-scenario-environment-controller" -import {projectExistsMiddleware} from "../middleware/project-scenario-exists"; +import { projectExistsMiddleware } from "../middleware/project-scenario-exists" export class ScenarioRoutes { From a9bcaecc473b3c8fb916187064270f1266d39d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 19:30:02 +0200 Subject: [PATCH 03/13] file renamed --- ...{project-scenario-exists.ts => project-exists-middleware.ts} | 0 src/server/routes/item.ts | 2 +- src/server/routes/label.ts | 2 +- src/server/routes/scenario.ts | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename src/server/middleware/{project-scenario-exists.ts => project-exists-middleware.ts} (100%) diff --git a/src/server/middleware/project-scenario-exists.ts b/src/server/middleware/project-exists-middleware.ts similarity index 100% rename from src/server/middleware/project-scenario-exists.ts rename to src/server/middleware/project-exists-middleware.ts diff --git a/src/server/routes/item.ts b/src/server/routes/item.ts index d958a48e..4a9f2e64 100644 --- a/src/server/routes/item.ts +++ b/src/server/routes/item.ts @@ -33,7 +33,7 @@ import { getItemChartSettingsController } from "../controllers/item/get-item-cha import { AllowedRoles, authorizationMiddleware } from "../middleware/authorization-middleware" import { authenticationMiddleware } from "../middleware/authentication-middleware" import { getRequestStatsExportController } from "../controllers/item/get-request-stats-export-controller" -import { projectExistsMiddleware } from "../middleware/project-scenario-exists" +import { projectExistsMiddleware } from "../middleware/project-exists-middleware" export class ItemsRoutes { diff --git a/src/server/routes/label.ts b/src/server/routes/label.ts index 4defc4ac..626f6b25 100644 --- a/src/server/routes/label.ts +++ b/src/server/routes/label.ts @@ -8,7 +8,7 @@ import { getLabelVirtualUsersController } from "../controllers/label/get-label-v import { getLabelErrorsController } from "../controllers/label/get-label-errors-controller" import { AllowedRoles, authorizationMiddleware } from "../middleware/authorization-middleware" import { authenticationMiddleware } from "../middleware/authentication-middleware" -import { projectExistsMiddleware } from "../middleware/project-scenario-exists" +import { projectExistsMiddleware } from "../middleware/project-exists-middleware" export class LabelRoutes { diff --git a/src/server/routes/scenario.ts b/src/server/routes/scenario.ts index 95bb0b22..08625d8f 100644 --- a/src/server/routes/scenario.ts +++ b/src/server/routes/scenario.ts @@ -28,7 +28,7 @@ import { AllowedRoles, authorizationMiddleware } from "../middleware/authorizati import { IGetUserAuthInfoRequest } from "../middleware/request.model" import { postScenarioTrendsSettings } from "../controllers/scenario/trends/update-scenario-trends-settings-controller" import { getScenarioEnvironmentController } from "../controllers/scenario/get-scenario-environment-controller" -import { projectExistsMiddleware } from "../middleware/project-scenario-exists" +import { projectExistsMiddleware } from "../middleware/project-exists-middleware" export class ScenarioRoutes { From cc99ced0891ba96396c13d75227c616fd8f8e85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 19:49:49 +0200 Subject: [PATCH 04/13] middleware unit test added, unused route removed --- .../authentication-middleware.spec.ts | 2 +- .../project-exists-middleware.spec.ts | 35 +++++++++++++++++++ .../middleware/project-exists-middleware.ts | 1 + src/server/routes/project.ts | 7 ++-- 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 src/server/middleware/project-exists-middleware.spec.ts diff --git a/src/server/middleware/authentication-middleware.spec.ts b/src/server/middleware/authentication-middleware.spec.ts index 5d89f0a2..872fc4b6 100644 --- a/src/server/middleware/authentication-middleware.spec.ts +++ b/src/server/middleware/authentication-middleware.spec.ts @@ -25,7 +25,7 @@ describe("AuthenticationMiddleware", () => { }) describe("Query token", () => { - it("should return unathorized when invalid query token provided", async () => { + it("should return unauthorized when invalid query token provided", async () => { await authenticationMiddleware({ headers: {}, query: { token: "123" }, diff --git a/src/server/middleware/project-exists-middleware.spec.ts b/src/server/middleware/project-exists-middleware.spec.ts new file mode 100644 index 00000000..fc21759f --- /dev/null +++ b/src/server/middleware/project-exists-middleware.spec.ts @@ -0,0 +1,35 @@ +import { IGetUserAuthInfoRequest } from "./request.model" +import { Response, NextFunction } from "express" +import { projectExistsMiddleware } from "./project-exists-middleware" +import { db } from "../../db/db" +import Boom = require("boom") + +jest.mock("../../db/db") + +describe.only("projectExistsMiddleware", () => { + const nextFunction: NextFunction = jest.fn() + + beforeEach(() => { + jest.resetAllMocks() + }) + it("should return 404 when no project found", async () => { + const request: any = { params: { projectName: "does not exist" } } + db.oneOrNone = jest.fn().mockReturnValueOnce(null) + + await projectExistsMiddleware(request as unknown as IGetUserAuthInfoRequest, + {} as unknown as Response, nextFunction) + expect(nextFunction).toHaveBeenCalledTimes(1) + expect(nextFunction).toHaveBeenCalledWith(Boom.notFound("Project not found")) + }) + + it("should proceed when project found", async () => { + const request: any = { params: { projectName: "my-project" } } + db.oneOrNone = jest.fn().mockReturnValueOnce("projectId") + + await projectExistsMiddleware(request as unknown as IGetUserAuthInfoRequest, + {} as unknown as Response, nextFunction) + expect(nextFunction).toHaveBeenCalledTimes(1) + expect(nextFunction).toHaveBeenCalledWith() + }) + +}) diff --git a/src/server/middleware/project-exists-middleware.ts b/src/server/middleware/project-exists-middleware.ts index 4cffdce0..944e9b32 100644 --- a/src/server/middleware/project-exists-middleware.ts +++ b/src/server/middleware/project-exists-middleware.ts @@ -11,4 +11,5 @@ export const projectExistsMiddleware = async (req: IGetUserAuthInfoRequest, res: if (!project) { return next(boom.notFound("Project not found")) } + next() } diff --git a/src/server/routes/project.ts b/src/server/routes/project.ts index 09bfb1f5..b5d43a9f 100644 --- a/src/server/routes/project.ts +++ b/src/server/routes/project.ts @@ -13,6 +13,7 @@ import { getProjectController } from "../controllers/project/get-project-control import { AllowedRoles, authorizationMiddleware } from "../middleware/authorization-middleware" import { authenticationMiddleware } from "../middleware/authentication-middleware" import { IGetUserAuthInfoRequest } from "../middleware/request.model" +import { projectExistsMiddleware } from "../middleware/project-exists-middleware" export class ProjectRoutes { routes(app: express.Application): void { @@ -47,12 +48,14 @@ export class ProjectRoutes { authenticationMiddleware, authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(projectNameParam), + projectExistsMiddleware, wrapAsync((req: Request, res: Response) => deleteProjectController(req, res))) .get( authenticationMiddleware, authorizationMiddleware([AllowedRoles.Readonly, AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(projectNameParam), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => getProjectController(req, res))) @@ -61,11 +64,9 @@ export class ProjectRoutes { authorizationMiddleware([AllowedRoles.Operator, AllowedRoles.Admin]), paramsSchemaValidator(projectNameParam), bodySchemaValidator(updateProjectSchema), + projectExistsMiddleware, wrapAsync((req: IGetUserAuthInfoRequest, res: Response) => updateProjectController(req, res))) - - app.route("/api/projects/:projectName/allowed-users") - .get() } } From a168171339fedc218e6ae63f7c1abfdccba24602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 19:50:38 +0200 Subject: [PATCH 05/13] removing only --- src/server/middleware/project-exists-middleware.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/middleware/project-exists-middleware.spec.ts b/src/server/middleware/project-exists-middleware.spec.ts index fc21759f..031ed630 100644 --- a/src/server/middleware/project-exists-middleware.spec.ts +++ b/src/server/middleware/project-exists-middleware.spec.ts @@ -6,7 +6,7 @@ import Boom = require("boom") jest.mock("../../db/db") -describe.only("projectExistsMiddleware", () => { +describe("projectExistsMiddleware", () => { const nextFunction: NextFunction = jest.fn() beforeEach(() => { From 2dc1f28fe9930eadf72f818e9d2a3752e9301823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 19:52:47 +0200 Subject: [PATCH 06/13] increasing timeout for integration tests --- integration.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/integration.config.js b/integration.config.js index c7e6b1a5..8e8b1472 100644 --- a/integration.config.js +++ b/integration.config.js @@ -11,4 +11,5 @@ module.exports = { verbose: true, setupFilesAfterEnv: ["/src/tests/integration/helper/setup.ts"], reporters: ["default"], + testTimeout: 20000, } From bc374e1be990a4b170f31de4d550c50382dad258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 20:02:36 +0200 Subject: [PATCH 07/13] projects 404 tests --- src/tests/integration/project.spec.ts | 117 +++++++++++++++----------- 1 file changed, 67 insertions(+), 50 deletions(-) diff --git a/src/tests/integration/project.spec.ts b/src/tests/integration/project.spec.ts index 0b6dd2d0..3b3e20d5 100644 --- a/src/tests/integration/project.spec.ts +++ b/src/tests/integration/project.spec.ts @@ -5,58 +5,75 @@ import { StatusCode } from "../../server/utils/status-code" describe("Projects", () => { - let credentials - beforeAll(async () => { - ({ data: credentials } = await userSetup()) - }) - describe("POST /projects", () => { - it("should be able to create new project", async () => { - await stateSetup(States.EmptyDb) - await request(__server__) - .post("/api/projects") - .set(__tokenHeaderKey__, credentials.token) - .send({ projectName: "test-project-000" }) - .set("Accept", "application/json") - .expect(StatusCode.Created) + let credentials + beforeAll(async () => { + ({ data: credentials } = await userSetup()) }) - it("should return 400 when no projectName provided", async () => { - await stateSetup(States.EmptyDb) - await request(__server__) - .post("/api/projects") - .set(__tokenHeaderKey__, credentials.token) - .send({}) - .set("Accept", "application/json") - .expect(StatusCode.BadRequest) + describe("POST /projects", () => { + it("should be able to create new project", async () => { + await stateSetup(States.EmptyDb) + await request(__server__) + .post("/api/projects") + .set(__tokenHeaderKey__, credentials.token) + .send({ projectName: "test-project-000" }) + .set("Accept", "application/json") + .expect(StatusCode.Created) + }) + it("should return 400 when no projectName provided", async () => { + await stateSetup(States.EmptyDb) + await request(__server__) + .post("/api/projects") + .set(__tokenHeaderKey__, credentials.token) + .send({}) + .set("Accept", "application/json") + .expect(StatusCode.BadRequest) + }) + it("should not be able to create two project with same name", async () => { + await stateSetup(States.ExistingProject) + await request(__server__) + .post("/api/projects") + .set(__tokenHeaderKey__, credentials.token) + .send({ projectName: "test-project" }) + .set("Accept", "application/json") + .expect(StatusCode.Conflict) + }) }) - it("should not be able to create two project with same name", async () => { - await stateSetup(States.ExistingProject) - await request(__server__) - .post("/api/projects") - .set(__tokenHeaderKey__, credentials.token) - .send({ projectName: "test-project" }) - .set("Accept", "application/json") - .expect(StatusCode.Conflict) + describe("PUT /projects/${projectName}", () => { + it("should be able to update project", async () => { + await stateSetup(States.ExistingProject) + await request(__server__) + .put("/api/projects/test-project") + .set(__tokenHeaderKey__, credentials.token) + .send({ projectName: "test-project", upsertScenario: true, projectMembers: [] }) + .set("Accept", "application/json") + .expect(StatusCode.NoContent) + }) + it("should return 404 when project does not exist", async () => { + await stateSetup(States.ExistingProject) + await request(__server__) + .put("/api/projects/test-project-1") + .set(__tokenHeaderKey__, credentials.token) + .send({ projectName: "test-project", upsertScenario: true, projectMembers: [] }) + .set("Accept", "application/json") + .expect(StatusCode.NoContent) + }) }) - }) - describe("PUT /projects/${projectName}", () => { - it("should be able to update project", async () => { - await stateSetup(States.ExistingProject) - await request(__server__) - .put("/api/projects/test-project") - .set(__tokenHeaderKey__, credentials.token) - .send({ projectName: "test-project", upsertScenario: true, projectMembers: [] }) - .set("Accept", "application/json") - .expect(StatusCode.NoContent) + describe("DELETE /projects/${projectName}", () => { + it("should be able to delete project", async () => { + await stateSetup(States.ExistingProject) + await request(__server__) + .delete("/api/projects/test-project") + .set(__tokenHeaderKey__, credentials.token) + .set("Accept", "application/json") + .expect(StatusCode.NoContent) + }) + it("should return 404 when project does not exist", async () => { + await stateSetup(States.ExistingProject) + await request(__server__) + .delete("/api/projects/test-project-1") + .set(__tokenHeaderKey__, credentials.token) + .set("Accept", "application/json") + .expect(StatusCode.NoContent) + }) }) - }) - describe("DELETE /projects/${projectName}", () => { - it("should be able to delete project", async () => { - await stateSetup(States.ExistingProject) - await request(__server__) - .delete("/api/projects/test-project") - .set(__tokenHeaderKey__, credentials.token) - .set("Accept", "application/json") - .expect(StatusCode.NoContent) - }) - }) }) From 02bffa787915b867b193be2710687ba250e8f292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 20:06:39 +0200 Subject: [PATCH 08/13] status code fix --- src/tests/integration/project.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/integration/project.spec.ts b/src/tests/integration/project.spec.ts index 3b3e20d5..931983c6 100644 --- a/src/tests/integration/project.spec.ts +++ b/src/tests/integration/project.spec.ts @@ -55,7 +55,7 @@ describe("Projects", () => { .set(__tokenHeaderKey__, credentials.token) .send({ projectName: "test-project", upsertScenario: true, projectMembers: [] }) .set("Accept", "application/json") - .expect(StatusCode.NoContent) + .expect(StatusCode.NotFound) }) }) describe("DELETE /projects/${projectName}", () => { @@ -73,7 +73,7 @@ describe("Projects", () => { .delete("/api/projects/test-project-1") .set(__tokenHeaderKey__, credentials.token) .set("Accept", "application/json") - .expect(StatusCode.NoContent) + .expect(StatusCode.NotFound) }) }) }) From ddfb3e1092f9e09fe4110d8e6f0c105b6df9a665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 20:10:31 +0200 Subject: [PATCH 09/13] project not found tests for scenario tests --- src/tests/integration/scenario.spec.ts | 89 ++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/tests/integration/scenario.spec.ts b/src/tests/integration/scenario.spec.ts index 55c25251..202cb125 100644 --- a/src/tests/integration/scenario.spec.ts +++ b/src/tests/integration/scenario.spec.ts @@ -36,6 +36,15 @@ describe("Scenario", () => { .set("Accept", "application/json") .expect(StatusCode.BadRequest) }) + it("should return 404 when project does not exist", async () => { + await stateSetup(States.ExistingScenario) + await request(__server__) + .post("/api/projects/test-project-1/scenarios") + .set(__tokenHeaderKey__, credentials.token) + .send({ scenarioName: "test-scenario" }) + .set("Accept", "application/json") + .expect(StatusCode.NotFound) + }) }) describe("PUT /projects/{projectName}/scenarios/{scenarioName}", () => { it("should be able to update scenario", async () => { @@ -94,6 +103,62 @@ describe("Scenario", () => { .set("Accept", "application/json") .expect(StatusCode.NoContent) }) + it("should return 404 when project does not exist", async () => { + await stateSetup(States.ExistingScenario) + await request(__server__) + .put("/api/projects/test-project-1/scenarios/test-scenario") + .set(__tokenHeaderKey__, credentials.token) + .send({ + scenarioName: "test-scenario", + analysisEnabled: false, + zeroErrorToleranceEnabled: true, + deleteSamples: false, + keepTestRunsPeriod: 7, + generateShareToken: true, + extraAggregations: false, + thresholds: { + enabled: true, + percentile: 4.2, + errorRate: 4.2, + throughput: 8.3, + }, + labelTrendChartSettings: { + avgConnectionTime: true, + avgLatency: true, + avgResponseTime: true, + errorRate: true, + p90: true, + p95: true, + p99: true, + throughput: false, + virtualUsers: true, + }, + userSettings: { + requestStats: { + samples: true, + avg: true, + min: true, + max: true, + p90: true, + p95: true, + p99: true, + throughput: true, + network: true, + errorRate: true, + failures: true, + apdex: true, + standardDeviation: true, + }, + }, + apdexSettings: { + toleratingThreshold: 200, + satisfyingThreshold: 50, + enabled: true, + }, + }) + .set("Accept", "application/json") + .expect(StatusCode.NotFound) + }) }) describe("POST /projects/{projectName}/scenarios/{scenarioName}/trends/settings", () => { it("should be able to update scenario trends settings", async () => { @@ -112,6 +177,22 @@ describe("Scenario", () => { }) .expect(StatusCode.NoContent) }) + it("should return 404 when project does not exist", async () => { + await stateSetup(States.ExistingScenario) + await request(__server__) + .post("/api/projects/test-project-1/scenarios/test-scenario/trends/settings") + .set(__tokenHeaderKey__, credentials.token) + .set("Accept", "application/json") + .send({ + aggregatedTrends: true, + labelMetrics: { + errorRate: true, + throughput: true, + percentile90: false, + }, + }) + .expect(StatusCode.NotFound) + }) }) describe("DELETE /projects/{projectName}/scenarios/{scenarioName}", () => { it("should be able to delete scenario", async () => { @@ -122,5 +203,13 @@ describe("Scenario", () => { .set("Accept", "application/json") .expect(StatusCode.NoContent) }) + it("should return 404 when project does not exist", async () => { + await stateSetup(States.ExistingScenario) + await request(__server__) + .delete("/api/projects/test-project-1/scenarios/test-scenario") + .set(__tokenHeaderKey__, credentials.token) + .set("Accept", "application/json") + .expect(StatusCode.NotFound) + }) }) }) From ff9a6ff3430fb93ca5ea65d2427010841e6f0cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 20:18:17 +0200 Subject: [PATCH 10/13] project not found tests for item --- src/tests/integration/items.spec.ts | 75 +++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/tests/integration/items.spec.ts b/src/tests/integration/items.spec.ts index 40bb93e1..b505fbd5 100644 --- a/src/tests/integration/items.spec.ts +++ b/src/tests/integration/items.spec.ts @@ -33,6 +33,15 @@ describe("Items", () => { .send({ environment: "test" }) .expect(StatusCode.Created) }) + it("should return 404 when project does not exist", async () => { + await stateSetup(States.ExistingScenario) + await request(__server__) + .post("/api/projects/test-project-1/scenarios/test-scenario/items/start-async") + .set(__tokenHeaderKey__, token) + .set("Accept", "application/json") + .send({ environment: "test" }) + .expect(StatusCode.NotFound) + }) }) describe("PUT /projects/{projectName}/scenarios/{scenarioName}/items/{itemId}", () => { it("should be able to update test item", async () => { @@ -48,6 +57,19 @@ describe("Items", () => { }) .expect(StatusCode.NoContent) }) + it("should return 404 when project does not exist", async () => { + const { data: { itemId } } = await stateSetup(States.ExistingTestItem) + await request(__server__) + .put(`/api/projects/test-project-1/scenarios/test-scenario/items/${itemId}`) + .set(__tokenHeaderKey__, credentials.token) + .set("Accept", "application/json") + .send({ + environment: "new-test-environment", + note: "new-test-note", + base: true, + }) + .expect(StatusCode.NotFound) + }) }) describe("DELETE /projects/{projectName}/scenarios/{scenarioName}/items/{itemId}", () => { it("should be able to delete test item", async () => { @@ -63,6 +85,19 @@ describe("Items", () => { }) .expect(StatusCode.NoContent) }) + it("should return 404 when project does not exist", async () => { + const { data: { itemId } } = await stateSetup(States.ExistingTestItem) + await request(__server__) + .delete(`/api/projects/test-project-1/scenarios/test-scenario/items/${itemId}`) + .set(__tokenHeaderKey__, credentials.token) + .set("Accept", "application/json") + .send({ + environment: "new-test-environment", + note: "new-test-note", + base: true, + }) + .expect(StatusCode.NotFound) + }) }) describe("POST /projects/{projectName}/scenarios/{scenarioName}/items/{itemId}/share-tokens", () => { it("should be able to create new share token", async () => { @@ -76,6 +111,17 @@ describe("Items", () => { }) .expect(StatusCode.Created) }) + it("should return 404 when project does not exist", async () => { + const { data: { itemId } } = await stateSetup(States.ExistingTestItem) + await request(__server__) + .post(`/api/projects/test-project-1/scenarios/test-scenario/items/${itemId}/share-tokens`) + .set(__tokenHeaderKey__, credentials.token) + .set("Accept", "application/json") + .send({ + name: "test-token", + }) + .expect(StatusCode.NotFound) + }) }) describe("POST /projects/{projectName}/scenarios/{scenarioName}/items/{itemId}/custom-chart-settings", () => { it("should be able to upsert chart settings", async () => { @@ -87,6 +133,15 @@ describe("Items", () => { .send([{ name: "test", metric: "test" }]) .expect(StatusCode.Ok) }) + it("should return 404 when project does not exist", async () => { + const { data: { itemId } } = await stateSetup(States.ExistingTestItem) + await request(__server__) + .post(`/api/projects/test-project-1/scenarios/test-scenario/items/${itemId}/custom-chart-settings`) + .set(__tokenHeaderKey__, credentials.token) + .set("Accept", "application/json") + .send([{ name: "test", metric: "test" }]) + .expect(StatusCode.NotFound) + }) }) describe("GET /projects/{projectName}/scenarios/{scenarioName}/items/{itemId}/custom-chart-settings", () => { it("should be able to upsert chart settings", async () => { @@ -97,6 +152,14 @@ describe("Items", () => { .set("Accept", "application/json") .expect(StatusCode.Ok) }) + it("should return 404 when project does not exist", async () => { + const { data: { itemId } } = await stateSetup(States.ExistingTestItem) + await request(__server__) + .get(`/api/projects/test-project-1/scenarios/test-scenario/items/${itemId}/custom-chart-settings`) + .set(__tokenHeaderKey__, credentials.token) + .set("Accept", "application/json") + .expect(StatusCode.NotFound) + }) }) describe("POST /projects/{projectName}/scenarios/{scenarioName}/items", () => { it("should be able to create test item", async () => { @@ -135,5 +198,17 @@ describe("Items", () => { .field("hostname", "localhost") .expect(StatusCode.Ok) }) + it("should return 404 when project does not exist", async () => { + await stateSetup(States.ExistingScenario) + await request(__server__) + .post("/api/projects/test-project-1/scenarios/test-scenario/items") + .set(__tokenHeaderKey__, credentials.token) + .attach("kpi", path.join(__dirname, "./test-data/kpi.jtl"), "kpi.jtl") + .field("environment", "test-environment") + .field("note", "test-note") + .field("status", ItemStatus.Passed) + .field("hostname", "localhost") + .expect(StatusCode.NotFound) + }) }) }) From 21f1601ba891d31c9eed9ed8a2d97a1609658798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 20:28:45 +0200 Subject: [PATCH 11/13] stop async item test --- src/tests/integration/items.spec.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/tests/integration/items.spec.ts b/src/tests/integration/items.spec.ts index b505fbd5..dfad290e 100644 --- a/src/tests/integration/items.spec.ts +++ b/src/tests/integration/items.spec.ts @@ -43,6 +43,26 @@ describe("Items", () => { .expect(StatusCode.NotFound) }) }) + describe("POST /api/projects/:projectName/scenarios/:scenarioName/items/{itemId}/stop-async", () => { + it("should be able to stop async item", async () => { + const { data: { itemId } } = await stateSetup(States.ExistingTestItem) + await request(__server__) + .post(`/api/projects/test-project/scenarios/test-scenario/items/${itemId}/stop-async`) + .set(__tokenHeaderKey__, token) + .set("Accept", "application/json") + .send({ environment: "test" }) + .expect(StatusCode.Ok) + }) + it("should return 404 when project does not exist", async () => { + const { data: { itemId } } = await stateSetup(States.ExistingTestItem) + await request(__server__) + .post(`/api/projects/test-project-1/scenarios/test-scenario/items/${itemId}/stop-async`) + .set(__tokenHeaderKey__, token) + .set("Accept", "application/json") + .send({ environment: "test" }) + .expect(StatusCode.NotFound) + }) + }) describe("PUT /projects/{projectName}/scenarios/{scenarioName}/items/{itemId}", () => { it("should be able to update test item", async () => { const { data: { itemId } } = await stateSetup(States.ExistingTestItem) From 53a924947c6f7d9b5d77d30785628e7fefe945a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 20:36:26 +0200 Subject: [PATCH 12/13] test fix --- src/tests/integration/items.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/integration/items.spec.ts b/src/tests/integration/items.spec.ts index dfad290e..19973e10 100644 --- a/src/tests/integration/items.spec.ts +++ b/src/tests/integration/items.spec.ts @@ -50,7 +50,7 @@ describe("Items", () => { .post(`/api/projects/test-project/scenarios/test-scenario/items/${itemId}/stop-async`) .set(__tokenHeaderKey__, token) .set("Accept", "application/json") - .send({ environment: "test" }) + .send({ status: "1" }) .expect(StatusCode.Ok) }) it("should return 404 when project does not exist", async () => { From 202162e05b6ca9ee4448dc098e522a00b9895cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lud=C4=9Bk=20Nov=C3=BD?= <13610612+ludeknovy@users.noreply.github.com> Date: Wed, 6 Sep 2023 20:39:56 +0200 Subject: [PATCH 13/13] fix --- src/tests/integration/items.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/integration/items.spec.ts b/src/tests/integration/items.spec.ts index 19973e10..5936c735 100644 --- a/src/tests/integration/items.spec.ts +++ b/src/tests/integration/items.spec.ts @@ -59,7 +59,7 @@ describe("Items", () => { .post(`/api/projects/test-project-1/scenarios/test-scenario/items/${itemId}/stop-async`) .set(__tokenHeaderKey__, token) .set("Accept", "application/json") - .send({ environment: "test" }) + .send({ status: "1" }) .expect(StatusCode.NotFound) }) })