feat: Expose booking created at in v2 API response (#17452)

* feat: Expose booking created at in booking detailed view and v2 API response

* Fix tests

* Fix spacing

* Add API v2 tests to verify createdAt is present while creating a booking and fetching a booking

* Add test to validate createdAt after rescheduling a booking
This commit is contained in:
Anwar Sadath authored and GitHub committed 2024-11-22 13:50:11 +05:30
1 parent d03651312e
commit 1cf84a270c
4 files changed
+39 -1

No files matched your search

@@ -328,12 +328,14 @@ describe("Bookings Endpoints 2024-08-13", () => {
},
};
const beforeCreate = new Date();
return request(app.getHttpServer())
.post("/v2/bookings")
.send(body)
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
.expect(201)
.then(async (response) => {
const afterCreate = new Date();
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
expect(responseBody.status).toEqual(SUCCESS_STATUS);
expect(responseBody.data).toBeDefined();
@@ -367,6 +369,12 @@ describe("Bookings Endpoints 2024-08-13", () => {
email: body.attendee.email,
...body.bookingFieldsResponses,
});
// Check createdAt date is between the time of the request and after the request
const createdAtDate = new Date(data.createdAt);
expect(createdAtDate.getTime()).toBeGreaterThanOrEqual(beforeCreate.getTime());
expect(createdAtDate.getTime()).toBeLessThanOrEqual(afterCreate.getTime());
expect(data.metadata).toEqual(body.metadata);
createdBooking = data;
} else {
@@ -503,6 +511,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
expect(data.attendees[0]).toEqual(createdBooking.attendees[0]);
expect(data.location).toEqual(createdBooking.location);
expect(data.absentHost).toEqual(createdBooking.absentHost);
expect(data.createdAt).toEqual(createdBooking.createdAt);
} else {
throw new Error(
"Invalid response data - expected booking but received array of possibily recurring bookings"
@@ -976,12 +985,14 @@ describe("Bookings Endpoints 2024-08-13", () => {
reschedulingReason: "Flying to mars that day",
};
const beforeCreate = new Date();
return request(app.getHttpServer())
.post(`/v2/bookings/${createdBooking.uid}/reschedule`)
.send(body)
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
.expect(201)
.then(async (response) => {
const afterCreate = new Date();
const responseBody: RescheduleBookingOutput_2024_08_13 = response.body;
expect(responseBody.status).toEqual(SUCCESS_STATUS);
expect(responseBody.data).toBeDefined();
@@ -1003,6 +1014,12 @@ describe("Bookings Endpoints 2024-08-13", () => {
expect(data.absentHost).toEqual(createdBooking.absentHost);
expect(data.metadata).toEqual(createdBooking.metadata);
// When a booking is rescheduled, a new booking is created and the old booking is cancelled.
// We want to make sure the createdAt date of the new booking is between the beforeCreate and afterCreate dates.
const createdAtDate = new Date(data.createdAt);
expect(createdAtDate.getTime()).toBeGreaterThanOrEqual(beforeCreate.getTime());
expect(createdAtDate.getTime()).toBeLessThanOrEqual(afterCreate.getTime());
rescheduledBooking = data;
});
});
@@ -50,7 +50,9 @@ type DatabaseBooking = Booking & {
noShow: boolean | null;
bookingSeat?: BookingSeat | null;
}[];
} & { user: { id: number; name: string | null; email: string } | null };
user: { id: number; name: string | null; email: string } | null;
createdAt: Date;
};
type BookingWithUser = Booking & { user: { id: number; name: string | null; email: string } | null };
@@ -103,6 +105,7 @@ export class OutputBookingsService_2024_08_13 {
// note(Lauris): meetingUrl is deprecated
meetingUrl: databaseBooking.location,
absentHost: !!databaseBooking.noShowHost,
createdAt: databaseBooking.createdAt,
};
const bookingTransformed = plainToClass(BookingOutput_2024_08_13, booking, { strategy: "excludeAll" });
@@ -165,6 +168,7 @@ export class OutputBookingsService_2024_08_13 {
recurringBookingUid: databaseBooking.recurringEventId,
absentHost: !!databaseBooking.noShowHost,
bookingFieldsResponses: databaseBooking.responses,
createdAt: databaseBooking.createdAt,
};
const bookingTransformed = plainToClass(RecurringBookingOutput_2024_08_13, booking, {
@@ -208,6 +212,7 @@ export class OutputBookingsService_2024_08_13 {
// note(Lauris): meetingUrl is deprecated
meetingUrl: databaseBooking.location,
absentHost: !!databaseBooking.noShowHost,
createdAt: databaseBooking.createdAt,
};
const parsed = plainToClass(GetSeatedBookingOutput_2024_08_13, booking, { strategy: "excludeAll" });
@@ -302,6 +307,7 @@ export class OutputBookingsService_2024_08_13 {
meetingUrl: databaseBooking.location,
recurringBookingUid: databaseBooking.recurringEventId,
absentHost: !!databaseBooking.noShowHost,
createdAt: databaseBooking.createdAt,
};
const parsed = plainToClass(GetRecurringSeatedBookingOutput_2024_08_13, booking, {
+10
View File
@@ -13122,6 +13122,10 @@
"type": "boolean",
"example": true
},
"createdAt": {
"type": "string",
"example": "2024-08-13T15:30:00Z"
},
"metadata": {
"type": "object",
"example": {
@@ -13165,6 +13169,7 @@
"eventTypeId",
"eventType",
"absentHost",
"createdAt",
"attendees"
]
},
@@ -13250,6 +13255,10 @@
"type": "boolean",
"example": true
},
"createdAt": {
"type": "string",
"example": "2024-08-13T15:30:00Z"
},
"metadata": {
"type": "object",
"example": {
@@ -13297,6 +13306,7 @@
"eventTypeId",
"eventType",
"absentHost",
"createdAt",
"attendees",
"recurringBookingUid"
]
@@ -200,6 +200,11 @@ class BaseBookingOutput_2024_08_13 {
@Expose()
absentHost!: boolean;
@ApiProperty({ type: String, example: "2024-08-13T15:30:00Z" })
@IsDateString()
@Expose()
createdAt!: string;
@ApiProperty({
type: Object,
example: { key: "value" },