Skip to content
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c9851e2
fix: resolve username constraint violation in removeMember
devin-ai-integration[bot] Jul 30, 2025
6121a2a
test: update removeMember test to verify constraint violation scenario
devin-ai-integration[bot] Jul 30, 2025
8760e3c
test: add comprehensive unit tests for handleInstantMeeting
devin-ai-integration[bot] Jul 31, 2025
c00f61b
update
anikdhabal Jul 31, 2025
18e7694
Update handleInstantMeeting.test.ts
anikdhabal Jul 31, 2025
881dac5
fix: redir parameter for connect atoms (#22815)
Ryukemeister Jul 30, 2025
1a5eca3
feat: Support an array response for a field when used as `Value of Fi…
hariombalhara Jul 30, 2025
e7e40bf
fix: flaky e2e (#22819)
anikdhabal Jul 30, 2025
187b8df
fix: merge working hours when adjacent (#21912)
emrysal Jul 30, 2025
c828a02
feat: Improving Booking Visibility at Month-End (#22770)
CarinaWolli Jul 30, 2025
171c707
chore: Refactor logs (#22824)
joeauyeung Jul 31, 2025
06dec5f
fix: Errors in org onboarding in some edge cases (#22711)
hariombalhara Jul 31, 2025
a35ea94
feat: enable PBAC checking on organization settings page (#22467)
sean-brydon Jul 31, 2025
6bf394f
refactor: convert checkBookingLimits to class service with dependency…
devin-ai-integration[bot] Jul 31, 2025
5dce6b4
fix: Return empty available days if error querying calendar (#22828)
joeauyeung Jul 31, 2025
1ca64f4
chore: release v5.5.9
emrysal Jul 31, 2025
72094fc
include mobile layout (#22836)
CarinaWolli Jul 31, 2025
533d51a
test: fix handleInstantMeeting test with setupAndTeardown and proper …
devin-ai-integration[bot] Jul 31, 2025
0bdbaea
Merge branch 'main' into devin/fix-username-constraint-removemember-1…
anikdhabal Jul 31, 2025
aed4bf8
fix typo
anikdhabal Jul 31, 2025
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
203 changes: 203 additions & 0 deletions packages/features/instant-meeting/handleInstantMeeting.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
import prismock from "../../../tests/libs/__mocks__/prisma";

import {
createBookingScenario,
getScenarioData,
getGoogleCalendarCredential,
TestData,
getOrganizer,
mockSuccessfulVideoMeetingCreation,
mockCalendarToHaveNoBusySlots,
mockNoTranslations,
} from "@calcom/web/test/utils/bookingScenario/bookingScenario";

import type { NextApiRequest } from "next";
import { describe, it, expect, vi, beforeEach } from "vitest";

import { BookingStatus } from "@calcom/prisma/enums";

vi.mock("@calcom/features/notifications/sendNotification", () => ({
sendNotification: vi.fn(),
}));

vi.mock("@calcom/lib/videoClient", () => ({
createInstantMeetingWithCalVideo: vi.fn().mockResolvedValue({
type: "daily_video",
id: "MOCK_INSTANT_MEETING_ID",
password: "MOCK_INSTANT_PASS",
url: "http://mock-dailyvideo.example.com/instant-meeting-url",
}),
}));

describe("handleInstantMeeting", () => {
beforeEach(() => {
mockNoTranslations();
});
describe("team event instant meeting", () => {
it("should successfully create instant meeting for team event", async () => {
const handler = (await import("./handleInstantMeeting")).default;
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 });

await createBookingScenario(
getScenarioData({
eventTypes: [
{
id: 1,
slotInterval: 45,
length: 45,
users: [
{
id: 101,
},
],
team: {
id: 1,
},
instantMeetingExpiryTimeOffsetInSeconds: 90,
},
],
organizer,
apps: [TestData.apps["daily-video"], TestData.apps["google-calendar"]],
})
);

mockSuccessfulVideoMeetingCreation({
metadataLookupKey: "dailyvideo",
videoMeetingData: {
id: "MOCK_ID",
password: "MOCK_PASS",
url: `http://mock-dailyvideo.example.com/meeting-1`,
},
});
mockCalendarToHaveNoBusySlots("googlecalendar", {
create: {
uid: "MOCKED_GOOGLE_CALENDAR_EVENT_ID",
},
});

const mockReqBody = {
eventTypeId: 1,
name: "Test User",
email: "test@example.com",
timeZone: "UTC",
language: "en",
start: `${plus1DateString}T04:00:00.000Z`,
end: `${plus1DateString}T04:45:00.000Z`,
responses: {
name: "Test User",
email: "test@example.com",
},
metadata: {},
};

const mockRequest = {
body: mockReqBody,
method: "POST",
headers: {},
query: {},
cookies: {},
url: "/api/instant-meeting",
} as NextApiRequest;

const result = await handler(mockRequest);

expect(result.message).toBe("Success");
expect(result.bookingId).toBeDefined();
expect(result.bookingUid).toBeDefined();
expect(result.meetingTokenId).toBeDefined();
expect(result.expires).toBeInstanceOf(Date);

const booking = await prismock.booking.findUnique({
where: { id: result.bookingId },
include: { attendees: true, references: true },
});

expect(booking).toBeDefined();
expect(booking?.status).toBe(BookingStatus.AWAITING_HOST);
expect(booking?.attendees).toHaveLength(1);
expect(booking?.attendees[0].email).toBe("test@example.com");
expect(booking?.references).toHaveLength(1);
expect(booking?.references[0].type).toBe("daily_video");
});

it("should throw error for non-team event types", async () => {
const handler = (await import("./handleInstantMeeting")).default;
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 });

await createBookingScenario(
getScenarioData({
eventTypes: [
{
id: 1,
slotInterval: 45,
length: 45,
users: [
{
id: 101,
},
],
},
],
organizer,
apps: [TestData.apps["daily-video"], TestData.apps["google-calendar"]],
})
);

const mockReqBody = {
eventTypeId: 1,
name: "Test User",
email: "test@example.com",
timeZone: "UTC",
language: "en",
start: `${plus1DateString}T04:00:00.000Z`,
end: `${plus1DateString}T04:45:00.000Z`,
responses: {
name: "Test User",
email: "test@example.com",
},
metadata: {},
};

const mockRequest = {
body: mockReqBody,
method: "POST",
headers: {},
query: {},
cookies: {},
url: "/api/instant-meeting",
} as NextApiRequest;

await expect(handler(mockRequest)).rejects.toThrow(
"Only Team Event Types are supported for Instant Meeting"
);
});
});
});

function getDate(param: { dateIncrement?: number } = {}) {
const { dateIncrement = 0 } = param;
const date = new Date();
date.setDate(date.getDate() + dateIncrement);
return {
date,
dateString: date.toISOString().split("T")[0],
};
}
Loading