* feat: Cal.diy — community-driven MIT-licensed fork of Cal.com This squashed commit contains all Cal.diy changes applied on top of calcom/cal.com main: - Rebrand Cal.com to Cal.diy across the entire codebase - Remove Enterprise Edition (EE) features, license checks, and AGPL restrictions - Switch license from AGPL-3.0 to MIT - Remove docs/ directory (migrated to Nextra at cal.diy) - Remove dead code: org tests, EE tips, platform nav, premium username, SAML/SSO, etc. - Clean up .env.example for self-hosted Cal.diy - Update Docker image references to calcom/cal.diy - Update README, CONTRIBUTING.md, and issue templates for Cal.diy community fork - Add PR welcome bot for Cal.diy contributors - Fix API v2 breaking changes oasdiff ignore entries - Replace Blacksmith CI runners with default GitHub Actions 3893 files changed, 20789 insertions(+), 411020 deletions(-) Co-Authored-By: benny@cal.com <sldisek783@gmail.com> * refactor: remove org-specific /organizations/:orgId endpoints from API v2 atoms controllers (#1701) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: revert Cal.diy Inc to Cal.com, Inc. in license files, copyright notices, and package metadata (#1702) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * rip out org related comments in api v2 --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
225 lines
6.5 KiB
TypeScript
225 lines
6.5 KiB
TypeScript
import {
|
|
getDate,
|
|
createBookingScenario,
|
|
Timezones,
|
|
TestData,
|
|
mockCalendar,
|
|
createDelegationCredential,
|
|
createOrganization,
|
|
getOrganizer,
|
|
} from "@calcom/testing/lib/bookingScenario/bookingScenario";
|
|
import { expectNoAttemptToGetAvailability } from "@calcom/testing/lib/bookingScenario/expects";
|
|
|
|
import { describe, test } from "vitest";
|
|
|
|
import { getAvailableSlotsService } from "@calcom/features/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,
|
|
},
|
|
});
|
|
|
|
// With EE removal, delegation credentials are stubbed so Google Calendar busy times are not fetched.
|
|
// All slots in the user's availability window are returned.
|
|
expect(scheduleForDayWithAGoogleCalendarBooking).toHaveTimeSlots(
|
|
[
|
|
`04:00:00.000Z`,
|
|
`04:45:00.000Z`,
|
|
`05:30:00.000Z`,
|
|
`06:15:00.000Z`,
|
|
`07:00:00.000Z`,
|
|
`07:45:00.000Z`,
|
|
`08:30:00.000Z`,
|
|
`09:15:00.000Z`,
|
|
`10:00:00.000Z`,
|
|
`10:45:00.000Z`,
|
|
`11:30: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,
|
|
}
|
|
);
|
|
});
|
|
});
|
|
});
|