Files
calendar/packages/lib/server/getLuckyUser.integration-test.ts
T
cd311f076c feat: Round Robin Weights (#15558)
* WIP

* add frontend

* backend to update weight

* UI improvements

* WIP weight algorithm

* enable weights switch + algorithm improvements

* fix weightDescription

* clean up code

* remove OOOEntryHost from schema.prisma

* implement logic (not yet tested)

* add tests for weight algorithm

* add test with weight adjustment

* finish unit tests

* fix type error

* fix type error

* add migration

* fix type error

* fix event type update handler

* fix failing test

* UI fixes for saving hosts

* make sure weightAdjustment is not lost on host changes

* fix weightadjustment for new hosts

* add weightAdjustment to availableUsers

* fix type errors

* fix default value for weight

* make weight and weightAdjustment optional

* fix type errors from schema changes

* type fix

* clean up code

* improve comments

* remove comment

* clean up code

* add tests & weight adjustment improvments

* better variable naming

* fixes for weight adjustments

* make weightAdjustments proportional to weights

* fix previous host weight adjustments

* improved tests for weight adjustments

* save weight and priority + sort hosts correctly

* fix type error

* code clean up

* remove console.log

* use BookingRepository to fetch bookings of users

* use BookingRepository to fetch bookings in getLuckyUser

* fix type errors

* fix weightAdjustment if changed from fixed to rr host

* disable weights when 'assign all' is enabled

* typo

* allow 0 weight

* set min (and max) for weight and priority

* use useWatch

* code clean up

* fix type error

* only count accepted bookings for RR

* fix type error

* improve data fetching of bookings

* only filter bookings of availableUsers

* code clean up form feedback

* fix tests

* don't count no show bookings

* code clean up

* choose user with highest weight

* use one reduce instead of two

* use reduce instead of filter and map

* don't show weights toggle when 'assign all' is enabled

* design fixes

* fix type errors

* fix: type check

* Update packages/features/eventtypes/components/AddMembersWithSwitch.tsx

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
2024-08-15 15:01:15 +01:00

381 lines
11 KiB
TypeScript

import { describe, it, expect, afterEach, beforeAll, afterAll } from "vitest";
import prisma from "@calcom/prisma";
import { getLuckyUser } from "./getLuckyUser";
describe("getLuckyUser tests", () => {
describe("should not consider no show bookings for round robin: ", () => {
let userIds: number[] = [];
let eventTypeId: number;
beforeAll(async () => {
const event = await prisma.eventType.create({
data: {
title: "Test Event",
slug: "test-event",
length: 15,
},
select: {
id: true,
},
});
eventTypeId = event.id;
});
afterEach(async () => {
await prisma.user.deleteMany({
where: {
id: {
in: userIds,
},
},
});
userIds = [];
});
afterAll(async () => {
await prisma.eventType.delete({
where: {
id: eventTypeId,
},
});
});
it("When a host is no show, that is chosen when competing with another host that showed up for the booking", async () => {
const organizerThatShowedUp = await prisma.user.create({
data: {
email: "test-user1@example.com",
bookings: {
create: [
{
uid: "uuid-test-user1-booking1",
createdAt: new Date("2022-01-25T05:30:00.000Z"),
title: "Test user 1 Booking",
startTime: new Date(),
endTime: new Date(),
eventTypeId,
attendees: {
create: [
{
name: "test-attendee",
email: "test-attendee@example.com",
timeZone: "Asia/Calcutta",
},
],
},
},
],
},
},
});
const organizerThatDidntShowUp = await prisma.user.create({
data: {
email: "test-user2@example.com",
bookings: {
create: [
{
uid: "uuid-test-user2-booking1",
title: "Test User 2 Booking",
createdAt: new Date("2022-01-25T06:30:00.000Z"),
noShowHost: true,
startTime: new Date(),
endTime: new Date(),
attendees: {
create: [
{
name: "test-attendee",
email: "test-attendee@example.com",
timeZone: "Asia/Calcutta",
},
],
},
eventTypeId,
},
],
},
},
});
userIds.push(organizerThatShowedUp.id, organizerThatDidntShowUp.id);
expect(
getLuckyUser("MAXIMIZE_AVAILABILITY", {
availableUsers: [organizerThatShowedUp, organizerThatDidntShowUp],
eventType: {
id: eventTypeId,
isRRWeightsEnabled: false,
},
allRRHosts: [],
})
).resolves.toStrictEqual(organizerThatDidntShowUp);
});
it("When a attendee is a noShow for organizers booking, that organizer is competing with another host whose attendee showed up for the booking", async () => {
const organizerWhoseAttendeeShowedUp = await prisma.user.create({
data: {
email: "test-user1@example.com",
bookings: {
create: [
{
uid: "uuid-test-user1-booking1",
createdAt: new Date("2022-01-25T05:30:00.000Z"),
title: "Test User 1 Booking",
startTime: new Date(),
endTime: new Date(),
eventTypeId,
attendees: {
create: [
{
name: "test-attendee",
email: "test-attendee@example.com",
timeZone: "Asia/Calcutta",
},
],
},
},
],
},
},
});
const organizerWhoseAttendeeDidntShowUp = await prisma.user.create({
data: {
email: "test-user2@example.com",
bookings: {
create: [
{
uid: "uuid-test-user2-booking1",
title: "Test User 2 Booking",
createdAt: new Date("2022-01-25T06:30:00.000Z"),
startTime: new Date(),
endTime: new Date(),
attendees: {
create: [
{
noShow: true,
name: "test-attendee",
email: "test-attendee@example.com",
timeZone: "Asia/Calcutta",
},
],
},
eventTypeId,
},
],
},
},
});
userIds.push(organizerWhoseAttendeeShowedUp.id, organizerWhoseAttendeeDidntShowUp.id);
expect(
getLuckyUser("MAXIMIZE_AVAILABILITY", {
availableUsers: [organizerWhoseAttendeeShowedUp, organizerWhoseAttendeeDidntShowUp],
eventType: {
id: eventTypeId,
isRRWeightsEnabled: false,
},
allRRHosts: [],
})
).resolves.toStrictEqual(organizerWhoseAttendeeDidntShowUp);
});
it("When a organizer is attendee (event types with fixed hosts) and no show, that organizer is competing other hosts", async () => {
const organizerWhoseAttendeeShowedUp = await prisma.user.create({
data: {
email: "test-user1@example.com",
bookings: {
create: [
{
uid: "uuid-test-user1-booking1",
createdAt: new Date("2022-01-25T05:30:00.000Z"),
title: "Test User 1 Booking",
startTime: new Date(),
endTime: new Date(),
eventTypeId,
attendees: {
create: [
{
name: "test-attendee",
email: "test-attendee@example.com",
timeZone: "Asia/Calcutta",
},
],
},
},
],
},
},
});
const fixedHostOrganizerWhoseAttendeeDidNotShowUp = await prisma.user.create({
data: {
email: "test-user2@example.com",
bookings: {
create: [
{
uid: "uuid-test-user2-booking1",
title: `Test User 2 Booking`,
createdAt: new Date("2022-01-25T06:30:00.000Z"),
startTime: new Date(),
endTime: new Date(),
attendees: {
create: [
{
name: "test-attendee",
email: "test-attendee@example.com",
timeZone: "Asia/Calcutta",
},
],
},
eventTypeId,
},
// User2 is fixed user, User 3 was selected as round robin host but did not show up so this booking should be counted for User 3
{
uid: "uuid-test-user2-booking2",
title: `Test User 2 Booking 2`,
createdAt: new Date("2022-01-25T07:30:00.000Z"),
startTime: new Date(),
endTime: new Date(),
attendees: {
create: [
{
name: "test-attendee",
email: "test-user3@example.com",
timeZone: "Asia/Calcutta",
noShow: true,
},
],
},
eventTypeId,
},
],
},
},
});
const organizerWhoWasAttendeeAndDidntShowUp = await prisma.user.create({
data: {
email: `test-user3@example.com`,
bookings: {
create: [
{
uid: "uuid-test-user3-booking1",
title: `Test User 3 Booking`,
createdAt: new Date("2022-01-25T04:30:00.000Z"),
startTime: new Date(),
endTime: new Date(),
attendees: {
create: [
{
name: "test-attendee",
email: "test-attendee@example.com",
timeZone: "Asia/Calcutta",
},
],
},
eventTypeId,
},
],
},
},
});
userIds.push(
organizerWhoseAttendeeShowedUp.id,
fixedHostOrganizerWhoseAttendeeDidNotShowUp.id,
organizerWhoWasAttendeeAndDidntShowUp.id
);
expect(
getLuckyUser("MAXIMIZE_AVAILABILITY", {
availableUsers: [
organizerWhoseAttendeeShowedUp,
fixedHostOrganizerWhoseAttendeeDidNotShowUp,
organizerWhoWasAttendeeAndDidntShowUp,
],
eventType: {
id: eventTypeId,
isRRWeightsEnabled: false,
},
allRRHosts: [],
})
).resolves.toStrictEqual(organizerWhoWasAttendeeAndDidntShowUp);
});
it("should consider booking when noShowHost is null", async () => {
const user1 = await prisma.user.create({
data: {
email: "test-user1@example.com",
bookings: {
create: [
{
uid: "uuid-test-user1-booking1",
createdAt: new Date("2022-01-25T07:30:00.000Z"),
title: "Test user 1 Booking",
startTime: new Date(),
noShowHost: null,
endTime: new Date(),
eventTypeId,
attendees: {
create: [
{
name: "test-attendee",
email: "test-attendee@example.com",
timeZone: "Asia/Calcutta",
},
],
},
},
],
},
},
});
const user2 = await prisma.user.create({
data: {
email: "test-user2@example.com",
bookings: {
create: [
{
uid: "uuid-test-user2-booking1",
title: "Test User 2 Booking",
createdAt: new Date("2022-01-25T06:30:00.000Z"),
noShowHost: null,
startTime: new Date(),
endTime: new Date(),
attendees: {
create: [
{
name: "test-attendee",
email: "test-attendee@example.com",
timeZone: "Asia/Calcutta",
},
],
},
eventTypeId,
},
],
},
},
});
userIds.push(user1.id, user2.id);
expect(
getLuckyUser("MAXIMIZE_AVAILABILITY", {
availableUsers: [user1, user2],
eventType: {
id: eventTypeId,
isRRWeightsEnabled: false,
},
allRRHosts: [],
})
).resolves.toStrictEqual(user2);
});
});
});