test/unit/api/v2/assetTypes/asset.types.controller.spec.tsmodified
import sinon from "sinon";
import * as chai from "chai";
import chaiAsPromised from "chai-as-promised";
import sinonChai from "sinon-chai";
import { mockRequest, mockResponse, RequestOutput, ResponseOutput } from "mock-req-res";
import * as service from "../../../../../src/services/asset.types.service";
import * as controller from "../../../../../src/api/v2/projects/assettypes/asset.types.controller";
import { NotFoundError } from "../../../../../src/types/errortypes";
import { AssetType } from "../../../../../src/services/asset.types.service";

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

/* eslint-disable @typescript-eslint/no-explicit-any */
describe("AssetTypes Controller", () => {
    let req: RequestOutput;
    let res: ResponseOutput;
    const projectId = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
    const assetTypeId = "11111111-2222-3333-4444-555555555555";

    const sampleAssetType: AssetType = {
        assetTypeId,
        name: "Pump",
        description: "Mechanical pumps",
        createdBy: "user@example.com",
        insertedOn: new Date("2025-01-01T00:00:00Z"),
        lastModifiedOn: null,
        lastModifiedBy: null,
    };

    const sampleAssetTypeNoDescription: AssetType = {
        assetTypeId,
        name: "Pump",
        description: null,
        createdBy: "user@example.com",
        insertedOn: new Date("2025-01-01T00:00:00Z"),
        lastModifiedOn: null,
        lastModifiedBy: null,
    };

    beforeEach(() => {
        res = mockResponse();
    });

    afterEach(() => {
        sinon.restore();
    });

    describe("listAssetTypes", () => {
        it("should return 200 with the list of asset types", async () => {
            req = mockRequest({ params: { projectId }, query: {} });
            sinon.stub(service, "listAssetTypes").resolves([sampleAssetType]);

            await controller.listAssetTypes(req as any, res as any);

            expect(res.status).to.have.been.calledWith(200);
            expect(res.json).to.have.been.calledWith([sampleAssetType]);
        });

        it("should pass the projectId through to the service", async () => {
            req = mockRequest({ params: { projectId }, query: {} });
            const listStub = sinon.stub(service, "listAssetTypes").resolves([]);

            await controller.listAssetTypes(req as any, res as any);

            expect(listStub).to.have.been.calledWith(projectId);
            expect(res.status).to.have.been.calledWith(200);
            expect(res.json).to.have.been.calledWith([]);
        });

        it("should return 500 on unexpected error", async () => {
            req = mockRequest({ params: { projectId }, query: {} });
            sinon.stub(service, "listAssetTypes").throws(new Error("DB error"));

            await controller.listAssetTypes(req as any, res as any);

            expect(res.status).to.have.been.calledWith(500);
        });
    });

    describe("getAssetType", () => {
        it("should return 200 with the asset type", async () => {
            req = mockRequest({ params: { projectId, assetTypeId } });
            sinon.stub(service, "getAssetTypeById").resolves(sampleAssetType);

            await controller.getAssetType(req as any, res as any);

            expect(res.status).to.have.been.calledWith(200);
            expect(res.json).to.have.been.calledWith(sampleAssetType);
        });

        it("should return 404 when asset type not found", async () => {
            req = mockRequest({ params: { projectId, assetTypeId } });
            sinon.stub(service, "getAssetTypeById").throws(new NotFoundError("Not found"));

            await controller.getAssetType(req as any, res as any);

            expect(res.status).to.have.been.calledWith(404);
        });
    });

    describe("createAssetType", () => {
        it("should return 201 with the created asset type", async () => {
            req = mockRequest({ params: { projectId }, body: { name: "Pump", description: "Mechanical pumps" } });
            sinon.stub(service, "createAssetType").resolves(sampleAssetType);

            await controller.createAssetType(req as any, res as any);

            expect(res.status).to.have.been.calledWith(201);
            expect(res.json).to.have.been.calledWith(sampleAssetType);
        });

        it("should return 201 without description", async () => {
            req = mockRequest({ params: { projectId }, body: { name: "Pump" } });
            const createStub = sinon.stub(service, "createAssetType").resolves(sampleAssetTypeNoDescription);

            await controller.createAssetType(req as any, res as any);

            expect(createStub).to.have.been.calledWith(projectId, "Pump", null);
            expect(res.status).to.have.been.calledWith(201);
            expect(res.json).to.have.been.calledWith(sampleAssetTypeNoDescription);
        });

        it("should return 500 on unexpected error", async () => {
            req = mockRequest({ params: { projectId }, body: { name: "Pump" } });
            sinon.stub(service, "createAssetType").throws(new Error("DB error"));

            await controller.createAssetType(req as any, res as any);

            expect(res.status).to.have.been.calledWith(500);
        });
    });
});