Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add unit tests for sms sending #14737

Merged
merged 15 commits into from May 2, 2024
11 changes: 11 additions & 0 deletions apps/web/test/fixtures/fixtures.ts
Expand Up @@ -2,19 +2,30 @@
import { test as base } from "vitest";

import { getTestEmails } from "@calcom/lib/testEmails";
import { getTestSMS } from "@calcom/lib/testSMS";

export interface Fixtures {
emails: ReturnType<typeof getEmailsFixture>;
sms: ReturnType<typeof getSMSFixture>;
}

export const test = base.extend<Fixtures>({
emails: async ({}, use) => {
await use(getEmailsFixture());
},
sms: async ({}, use) => {
await use(getSMSFixture());
},
});

function getEmailsFixture() {
return {
get: getTestEmails,
};
}

function getSMSFixture() {
return {
get: getTestSMS,
};
}
5 changes: 4 additions & 1 deletion apps/web/test/utils/bookingScenario/bookingScenario.ts
Expand Up @@ -19,7 +19,7 @@ import logger from "@calcom/lib/logger";
import { safeStringify } from "@calcom/lib/safeStringify";
import { ProfileRepository } from "@calcom/lib/server/repository/profile";
import type { WorkflowActions, WorkflowTemplates, WorkflowTriggerEvents } from "@calcom/prisma/client";
import type { SchedulingType } from "@calcom/prisma/enums";
import type { SchedulingType, SMSLockState } from "@calcom/prisma/enums";
import type { BookingStatus } from "@calcom/prisma/enums";
import type { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import type { userMetadataType } from "@calcom/prisma/zod-utils";
Expand Down Expand Up @@ -952,6 +952,7 @@ export function getOrganizer({
teams,
organizationId,
metadata,
smsLockState,
}: {
name: string;
email: string;
Expand All @@ -965,6 +966,7 @@ export function getOrganizer({
weekStart?: WeekDays;
teams?: InputUser["teams"];
metadata?: userMetadataType;
smsLockState?: SMSLockState;
}) {
return {
...TestData.users.example,
Expand All @@ -981,6 +983,7 @@ export function getOrganizer({
organizationId,
profiles: [],
metadata,
smsLockState,
};
}

Expand Down
68 changes: 51 additions & 17 deletions apps/web/test/utils/bookingScenario/expects.ts
Expand Up @@ -170,7 +170,7 @@
pass: false,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
actual: icsObject[icsKey].uid!,

Check warning on line 173 in apps/web/test/utils/bookingScenario/expects.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

apps/web/test/utils/bookingScenario/expects.ts#L173

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
expected: expectedEmail.ics?.iCalUID,
message: () => `Expected ICS UID ${isNot ? "is" : "isn't"} present in actual`,
};
Expand Down Expand Up @@ -307,38 +307,72 @@

export function expectWorkflowToBeTriggered({
emails,
organizer,
destinationEmail,
emailsToReceive,
}: {
emails: Fixtures["emails"];
organizer: { email: string; name: string; timeZone: string };
destinationEmail?: string;
emailsToReceive: string[];
}) {
const subjectPattern = /^Reminder: /i;
expect(emails.get()).toEqual(
expect.arrayContaining([
expect.objectContaining({
subject: expect.stringMatching(subjectPattern),
to: destinationEmail ?? organizer.email,
}),
])
);
emailsToReceive.forEach((email) => {
expect(emails.get()).toEqual(
expect.arrayContaining([
expect.objectContaining({
subject: expect.stringMatching(subjectPattern),
to: email,
}),
])
);
});
}

export function expectWorkflowToBeNotTriggered({
emails,
organizer,
emailsToReceive,
}: {
emails: Fixtures["emails"];
organizer: { email: string; name: string; timeZone: string };
emailsToReceive: string[];
}) {
const subjectPattern = /^Reminder: /i;

expect(emails.get()).not.toEqual(
emailsToReceive.forEach((email) => {
expect(emails.get()).not.toEqual(
expect.arrayContaining([
expect.objectContaining({
subject: expect.stringMatching(subjectPattern),
to: email,
}),
])
);
});
}

export function expectSMSWorkflowToBeTriggered({
sms,
toNumber,
}: {
sms: Fixtures["sms"];
toNumber: string;
}) {
expect(sms.get()).toEqual(
expect.arrayContaining([
expect.objectContaining({
to: toNumber,
}),
])
);
}

export function expectSMSWorkflowToBeNotTriggered({
sms,
toNumber,
}: {
sms: Fixtures["sms"];
toNumber: string;
}) {
expect(sms.get()).not.toEqual(
expect.arrayContaining([
expect.objectContaining({
subject: expect.stringMatching(subjectPattern),
to: organizer.email,
to: toNumber,
}),
])
);
Expand Down Expand Up @@ -735,7 +769,7 @@
booker,
booking,
bookNewTimePath,
organizer,

Check warning on line 772 in apps/web/test/utils/bookingScenario/expects.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

apps/web/test/utils/bookingScenario/expects.ts#L772

[@typescript-eslint/no-unused-vars] 'organizer' is defined but never used. Allowed unused args must match /^_/u.
}: {
emails: Fixtures["emails"];
organizer: ReturnType<typeof getOrganizer>;
Expand Down
Expand Up @@ -30,6 +30,7 @@ export function getMockRequestDataForBooking({
email: string;
name: string;
location: { optionValue: ""; value: string };
smsReminderNumber?: string;
};
};
}) {
Expand Down
6 changes: 4 additions & 2 deletions apps/web/test/utils/bookingScenario/test.ts
Expand Up @@ -15,7 +15,7 @@ const _testWithAndWithoutOrg = (
const t = mode === "only" ? test.only : mode === "skip" ? test.skip : test;
t(
`${description} - With org`,
async ({ emails, meta, task, onTestFailed, expect, skip }) => {
async ({ emails, sms, meta, task, onTestFailed, expect, skip }) => {
const org = await createOrganization({
name: "Test Org",
slug: "testorg",
Expand All @@ -27,6 +27,7 @@ const _testWithAndWithoutOrg = (
onTestFailed,
expect,
emails,
sms,
skip,
org: {
organization: org,
Expand All @@ -39,9 +40,10 @@ const _testWithAndWithoutOrg = (

t(
`${description}`,
async ({ emails, meta, task, onTestFailed, expect, skip }) => {
async ({ emails, sms, meta, task, onTestFailed, expect, skip }) => {
await fn({
emails,
sms,
meta,
task,
onTestFailed,
Expand Down
Expand Up @@ -42,6 +42,7 @@ import {
import { createMockNextJsRequest } from "@calcom/web/test/utils/bookingScenario/createMockNextJsRequest";
import {
expectWorkflowToBeTriggered,
expectWorkflowToBeNotTriggered,
expectSuccessfulBookingCreationEmails,
expectBookingToBeInDatabase,
expectAwaitingPaymentEmails,
Expand All @@ -51,7 +52,6 @@ import {
expectBookingPaymentIntiatedWebhookToHaveBeenFired,
expectBrokenIntegrationEmails,
expectSuccessfulCalendarEventCreationInCalendar,
expectWorkflowToBeNotTriggered,
expectICalUIDAsString,
} from "@calcom/web/test/utils/bookingScenario/expects";
import { getMockRequestDataForBooking } from "@calcom/web/test/utils/bookingScenario/getMockRequestDataForBooking";
Expand Down Expand Up @@ -215,9 +215,8 @@ describe("handleNewBooking", () => {
});

expectWorkflowToBeTriggered({
organizer,
emailsToReceive: [organizerDestinationCalendarEmailOnEventType],
emails,
destinationEmail: organizerDestinationCalendarEmailOnEventType,
});
expectSuccessfulCalendarEventCreationInCalendar(calendarMock, {
calendarId: "event-type-1@google-calendar.com",
Expand Down Expand Up @@ -379,7 +378,7 @@ describe("handleNewBooking", () => {
iCalUID: createdBooking.iCalUID,
});

expectWorkflowToBeTriggered({ organizer, emails });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });
expectSuccessfulCalendarEventCreationInCalendar(calendarMock, {
videoCallUrl: "http://mock-dailyvideo.example.com/meeting-1",
// We won't be sending evt.destinationCalendar in this case.
Expand Down Expand Up @@ -541,7 +540,7 @@ describe("handleNewBooking", () => {
iCalUID: createdBooking.iCalUID,
});

expectWorkflowToBeTriggered({ organizer, emails });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });
expectSuccessfulCalendarEventCreationInCalendar(calendarMock, {
calendarId: "organizer@google-calendar.com",
videoCallUrl: "http://mock-dailyvideo.example.com/meeting-1",
Expand Down Expand Up @@ -675,7 +674,7 @@ describe("handleNewBooking", () => {
],
});

expectWorkflowToBeTriggered({ organizer, emails });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

// FIXME: We should send Broken Integration emails on calendar event creation failure
// expectCalendarEventCreationFailureEmails({ booker, organizer, emails });
Expand Down Expand Up @@ -825,7 +824,7 @@ describe("handleNewBooking", () => {
iCalUID: createdBooking.iCalUID,
});

expectWorkflowToBeTriggered({ organizer, emails });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

expectSuccessfulCalendarEventCreationInCalendar(calendarMock, {
calendarId: "organizer@google-calendar.com",
Expand Down Expand Up @@ -982,7 +981,7 @@ describe("handleNewBooking", () => {
],
});

expectWorkflowToBeTriggered({ organizer, emails });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });
expectSuccessfulCalendarEventCreationInCalendar(calendarMock, {
calendarId: "organizer@google-calendar.com",
videoCallUrl: "http://mock-dailyvideo.example.com/meeting-1",
Expand Down Expand Up @@ -1511,7 +1510,7 @@ describe("handleNewBooking", () => {
status: BookingStatus.PENDING,
});

expectWorkflowToBeNotTriggered({ organizer, emails });
expectWorkflowToBeNotTriggered({ emailsToReceive: [organizer.email], emails });

expectBookingRequestedEmails({
booker,
Expand Down Expand Up @@ -1636,7 +1635,7 @@ describe("handleNewBooking", () => {
}),
});

expectWorkflowToBeNotTriggered({ organizer, emails });
expectWorkflowToBeNotTriggered({ emailsToReceive: [organizer.email], emails });

expectBookingRequestedEmails({
booker,
Expand Down Expand Up @@ -1764,7 +1763,7 @@ describe("handleNewBooking", () => {
iCalUID: createdBooking.iCalUID,
});

expectWorkflowToBeTriggered({ organizer, emails });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

const iCalUID = expectICalUIDAsString(createdBooking.iCalUID);

Expand Down Expand Up @@ -1897,7 +1896,7 @@ describe("handleNewBooking", () => {
iCalUID: createdBooking.iCalUID,
});

expectWorkflowToBeNotTriggered({ organizer, emails });
expectWorkflowToBeNotTriggered({ emailsToReceive: [organizer.email], emails });

expectBookingRequestedEmails({ booker, organizer, emails });

Expand Down Expand Up @@ -2076,7 +2075,7 @@ describe("handleNewBooking", () => {
iCalUID: createdBooking.iCalUID,
});

expectWorkflowToBeTriggered({ organizer, emails });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

const iCalUID = expectICalUIDAsString(createdBooking.iCalUID);

Expand Down Expand Up @@ -2220,7 +2219,7 @@ describe("handleNewBooking", () => {
}),
});

expectWorkflowToBeNotTriggered({ organizer, emails });
expectWorkflowToBeNotTriggered({ emailsToReceive: [organizer.email], emails });

expectAwaitingPaymentEmails({ organizer, booker, emails });

Expand All @@ -2244,7 +2243,7 @@ describe("handleNewBooking", () => {
status: BookingStatus.ACCEPTED,
});

expectWorkflowToBeTriggered({ organizer, emails });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

expectBookingCreatedWebhookToHaveBeenFired({
booker,
Expand Down Expand Up @@ -2374,7 +2373,7 @@ describe("handleNewBooking", () => {
status: BookingStatus.PENDING,
});

expectWorkflowToBeNotTriggered({ organizer, emails });
expectWorkflowToBeNotTriggered({ emailsToReceive: [organizer.email], emails });

expectAwaitingPaymentEmails({ organizer, booker, emails });
expectBookingPaymentIntiatedWebhookToHaveBeenFired({
Expand Down
Expand Up @@ -240,7 +240,7 @@ describe("handleNewBooking", () => {
],
},
});
expectWorkflowToBeTriggered({ emails, organizer });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

expectSuccessfulVideoMeetingUpdationInCalendar(videoMock, {
calEvent: {
Expand Down Expand Up @@ -459,7 +459,7 @@ describe("handleNewBooking", () => {
},
});

expectWorkflowToBeTriggered({ emails, organizer });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

expectSuccessfulVideoMeetingUpdationInCalendar(videoMock, {
calEvent: {
Expand Down Expand Up @@ -656,7 +656,7 @@ describe("handleNewBooking", () => {
},
});

expectWorkflowToBeTriggered({ emails, organizer });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

// FIXME: We should send Broken Integration emails on calendar event updation failure
// expectBrokenIntegrationEmails({ booker, organizer, emails });
Expand Down Expand Up @@ -850,7 +850,7 @@ describe("handleNewBooking", () => {
},
});

expectWorkflowToBeTriggered({ emails, organizer });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

expectBookingRequestedEmails({
booker,
Expand Down Expand Up @@ -1085,7 +1085,7 @@ describe("handleNewBooking", () => {
},
});

expectWorkflowToBeTriggered({ emails, organizer });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

expectSuccessfulVideoMeetingUpdationInCalendar(videoMock, {
calEvent: {
Expand Down Expand Up @@ -1312,7 +1312,7 @@ describe("handleNewBooking", () => {
},
});

//expectWorkflowToBeTriggered({emails, organizer});
//expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

expectBookingRequestedEmails({
booker,
Expand Down Expand Up @@ -1559,7 +1559,7 @@ describe("handleNewBooking", () => {
},
});

expectWorkflowToBeTriggered({ emails, organizer });
expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });

expectSuccessfulVideoMeetingUpdationInCalendar(videoMock, {
calEvent: {
Expand Down