One test Working with prismock
parent
b348866fc2
commit
c2d53fef3c
|
@ -4,7 +4,6 @@ import prismaMock from "../../../../tests/libs/__mocks__/prisma";
|
|||
import { diff } from "jest-diff";
|
||||
import { describe, expect, vi, beforeEach, afterEach, test } from "vitest";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { BookingStatus } from "@calcom/prisma/enums";
|
||||
import type { Slot } from "@calcom/trpc/server/routers/viewer/slots/types";
|
||||
import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util";
|
||||
|
@ -15,10 +14,6 @@ import {
|
|||
createBookingScenario,
|
||||
} from "../utils/bookingScenario/bookingScenario";
|
||||
|
||||
// TODO: Mock properly
|
||||
prismaMock.eventType.findUnique.mockResolvedValue(null);
|
||||
prismaMock.user.findMany.mockResolvedValue([]);
|
||||
|
||||
vi.mock("@calcom/lib/constants", () => ({
|
||||
IS_PRODUCTION: true,
|
||||
WEBAPP_URL: "http://localhost:3000",
|
||||
|
@ -149,13 +144,13 @@ const TestData = {
|
|||
};
|
||||
|
||||
const cleanup = async () => {
|
||||
await prisma.eventType.deleteMany();
|
||||
await prisma.user.deleteMany();
|
||||
await prisma.schedule.deleteMany();
|
||||
await prisma.selectedCalendar.deleteMany();
|
||||
await prisma.credential.deleteMany();
|
||||
await prisma.booking.deleteMany();
|
||||
await prisma.app.deleteMany();
|
||||
await prismaMock.eventType.deleteMany();
|
||||
await prismaMock.user.deleteMany();
|
||||
await prismaMock.schedule.deleteMany();
|
||||
await prismaMock.selectedCalendar.deleteMany();
|
||||
await prismaMock.credential.deleteMany();
|
||||
await prismaMock.booking.deleteMany();
|
||||
await prismaMock.app.deleteMany();
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
|
@ -204,7 +199,7 @@ describe("getSchedule", () => {
|
|||
apps: [TestData.apps.googleCalendar],
|
||||
};
|
||||
// An event with one accepted booking
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
const scheduleForDayWithAGoogleCalendarBooking = await getSchedule({
|
||||
input: {
|
||||
|
@ -231,7 +226,7 @@ describe("getSchedule", () => {
|
|||
const { dateString: plus3DateString } = getDate({ dateIncrement: 3 });
|
||||
|
||||
// An event with one accepted booking
|
||||
createBookingScenario({
|
||||
await createBookingScenario({
|
||||
// An event with length 30 minutes, slotInterval 45 minutes, and minimumBookingNotice 1440 minutes (24 hours)
|
||||
eventTypes: [
|
||||
{
|
||||
|
@ -357,7 +352,7 @@ describe("getSchedule", () => {
|
|||
});
|
||||
|
||||
test("slots are available as per `length`, `slotInterval` of the event", async () => {
|
||||
createBookingScenario({
|
||||
await createBookingScenario({
|
||||
eventTypes: [
|
||||
{
|
||||
id: 1,
|
||||
|
@ -447,7 +442,7 @@ describe("getSchedule", () => {
|
|||
|
||||
// FIXME: Fix minimumBookingNotice is respected test
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip("minimumBookingNotice is respected", async () => {
|
||||
test("minimumBookingNotice is respected", async () => {
|
||||
vi.useFakeTimers().setSystemTime(
|
||||
(() => {
|
||||
const today = new Date();
|
||||
|
@ -456,7 +451,7 @@ describe("getSchedule", () => {
|
|||
})()
|
||||
);
|
||||
|
||||
createBookingScenario({
|
||||
await createBookingScenario({
|
||||
eventTypes: [
|
||||
{
|
||||
id: 1,
|
||||
|
@ -572,7 +567,7 @@ describe("getSchedule", () => {
|
|||
apps: [TestData.apps.googleCalendar],
|
||||
};
|
||||
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
const scheduleForEventOnADayWithNonCalBooking = await getSchedule({
|
||||
input: {
|
||||
|
@ -646,7 +641,7 @@ describe("getSchedule", () => {
|
|||
apps: [TestData.apps.googleCalendar],
|
||||
};
|
||||
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
const scheduleForEventOnADayWithCalBooking = await getSchedule({
|
||||
input: {
|
||||
|
@ -704,7 +699,7 @@ describe("getSchedule", () => {
|
|||
apps: [TestData.apps.googleCalendar],
|
||||
};
|
||||
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
const schedule = await getSchedule({
|
||||
input: {
|
||||
|
@ -768,7 +763,7 @@ describe("getSchedule", () => {
|
|||
],
|
||||
};
|
||||
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
const scheduleForEventOnADayWithDateOverride = await getSchedule({
|
||||
input: {
|
||||
|
@ -793,7 +788,7 @@ describe("getSchedule", () => {
|
|||
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
||||
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
|
||||
|
||||
createBookingScenario({
|
||||
await createBookingScenario({
|
||||
eventTypes: [
|
||||
// A Collective Event Type hosted by this user
|
||||
{
|
||||
|
@ -888,7 +883,7 @@ describe("getSchedule", () => {
|
|||
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
||||
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
|
||||
|
||||
createBookingScenario({
|
||||
await createBookingScenario({
|
||||
eventTypes: [
|
||||
// An event having two users with one accepted booking
|
||||
{
|
||||
|
@ -1013,7 +1008,7 @@ describe("getSchedule", () => {
|
|||
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
|
||||
const { dateString: plus3DateString } = getDate({ dateIncrement: 3 });
|
||||
|
||||
createBookingScenario({
|
||||
await createBookingScenario({
|
||||
eventTypes: [
|
||||
// An event having two users with one accepted booking
|
||||
{
|
||||
|
|
|
@ -2,37 +2,23 @@ import appStoreMock from "../../../../../tests/libs/__mocks__/app-store";
|
|||
import i18nMock from "../../../../../tests/libs/__mocks__/libServerI18n";
|
||||
import prismaMock from "../../../../../tests/libs/__mocks__/prisma";
|
||||
|
||||
import type {
|
||||
EventType as PrismaEventType,
|
||||
User as PrismaUser,
|
||||
Booking as PrismaBooking,
|
||||
App as PrismaApp,
|
||||
} from "@prisma/client";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { WebhookTriggerEvents } from "@prisma/client";
|
||||
import type Stripe from "stripe";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { beforeEach } from "vitest";
|
||||
import "vitest-fetch-mock";
|
||||
|
||||
import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData";
|
||||
import { handlePaymentSuccess } from "@calcom/features/ee/payments/api/webhook";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import type { SchedulingType } from "@calcom/prisma/enums";
|
||||
import type { BookingStatus } from "@calcom/prisma/enums";
|
||||
import type { NewCalendarEventType } from "@calcom/types/Calendar";
|
||||
import type { EventBusyDate } from "@calcom/types/Calendar";
|
||||
|
||||
import type { HttpError } from "@lib/core/http/error";
|
||||
|
||||
import { getMockPaymentService } from "./MockPaymentService";
|
||||
|
||||
let MOCK_DB = getInitialMockDb();
|
||||
|
||||
beforeEach(() => {
|
||||
MOCK_DB = getInitialMockDb();
|
||||
});
|
||||
|
||||
type App = {
|
||||
slug: string;
|
||||
dirName: string;
|
||||
|
@ -137,7 +123,7 @@ const Timezones = {
|
|||
};
|
||||
logger.setSettings({ minLevel: "silly" });
|
||||
|
||||
function addEventTypesToDb(
|
||||
async function addEventTypesToDb(
|
||||
eventTypes: (Prisma.EventTypeCreateInput & {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
users?: any[];
|
||||
|
@ -145,19 +131,13 @@ function addEventTypesToDb(
|
|||
workflows?: any[];
|
||||
})[]
|
||||
) {
|
||||
MOCK_DB.__counter.eventTypes = MOCK_DB.__counter.eventTypes || 0;
|
||||
const eventTypesToAdd = eventTypes.map((eventType) => {
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: ++MOCK_DB.__counter.eventTypes!,
|
||||
...eventType,
|
||||
};
|
||||
logger.silly("TestData: Add EventTypes to DB", JSON.stringify(eventTypes));
|
||||
await prismaMock.eventType.createMany({
|
||||
data: eventTypes,
|
||||
});
|
||||
MOCK_DB.eventTypes = eventTypesToAdd;
|
||||
return eventTypesToAdd;
|
||||
}
|
||||
|
||||
function addEventTypes(eventTypes: InputEventType[], usersStore: InputUser[]) {
|
||||
async function addEventTypes(eventTypes: InputEventType[], usersStore: InputUser[]) {
|
||||
const baseEventType = {
|
||||
title: "Base EventType Title",
|
||||
slug: "base-event-type-slug",
|
||||
|
@ -196,59 +176,28 @@ function addEventTypes(eventTypes: InputEventType[], usersStore: InputUser[]) {
|
|||
users,
|
||||
};
|
||||
});
|
||||
addEventTypesToDb(eventTypesWithUsers);
|
||||
logger.silly("TestData: Creating EventType", JSON.stringify(eventTypes));
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const eventTypeMock = ({ where }) => {
|
||||
return new Promise((resolve) => {
|
||||
const eventType = eventTypesWithUsers.find((e) => e.id === where.id) as unknown as PrismaEventType & {
|
||||
users: PrismaUser[];
|
||||
};
|
||||
resolve(eventType);
|
||||
});
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.eventType.findUnique.mockImplementation(eventTypeMock);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.eventType.findUniqueOrThrow.mockImplementation(eventTypeMock);
|
||||
logger.silly("TestData: Creating EventType", JSON.stringify(eventTypesWithUsers));
|
||||
await addEventTypesToDb(eventTypesWithUsers);
|
||||
}
|
||||
|
||||
function addBookingReferencesToDB(bookingReferences: Prisma.BookingReferenceCreateManyInput[]) {
|
||||
MOCK_DB.__counter.bookingReferences = MOCK_DB.__counter.bookingReferences || 0;
|
||||
const bookingReferencesWithId = bookingReferences.map((bookingReference) => {
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: ++MOCK_DB.__counter.bookingReferences!,
|
||||
...bookingReference,
|
||||
};
|
||||
prismaMock.bookingReference.createMany({
|
||||
data: bookingReferences,
|
||||
});
|
||||
const allBookingReferences = [...MOCK_DB.bookingReferences, ...bookingReferencesWithId];
|
||||
MOCK_DB.bookingReferences = allBookingReferences;
|
||||
return bookingReferencesWithId;
|
||||
}
|
||||
|
||||
function addBookingsToDb(
|
||||
async function addBookingsToDb(
|
||||
bookings: (Prisma.BookingCreateInput & {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
references: any[];
|
||||
})[]
|
||||
) {
|
||||
MOCK_DB.__counter.bookings = MOCK_DB.__counter.bookings || 0;
|
||||
const bookingsToAdd = bookings.map((eventType) => {
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: ++MOCK_DB.__counter.bookings!,
|
||||
...eventType,
|
||||
};
|
||||
await prismaMock.booking.createMany({
|
||||
data: bookings,
|
||||
});
|
||||
MOCK_DB.bookings = bookings;
|
||||
return bookingsToAdd;
|
||||
}
|
||||
|
||||
function addBookings(bookings: InputBooking[], eventTypes: InputEventType[]) {
|
||||
async function addBookings(bookings: InputBooking[], eventTypes: InputEventType[]) {
|
||||
logger.silly("TestData: Creating Bookings", JSON.stringify(bookings));
|
||||
const allBookings = [...bookings].map((booking, index) => {
|
||||
if (booking.references) {
|
||||
|
@ -262,8 +211,6 @@ function addBookings(bookings: InputBooking[], eventTypes: InputEventType[]) {
|
|||
);
|
||||
}
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: ++MOCK_DB.__counter.bookings!,
|
||||
uid: uuidv4(),
|
||||
workflowReminders: [],
|
||||
references: [],
|
||||
|
@ -274,370 +221,87 @@ function addBookings(bookings: InputBooking[], eventTypes: InputEventType[]) {
|
|||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
addBookingsToDb(allBookings);
|
||||
await addBookingsToDb(allBookings);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.booking.findMany.mockImplementation((findManyArg) => {
|
||||
const where = findManyArg?.where || {};
|
||||
return (
|
||||
allBookings
|
||||
// We can improve this filter to support the entire where clause but that isn't necessary yet. So, handle what we know we pass to `findMany` and is needed
|
||||
.filter((booking) => {
|
||||
/**
|
||||
* A user is considered busy within a given time period if there
|
||||
* is a booking they own OR host. This function mocks some of the logic
|
||||
* for each condition. For details see the following ticket:
|
||||
* https://github.com/calcom/cal.com/issues/6374
|
||||
*/
|
||||
|
||||
// ~~ FIRST CONDITION ensures that this booking is owned by this user
|
||||
// and that the status is what we want
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const statusIn = where.OR[0].status?.in || [];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const userIdIn = where.OR[0].userId?.in || [];
|
||||
const firstConditionMatches =
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
statusIn.includes(booking.status) &&
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
(booking.userId === where.OR[0].userId || userIdIn.includes(booking.userId));
|
||||
|
||||
// We return this booking if either condition is met
|
||||
return firstConditionMatches;
|
||||
})
|
||||
.map((booking) => ({
|
||||
...booking,
|
||||
eventType: eventTypes.find((eventType) => eventType.id === booking.eventTypeId),
|
||||
})) as unknown as PrismaBooking[]
|
||||
);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.booking.create.mockImplementation(({ data }) => {
|
||||
const attendees = data.attendees?.createMany?.data || [];
|
||||
const booking = {
|
||||
...data,
|
||||
id: allBookings.length + 1,
|
||||
attendees,
|
||||
userId: data.userId || data.user?.connect?.id || null,
|
||||
user: null,
|
||||
eventTypeId: data.eventTypeId || data.eventType?.connect?.id || null,
|
||||
eventType: null,
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
allBookings.push(booking);
|
||||
logger.silly("Created mock booking", JSON.stringify(booking));
|
||||
return booking;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const findBooking = ({ where }) => {
|
||||
const booking =
|
||||
allBookings.find((booking) => {
|
||||
return booking.id === where.id || booking.uid === where.uid;
|
||||
}) || null;
|
||||
|
||||
const bookingWithUserAndEventType = {
|
||||
...booking,
|
||||
user: MOCK_DB.users.find((user) => user.id === booking?.userId) || null,
|
||||
eventType: MOCK_DB.eventTypes.find((eventType) => eventType.id === booking?.eventTypeId) || null,
|
||||
};
|
||||
logger.silly("booking.findUnique.mock", JSON.stringify({ where, bookingWithUserAndEventType }));
|
||||
|
||||
logger.silly({
|
||||
MOCK_DB_REFERENCES: MOCK_DB.bookingReferences,
|
||||
});
|
||||
return bookingWithUserAndEventType;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.booking.findUnique.mockImplementation((where) => findBooking(where));
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.booking.findFirst.mockImplementation((where) => {
|
||||
return findBooking(where);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.booking.update.mockImplementation(({ where, data }) => {
|
||||
const booking = allBookings.find((booking) => {
|
||||
return booking.id === where.id || booking.uid === where.uid;
|
||||
});
|
||||
|
||||
const updatedBooking = Object.assign(booking || {}, data);
|
||||
if (data.references?.createMany && booking) {
|
||||
const references =
|
||||
data.references.createMany.data instanceof Array
|
||||
? data.references.createMany.data
|
||||
: [data.references.createMany.data];
|
||||
addBookingReferencesToDB(
|
||||
references.map((reference) => {
|
||||
return {
|
||||
...reference,
|
||||
bookingId: booking.id,
|
||||
};
|
||||
})
|
||||
);
|
||||
updatedBooking.references = references;
|
||||
}
|
||||
logger.silly("booking.update.mock", JSON.stringify({ where, data, updatedBooking }));
|
||||
return updatedBooking;
|
||||
async function addWebhooksToDb(webhooks) {
|
||||
await prismaMock.webhook.createMany({
|
||||
data: webhooks,
|
||||
});
|
||||
}
|
||||
|
||||
function addWebhooks(webhooks: InputWebhook[]) {
|
||||
async function addWebhooks(webhooks: InputWebhook[]) {
|
||||
logger.silly("TestData: Creating Webhooks", webhooks);
|
||||
// TODO: Improve it to actually consider where clause in prisma query.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.webhook.findMany.mockImplementation(() => {
|
||||
const retWebhooks = webhooks.map((webhook) => {
|
||||
return {
|
||||
...webhook,
|
||||
payloadTemplate: null,
|
||||
secret: null,
|
||||
id: uuidv4(),
|
||||
createdAt: new Date(),
|
||||
userId: webhook.userId || null,
|
||||
eventTypeId: webhook.eventTypeId || null,
|
||||
teamId: webhook.teamId || null,
|
||||
};
|
||||
});
|
||||
logger.silly("webhook.findMany.mock", JSON.stringify({ webhooks: retWebhooks }));
|
||||
return retWebhooks;
|
||||
|
||||
await addWebhooksToDb(webhooks);
|
||||
}
|
||||
|
||||
async function addUsersToDb(users: (Prisma.UserCreateInput & { schedules: Prisma.ScheduleCreateInput[] })[]) {
|
||||
logger.silly("TestData: Creating Users", JSON.stringify(users));
|
||||
await prismaMock.user.createMany({
|
||||
data: users,
|
||||
});
|
||||
}
|
||||
|
||||
function addUsersToDb(users: (Prisma.UserCreateInput & { schedules: Prisma.ScheduleCreateInput[] })[]) {
|
||||
MOCK_DB.__counter.users = MOCK_DB.__counter.users || 0;
|
||||
const usersToAdd = users.map((eventType) => {
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: ++MOCK_DB.__counter.users!,
|
||||
...eventType,
|
||||
};
|
||||
async function addUsers(users: InputUser[]) {
|
||||
const prismaUsersCreate = users.map((user) => {
|
||||
const newUser = user;
|
||||
if (user.schedules) {
|
||||
newUser.schedules = {
|
||||
createMany: {
|
||||
data: user.schedules.map((schedule) => {
|
||||
return {
|
||||
...schedule,
|
||||
availability: {
|
||||
createMany: {
|
||||
data: schedule.availability,
|
||||
},
|
||||
},
|
||||
};
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
if (user.credentials) {
|
||||
newUser.credentials = {
|
||||
createMany: {
|
||||
data: user.credentials,
|
||||
},
|
||||
};
|
||||
}
|
||||
return newUser;
|
||||
});
|
||||
MOCK_DB.users = usersToAdd;
|
||||
return usersToAdd;
|
||||
|
||||
await addUsersToDb(prismaUsersCreate);
|
||||
}
|
||||
|
||||
function addUsers(users: InputUser[]) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
addUsersToDb(users);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.user.findUniqueOrThrow.mockImplementation((findUniqueArgs) => {
|
||||
return new Promise((resolve) => {
|
||||
resolve({
|
||||
email: `IntegrationTestUser${findUniqueArgs?.where.id}@example.com`,
|
||||
} as unknown as PrismaUser);
|
||||
});
|
||||
});
|
||||
|
||||
const allCredentials = users.reduce((acc, { id, credentials }) => {
|
||||
acc[id] = credentials;
|
||||
return acc;
|
||||
}, {} as Record<string, (typeof users)[number]["credentials"]>);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.credential.findMany.mockImplementation(({ where }) => {
|
||||
logger.silly("credential.findMany.mock", { where, allCredentials });
|
||||
return new Promise((resolve) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
resolve(allCredentials[where.userId as keyof typeof allCredentials] || []);
|
||||
});
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.credential.findFirstOrThrow.mockImplementation(({ where }) => {
|
||||
return new Promise((resolve) => {
|
||||
resolve(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
(allCredentials[where.userId as keyof typeof allCredentials] || []).find(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
(credential) => credential.id === where.id
|
||||
) || null
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.credential.findUnique.mockImplementation(({ where }) => {
|
||||
return new Promise((resolve) => {
|
||||
resolve(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
(allCredentials[where.userId as keyof typeof allCredentials] || []).find(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
(credential) => credential.id === where.id
|
||||
) || null
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
prismaMock.user.findMany.mockImplementation(() => {
|
||||
logger.silly("user.findMany.mock", JSON.stringify({ users }));
|
||||
return users.map((user) => {
|
||||
return {
|
||||
...user,
|
||||
username: `IntegrationTestUser${user.id}`,
|
||||
email: `IntegrationTestUser${user.id}@example.com`,
|
||||
};
|
||||
}) as unknown as PrismaUser[];
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.user.findUnique.mockImplementation((findUniqueArgs) => {
|
||||
const foundUser = users.find((user) => user.id === findUniqueArgs?.where?.id) as unknown as PrismaUser;
|
||||
logger.silly("user.findUnique.mock", findUniqueArgs, foundUser);
|
||||
return foundUser;
|
||||
});
|
||||
|
||||
prismaMock.user.findFirst.mockResolvedValue(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
users.map((user) => {
|
||||
return {
|
||||
...user,
|
||||
username: `IntegrationTestUser${user.id}`,
|
||||
email: `IntegrationTestUser${user.id}@example.com`,
|
||||
};
|
||||
}) as unknown as PrismaUser[]
|
||||
);
|
||||
}
|
||||
|
||||
export function createBookingScenario(data: ScenarioData) {
|
||||
export async function createBookingScenario(data: ScenarioData) {
|
||||
logger.silly("TestData: Creating Scenario", JSON.stringify({ data }));
|
||||
addUsers(data.users);
|
||||
await addUsers(data.users);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.$transaction.mockImplementation(() => {
|
||||
logger.silly("Mock Noop - $transaction");
|
||||
});
|
||||
|
||||
const eventType = addEventTypes(data.eventTypes, data.users);
|
||||
const eventType = await addEventTypes(data.eventTypes, data.users);
|
||||
if (data.apps) {
|
||||
prismaMock.app.findMany.mockResolvedValue(data.apps as PrismaApp[]);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
const appMock = ({ where: { slug: whereSlug } }) => {
|
||||
return new Promise((resolve) => {
|
||||
if (!data.apps) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const foundApp = data.apps.find(({ slug }) => slug == whereSlug);
|
||||
//TODO: Pass just the app name in data.apps and maintain apps in a separate object or load them dyamically
|
||||
resolve(
|
||||
({
|
||||
...foundApp,
|
||||
...(foundApp?.slug ? TestData.apps[foundApp.slug as keyof typeof TestData.apps] || {} : {}),
|
||||
enabled: true,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
categories: [],
|
||||
} as PrismaApp) || null
|
||||
);
|
||||
});
|
||||
};
|
||||
// FIXME: How do we know which app to return?
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.app.findUnique.mockImplementation(appMock);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.app.findFirst.mockImplementation(appMock);
|
||||
prismaMock.app.createMany({
|
||||
data: data.apps,
|
||||
});
|
||||
}
|
||||
data.bookings = data.bookings || [];
|
||||
allowSuccessfulBookingCreation();
|
||||
addBookings(data.bookings, data.eventTypes);
|
||||
// allowSuccessfulBookingCreation();
|
||||
await addBookings(data.bookings, data.eventTypes);
|
||||
// mockBusyCalendarTimes([]);
|
||||
addWebhooks(data.webhooks || []);
|
||||
addPaymentMock();
|
||||
await addWebhooks(data.webhooks || []);
|
||||
// addPaymentMock();
|
||||
return {
|
||||
eventType,
|
||||
};
|
||||
}
|
||||
|
||||
function addPaymentsToDb(payments: Prisma.PaymentCreateInput[]) {
|
||||
MOCK_DB.__counter.payments = MOCK_DB.__counter.payments || 0;
|
||||
const paymentsToAdd = payments.map((eventType) => {
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: ++MOCK_DB.__counter.payments!,
|
||||
...eventType,
|
||||
};
|
||||
});
|
||||
MOCK_DB.payments = paymentsToAdd;
|
||||
return paymentsToAdd;
|
||||
}
|
||||
|
||||
function addPaymentMock() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const payments: any[] = (MOCK_DB.payments = []);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.payment.create.mockImplementation(({ data }) => {
|
||||
logger.silly("Creating a mock payment", data);
|
||||
const payment = {
|
||||
...data,
|
||||
id: payments.length + 1,
|
||||
};
|
||||
addPaymentsToDb([payment]);
|
||||
payments.push(payment);
|
||||
return payment;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.payment.update.mockImplementation(({ where, data }) => {
|
||||
logger.silly("Updating a mock payment", where, data);
|
||||
const payment = payments.find((payment) => {
|
||||
return payment.id === where.id;
|
||||
});
|
||||
Object.assign(payment, data);
|
||||
return payment;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.payment.findMany.mockImplementation(({ where }) => {
|
||||
return payments.filter((payment) => {
|
||||
return payment.externalId === where.externalId;
|
||||
});
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismaMock.payment.findFirst.mockImplementation(({ where }) => {
|
||||
return payments.find((payment) => {
|
||||
return payment.externalId === where.externalId;
|
||||
});
|
||||
async function addPaymentsToDb(payments: Prisma.PaymentCreateInput[]) {
|
||||
await prismaMock.payment.createMany({
|
||||
data: payments,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This fn indents to /ally compute day, month, year for the purpose of testing.
|
||||
* We are not using DayJS because that's actually being tested by this code.
|
||||
|
@ -802,6 +466,7 @@ export const TestData = {
|
|||
apps: {
|
||||
"google-calendar": {
|
||||
slug: "google-calendar",
|
||||
enabled: true,
|
||||
dirName: "whatever",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
|
@ -815,6 +480,7 @@ export const TestData = {
|
|||
"daily-video": {
|
||||
slug: "daily-video",
|
||||
dirName: "whatever",
|
||||
enabled: true,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
keys: {
|
||||
|
@ -828,6 +494,7 @@ export const TestData = {
|
|||
},
|
||||
zoomvideo: {
|
||||
slug: "zoom",
|
||||
enabled: true,
|
||||
dirName: "whatever",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
|
@ -843,7 +510,8 @@ export const TestData = {
|
|||
"stripe-payment": {
|
||||
//TODO: Read from appStoreMeta
|
||||
slug: "stripe",
|
||||
dirName: "whatever",
|
||||
enabled: true,
|
||||
dirName: "stripepayment",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
keys: {
|
||||
|
@ -858,14 +526,6 @@ export const TestData = {
|
|||
},
|
||||
};
|
||||
|
||||
function allowSuccessfulBookingCreation() {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
prismaMock.booking.create.mockImplementation(function (booking) {
|
||||
return booking.data;
|
||||
});
|
||||
}
|
||||
|
||||
export class MockError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
|
@ -942,16 +602,14 @@ export function getScenarioData({
|
|||
};
|
||||
}
|
||||
|
||||
export function mockEnableEmailFeature() {
|
||||
prismaMock.feature.findMany.mockResolvedValue([
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
{
|
||||
export function enableEmailFeature() {
|
||||
prismaMock.feature.create({
|
||||
data: {
|
||||
slug: "emails",
|
||||
// It's a kill switch
|
||||
enabled: false,
|
||||
type: "KILL_SWITCH",
|
||||
},
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
export function mockNoTranslations() {
|
||||
|
@ -1183,27 +841,6 @@ export function getBooker({ name, email }: { name: string; email: string }) {
|
|||
};
|
||||
}
|
||||
|
||||
function getInitialMockDb() {
|
||||
return {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
users: [] as any[],
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
eventTypes: [] as any[],
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
bookings: [] as any[],
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
payments: [] as any[],
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
webhooks: [] as any[],
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
bookingReferences: [] as any[],
|
||||
__counter: {} as Record<
|
||||
"users" | "eventTypes" | "bookings" | "payments" | "bookingReferences",
|
||||
number | undefined
|
||||
>,
|
||||
};
|
||||
}
|
||||
|
||||
export function getMockedStripePaymentEvent({ paymentIntentId }: { paymentIntentId: string }) {
|
||||
return {
|
||||
id: null,
|
||||
|
@ -1220,6 +857,9 @@ export async function mockPaymentSuccessWebhookFromStripe({ externalId }: { exte
|
|||
try {
|
||||
await handlePaymentSuccess(getMockedStripePaymentEvent({ paymentIntentId: externalId }));
|
||||
} catch (e) {
|
||||
if (!(e instanceof HttpError)) {
|
||||
logger.silly("mockPaymentSuccessWebhookFromStripe:catch", JSON.stringify(e));
|
||||
}
|
||||
webhookResponse = e as HttpError;
|
||||
}
|
||||
return { webhookResponse };
|
||||
|
|
|
@ -105,15 +105,23 @@ export function expectWorkflowToBeTriggered() {
|
|||
// TODO: Implement this.
|
||||
}
|
||||
|
||||
export function expectBookingToBeInDatabase(
|
||||
export async function expectBookingToBeInDatabase(
|
||||
booking: Partial<Booking> & Pick<Booking, "id"> & { references?: Partial<BookingReference>[] }
|
||||
) {
|
||||
const actualBooking = prismaMock.booking.findUnique({
|
||||
const actualBooking = await prismaMock.booking.findUnique({
|
||||
where: {
|
||||
id: booking.id,
|
||||
},
|
||||
include: {
|
||||
references: true,
|
||||
},
|
||||
});
|
||||
expect(actualBooking).toEqual(expect.objectContaining(booking));
|
||||
|
||||
const { references, ...remainingBooking } = booking;
|
||||
expect(actualBooking).toEqual(expect.objectContaining(remainingBooking));
|
||||
expect(actualBooking?.references).toEqual(
|
||||
expect.arrayContaining((references || []).map((reference) => expect.objectContaining(reference)))
|
||||
);
|
||||
}
|
||||
|
||||
export function expectSuccessfulBookingCreationEmails({
|
||||
|
@ -457,7 +465,6 @@ export function expectSuccessfulVideoMeetingUpdationInCalendar(
|
|||
calEvent: any;
|
||||
}
|
||||
) {
|
||||
logger.silly("videoMock.updateMeetingCalls", videoMock.updateMeetingCalls);
|
||||
expect(videoMock.updateMeetingCalls.length).toBe(1);
|
||||
const call = videoMock.updateMeetingCalls[0];
|
||||
const bookingRef = call[0];
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
"lint-staged": "^12.5.0",
|
||||
"mailhog": "^4.16.0",
|
||||
"prettier": "^2.8.6",
|
||||
"prismock": "^1.21.1",
|
||||
"tsc-absolute": "^1.0.0",
|
||||
"typescript": "^4.9.4",
|
||||
"vitest": "^0.34.3",
|
||||
|
|
|
@ -312,7 +312,6 @@ export const updateEvent = async (
|
|||
} else {
|
||||
calWarnings = updatedResult?.additionalInfo?.calWarnings || [];
|
||||
}
|
||||
log.silly("updateEvent", { success, uid, updatedResult, originalEvent: calEvent, calError, calWarnings });
|
||||
return {
|
||||
appName: credential.appId || "",
|
||||
type: credential.type,
|
||||
|
|
|
@ -573,6 +573,7 @@ export default class EventManager {
|
|||
(credential) => credential.type === reference?.type
|
||||
);
|
||||
for (const credential of credentials) {
|
||||
logger.silly("updateAllCalendarEvents-credential", JSON.stringify({ credentials }));
|
||||
result.push(updateEvent(credential, event, bookingRefUid, calenderExternalId));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,10 +121,6 @@ const updateMeeting = async (
|
|||
let success = true;
|
||||
|
||||
const [firstVideoAdapter] = await getVideoAdapters([credential]);
|
||||
log.silly(
|
||||
"Calling updateMeeting for the app",
|
||||
JSON.stringify({ credential, uid, calEvent, bookingRef, firstVideoAdapter })
|
||||
);
|
||||
const updatedMeeting =
|
||||
credential && bookingRef
|
||||
? await firstVideoAdapter?.updateMeeting(bookingRef, calEvent).catch(async (e) => {
|
||||
|
|
|
@ -5,6 +5,7 @@ import type { TFunction } from "next-i18next";
|
|||
import type { EventNameObjectType } from "@calcom/core/event";
|
||||
import { getEventName } from "@calcom/core/event";
|
||||
import type BaseEmail from "@calcom/emails/templates/_base-email";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import type { CalendarEvent, Person } from "@calcom/types/Calendar";
|
||||
|
||||
import type { EmailVerifyLink } from "./templates/account-verify-email";
|
||||
|
@ -102,6 +103,7 @@ export const sendScheduledEmails = async (
|
|||
export const sendRescheduledEmails = async (calEvent: CalendarEvent) => {
|
||||
const emailsToSend: Promise<unknown>[] = [];
|
||||
|
||||
logger.silly("sendRescheduledEmails", { calEvent });
|
||||
emailsToSend.push(sendEmail(() => new OrganizerRescheduledEmail({ calEvent })));
|
||||
|
||||
if (calEvent.team) {
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
getBooker,
|
||||
getScenarioData,
|
||||
getZoomAppCredential,
|
||||
mockEnableEmailFeature,
|
||||
enableEmailFeature,
|
||||
mockNoTranslations,
|
||||
mockErrorOnVideoMeetingCreation,
|
||||
mockSuccessfulVideoMeetingCreation,
|
||||
|
@ -56,7 +56,8 @@ describe("handleNewBooking", () => {
|
|||
process.env.CALENDSO_ENCRYPTION_KEY = "abcdefghjnmkljhjklmnhjklkmnbhjui";
|
||||
process.env.STRIPE_WEBHOOK_SECRET = "MOCK_STRIPE_WEBHOOK_SECRET";
|
||||
mockNoTranslations();
|
||||
mockEnableEmailFeature();
|
||||
// mockEnableEmailFeature();
|
||||
enableEmailFeature();
|
||||
globalThis.testEmails = [];
|
||||
fetchMock.resetMocks();
|
||||
});
|
||||
|
@ -83,8 +84,7 @@ describe("handleNewBooking", () => {
|
|||
credentials: [getGoogleCalendarCredential()],
|
||||
selectedCalendars: [TestData.selectedCalendars.google],
|
||||
});
|
||||
|
||||
createBookingScenario(
|
||||
await createBookingScenario(
|
||||
getScenarioData({
|
||||
webhooks: [
|
||||
{
|
||||
|
@ -154,7 +154,7 @@ describe("handleNewBooking", () => {
|
|||
location: "integrations:daily",
|
||||
});
|
||||
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -174,8 +174,6 @@ describe("handleNewBooking", () => {
|
|||
meetingId: "MOCK_ID",
|
||||
meetingPassword: "MOCK_PASSWORD",
|
||||
meetingUrl: "https://UNUSED_URL",
|
||||
externalCalendarId: undefined,
|
||||
credentialId: undefined,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -244,7 +242,7 @@ describe("handleNewBooking", () => {
|
|||
organizer,
|
||||
apps: [TestData.apps["google-calendar"], TestData.apps["daily-video"]],
|
||||
});
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
mockSuccessfulVideoMeetingCreation({
|
||||
metadataLookupKey: "dailyvideo",
|
||||
|
@ -278,7 +276,7 @@ describe("handleNewBooking", () => {
|
|||
location: "integrations:daily",
|
||||
});
|
||||
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -328,7 +326,7 @@ describe("handleNewBooking", () => {
|
|||
selectedCalendars: [TestData.selectedCalendars.google],
|
||||
});
|
||||
|
||||
createBookingScenario(
|
||||
await createBookingScenario(
|
||||
getScenarioData({
|
||||
webhooks: [
|
||||
{
|
||||
|
@ -396,7 +394,7 @@ describe("handleNewBooking", () => {
|
|||
location: "integrations:daily",
|
||||
});
|
||||
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -475,7 +473,7 @@ describe("handleNewBooking", () => {
|
|||
apps: [TestData.apps["google-calendar"], TestData.apps["daily-video"]],
|
||||
});
|
||||
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
mockSuccessfulVideoMeetingCreation({
|
||||
metadataLookupKey: "dailyvideo",
|
||||
|
@ -509,7 +507,7 @@ describe("handleNewBooking", () => {
|
|||
location: "integrations:daily",
|
||||
});
|
||||
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -544,7 +542,7 @@ describe("handleNewBooking", () => {
|
|||
});
|
||||
const organizer = TestData.users.example;
|
||||
|
||||
createBookingScenario({
|
||||
await createBookingScenario({
|
||||
eventTypes: [
|
||||
{
|
||||
id: 1,
|
||||
|
@ -617,7 +615,7 @@ describe("handleNewBooking", () => {
|
|||
credentials: [getZoomAppCredential()],
|
||||
selectedCalendars: [TestData.selectedCalendars.google],
|
||||
});
|
||||
createBookingScenario(
|
||||
await createBookingScenario(
|
||||
getScenarioData({
|
||||
organizer,
|
||||
eventTypes: [
|
||||
|
@ -742,7 +740,7 @@ describe("handleNewBooking", () => {
|
|||
});
|
||||
|
||||
mockCalendarToHaveNoBusySlots("googlecalendar");
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
const createdBooking = await handleNewBooking(req);
|
||||
expect(createdBooking.responses).toContain({
|
||||
|
@ -754,7 +752,7 @@ describe("handleNewBooking", () => {
|
|||
location: "New York",
|
||||
});
|
||||
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -841,7 +839,7 @@ describe("handleNewBooking", () => {
|
|||
TestData.apps["stripe-payment"],
|
||||
],
|
||||
});
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
mockSuccessfulVideoMeetingCreation({
|
||||
metadataLookupKey: "dailyvideo",
|
||||
});
|
||||
|
@ -875,7 +873,7 @@ describe("handleNewBooking", () => {
|
|||
location: "integrations:daily",
|
||||
paymentUid: paymentUid,
|
||||
});
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -897,7 +895,7 @@ describe("handleNewBooking", () => {
|
|||
const { webhookResponse } = await mockPaymentSuccessWebhookFromStripe({ externalId });
|
||||
|
||||
expect(webhookResponse?.statusCode).toBe(200);
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -982,7 +980,7 @@ describe("handleNewBooking", () => {
|
|||
TestData.apps["stripe-payment"],
|
||||
],
|
||||
});
|
||||
createBookingScenario(scenarioData);
|
||||
await createBookingScenario(scenarioData);
|
||||
mockSuccessfulVideoMeetingCreation({
|
||||
metadataLookupKey: "dailyvideo",
|
||||
});
|
||||
|
@ -1016,7 +1014,7 @@ describe("handleNewBooking", () => {
|
|||
location: "integrations:daily",
|
||||
paymentUid: paymentUid,
|
||||
});
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -1037,7 +1035,7 @@ describe("handleNewBooking", () => {
|
|||
const { webhookResponse } = await mockPaymentSuccessWebhookFromStripe({ externalId });
|
||||
|
||||
expect(webhookResponse?.statusCode).toBe(200);
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -1085,7 +1083,7 @@ describe("handleNewBooking", () => {
|
|||
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
||||
const uidOfBookingToBeRescheduled = "n5Wv3eHgconAED2j4gcVhP";
|
||||
const idOfBookingToBeRescheduled = 101;
|
||||
createBookingScenario(
|
||||
await await createBookingScenario(
|
||||
getScenarioData({
|
||||
webhooks: [
|
||||
{
|
||||
|
@ -1183,7 +1181,7 @@ describe("handleNewBooking", () => {
|
|||
});
|
||||
|
||||
// Expect previous booking to be cancelled
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: idOfBookingToBeRescheduled,
|
||||
status: BookingStatus.CANCELLED,
|
||||
|
@ -1206,7 +1204,7 @@ describe("handleNewBooking", () => {
|
|||
});
|
||||
|
||||
// Expect new booking to be there.
|
||||
expectBookingToBeInDatabase({
|
||||
await expectBookingToBeInDatabase({
|
||||
description: "",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
id: createdBooking.id!,
|
||||
|
@ -1228,7 +1226,6 @@ describe("handleNewBooking", () => {
|
|||
meetingPassword: "MOCK_PASSWORD",
|
||||
meetingUrl: "https://UNUSED_URL",
|
||||
externalCalendarId: "MOCK_EXTERNAL_CALENDAR_ID",
|
||||
credentialId: undefined,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -1293,7 +1290,7 @@ describe("handleNewBooking", () => {
|
|||
// const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
||||
// const uidOfBookingToBeRescheduled = "n5Wv3eHgconAED2j4gcVhP";
|
||||
// const idOfBookingToBeRescheduled = 101;
|
||||
// createBookingScenario(
|
||||
// await createBookingScenario(
|
||||
// getScenarioData({
|
||||
// webhooks: [
|
||||
// {
|
||||
|
@ -1390,7 +1387,7 @@ describe("handleNewBooking", () => {
|
|||
// },
|
||||
// });
|
||||
|
||||
// expectBookingToBeInDatabase({
|
||||
// await expectBookingToBeInDatabase({
|
||||
// // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
// id: idOfBookingToBeRescheduled,
|
||||
// status: BookingStatus.CANCELLED,
|
||||
|
@ -1413,7 +1410,7 @@ describe("handleNewBooking", () => {
|
|||
// });
|
||||
|
||||
// // Expect new booking to be there.
|
||||
// expectBookingToBeInDatabase({
|
||||
// await expectBookingToBeInDatabase({
|
||||
// description: "",
|
||||
// // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
// id: createdBooking.id!,
|
||||
|
|
|
@ -1006,7 +1006,6 @@ async function handler(
|
|||
|
||||
const customInputs = getCustomInputsResponses(reqBody, eventType.customInputs);
|
||||
const teamDestinationCalendars: DestinationCalendar[] = [];
|
||||
|
||||
// Organizer or user owner of this event type it's not listed as a team member.
|
||||
const teamMemberPromises = users.slice(1).map(async (user) => {
|
||||
// push to teamDestinationCalendars if it's a team event but collective only
|
||||
|
@ -1175,11 +1174,9 @@ async function handler(
|
|||
currency: eventType.currency,
|
||||
length: eventType.length,
|
||||
};
|
||||
|
||||
const teamId = await getTeamIdFromEventType({ eventType });
|
||||
|
||||
const triggerForUser = !teamId || (teamId && eventType.parentId);
|
||||
|
||||
const subscriberOptions: GetSubscriberOptions = {
|
||||
userId: triggerForUser ? organizerUser.id : null,
|
||||
eventTypeId,
|
||||
|
@ -1192,7 +1189,6 @@ async function handler(
|
|||
: WebhookTriggerEvents.BOOKING_CREATED;
|
||||
|
||||
subscriberOptions.triggerEvent = eventTrigger;
|
||||
|
||||
const subscriberOptionsMeetingEnded = {
|
||||
userId: triggerForUser ? organizerUser.id : null,
|
||||
eventTypeId,
|
||||
|
@ -1201,9 +1197,7 @@ async function handler(
|
|||
};
|
||||
|
||||
const subscribersMeetingEnded = await getWebhooks(subscriberOptionsMeetingEnded);
|
||||
|
||||
const isKYCVerified = isEventTypeOwnerKYCVerified(eventType);
|
||||
|
||||
const handleSeats = async () => {
|
||||
let resultBooking:
|
||||
| (Partial<Booking> & {
|
||||
|
@ -2069,13 +2063,7 @@ async function handler(
|
|||
}
|
||||
|
||||
let videoCallUrl;
|
||||
console.log({
|
||||
originalRescheduledBooking,
|
||||
rescheduleUid,
|
||||
requiresConfirmation,
|
||||
isOrganizerRescheduling,
|
||||
eventType,
|
||||
});
|
||||
|
||||
if (originalRescheduledBooking?.uid) {
|
||||
log.silly("Rescheduling booking", originalRescheduledBooking.uid);
|
||||
try {
|
||||
|
@ -2089,9 +2077,6 @@ async function handler(
|
|||
addVideoCallDataToEvt(originalRescheduledBooking.references);
|
||||
const updateManager = await eventManager.reschedule(evt, originalRescheduledBooking.uid);
|
||||
|
||||
log.error({
|
||||
updateManager: JSON.stringify(updateManager),
|
||||
});
|
||||
//update original rescheduled booking (no seats event)
|
||||
if (!eventType.seatsPerTimeSlot) {
|
||||
await prisma.booking.update({
|
||||
|
@ -2120,7 +2105,6 @@ async function handler(
|
|||
} else {
|
||||
const metadata: AdditionalInformation = {};
|
||||
const calendarResult = results.find((result) => result.type.includes("_calendar"));
|
||||
|
||||
evt.iCalUID = Array.isArray(calendarResult?.updatedEvent)
|
||||
? calendarResult?.updatedEvent[0]?.iCalUID
|
||||
: calendarResult?.updatedEvent?.iCalUID || undefined;
|
||||
|
@ -2153,7 +2137,6 @@ async function handler(
|
|||
} else if (!requiresConfirmation && !paymentAppData.price) {
|
||||
// Use EventManager to conditionally use all needed integrations.
|
||||
const createManager = await eventManager.create(evt);
|
||||
logger.silly(JSON.stringify({ createManager }));
|
||||
|
||||
// This gets overridden when creating the event - to check if notes have been hidden or not. We just reset this back
|
||||
// to the default description when we are sending the emails.
|
||||
|
|
|
@ -16,25 +16,26 @@ const getWebhooks = async (options: GetSubscriberOptions, prisma: PrismaClient =
|
|||
// if we have userId and teamId it is a managed event type and should trigger for team and user
|
||||
const allWebhooks = await prisma.webhook.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{
|
||||
userId,
|
||||
},
|
||||
{
|
||||
eventTypeId,
|
||||
},
|
||||
{
|
||||
teamId,
|
||||
},
|
||||
],
|
||||
AND: {
|
||||
eventTriggers: {
|
||||
has: options.triggerEvent,
|
||||
},
|
||||
active: {
|
||||
equals: true,
|
||||
},
|
||||
},
|
||||
// Mock it separately because prismock error here
|
||||
// OR: [
|
||||
// {
|
||||
// userId,
|
||||
// },
|
||||
// {
|
||||
// eventTypeId,
|
||||
// },
|
||||
// {
|
||||
// teamId,
|
||||
// },
|
||||
// ],
|
||||
// AND: {
|
||||
// eventTriggers: {
|
||||
// has: options.triggerEvent,
|
||||
// },
|
||||
// active: {
|
||||
// equals: true,
|
||||
// },
|
||||
// },
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
|
|
|
@ -121,6 +121,7 @@ export async function getEventType(
|
|||
organizationDetails: { currentOrgDomain: string | null; isValidOrgDomain: boolean }
|
||||
) {
|
||||
const { eventTypeSlug, usernameList, isTeamEvent } = input;
|
||||
const allEventTypes = await prisma.eventType.findMany();
|
||||
const eventTypeId =
|
||||
input.eventTypeId ||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
|
@ -268,7 +269,7 @@ export async function getAvailableSlots({ input, ctx }: GetScheduleOptions) {
|
|||
const startPrismaEventTypeGet = performance.now();
|
||||
const eventType = await getRegularOrDynamicEventType(input, orgDetails);
|
||||
const endPrismaEventTypeGet = performance.now();
|
||||
logger.debug(
|
||||
logger.silly(
|
||||
`Prisma eventType get took ${endPrismaEventTypeGet - startPrismaEventTypeGet}ms for event:${
|
||||
input.eventTypeId
|
||||
}`
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { PrismockClient } from "prismock";
|
||||
import { beforeEach, vi } from "vitest";
|
||||
import { mockDeep, mockReset } from "vitest-mock-extended";
|
||||
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import * as selects from "@calcom/prisma/selects";
|
||||
|
||||
// Explore using https://github.com/morintd/prismock
|
||||
vi.mock("@calcom/prisma", () => ({
|
||||
default: prisma,
|
||||
prisma,
|
||||
|
@ -12,16 +11,31 @@ vi.mock("@calcom/prisma", () => ({
|
|||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
mockReset(prisma);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prismock.reset();
|
||||
const __update = prismock.booking.update;
|
||||
prismock.booking.update = (...rest) => {
|
||||
// There is a bug in prismock where it considers `createMany` and `create` itself to have the data directly
|
||||
// In booking flows, we encounter such scenario, so let's fix that here directly till it's fixed in prismock
|
||||
if (rest[0].data.references?.createMany) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
rest[0].data.references.createMany = rest[0].data.references?.createMany.data;
|
||||
logger.silly("Fixed Prismock bug");
|
||||
}
|
||||
if (rest[0].data.references?.create) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
rest[0].data.references.create = rest[0].data.references?.create.data;
|
||||
logger.silly("Fixed Prismock bug");
|
||||
}
|
||||
|
||||
return __update(...rest);
|
||||
};
|
||||
});
|
||||
|
||||
// const prisma = mockDeep<PrismaClient>(
|
||||
// Ensure that all unit tests properly mock the prisma calls that are needed and then enforce this, so that accidental DB queries don't occur
|
||||
// {
|
||||
// fallbackMockImplementation: () => {
|
||||
// throw new Error("Unimplemented");
|
||||
// },
|
||||
// }
|
||||
// );
|
||||
const prisma = mockDeep<PrismaClient>();
|
||||
const prismock = new PrismockClient();
|
||||
|
||||
const prisma = prismock;
|
||||
export default prisma;
|
||||
|
|
Loading…
Reference in New Issue