import { describe, it, expect } from "vitest"; import { validate } from "class-validator"; import { plainToInstance } from "class-transformer"; import { QueryActivityLogDto } from "./query-activity-log.dto"; import { ActivityAction, EntityType } from "@prisma/client"; describe("QueryActivityLogDto", () => { describe("workspaceId validation", () => { it("should pass with valid UUID", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", }); const errors = await validate(dto); expect(errors).toHaveLength(0); }); it("should fail with invalid UUID", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "invalid-uuid", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); expect(errors[0].property).toBe("workspaceId"); expect(errors[0].constraints?.isUuid).toBeDefined(); }); it("should pass when workspaceId is missing (it's optional)", async () => { const dto = plainToInstance(QueryActivityLogDto, {}); const errors = await validate(dto); // workspaceId is optional in DTO since it's set by controller from @Workspace() decorator const workspaceIdError = errors.find((e) => e.property === "workspaceId"); expect(workspaceIdError).toBeUndefined(); }); }); describe("userId validation", () => { it("should pass with valid UUID", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", userId: "550e8400-e29b-41d4-a716-446655440001", }); const errors = await validate(dto); expect(errors).toHaveLength(0); }); it("should fail with invalid UUID", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", userId: "not-a-uuid", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); expect(errors[0].property).toBe("userId"); }); it("should pass when userId is not provided (optional)", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", }); const errors = await validate(dto); expect(errors).toHaveLength(0); }); }); describe("action validation", () => { it("should pass with valid ActivityAction", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", action: ActivityAction.CREATED, }); const errors = await validate(dto); expect(errors).toHaveLength(0); }); it("should fail with invalid action value", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", action: "INVALID_ACTION", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); expect(errors[0].property).toBe("action"); }); it("should pass when action is not provided (optional)", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", }); const errors = await validate(dto); expect(errors).toHaveLength(0); }); }); describe("entityType validation", () => { it("should pass with valid EntityType", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", entityType: EntityType.TASK, }); const errors = await validate(dto); expect(errors).toHaveLength(0); }); it("should fail with invalid entityType value", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", entityType: "INVALID_TYPE", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); expect(errors[0].property).toBe("entityType"); }); }); describe("entityId validation", () => { it("should pass with valid UUID", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", entityId: "550e8400-e29b-41d4-a716-446655440002", }); const errors = await validate(dto); expect(errors).toHaveLength(0); }); it("should fail with invalid UUID", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", entityId: "invalid-entity-id", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); expect(errors[0].property).toBe("entityId"); }); }); describe("date validation", () => { it("should pass with valid ISO date strings", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", startDate: "2024-01-01T00:00:00.000Z", endDate: "2024-01-31T23:59:59.999Z", }); const errors = await validate(dto); expect(errors).toHaveLength(0); }); it("should fail with invalid date format", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", startDate: "not-a-date", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); expect(errors[0].property).toBe("startDate"); }); }); describe("pagination validation", () => { it("should pass with valid page and limit", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", page: "1", limit: "50", }); const errors = await validate(dto); expect(errors).toHaveLength(0); expect(dto.page).toBe(1); expect(dto.limit).toBe(50); }); it("should fail when page is less than 1", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", page: "0", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); const pageError = errors.find((e) => e.property === "page"); expect(pageError?.constraints?.min).toBeDefined(); }); it("should fail when limit exceeds 100", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", limit: "101", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); const limitError = errors.find((e) => e.property === "limit"); expect(limitError?.constraints?.max).toBeDefined(); }); it("should fail when page is not an integer", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", page: "1.5", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); const pageError = errors.find((e) => e.property === "page"); expect(pageError?.constraints?.isInt).toBeDefined(); }); it("should fail when limit is not an integer", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", limit: "50.5", }); const errors = await validate(dto); expect(errors.length).toBeGreaterThan(0); const limitError = errors.find((e) => e.property === "limit"); expect(limitError?.constraints?.isInt).toBeDefined(); }); }); describe("multiple filters", () => { it("should pass with all valid filters combined", async () => { const dto = plainToInstance(QueryActivityLogDto, { workspaceId: "550e8400-e29b-41d4-a716-446655440000", userId: "550e8400-e29b-41d4-a716-446655440001", action: ActivityAction.UPDATED, entityType: EntityType.PROJECT, entityId: "550e8400-e29b-41d4-a716-446655440002", startDate: "2024-01-01T00:00:00.000Z", endDate: "2024-01-31T23:59:59.999Z", page: "2", limit: "25", }); const errors = await validate(dto); expect(errors).toHaveLength(0); }); }); });