Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 64 additions & 95 deletions apps/web/test/lib/handleChildrenEventTypes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,23 @@ describe("handleChildrenEventTypes", () => {
// Setup transaction mock to execute the callback
setupTransactionMock();

// Mock findMany to return empty array (no workflows to link)
prismaMock.eventType.findMany.mockResolvedValue([]);
// Mock createManyAndReturn to return the created event type (full EventType shape required for type safety)
const createdEventType = {
...evType,
id: 123,
userId: 4,
schedulingType,
teamId,
timeZone,
requiresBookerEmailVerification,
lockTimeZoneToggleOnBookingPage,
useEventTypeDestinationCalendarEmail,
secondaryEmailId,
autoTranslateDescriptionEnabled,
includeNoShowInRRCalculation,
instantMeetingScheduleId,
};
prismaMock.eventType.createManyAndReturn.mockResolvedValue([createdEventType]);

const result = await updateChildrenEventTypes({
eventTypeId: 1,
Expand All @@ -162,7 +177,7 @@ describe("handleChildrenEventTypes", () => {
updatedValues: {},
});
const { createdAt, updatedAt, ...expectedEvType } = evType;
expect(prismaMock.eventType.createMany).toHaveBeenCalledWith({
expect(prismaMock.eventType.createManyAndReturn).toHaveBeenCalledWith({
data: [
{
...expectedEvType,
Expand All @@ -183,6 +198,7 @@ describe("handleChildrenEventTypes", () => {
},
],
skipDuplicates: true,
select: { id: true, userId: true },
});
expect(result.newUserIds).toEqual([4]);
expect(result.oldUserIds).toEqual([]);
Expand Down Expand Up @@ -329,8 +345,24 @@ describe("handleChildrenEventTypes", () => {
// Setup transaction mock to execute the callback
setupTransactionMock();

// Mock findMany to return empty array (no workflows to link)
prismaMock.eventType.findMany.mockResolvedValue([]);
// Mock createManyAndReturn to return the created event type (full EventType shape required for type safety)
const createdEventType = {
...evType,
id: 123,
userId: 4,
schedulingType,
teamId,
timeZone,
requiresBookerEmailVerification,
lockTimeZoneToggleOnBookingPage,
useEventTypeDestinationCalendarEmail,
secondaryEmailId,
autoTranslateDescriptionEnabled,
includeNoShowInRRCalculation,
instantMeetingScheduleId,
assignRRMembersUsingSegment,
};
prismaMock.eventType.createManyAndReturn.mockResolvedValue([createdEventType]);

prismaMock.eventType.deleteMany.mockResolvedValue([123] as unknown as Prisma.BatchPayload);
const result = await updateChildrenEventTypes({
Expand All @@ -344,7 +376,7 @@ describe("handleChildrenEventTypes", () => {
updatedValues: {},
});
const { createdAt, updatedAt, ...expectedEvType } = evType;
expect(prismaMock.eventType.createMany).toHaveBeenCalledWith({
expect(prismaMock.eventType.createManyAndReturn).toHaveBeenCalledWith({
data: [
{
...expectedEvType,
Expand All @@ -366,6 +398,7 @@ describe("handleChildrenEventTypes", () => {
},
],
skipDuplicates: true,
select: { id: true, userId: true },
});
expect(result.newUserIds).toEqual([4]);
expect(result.oldUserIds).toEqual([]);
Expand Down Expand Up @@ -471,92 +504,27 @@ describe("handleChildrenEventTypes", () => {
// Setup transaction mock to execute the callback
setupTransactionMock();

// Mock findMany to return the newly created event type for workflow linking
// This simulates the event type created for user 5
prismaMock.eventType.findMany.mockResolvedValue([
{
id: 3,
title: "test",
slug: "test",
description: null,
position: 0,
locations: [],
length: 30,
offsetStart: 0,
hidden: false,
userId: 5,
profileId: null,
teamId: null,
eventName: null,
parentId: 1,
bookingFields: null,
timeZone: null,
periodType: "UNLIMITED",
periodStartDate: null,
periodEndDate: null,
periodDays: null,
periodCountCalendarDays: null,
lockTimeZoneToggleOnBookingPage: false,
lockedTimeZone: null,
requiresConfirmation: false,
requiresConfirmationWillBlockSlot: false,
requiresConfirmationForFreeEmail: false,
requiresBookerEmailVerification: false,
canSendCalVideoTranscriptionEmails: true,
autoTranslateDescriptionEnabled: false,
recurringEvent: null,
disableGuests: false,
hideCalendarNotes: false,
hideCalendarEventDetails: false,
minimumBookingNotice: 120,
beforeEventBuffer: 0,
afterEventBuffer: 0,
seatsPerTimeSlot: null,
onlyShowFirstAvailableSlot: false,
showOptimizedSlots: false,
disableCancelling: false,
disableRescheduling: false,
seatsShowAttendees: false,
seatsShowAvailabilityCount: true,
schedulingType: null,
scheduleId: null,
price: 0,
currency: "usd",
slotInterval: null,
metadata: {},
successRedirectUrl: null,
forwardParamsSuccessRedirect: true,
bookingLimits: null,
durationLimits: null,
isInstantEvent: false,
instantMeetingExpiryTimeOffsetInSeconds: 90,
instantMeetingScheduleId: null,
assignAllTeamMembers: false,
useEventTypeDestinationCalendarEmail: false,
secondaryEmailId: null,
eventTypeColor: null,
rescheduleWithSameRoundRobinHost: false,
rrSegmentQueryValue: null,
assignRRMembersUsingSegment: false,
useEventLevelSelectedCalendars: false,
restrictionScheduleId: null,
useBookerTimezone: false,
allowReschedulingCancelledBookings: false,
includeNoShowInRRCalculation: false,
interfaceLanguage: null,
customReplyToEmail: null,
createdAt: new Date(),
updatedAt: new Date(),
instantMeetingParameters: [],
isRRWeightsEnabled: false,
maxLeadThreshold: null,
allowReschedulingPastBookings: false,
hideOrganizerEmail: false,
maxActiveBookingsPerBooker: null,
maxActiveBookingPerBookerOfferReschedule: false,
bookingRequiresAuthentication: false,
},
]);
// Mock createManyAndReturn to return the newly created event type for workflow linking
// This simulates the event type created for user 5 (full EventType shape required for type safety)
const createdEventType = {
...evType,
id: 3,
userId: 5,
schedulingType: _schedulingType,
teamId: _teamId,
locations: _locations,
timeZone: _timeZone,
parentId: _parentId,
requiresBookerEmailVerification,
lockTimeZoneToggleOnBookingPage,
useEventTypeDestinationCalendarEmail,
secondaryEmailId,
autoTranslateDescriptionEnabled,
includeNoShowInRRCalculation,
instantMeetingScheduleId,
assignRRMembersUsingSegment,
};
prismaMock.eventType.createManyAndReturn.mockResolvedValue([createdEventType]);

// Mock the event type that will be returned for existing users
const mockUpdatedEventType = {
Expand Down Expand Up @@ -601,9 +569,9 @@ describe("handleChildrenEventTypes", () => {

const { createdAt, updatedAt, ...expectedEvType } = evType;
if ("workflows" in expectedEvType) delete expectedEvType.workflows;
// Verify createMany was called for new users (user 5)
// Note: createMany doesn't support nested relations like workflows, so they're handled separately
expect(prismaMock.eventType.createMany).toHaveBeenCalledWith({
// Verify createManyAndReturn was called for new users (user 5)
// Note: createManyAndReturn doesn't support nested relations like workflows, so they're handled separately
expect(prismaMock.eventType.createManyAndReturn).toHaveBeenCalledWith({
data: [
{
...expectedEvType,
Expand All @@ -627,6 +595,7 @@ describe("handleChildrenEventTypes", () => {
},
],
skipDuplicates: true,
select: { id: true, userId: true },
});

// Verify workflowsOnEventTypes.createMany was called for new users' workflows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,9 @@ export default async function handleChildrenEventTypes({
});

await prisma.$transaction(async (tx) => {
await tx.eventType.createMany({
const createdEvents = await tx.eventType.createManyAndReturn({
data: eventTypesToCreateData,
skipDuplicates: true,
});

// Fetch the newly created event types to connect users and workflows
const createdEvents = await tx.eventType.findMany({
where: { parentId: parentId, userId: { in: newUserIds } },
select: { id: true, userId: true },
});

Expand Down
Loading