* add rrTimeStampBasis to prisma schema * add rr time stamp basis setting * update migration * add getLuckyUser logic * add rrTimestampBasis to tests * add load balancing warning message * disable load balancing logic * disable load balancing in event type settings * add missing translations * fix UI * disable load balancing on all team event types * don't show routing forms in router position * use correct interval times * fix variable naming * fix event type update handler * add test to booking.test.ts * add test for getting interval times * remove not needed prop * fix label * improve warning message * fix removing maxLeadTreshold * fix typo * fix disabling maxLeadThreshold * add back missing translation * improve rr reset interval label * fix rr_load_balancing_disabled text * improve test * fix description * only use rrTimestampBasis in weights round robin * fix dropdown width --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com>
250 lines
7.8 KiB
TypeScript
250 lines
7.8 KiB
TypeScript
import prismaMock from "../../../../tests/libs/__mocks__/prisma";
|
|
|
|
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
|
|
import { BookingStatus, RRTimestampBasis } from "@calcom/prisma/enums";
|
|
|
|
import { BookingRepository } from "./booking";
|
|
|
|
const createAttendeeNoShowTestBookings = async () => {
|
|
await Promise.all([
|
|
prismaMock.booking.create({
|
|
data: {
|
|
userId: 1,
|
|
uid: "123",
|
|
eventTypeId: 1,
|
|
status: BookingStatus.ACCEPTED,
|
|
attendees: {
|
|
create: {
|
|
email: "test1@example.com",
|
|
noShow: false,
|
|
name: "Test 1",
|
|
timeZone: "America/Toronto",
|
|
},
|
|
},
|
|
startTime: new Date("2025-05-01T00:00:00.000Z"),
|
|
endTime: new Date("2025-05-01T01:00:00.000Z"),
|
|
title: "Test Event",
|
|
},
|
|
}),
|
|
prismaMock.booking.create({
|
|
data: {
|
|
userId: 1,
|
|
uid: "123",
|
|
eventTypeId: 1,
|
|
status: BookingStatus.ACCEPTED,
|
|
attendees: {
|
|
create: {
|
|
email: "test1@example.com",
|
|
noShow: true,
|
|
name: "Test 1",
|
|
timeZone: "America/Toronto",
|
|
},
|
|
},
|
|
startTime: new Date("2025-05-01T00:00:00.000Z"),
|
|
endTime: new Date("2025-05-01T01:00:00.000Z"),
|
|
title: "Test Event",
|
|
},
|
|
}),
|
|
]);
|
|
};
|
|
|
|
const createHostNoShowTestBookings = async () => {
|
|
await Promise.all([
|
|
prismaMock.booking.create({
|
|
data: {
|
|
userId: 1,
|
|
uid: "123",
|
|
eventTypeId: 1,
|
|
status: BookingStatus.ACCEPTED,
|
|
attendees: {
|
|
create: {
|
|
email: "test1@example.com",
|
|
noShow: false,
|
|
name: "Test 1",
|
|
timeZone: "America/Toronto",
|
|
},
|
|
},
|
|
startTime: new Date("2025-05-01T00:00:00.000Z"),
|
|
endTime: new Date("2025-05-01T01:00:00.000Z"),
|
|
title: "Test Event",
|
|
noShowHost: false,
|
|
},
|
|
}),
|
|
prismaMock.booking.create({
|
|
data: {
|
|
userId: 1,
|
|
uid: "123",
|
|
eventTypeId: 1,
|
|
status: BookingStatus.ACCEPTED,
|
|
attendees: {
|
|
create: {
|
|
email: "test1@example.com",
|
|
noShow: false,
|
|
name: "Test 1",
|
|
timeZone: "America/Toronto",
|
|
},
|
|
},
|
|
startTime: new Date("2025-05-01T00:00:00.000Z"),
|
|
endTime: new Date("2025-05-01T01:00:00.000Z"),
|
|
title: "Test Event",
|
|
noShowHost: true,
|
|
},
|
|
}),
|
|
]);
|
|
};
|
|
|
|
describe("BookingRepository", () => {
|
|
beforeEach(() => {
|
|
vi.setSystemTime(new Date("2025-05-01T00:00:00.000Z"));
|
|
vi.resetAllMocks();
|
|
});
|
|
describe("getAllBookingsForRoundRobin", () => {
|
|
describe("includeNoShowInRRCalculation", () => {
|
|
it("it should not include bookings where the attendee is a no show", async () => {
|
|
await createAttendeeNoShowTestBookings();
|
|
|
|
const bookings = await BookingRepository.getAllBookingsForRoundRobin({
|
|
users: [{ id: 1, email: "organizer1@example.com" }],
|
|
eventTypeId: 1,
|
|
startDate: new Date(),
|
|
endDate: new Date(),
|
|
includeNoShowInRRCalculation: false,
|
|
virtualQueuesData: null,
|
|
});
|
|
|
|
expect(bookings).toHaveLength(1);
|
|
});
|
|
it("it should include bookings where the attendee is a no show", async () => {
|
|
await createAttendeeNoShowTestBookings();
|
|
|
|
const bookings = await BookingRepository.getAllBookingsForRoundRobin({
|
|
users: [{ id: 1, email: "organizer1@example.com" }],
|
|
eventTypeId: 1,
|
|
startDate: new Date(),
|
|
endDate: new Date(),
|
|
includeNoShowInRRCalculation: true,
|
|
virtualQueuesData: null,
|
|
});
|
|
|
|
expect(bookings).toHaveLength(2);
|
|
});
|
|
it("it should not include bookings where the host is a no show", async () => {
|
|
await createHostNoShowTestBookings();
|
|
|
|
const bookings = await BookingRepository.getAllBookingsForRoundRobin({
|
|
users: [{ id: 1, email: "organizer1@example.com" }],
|
|
eventTypeId: 1,
|
|
startDate: new Date(),
|
|
endDate: new Date(),
|
|
includeNoShowInRRCalculation: false,
|
|
virtualQueuesData: null,
|
|
});
|
|
|
|
expect(bookings).toHaveLength(1);
|
|
});
|
|
it("it should include bookings where the host is a no show", async () => {
|
|
await createHostNoShowTestBookings();
|
|
|
|
const bookings = await BookingRepository.getAllBookingsForRoundRobin({
|
|
users: [{ id: 1, email: "organizer1@example.com" }],
|
|
eventTypeId: 1,
|
|
startDate: new Date(),
|
|
endDate: new Date(),
|
|
includeNoShowInRRCalculation: true,
|
|
virtualQueuesData: null,
|
|
});
|
|
|
|
expect(bookings).toHaveLength(2);
|
|
});
|
|
it("it should not include bookings where the host or an attendee is a no show", async () => {
|
|
await createHostNoShowTestBookings();
|
|
await createAttendeeNoShowTestBookings();
|
|
|
|
const bookings = await BookingRepository.getAllBookingsForRoundRobin({
|
|
users: [{ id: 1, email: "organizer1@example.com" }],
|
|
eventTypeId: 1,
|
|
startDate: new Date(),
|
|
endDate: new Date(),
|
|
includeNoShowInRRCalculation: false,
|
|
virtualQueuesData: null,
|
|
});
|
|
|
|
expect(bookings).toHaveLength(2);
|
|
});
|
|
it("it should include bookings where the host or an attendee is a no show", async () => {
|
|
await createHostNoShowTestBookings();
|
|
await createAttendeeNoShowTestBookings();
|
|
|
|
const bookings = await BookingRepository.getAllBookingsForRoundRobin({
|
|
users: [{ id: 1, email: "organizer1@example.com" }],
|
|
eventTypeId: 1,
|
|
startDate: new Date(),
|
|
endDate: new Date(),
|
|
includeNoShowInRRCalculation: true,
|
|
virtualQueuesData: null,
|
|
});
|
|
|
|
expect(bookings).toHaveLength(4);
|
|
});
|
|
});
|
|
it("should use start time as timestamp basis for the booking count", async () => {
|
|
await Promise.all([
|
|
prismaMock.booking.create({
|
|
data: {
|
|
userId: 1,
|
|
uid: "booking_may",
|
|
eventTypeId: 1,
|
|
status: BookingStatus.ACCEPTED,
|
|
attendees: {
|
|
create: {
|
|
email: "test1@example.com",
|
|
noShow: false,
|
|
name: "Test 1",
|
|
timeZone: "America/Toronto",
|
|
},
|
|
},
|
|
startTime: new Date("2025-05-26T00:00:00.000Z"),
|
|
endTime: new Date("2025-05-26T01:00:00.000Z"),
|
|
createdAt: new Date("2025-05-03T00:00:00.000Z"),
|
|
title: "Test Event",
|
|
},
|
|
}),
|
|
prismaMock.booking.create({
|
|
data: {
|
|
userId: 1,
|
|
uid: "booking_june",
|
|
eventTypeId: 1,
|
|
status: BookingStatus.ACCEPTED,
|
|
attendees: {
|
|
create: {
|
|
email: "test1@example.com",
|
|
noShow: true,
|
|
name: "Test 1",
|
|
timeZone: "America/Toronto",
|
|
},
|
|
},
|
|
startTime: new Date("2025-06-26T00:00:00.000Z"),
|
|
endTime: new Date("2025-06-26T01:00:00.000Z"),
|
|
createdAt: new Date("2025-05-03T00:00:00.000Z"),
|
|
title: "Test Event",
|
|
},
|
|
}),
|
|
]);
|
|
|
|
const bookings = await BookingRepository.getAllBookingsForRoundRobin({
|
|
users: [{ id: 1, email: "organizer1@example.com" }],
|
|
eventTypeId: 1,
|
|
startDate: new Date("2025-06-01T00:00:00.000Z"),
|
|
endDate: new Date("2025-06-30T23:59:00.000Z"),
|
|
includeNoShowInRRCalculation: true,
|
|
virtualQueuesData: null,
|
|
rrTimestampBasis: RRTimestampBasis.START_TIME,
|
|
});
|
|
|
|
expect(bookings).toHaveLength(1);
|
|
expect(bookings[0].startTime.toISOString()).toBe(new Date("2025-06-26T00:00:00.000Z").toISOString());
|
|
});
|
|
});
|
|
});
|