Files
calendar/packages/features/bookingReport/repositories/PrismaBookingReportRepository.test.ts
T
Udit TakkarandGitHub 0330d14210 feat: system admin blocklist table (#25039)
* feat: system admin blocklist table

* chore: text

* fix: type error

* fix: type error

* fix: type error

* fix: frontend bug

* chore: improvments

* refactor: use shared components

* refactor: improvements

* fix: delete

* refactor: support multiple watchlist

* chore: update translation

* fix: type err

* fix: bulk bug

* tests: add unit test

* refactor: file

* refactor: file

* fix: type error

* fix: type error

* chore: translation

* refactor: use shared comments

* fix: imports

* fix: type error
2026-01-09 08:19:54 -03:00

368 lines
12 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from "vitest";
import type { PrismaClient } from "@calcom/prisma";
import { BookingReportReason } from "@calcom/prisma/enums";
import type { CreateBookingReportInput } from "./IBookingReportRepository";
import { PrismaBookingReportRepository } from "./PrismaBookingReportRepository";
vi.mock("@sentry/nextjs", () => ({
captureException: vi.fn(),
}));
describe("PrismaBookingReportRepository", () => {
let repository: PrismaBookingReportRepository;
const mockPrisma = {
bookingReport: {
create: vi.fn(),
findUnique: vi.fn(),
findMany: vi.fn(),
findFirst: vi.fn(),
update: vi.fn(),
updateMany: vi.fn(),
count: vi.fn(),
},
} as unknown as PrismaClient;
beforeEach(() => {
vi.clearAllMocks();
repository = new PrismaBookingReportRepository(mockPrisma);
});
describe("createReport", () => {
it("should create a booking report with all fields", async () => {
const input: CreateBookingReportInput = {
bookingUid: "test-booking-uid-1",
bookerEmail: "booker@example.com",
reportedById: 1,
reason: BookingReportReason.SPAM,
description: "This is spam",
cancelled: true,
organizationId: 10,
};
const mockCreatedReport = { id: "report-123" };
mockPrisma.bookingReport.create.mockResolvedValue(mockCreatedReport);
const result = await repository.createReport(input);
expect(result).toEqual({ id: "report-123" });
expect(mockPrisma.bookingReport.create).toHaveBeenCalledWith({
data: {
bookingUid: "test-booking-uid-1",
bookerEmail: "booker@example.com",
reportedById: 1,
reason: BookingReportReason.SPAM,
description: "This is spam",
cancelled: true,
organizationId: 10,
},
select: { id: true },
});
});
it("should create a booking report without optional fields", async () => {
const input: CreateBookingReportInput = {
bookingUid: "test-booking-uid-2",
bookerEmail: "user@example.com",
reportedById: 2,
reason: BookingReportReason.DONT_KNOW_PERSON,
cancelled: false,
};
const mockCreatedReport = { id: "report-456" };
mockPrisma.bookingReport.create.mockResolvedValue(mockCreatedReport);
const result = await repository.createReport(input);
expect(result).toEqual({ id: "report-456" });
expect(mockPrisma.bookingReport.create).toHaveBeenCalledWith({
data: {
bookingUid: "test-booking-uid-2",
bookerEmail: "user@example.com",
reportedById: 2,
reason: BookingReportReason.DONT_KNOW_PERSON,
description: undefined,
cancelled: false,
organizationId: undefined,
},
select: { id: true },
});
});
});
describe("findAllReportedBookings", () => {
it("should find all reported bookings with pagination", async () => {
const mockReports = [
{
id: "report-1",
bookingUid: "booking-1",
bookerEmail: "user1@example.com",
reportedById: 1,
reason: BookingReportReason.SPAM,
description: "Spam",
cancelled: false,
createdAt: new Date("2025-01-01T10:00:00Z"),
status: "PENDING",
systemStatus: "PENDING",
watchlistId: null,
globalWatchlistId: null,
organizationId: null,
reportedBy: null,
booking: {
id: 1,
uid: "booking-1",
title: "Test Booking",
startTime: new Date(),
endTime: new Date(),
},
watchlist: null,
globalWatchlist: null,
organization: null,
},
{
id: "report-2",
bookingUid: "booking-2",
bookerEmail: "user2@example.com",
reportedById: 2,
reason: BookingReportReason.DONT_KNOW_PERSON,
description: null,
cancelled: false,
createdAt: new Date("2025-01-01T11:00:00Z"),
status: "PENDING",
systemStatus: "PENDING",
watchlistId: null,
globalWatchlistId: null,
organizationId: null,
reportedBy: null,
booking: {
id: 2,
uid: "booking-2",
title: "Test Booking 2",
startTime: new Date(),
endTime: new Date(),
},
watchlist: null,
globalWatchlist: null,
organization: null,
},
];
mockPrisma.bookingReport.findMany.mockResolvedValue(mockReports);
mockPrisma.bookingReport.count.mockResolvedValue(2);
const result = await repository.findAllReportedBookings({ skip: 0, take: 10 });
expect(result).toEqual({
rows: mockReports.map((r) => ({ ...r, reporter: r.reportedBy })),
meta: { totalRowCount: 2 },
});
expect(mockPrisma.bookingReport.findMany).toHaveBeenCalled();
expect(mockPrisma.bookingReport.count).toHaveBeenCalled();
});
});
describe("updateReportStatus", () => {
it("should update report status with organizationId", async () => {
mockPrisma.bookingReport.updateMany.mockResolvedValue({ count: 1 });
await repository.updateReportStatus({
reportId: "report-123",
status: "BLOCKED",
organizationId: 100,
});
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: {
id: "report-123",
organizationId: 100,
},
data: { status: "BLOCKED" },
});
});
it("should update report status without organizationId", async () => {
mockPrisma.bookingReport.updateMany.mockResolvedValue({ count: 1 });
await repository.updateReportStatus({
reportId: "report-456",
status: "DISMISSED",
});
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: {
id: "report-456",
},
data: { status: "DISMISSED" },
});
});
it("should update report status to PENDING", async () => {
mockPrisma.bookingReport.updateMany.mockResolvedValue({ count: 1 });
await repository.updateReportStatus({
reportId: "report-789",
status: "PENDING",
organizationId: 200,
});
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: {
id: "report-789",
organizationId: 200,
},
data: { status: "PENDING" },
});
});
});
describe("updateSystemReportStatus", () => {
it("should update systemStatus with globalWatchlistId", async () => {
mockPrisma.bookingReport.update.mockResolvedValue({ id: "report-1" });
await repository.updateSystemReportStatus({
reportId: "report-123",
systemStatus: "BLOCKED",
globalWatchlistId: "watchlist-456",
});
expect(mockPrisma.bookingReport.update).toHaveBeenCalledWith({
where: { id: "report-123" },
data: {
systemStatus: "BLOCKED",
globalWatchlistId: "watchlist-456",
},
});
});
it("should update systemStatus without globalWatchlistId", async () => {
mockPrisma.bookingReport.update.mockResolvedValue({ id: "report-1" });
await repository.updateSystemReportStatus({
reportId: "report-456",
systemStatus: "DISMISSED",
});
expect(mockPrisma.bookingReport.update).toHaveBeenCalledWith({
where: { id: "report-456" },
data: {
systemStatus: "DISMISSED",
},
});
});
});
describe("bulkUpdateSystemReportStatus", () => {
it("should bulk update systemStatus with globalWatchlistId", async () => {
mockPrisma.bookingReport.updateMany.mockResolvedValue({ count: 3 });
const result = await repository.bulkUpdateSystemReportStatus({
reportIds: ["r1", "r2", "r3"],
systemStatus: "BLOCKED",
globalWatchlistId: "global-1",
});
expect(result).toEqual({ updated: 3 });
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: { id: { in: ["r1", "r2", "r3"] } },
data: {
systemStatus: "BLOCKED",
globalWatchlistId: "global-1",
},
});
});
it("should bulk update systemStatus without globalWatchlistId", async () => {
mockPrisma.bookingReport.updateMany.mockResolvedValue({ count: 2 });
const result = await repository.bulkUpdateSystemReportStatus({
reportIds: ["r1", "r2"],
systemStatus: "DISMISSED",
});
expect(result).toEqual({ updated: 2 });
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: { id: { in: ["r1", "r2"] } },
data: {
systemStatus: "DISMISSED",
},
});
});
});
describe("countSystemPendingReports", () => {
it("should count reports with systemStatus PENDING", async () => {
mockPrisma.bookingReport.count.mockResolvedValue(5);
const result = await repository.countSystemPendingReports();
expect(result).toBe(5);
expect(mockPrisma.bookingReport.count).toHaveBeenCalledWith({
where: { systemStatus: "PENDING" },
});
});
});
describe("bulkLinkGlobalWatchlistWithSystemStatus", () => {
it("should do nothing when links array is empty", async () => {
await repository.bulkLinkGlobalWatchlistWithSystemStatus({
links: [],
systemStatus: "BLOCKED",
});
expect(mockPrisma.bookingReport.updateMany).not.toHaveBeenCalled();
});
it("should link each report to its corresponding globalWatchlistId", async () => {
mockPrisma.bookingReport.updateMany.mockResolvedValue({ count: 1 });
await repository.bulkLinkGlobalWatchlistWithSystemStatus({
links: [
{ reportId: "r1", globalWatchlistId: "w1" },
{ reportId: "r2", globalWatchlistId: "w2" },
{ reportId: "r3", globalWatchlistId: "w3" },
],
systemStatus: "BLOCKED",
});
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledTimes(3);
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: { id: { in: ["r1"] } },
data: { globalWatchlistId: "w1", systemStatus: "BLOCKED" },
});
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: { id: { in: ["r2"] } },
data: { globalWatchlistId: "w2", systemStatus: "BLOCKED" },
});
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: { id: { in: ["r3"] } },
data: { globalWatchlistId: "w3", systemStatus: "BLOCKED" },
});
});
it("should group reports with the same globalWatchlistId", async () => {
mockPrisma.bookingReport.updateMany.mockResolvedValue({ count: 2 });
await repository.bulkLinkGlobalWatchlistWithSystemStatus({
links: [
{ reportId: "r1", globalWatchlistId: "w1" },
{ reportId: "r2", globalWatchlistId: "w1" },
{ reportId: "r3", globalWatchlistId: "w2" },
],
systemStatus: "BLOCKED",
});
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledTimes(2);
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: { id: { in: ["r1", "r2"] } },
data: { globalWatchlistId: "w1", systemStatus: "BLOCKED" },
});
expect(mockPrisma.bookingReport.updateMany).toHaveBeenCalledWith({
where: { id: { in: ["r3"] } },
data: { globalWatchlistId: "w2", systemStatus: "BLOCKED" },
});
});
});
});