Files
calendar/apps/web/test/handlers/requestReschedule.test.ts
T
12466fb064 feat: New Organization Schema along with the ability to invite existing users to an organization (#13002)
* Add profile table

Copy to profile table

Update schema

Migrations

* wip

* Get switcher working

* Add organization seeder

* wip

* Remove dead code

* Fix unit tests

* relevantProfile -> profile

* cache bust

* One more comment

* Squash migrations

* Copy to profile table

* Update schema

* Fix existing user invite flow

* Add profile table

* Copy to profile table

* Update schema

* Format

* Add profile table

Copy to profile table

Update schema

Migrations

* Format

* wip

Get switcher working

Add organization seeder

wip

Remove dead code

Fix unit tests

relevantProfile -> profile

cache bust

One more comment

Squash migrations

Copy to profile table

Update schema

Fix existing user invite flow

Add profile table

Copy to profile table

Update schema

chore: small improvements to signup (#13227)

* removed features on mobile, better background color

* nit

* dark mode nits

New Crowdin translations by Github Action

fix: event reschedule workflow trigger (#13122)

* fix event reschedule workflow trigger

* uncomment previously failed test

* review fix

---------

Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>

chore: added community support to help (#13213)

refactor: Abstract `handleSeats` from `handleNewBooking` (#12062)

* Refactor createBooking

* Type fix

* Abstract handleSeats

* Create Invitee type

* Create OrganizerUser type

* Abstract addVideoCallDataToEvt

* Abstract createLoggerWithEventDetails

* Abstract `handleAppStatus` from handler

* Create ReqAppsStatus type

* Move `deleteMeeting` and `getCalendar`

* Set parameters for `handleSeats`

* Typescript refactor

* Change function params from req

* Type fix

---------

Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Erik <erik@erosemberg.com>

fix: Dynamic group booking  org-migration redirect (#13223)

* fix: Dynamic group booking redirect

* Fix flaky private team test

test: Check availability tab and all your functions (teste2e-availability) (#12434)

* add changes

* add changes

* add changes

* add changes

* Requested changes

* Change way to grab element

---------

Co-authored-by: gitstart-calcom <gitstart-calcom@users.noreply.github.com>
Co-authored-by: gitstart-calcom <gitstart@users.noreply.github.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>

fix: Reschedule a cancelled booking (#13170)

* fix: Reschedule a cancelled booking

* canceled instead of cancelled

---------

Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>

v3.7.0

test: In Team Event type when location is Organizer Default App and U… (#12939)

* test: In Team Event type when location is Organizer Default App and User Metadata is emoty

* chore: use variable

* fix: type error

test: add test for invalid cal video (#13103)

* test: add test for invalid cal video

* chore: add confirm

* chore: fix type error

* chore: update code

* test: add unit test

* chore: type error

* chore

* chore: type

* chore: fix test

* chore

---------

Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>

chore: add error message for no availability (#13230)

* chore: add error message for no default user availability

* chore: check only availability

* chore: change message

* chore: add eventType

fix: Team revert with members (#13228)

refactor: Refactor seats logic (#12905)

* Refactor createBooking

* Type fix

* Abstract handleSeats

* Create Invitee type

* Create OrganizerUser type

* Abstract addVideoCallDataToEvt

* Abstract createLoggerWithEventDetails

* Abstract `handleAppStatus` from handler

* Create ReqAppsStatus type

* Move `deleteMeeting` and `getCalendar`

* Set parameters for `handleSeats`

* Typescript refactor

* Change function params from req

* Type fix

* Move handleSeats

* Abstract lastAttendeeDeleteBooking

* Create function for rescheduling seated events

* Fix imports on reschedule seats function

* Fix imports

* Import handleSeats function

* Fix rescheduleUid type

* Refactor owner reschedule to new time slot

* Refactor combine two booking times together

* Reschedule as an attendee

* Refactor createNewSeat

* Remove old handleSeats

* Remove lastAttendeeDeleteBooking from handleNewBooking

* Test for new attendee right params are passed

* Unit test params for reschedule

* Typo fix

* Clean up

* Create new seat test

* Test when attendee already signs up for booking

* Type fix

* Test reschedule move attendee to existing booking

* On reschedule create new booking

* Test on last attendee cancel booking

* Owner reschedule to new time slot

* Owner rescheduling, merge two bookings together

* Test: when merging more than available seats, then fail

* Test: fail when event is full

* Remove duplicate E2E tests

* Clean up

* Rename `addVideoCallDataToEvt` to `addVideoCallDataToEvent`

* Refactor `calcAppsStatus`

* Assign `evt` to resutl of `addVideoCallDataToEvent`

* Use prisma.transaction when moving attendees

* Clean create seat call

* Use ErrorCode enum

* Use attendeeRescheduledSeatedBooking function

* Await function

* Prevent double triggering of workflows

* Use inviteeToAdd in createNewSeat

* Remove unused error code

* Remove old handleSeats file

* Type fix

* Type fix

* Type fix

* Type fix

* Type fix

* Type fix

* Type fix

* Type fix

---------

Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Erik <erik@erosemberg.com>

feat: Allow admins to filter bookings only by attendee emails (#13236)

* chore: Allow admins to filter bookings only by attendee emails

* Fix type error

Fixed [CAL-2930] Org branding isnt centered in shell #13225 (#13237)

Add profile table

Copy to profile table

Update schema

Migrations

Format

* wip

* Add profile relation everywhere

* Fix schema

* Fix invite handler

* Add profileId during eventTypec reation

* Get dashboard working with profile relatioon

* Add workflow create repository

* Add profileId to host

* Add profileId to credential table

* Add destinationCalendar repository

* Add profileId to membership

* Revert all profile related changes

* Add acme and dunder

* Fix membership profileId usgae

* Various fixes

* Some renaming

* Fix failing tests

* Debugging next-aut

* Consolidate migrations

* Testing fixes

* Fix unit tests

* Self review feedback

* PR feedback

* Fix orgMigration as well

* Add profile schema and copy users to it

* Remove migrations from here

* Fix type issues

* Fix type error after main merge

* Remove movedFromUserId

* Add missing migration file

* Self review addressed

* Joe's review addressed

* Fix profile switcher

---------

Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
2024-02-02 21:34:13 +00:00

290 lines
8.6 KiB
TypeScript

import type { Request, Response } from "express";
import type { NextApiRequest, NextApiResponse } from "next";
import { describe } from "vitest";
import { SchedulingType } from "@calcom/prisma/enums";
import { BookingStatus } from "@calcom/prisma/enums";
import type { TRequestRescheduleInputSchema } from "@calcom/trpc/server/routers/viewer/bookings/requestReschedule.schema";
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
import { test } from "@calcom/web/test/fixtures/fixtures";
import {
createBookingScenario,
getGoogleCalendarCredential,
TestData,
getOrganizer,
getBooker,
getScenarioData,
getMockBookingAttendee,
getDate,
} from "@calcom/web/test/utils/bookingScenario/bookingScenario";
import { expectBookingRequestRescheduledEmails } from "@calcom/web/test/utils/bookingScenario/expects";
import { getSampleUserInSession } from "../utils/bookingScenario/getSampleUserInSession";
import { setupAndTeardown } from "../utils/bookingScenario/setupAndTeardown";
export type CustomNextApiRequest = NextApiRequest & Request;
export type CustomNextApiResponse = NextApiResponse & Response;
describe("Handler: requestReschedule", () => {
setupAndTeardown();
describe("User Event Booking", () => {
test(`should be able to request-reschedule for a user booking
1. RequestReschedule emails go to both attendee and the person requesting the reschedule`, async ({
emails,
}) => {
const { requestRescheduleHandler } = await import(
"@calcom/trpc/server/routers/viewer/bookings/requestReschedule.handler"
);
const booker = getBooker({
email: "booker@example.com",
name: "Booker",
});
const organizer = getOrganizer({
name: "Organizer",
email: "organizer@example.com",
id: 101,
schedules: [TestData.schedules.IstWorkHours],
credentials: [getGoogleCalendarCredential()],
selectedCalendars: [TestData.selectedCalendars.google],
});
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
const bookingUid = "MOCKED_BOOKING_UID";
const eventTypeSlug = "event-type-1";
await createBookingScenario(
getScenarioData({
webhooks: [
{
userId: organizer.id,
eventTriggers: ["BOOKING_CREATED"],
subscriberUrl: "http://my-webhook.example.com",
active: true,
eventTypeId: 1,
appId: null,
},
],
eventTypes: [
{
id: 1,
slug: eventTypeSlug,
slotInterval: 45,
length: 45,
users: [
{
id: 101,
},
],
},
],
bookings: [
{
uid: bookingUid,
eventTypeId: 1,
userId: 101,
status: BookingStatus.ACCEPTED,
startTime: `${plus1DateString}T05:00:00.000Z`,
endTime: `${plus1DateString}T05:15:00.000Z`,
attendees: [
getMockBookingAttendee({
id: 2,
name: booker.name,
email: booker.email,
// Booker's locale when the fresh booking happened earlier
locale: "hi",
// Booker's timezone when the fresh booking happened earlier
timeZone: "Asia/Kolkata",
}),
],
},
],
organizer,
apps: [TestData.apps["google-calendar"], TestData.apps["daily-video"]],
})
);
const loggedInUser = {
organizationId: null,
id: 101,
username: "reschedule-requester",
name: "Reschedule Requester",
email: "reschedule-requester@example.com",
};
await requestRescheduleHandler(
getTrpcHandlerData({
user: loggedInUser,
input: {
bookingId: bookingUid,
rescheduleReason: "",
},
})
);
expectBookingRequestRescheduledEmails({
booking: {
uid: bookingUid,
},
booker,
organizer: organizer,
loggedInUser,
emails,
bookNewTimePath: `/${organizer.username}/${eventTypeSlug}`,
});
});
});
describe("Team Event Booking", () => {
test(`should be able to request-reschedule for a team event booking
1. RequestReschedule emails go to both attendee and the person requesting the reschedule`, async ({
emails,
}) => {
const { requestRescheduleHandler } = await import(
"@calcom/trpc/server/routers/viewer/bookings/requestReschedule.handler"
);
const booker = getBooker({
email: "booker@example.com",
name: "Booker",
});
const organizer = getOrganizer({
name: "Organizer",
email: "organizer@example.com",
id: 101,
teams: [
{
membership: {
accepted: true,
},
team: {
id: 1,
name: "Team 1",
slug: "team-1",
},
},
],
schedules: [TestData.schedules.IstWorkHours],
credentials: [getGoogleCalendarCredential()],
selectedCalendars: [TestData.selectedCalendars.google],
});
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
const bookingUid = "MOCKED_BOOKING_UID";
const eventTypeSlug = "event-type-1";
await createBookingScenario(
getScenarioData({
webhooks: [
{
userId: organizer.id,
eventTriggers: ["BOOKING_CREATED"],
subscriberUrl: "http://my-webhook.example.com",
active: true,
eventTypeId: 1,
appId: null,
},
],
eventTypes: [
{
id: 1,
slug: eventTypeSlug,
slotInterval: 45,
teamId: 1,
schedulingType: SchedulingType.COLLECTIVE,
length: 45,
users: [
{
id: 101,
},
],
},
],
bookings: [
{
uid: bookingUid,
eventTypeId: 1,
userId: 101,
status: BookingStatus.ACCEPTED,
startTime: `${plus1DateString}T05:00:00.000Z`,
endTime: `${plus1DateString}T05:15:00.000Z`,
attendees: [
getMockBookingAttendee({
id: 2,
name: booker.name,
email: booker.email,
// Booker's locale when the fresh booking happened earlier
locale: "hi",
// Booker's timezone when the fresh booking happened earlier
timeZone: "Asia/Kolkata",
}),
],
},
],
organizer,
apps: [TestData.apps["google-calendar"], TestData.apps["daily-video"]],
})
);
const loggedInUser = {
organizationId: null,
id: 101,
username: "reschedule-requester",
name: "Reschedule Requester",
email: "reschedule-requester@example.com",
};
await requestRescheduleHandler(
getTrpcHandlerData({
user: loggedInUser,
input: {
bookingId: bookingUid,
rescheduleReason: "",
},
})
);
expectBookingRequestRescheduledEmails({
booking: {
uid: bookingUid,
},
booker,
organizer: organizer,
loggedInUser,
emails,
bookNewTimePath: "/team/team-1/event-type-1",
});
});
test.todo("Verify that the email should go to organizer as well as the team members");
});
});
function getTrpcHandlerData({
input,
user,
}: {
input: TRequestRescheduleInputSchema;
user: Partial<Omit<NonNullable<TrpcSessionUser>, "id" | "email" | "username">> &
Pick<NonNullable<TrpcSessionUser>, "id" | "email" | "username">;
}) {
return {
ctx: {
user: {
...getSampleUserInSession(),
...user,
avatarUrl: user.avatarUrl || null,
profile: {
upId: "",
id: 1,
name: "",
avatarUrl: "",
startTime: 0,
endTime: 0,
username: user.username || "",
organizationId: null,
organization: null,
bufferTime: 5,
avatar: null,
},
} as unknown as NonNullable<TrpcSessionUser>,
},
input: input,
};
}