test/unit/api/v2/assets/assets.validator.spec.tsmodified
import * as chai from "chai";
import chaiAsPromised from "chai-as-promised";
import sinonChai from "sinon-chai";
import { mockRequest, mockResponse, ResponseOutput } from "mock-req-res";
import { describe } from "mocha";
import sinon from "sinon";
import { validatePatchAssetRequest } from "../../../../../src/api/v2/projects/assets/assets.validator";

const expect = chai.expect;
chai.use(chaiAsPromised).use(sinonChai);
chai.should();

/* eslint-disable @typescript-eslint/no-explicit-any */
describe("Assets Validator tests", () => {
    let res: ResponseOutput;
    let next: sinon.SinonSpy;
    const projectId = "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee";
    const assetId = "11111111-2222-4333-8444-555555555555";
    const assetTypeId = "cccccccc-dddd-4eee-8fff-aaaaaaaaaaaa";
    const parentAssetId = "22222222-3333-4444-8555-666666666666";

    beforeEach(() => {
        res = mockResponse();
        next = sinon.spy();
    });

    describe("validatePatchAssetRequest", () => {
        it("should call next() when body contains a valid name", () => {
            const req = mockRequest({ params: { projectId, assetId }, body: { name: "New Name" } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(next).to.have.been.calledOnce;
        });

        it("should return 400 when projectId is invalid", () => {
            const req = mockRequest({ params: { projectId: "not-a-uuid", assetId }, body: { name: "New Name" } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(400);
            expect(next).to.not.have.been.called;
        });

        it("should return 400 when assetId is invalid", () => {
            const req = mockRequest({ params: { projectId, assetId: "not-a-uuid" }, body: { name: "New Name" } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(400);
            expect(next).to.not.have.been.called;
        });

        it("should return 400 when the body is empty", () => {
            const req = mockRequest({ params: { projectId, assetId }, body: {} });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(400);
            expect(next).to.not.have.been.called;
        });

        it("should return 406 when assetTypeId is supplied (relational field, out of scope)", () => {
            const req = mockRequest({ params: { projectId, assetId }, body: { assetTypeId } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(406);
            expect(next).to.not.have.been.called;
        });

        it("should return 406 when parentAssetId is supplied (relational field, out of scope)", () => {
            const req = mockRequest({ params: { projectId, assetId }, body: { parentAssetId } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(406);
            expect(next).to.not.have.been.called;
        });

        it("should return 406 when name is mixed with a relational field", () => {
            const req = mockRequest({ params: { projectId, assetId }, body: { name: "New Name", assetTypeId, parentAssetId } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(406);
            expect(next).to.not.have.been.called;
        });

        it("should return 406 when a non-patchable field is supplied", () => {
            const req = mockRequest({ params: { projectId, assetId }, body: { createdBy: "someone@example.com" } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(406);
            expect(next).to.not.have.been.called;
        });

        it("should return 406 when name is mixed with a non-patchable field", () => {
            const req = mockRequest({ params: { projectId, assetId }, body: { name: "New Name", createdBy: "someone@example.com" } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(406);
            expect(next).to.not.have.been.called;
        });

        it("should return 400 when name is blank", () => {
            const req = mockRequest({ params: { projectId, assetId }, body: { name: "   " } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(400);
            expect(next).to.not.have.been.called;
        });

        it("should return 400 when name is not a string", () => {
            const req = mockRequest({ params: { projectId, assetId }, body: { name: 123 } });

            validatePatchAssetRequest(req as any, res as any, next);

            expect(res.status).to.have.been.calledWith(400);
            expect(next).to.not.have.been.called;
        });
    });
});