* perf: implement quick app store loading optimizations - Add conditional app store imports in videoClient and handlePayment - Implement lazy calendar manager pattern in CalendarManager - Enhance createCachedImport with better concurrency handling - Create calendar-only registry for common calendar operations - Add performance instrumentation for debugging These optimizations reduce initial app store loading time by avoiding module-level imports and creating smaller, focused registries for calendar operations. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: revert getCalendar to use appStore for proper test mocking - Reverted getCalendar.ts to use main appStore instead of calendarStore - This ensures test mocking system works properly with existing appStoreMock - Fixes unit test failures where Google Calendar references were getting null values - All collective scheduling tests now pass Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * perf: implement CalendarServiceMap for optimized calendar loading - Add CalendarServiceMap generation following CrmServiceMap pattern - Update getCalendar.ts to use generated calendar service map - Remove manual calendar-registry.ts in favor of auto-generated approach - Reduces calendar initialization from loading 48+ apps to ~10 calendar apps Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: update test mocks for CalendarServiceMap compatibility - Add missing SelectedCalendar fields (createdAt, updatedAt, lastErrorAt, watchAttempts, etc.) - Fix CredentialPayload type errors by adding user.email and delegationCredentialId - Mock CalendarServiceMap to use vi.importActual for real calendar services - Ensure calendar service tests work with new lazy loading approach Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: resolve CalendarServiceMap test compatibility issues - Update getCalendarsEvents.test.ts mocks to work with CalendarServiceMap dynamic imports - Add missing SelectedCalendar fields (createdAt, updatedAt, lastErrorAt, watchAttempts, etc.) - Fix CredentialPayload type errors by adding user.email and delegationCredentialId - Use type assertion in getCalendar.ts to resolve credential type conflicts - Ensure calendar service tests work with new lazy loading approach Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: update test mocking for CalendarServiceMap compatibility - Add comprehensive vi.mock for calendar.services.generated in delegation-credential tests - Mock GoogleCalendarService and Office365CalendarService with proper return values - Update all test files to use await with mockCalendarToHaveNoBusySlots - Ensure calendar events return expected meetingId, meetingPassword, meetingUrl values - Fix async/await compatibility issues in booking scenario test utilities Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: resolve TypeScript errors in CalendarServiceMap mocking - Extract CalendarServiceMap promise to variable to fix 'always true' condition - Ensure vi.mocked is called on Promise type for proper mockResolvedValue access - Add await keywords to calendar mock calls in test files - Maintain existing functionality while making code type-safe Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * Remove Exchange 2013 and 2016 * Mock Exchange in all tests * Fix tests * Remove exchange 2013 and 2016 from app store index * Fix merge error * Await when getting calendar service * Fix selectedSlot test * Add missing variable * Update openapi.json * Updated CalendarService imports * try again * WIP migrate calendar apps to ES6 * Revert "WIP migrate calendar apps to ES6" This reverts commit 15bf2c83305e82050779d0bca3380fa9573db1e0. * Revert changes back to e23991024a5a455c14aa05f100a5b56288db343a This reverts all calendar service changes that were causing circular dependency issues during builds and E2E tests. * Remove circular dependency for location constants * Update yarn.lock with removed package * Add empty map when running E2E * Type fies * Fix merge conflict * Remove logging statements * Throw error and reset state if failing to load app * Revert "Remove Exchange 2013 and 2016" This reverts commit fedaf6346bd9e4c63337276d5a6f9e8c3943056c. * Re-introduce exchange{2013,2016} Revert the removal in app-store/index.ts also. * Trying to fix tests --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com> Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: Alex van Andel <me@alexvanandel.com>
209 lines
6.1 KiB
TypeScript
209 lines
6.1 KiB
TypeScript
import {
|
|
getDate,
|
|
createBookingScenario,
|
|
Timezones,
|
|
TestData,
|
|
mockCalendar,
|
|
createDelegationCredential,
|
|
createOrganization,
|
|
getOrganizer,
|
|
} from "../../utils/bookingScenario/bookingScenario";
|
|
import { expectNoAttemptToGetAvailability } from "../../utils/bookingScenario/expects";
|
|
|
|
import { describe, test } from "vitest";
|
|
|
|
import { getAvailableSlotsService } from "@calcom/lib/di/containers/AvailableSlots";
|
|
import { MembershipRole } from "@calcom/prisma/enums";
|
|
|
|
import { expect, expectedSlotsForSchedule } from "./expects";
|
|
import { setupAndTeardown } from "./setupAndTeardown";
|
|
|
|
describe("getSchedule", () => {
|
|
const availableSlotsService = getAvailableSlotsService();
|
|
setupAndTeardown();
|
|
|
|
describe("Delegation Credential", () => {
|
|
test("correctly identifies unavailable slots using DelegationCredential credentials", async () => {
|
|
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
|
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
|
|
|
|
const org = await createOrganization({
|
|
name: "Test Org",
|
|
slug: "testorg",
|
|
});
|
|
|
|
const payloadToMakePartOfOrganization = [
|
|
{
|
|
membership: {
|
|
accepted: true,
|
|
role: MembershipRole.ADMIN,
|
|
},
|
|
team: {
|
|
id: org.id,
|
|
name: "Test Org",
|
|
slug: "testorg",
|
|
},
|
|
},
|
|
];
|
|
|
|
const organizer = getOrganizer({
|
|
name: "Organizer",
|
|
email: "organizer@example.com",
|
|
id: 101,
|
|
schedules: [TestData.schedules.IstWorkHours],
|
|
selectedCalendars: [TestData.selectedCalendars.google],
|
|
// User must be part of organization to be able to use that organization's Delegation credential
|
|
teams: payloadToMakePartOfOrganization,
|
|
// No regular credentials provided
|
|
credentials: [],
|
|
});
|
|
|
|
await createDelegationCredential(org.id);
|
|
|
|
const googleCalendarMock = await mockCalendar("googlecalendar", {
|
|
create: {
|
|
uid: "MOCK_ID",
|
|
iCalUID: "MOCKED_GOOGLE_CALENDAR_ICS_ID",
|
|
},
|
|
busySlots: [
|
|
{
|
|
start: `${plus2DateString}T04:45:00.000Z`,
|
|
end: `${plus2DateString}T23:00:00.000Z`,
|
|
},
|
|
],
|
|
});
|
|
|
|
const scenarioData = {
|
|
eventTypes: [
|
|
{
|
|
id: 1,
|
|
slotInterval: 45,
|
|
length: 45,
|
|
users: [
|
|
{
|
|
id: organizer.id,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
users: [organizer],
|
|
apps: [TestData.apps["google-calendar"]],
|
|
};
|
|
|
|
await createBookingScenario(scenarioData);
|
|
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
|
|
input: {
|
|
eventTypeId: 1,
|
|
eventTypeSlug: "",
|
|
startTime: `${plus1DateString}T18:30:00.000Z`,
|
|
endTime: `${plus2DateString}T18:29:59.999Z`,
|
|
timeZone: Timezones["+5:30"],
|
|
isTeamEvent: false,
|
|
orgSlug: null,
|
|
},
|
|
});
|
|
|
|
// As per Google Calendar Availability, only 4PM(4-4:45PM) GMT slot would be available
|
|
expect(scheduleForDayWithAGoogleCalendarBooking).toHaveTimeSlots([`04:00:00.000Z`], {
|
|
dateString: plus2DateString,
|
|
});
|
|
});
|
|
|
|
test("fails to get schedule when user isn't part of the organization with Delegation credential", async () => {
|
|
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
|
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
|
|
|
|
const org = await createOrganization({
|
|
name: "Test Org",
|
|
slug: "testorg",
|
|
});
|
|
|
|
const anotherOrg = await createOrganization({
|
|
name: "Another Org",
|
|
slug: "anotherorg",
|
|
});
|
|
|
|
// User is part of a different org
|
|
const payloadToMakePartOfDifferentOrganization = [
|
|
{
|
|
membership: {
|
|
accepted: true,
|
|
role: MembershipRole.ADMIN,
|
|
},
|
|
team: {
|
|
id: anotherOrg.id,
|
|
name: "Another Org",
|
|
slug: "anotherorg",
|
|
},
|
|
},
|
|
];
|
|
|
|
const organizer = getOrganizer({
|
|
name: "Organizer",
|
|
email: "organizer@example.com",
|
|
id: 101,
|
|
schedules: [TestData.schedules.IstWorkHours],
|
|
selectedCalendars: [TestData.selectedCalendars.google],
|
|
teams: payloadToMakePartOfDifferentOrganization,
|
|
credentials: [],
|
|
});
|
|
|
|
// Create Delegation credential for the org user isn't part of
|
|
await createDelegationCredential(org.id);
|
|
|
|
const googleCalendarMock = await mockCalendar("googlecalendar", {
|
|
create: {
|
|
uid: "MOCK_ID",
|
|
iCalUID: "MOCKED_GOOGLE_CALENDAR_ICS_ID",
|
|
},
|
|
busySlots: [
|
|
{
|
|
start: `${plus2DateString}T04:45:00.000Z`,
|
|
end: `${plus2DateString}T23:00:00.000Z`,
|
|
},
|
|
],
|
|
});
|
|
|
|
const scenarioData = {
|
|
eventTypes: [
|
|
{
|
|
id: 1,
|
|
slotInterval: 60,
|
|
length: 60,
|
|
users: [
|
|
{
|
|
id: organizer.id,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
users: [organizer],
|
|
apps: [TestData.apps["google-calendar"]],
|
|
};
|
|
|
|
await createBookingScenario(scenarioData);
|
|
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
|
|
input: {
|
|
eventTypeId: 1,
|
|
eventTypeSlug: "",
|
|
startTime: `${plus1DateString}T18:30:00.000Z`,
|
|
endTime: `${plus2DateString}T18:29:59.999Z`,
|
|
timeZone: Timezones["+5:30"],
|
|
isTeamEvent: false,
|
|
orgSlug: null,
|
|
},
|
|
});
|
|
|
|
expectNoAttemptToGetAvailability(googleCalendarMock);
|
|
|
|
// All slots would be available as no DelegationCredential credentials are available
|
|
expect(scheduleForDayWithAGoogleCalendarBooking).toHaveTimeSlots(
|
|
expectedSlotsForSchedule.IstWorkHours.interval["1hr"].allPossibleSlotsStartingAt430,
|
|
{
|
|
dateString: plus2DateString,
|
|
}
|
|
);
|
|
});
|
|
});
|
|
});
|