fix: booker atom booking with split name (#20298)

This commit is contained in:
Lauris Skraucis
2025-03-21 13:25:32 +00:00
committed by GitHub
parent b94b16316f
commit 2e86f8404f
2 changed files with 99 additions and 3 deletions
@@ -351,6 +351,64 @@ describe("Bookings Endpoints 2024-04-15", () => {
});
});
it("should create a booking with split name", async () => {
const bookingStart = "2040-05-21T11:30:00.000Z";
const bookingEnd = "2040-05-21T12:30:00.000Z";
const bookingEventTypeId = eventTypeId;
const bookingTimeZone = "Europe/London";
const bookingLanguage = "en";
const bookingHashedLink = "";
const bookingMetadata = {
timeFormat: "12",
meetingType: "organizer-phone",
};
const bookingResponses = {
name: { firstName: "John", lastName: "Doe" },
email: "tester@example.com",
location: {
value: "link",
optionValue: "",
},
notes: "test",
};
const body: CreateBookingInput_2024_04_15 = {
start: bookingStart,
end: bookingEnd,
eventTypeId: bookingEventTypeId,
timeZone: bookingTimeZone,
language: bookingLanguage,
metadata: bookingMetadata,
hashedLink: bookingHashedLink,
responses: bookingResponses,
};
return request(app.getHttpServer())
.post("/v2/bookings")
.send(body)
.expect(201)
.then(async (response) => {
const responseBody: ApiSuccessResponse<Awaited<ReturnType<typeof handleNewBooking>>> =
response.body;
expect(responseBody.status).toEqual(SUCCESS_STATUS);
expect(responseBody.data).toBeDefined();
expect(responseBody.data.userPrimaryEmail).toBeDefined();
expect(responseBody.data.userPrimaryEmail).toEqual(userEmail);
expect(responseBody.data.id).toBeDefined();
expect(responseBody.data.uid).toBeDefined();
expect(responseBody.data.startTime).toEqual(bookingStart);
expect(responseBody.data.eventTypeId).toEqual(bookingEventTypeId);
expect(responseBody.data.user.timeZone).toEqual(bookingTimeZone);
expect(responseBody.data.metadata).toEqual(bookingMetadata);
expect(responseBody.data.responses).toEqual({
...bookingResponses,
name: `${bookingResponses.name.firstName} ${bookingResponses.name.lastName}`,
});
createdBooking = responseBody.data;
});
});
afterAll(async () => {
await userRepositoryFixture.deleteByEmail(user.email);
await bookingsRepositoryFixture.deleteAllBookings(user.id, user.email);
@@ -12,9 +12,42 @@ import {
isEmail,
Validate,
} from "class-validator";
import { ValidationOptions, registerDecorator } from "class-validator";
import { RESCHEDULED_BY_DOCS } from "@calcom/platform-types";
type BookingName = { firstName: string; lastName: string };
function ValidateBookingName(validationOptions?: ValidationOptions) {
return function (target: object, propertyName: string) {
registerDecorator({
name: "validateBookingName",
target: target.constructor,
propertyName: propertyName,
options: validationOptions,
validator: {
validate(value: any) {
if (typeof value === "string") {
return value.trim().length > 0;
}
if (typeof value === "object" && value !== null) {
return (
typeof value.firstName === "string" &&
typeof value.lastName === "string" &&
value.firstName.trim().length > 0 &&
value.lastName.trim().length > 0
);
}
return false;
},
defaultMessage(): string {
return "Name must be either a non-empty string or an object with non-empty firstName and lastName";
},
},
});
};
}
class Location {
@IsString()
@ApiProperty()
@@ -26,9 +59,14 @@ class Location {
}
class Response {
@IsString()
@ApiProperty()
name!: string;
@ApiProperty({
oneOf: [
{ type: "string" },
{ type: "object", properties: { firstName: { type: "string" }, lastName: { type: "string" } } },
],
})
@ValidateBookingName()
name!: string | BookingName;
@Validate((value: string) => !value || isEmail(value), {
message: "Invalid response email",