test: Round Robin Team Booking (#10413)

This commit is contained in:
Shivam Kalra
2023-07-27 17:18:08 +05:30
committed by GitHub
parent 660d28b286
commit e4a075b5e2
4 changed files with 117 additions and 78 deletions
+3 -1
View File
@@ -409,7 +409,9 @@ export default function Success(props: SuccessProps) {
</>
)}
<div className="font-medium">{t("what")}</div>
<div className="col-span-2 mb-6 last:mb-0">{eventName}</div>
<div className="col-span-2 mb-6 last:mb-0" data-testid="booking-title">
{eventName}
</div>
<div className="font-medium">{t("when")}</div>
<div className="col-span-2 mb-6 last:mb-0">
{reschedule && !!formerTime && (
+54 -6
View File
@@ -6,9 +6,10 @@ import { hashSync as hash } from "bcryptjs";
import dayjs from "@calcom/dayjs";
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
import { prisma } from "@calcom/prisma";
import { SchedulingType } from "@calcom/prisma/enums";
import { MembershipRole } from "@calcom/prisma/enums";
import { selectFirstAvailableTimeSlotNextMonth } from "../lib/testUtils";
import { selectFirstAvailableTimeSlotNextMonth, teamEventSlug, teamEventTitle } from "../lib/testUtils";
import type { TimeZoneEnum } from "./types";
// Don't import hashPassword from app as that ends up importing next-auth and initializing it before NEXTAUTH_URL can be updated during tests.
@@ -42,7 +43,7 @@ const createTeamAndAddUser = async (
) => {
const team = await prisma.team.create({
data: {
name: "",
name: `user-id-${user.id}'s Team`,
slug: `team-${workerInfo.workerIndex}-${Date.now()}`,
},
});
@@ -68,6 +69,10 @@ export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
scenario: {
seedRoutingForms?: boolean;
hasTeam?: true;
teammates?: CustomUserOpts[];
schedulingType?: SchedulingType;
teamEventTitle?: string;
teamEventSlug?: string;
} = {}
) => {
const _user = await prisma.user.create({
@@ -212,7 +217,7 @@ export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
});
if (scenario.hasTeam) {
const team = await createTeamAndAddUser({ user: { id: user.id, role: "OWNER" } }, workerInfo);
await prisma.eventType.create({
const teamEvent = await prisma.eventType.create({
data: {
team: {
connect: {
@@ -229,12 +234,48 @@ export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
id: _user.id,
},
},
schedulingType: "COLLECTIVE",
title: "Team Event - 30min",
slug: "team-event-30min",
schedulingType: scenario.schedulingType ?? SchedulingType.COLLECTIVE,
title: scenario.teamEventTitle ?? teamEventTitle,
slug: scenario.teamEventSlug ?? teamEventSlug,
length: 30,
},
});
if (scenario.teammates) {
// Create Teammate users
for (const teammateObj of scenario.teammates) {
const teamUser = await prisma.user.create({
data: createUser(workerInfo, teammateObj),
});
// Add teammates to the team
await prisma.membership.create({
data: {
teamId: team.id,
userId: teamUser.id,
role: MembershipRole.MEMBER,
accepted: true,
},
});
// Add teammate to the host list of team event
await prisma.host.create({
data: {
userId: teamUser.id,
eventTypeId: teamEvent.id,
isFixed: scenario.schedulingType === SchedulingType.COLLECTIVE ? true : false,
},
});
const teammateFixture = createUserFixture(
await prisma.user.findUniqueOrThrow({
where: { id: teamUser.id },
include: userIncludes,
}),
store.page
);
store.users.push(teammateFixture);
}
}
}
const userFixture = createUserFixture(user, store.page);
store.users.push(userFixture);
@@ -271,6 +312,7 @@ const createUserFixture = (user: UserWithIncludes, page: Page) => {
}))!;
return {
id: user.id,
name: user.name,
username: user.username,
eventTypes: user.eventTypes,
routingForms: user.routingForms,
@@ -280,6 +322,12 @@ const createUserFixture = (user: UserWithIncludes, page: Page) => {
logout: async () => {
await page.goto("/auth/logout");
},
getTeam: async () => {
return prisma.membership.findFirstOrThrow({
where: { userId: user.id },
include: { team: true },
});
},
getPaymentCredential: async () => getPaymentCredential(store.page),
setupEventWithPrice: async (eventType: Pick<Prisma.EventType, "id">) =>
setupEventWithPrice(eventType, store.page),
+3
View File
@@ -18,6 +18,9 @@ type RequestHandler = (opts: RequestHandlerOptions) => void;
export const testEmail = "test@example.com";
export const testName = "Test Testson";
export const teamEventTitle = "Team Event - 30min";
export const teamEventSlug = "team-event-30min";
export function createHttpServer(opts: { requestHandler?: RequestHandler } = {}) {
const {
requestHandler = ({ res }) => {
+57 -71
View File
@@ -1,10 +1,17 @@
import { expect } from "@playwright/test";
import { prisma } from "@calcom/prisma";
import { MembershipRole } from "@calcom/prisma/enums";
import { SchedulingType } from "@calcom/prisma/enums";
import { test } from "./lib/fixtures";
import { bookTimeSlot, selectFirstAvailableTimeSlotNextMonth, testName } from "./lib/testUtils";
import {
bookTimeSlot,
selectFirstAvailableTimeSlotNextMonth,
teamEventSlug,
teamEventTitle,
testName,
todo,
} from "./lib/testUtils";
test.describe.configure({ mode: "parallel" });
@@ -66,84 +73,63 @@ test.describe("Teams", () => {
});
test("Can create a booking for Collective EventType", async ({ page, users }) => {
const ownerObj = { username: "pro-user", name: "pro-user" };
const teamMate1Obj = { username: "teammate-1", name: "teammate-1" };
const teamMate2Obj = { username: "teammate-2", name: "teammate-2" };
const teamMatesObj = [
{ username: "teammate-1", name: "teammate-1" },
{ username: "teammate-2", name: "teammate-2" },
{ username: "teammate-3", name: "teammate-3" },
{ username: "teammate-4", name: "teammate-4" },
];
const owner = await users.create(ownerObj, { hasTeam: true });
const teamMate1 = await users.create(teamMate1Obj);
const teamMate2 = await users.create(teamMate2Obj);
teamMate1.username, teamMate2.username;
// TODO: Create a fixture and follow DRY
const { team } = await prisma.membership.findFirstOrThrow({
where: { userId: owner.id },
include: { team: true },
const owner = await users.create(ownerObj, {
hasTeam: true,
teammates: teamMatesObj,
schedulingType: SchedulingType.COLLECTIVE,
});
const { team } = await owner.getTeam();
// Add teamMate1 to the team
await prisma.membership.create({
data: {
teamId: team.id,
userId: teamMate1.id,
role: MembershipRole.MEMBER,
accepted: true,
},
});
// Add teamMate2 to the team
await prisma.membership.create({
data: {
teamId: team.id,
userId: teamMate2.id,
role: MembershipRole.MEMBER,
accepted: true,
},
});
// No need to remove membership row manually as it will be deleted with the user, at the end of the test.
const { id: eventTypeId } = await prisma.eventType.findFirstOrThrow({
where: { userId: owner.id, teamId: team.id },
select: { id: true },
});
// Assign owner and teammates to the eventtype host list
await prisma.host.create({
data: {
userId: owner.id,
eventTypeId,
isFixed: true,
},
});
await prisma.host.create({
data: {
userId: teamMate1.id,
eventTypeId,
isFixed: true,
},
});
await prisma.host.create({
data: {
userId: teamMate2.id,
eventTypeId,
isFixed: true,
},
});
await page.goto(`/team/${team.slug}/team-event-30min`);
await page.goto(`/team/${team.slug}/${teamEventSlug}`);
await selectFirstAvailableTimeSlotNextMonth(page);
await bookTimeSlot(page);
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
await expect(page.locator(`[data-testid="attendee-name-${testName}"]`)).toHaveText(testName);
// The first user added to the host list will be the host name
await expect(page.locator(`[data-testid="host-name-${ownerObj.name}"]`)).toHaveText(ownerObj.name);
for (const teammate of teamMatesObj) {
await expect(page.getByText(teammate.name, { exact: true })).toBeVisible();
}
// The remaining hosts will be shown as the attendees
await expect(page.locator(`[data-testid="attendee-name-${teamMate1Obj.name}"]`)).toHaveText(
teamMate1Obj.name
);
await expect(page.locator(`[data-testid="attendee-name-${teamMate2Obj.name}"]`)).toHaveText(
teamMate2Obj.name
);
// TODO: Assert whether the user received an email
});
test("Can create a booking for Round Robin EventType", async ({ page, users }) => {
const ownerObj = { username: "pro-user", name: "pro-user" };
const teamMatesObj = [
{ username: "teammate-1", name: "teammate-1" },
{ username: "teammate-2", name: "teammate-2" },
{ username: "teammate-3", name: "teammate-3" },
{ username: "teammate-4", name: "teammate-4" },
];
const owner = await users.create(ownerObj, {
hasTeam: true,
teammates: teamMatesObj,
schedulingType: SchedulingType.ROUND_ROBIN,
});
const { team } = await owner.getTeam();
await page.goto(`/team/${team.slug}/${teamEventSlug}`);
await selectFirstAvailableTimeSlotNextMonth(page);
await bookTimeSlot(page);
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
// The person who booked the meeting should be in the attendee list
await expect(page.locator(`[data-testid="attendee-name-${testName}"]`)).toHaveText(testName);
// The title of the booking
const BookingTitle = `${teamEventTitle} between ${team.name} and ${testName}`;
await expect(page.locator("[data-testid=booking-title]")).toHaveText(BookingTitle);
// TODO: Assert one of the teamates from the list to be the host
// TODO: Assert whether the user received an email
});
todo("Reschedule a Collective EventType booking");
todo("Reschedule a Round Robin EventType booking");
});