first commit
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import prismaMock from "../../../../../tests/libs/__mocks__/prisma";
|
||||
|
||||
import type { Payment, Prisma, PaymentOption, Booking } from "@prisma/client";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import "vitest-fetch-mock";
|
||||
|
||||
import { sendAwaitingPaymentEmail } from "@calcom/emails";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
import type { IAbstractPaymentService } from "@calcom/types/PaymentService";
|
||||
|
||||
export function getMockPaymentService() {
|
||||
function createPaymentLink(/*{ paymentUid, name, email, date }*/) {
|
||||
return "http://mock-payment.example.com/";
|
||||
}
|
||||
const paymentUid = uuidv4();
|
||||
const externalId = uuidv4();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
class MockPaymentService implements IAbstractPaymentService {
|
||||
// TODO: We shouldn't need to implement adding a row to Payment table but that's a requirement right now.
|
||||
// We should actually delegate table creation to the core app. Here, only the payment app specific logic should come
|
||||
async create(
|
||||
payment: Pick<Prisma.PaymentUncheckedCreateInput, "amount" | "currency">,
|
||||
bookingId: Booking["id"],
|
||||
userId: Booking["userId"],
|
||||
username: string | null,
|
||||
bookerName: string | null,
|
||||
bookerEmail: string,
|
||||
paymentOption: PaymentOption
|
||||
) {
|
||||
const paymentCreateData = {
|
||||
id: 1,
|
||||
uid: paymentUid,
|
||||
appId: null,
|
||||
bookingId,
|
||||
// booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade)
|
||||
fee: 10,
|
||||
success: true,
|
||||
refunded: false,
|
||||
data: {},
|
||||
externalId,
|
||||
paymentOption,
|
||||
amount: payment.amount,
|
||||
currency: payment.currency,
|
||||
};
|
||||
|
||||
const paymentData = prismaMock.payment.create({
|
||||
data: paymentCreateData,
|
||||
});
|
||||
logger.silly("Created mock payment", JSON.stringify({ paymentData }));
|
||||
|
||||
return paymentData;
|
||||
}
|
||||
async afterPayment(
|
||||
event: CalendarEvent,
|
||||
booking: {
|
||||
user: { email: string | null; name: string | null; timeZone: string } | null;
|
||||
id: number;
|
||||
startTime: { toISOString: () => string };
|
||||
uid: string;
|
||||
},
|
||||
paymentData: Payment
|
||||
): Promise<void> {
|
||||
// TODO: App implementing PaymentService is supposed to send email by itself at the moment.
|
||||
await sendAwaitingPaymentEmail({
|
||||
...event,
|
||||
paymentInfo: {
|
||||
link: createPaymentLink(/*{
|
||||
paymentUid: paymentData.uid,
|
||||
name: booking.user?.name,
|
||||
email: booking.user?.email,
|
||||
date: booking.startTime.toISOString(),
|
||||
}*/),
|
||||
paymentOption: paymentData.paymentOption || "ON_BOOKING",
|
||||
amount: paymentData.amount,
|
||||
currency: paymentData.currency,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
return {
|
||||
paymentUid,
|
||||
externalId,
|
||||
MockPaymentService,
|
||||
};
|
||||
}
|
||||
1782
calcom/apps/web/test/utils/bookingScenario/bookingScenario.ts
Normal file
1782
calcom/apps/web/test/utils/bookingScenario/bookingScenario.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
import { createMocks } from "node-mocks-http";
|
||||
|
||||
import type {
|
||||
CustomNextApiRequest,
|
||||
CustomNextApiResponse,
|
||||
} from "@calcom/features/bookings/lib/handleNewBooking/test/fresh-booking.test";
|
||||
|
||||
export function createMockNextJsRequest(...args: Parameters<typeof createMocks>) {
|
||||
return createMocks<CustomNextApiRequest, CustomNextApiResponse>(...args);
|
||||
}
|
||||
1247
calcom/apps/web/test/utils/bookingScenario/expects.ts
Normal file
1247
calcom/apps/web/test/utils/bookingScenario/expects.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
import { getDate } from "@calcom/web/test/utils/bookingScenario/bookingScenario";
|
||||
|
||||
import type { SchedulingType } from "@calcom/prisma/client";
|
||||
|
||||
export const DEFAULT_TIMEZONE_BOOKER = "Asia/Kolkata";
|
||||
export function getBasicMockRequestDataForBooking() {
|
||||
return {
|
||||
start: `${getDate({ dateIncrement: 1 }).dateString}T04:00:00.000Z`,
|
||||
end: `${getDate({ dateIncrement: 1 }).dateString}T04:30:00.000Z`,
|
||||
eventTypeSlug: "no-confirmation",
|
||||
timeZone: DEFAULT_TIMEZONE_BOOKER,
|
||||
language: "en",
|
||||
user: "teampro",
|
||||
metadata: {},
|
||||
hasHashedBookingLink: false,
|
||||
hashedLink: null,
|
||||
};
|
||||
}
|
||||
export function getMockRequestDataForBooking({
|
||||
data,
|
||||
}: {
|
||||
data: Partial<ReturnType<typeof getBasicMockRequestDataForBooking>> & {
|
||||
eventTypeId: number;
|
||||
user?: string;
|
||||
rescheduleUid?: string;
|
||||
bookingUid?: string;
|
||||
recurringEventId?: string;
|
||||
recurringCount?: number;
|
||||
schedulingType?: SchedulingType;
|
||||
responses: {
|
||||
email: string;
|
||||
name: string;
|
||||
location: { optionValue: ""; value: string };
|
||||
smsReminderNumber?: string;
|
||||
};
|
||||
};
|
||||
}) {
|
||||
return {
|
||||
...getBasicMockRequestDataForBooking(),
|
||||
...data,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import type z from "zod";
|
||||
|
||||
import type { schemaBookingCancelParams } from "@calcom/prisma/zod-utils";
|
||||
|
||||
export function getMockRequestDataForCancelBooking(data: z.infer<typeof schemaBookingCancelParams>) {
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { UserPermissionRole } from "@calcom/prisma/client";
|
||||
import { IdentityProvider } from "@calcom/prisma/enums";
|
||||
|
||||
export const getSampleUserInSession = function () {
|
||||
return {
|
||||
locale: "",
|
||||
avatar: "",
|
||||
organization: {
|
||||
isOrgAdmin: false,
|
||||
metadata: null,
|
||||
id: 1,
|
||||
requestedSlug: null,
|
||||
},
|
||||
profile: null,
|
||||
defaultScheduleId: null,
|
||||
name: "",
|
||||
defaultBookerLayouts: null,
|
||||
timeZone: "Asia/Kolkata",
|
||||
selectedCalendars: [],
|
||||
destinationCalendar: null,
|
||||
emailVerified: new Date(),
|
||||
allowDynamicBooking: false,
|
||||
bio: "",
|
||||
weekStart: "",
|
||||
startTime: 0,
|
||||
endTime: 0,
|
||||
bufferTime: 0,
|
||||
hideBranding: false,
|
||||
timeFormat: 12,
|
||||
twoFactorEnabled: false,
|
||||
identityProvider: IdentityProvider.CAL,
|
||||
brandColor: "#292929",
|
||||
darkBrandColor: "#fafafa",
|
||||
metadata: null,
|
||||
role: UserPermissionRole.USER,
|
||||
disableImpersonation: false,
|
||||
organizationId: null,
|
||||
theme: "",
|
||||
appTheme: "",
|
||||
createdDate: new Date(),
|
||||
trialEndsAt: new Date(),
|
||||
completedOnboarding: false,
|
||||
allowSEOIndexing: false,
|
||||
receiveMonthlyDigestEmail: false,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
import {
|
||||
enableEmailFeature,
|
||||
mockNoTranslations,
|
||||
} from "@calcom/web/test/utils/bookingScenario/bookingScenario";
|
||||
|
||||
import { beforeEach, afterEach } from "vitest";
|
||||
|
||||
export function setupAndTeardown() {
|
||||
beforeEach(() => {
|
||||
// Required to able to generate token in email in some cases
|
||||
//@ts-expect-error - It is a readonly variable
|
||||
process.env.CALENDSO_ENCRYPTION_KEY = "abcdefghjnmkljhjklmnhjklkmnbhjui";
|
||||
//@ts-expect-error - It is a readonly variable
|
||||
process.env.STRIPE_WEBHOOK_SECRET = "MOCK_STRIPE_WEBHOOK_SECRET";
|
||||
// We are setting it in vitest.config.ts because otherwise it's too late to set it.
|
||||
// process.env.DAILY_API_KEY = "MOCK_DAILY_API_KEY";
|
||||
|
||||
// Ensure that Rate Limiting isn't enforced for tests
|
||||
delete process.env.UNKEY_ROOT_KEY;
|
||||
mockNoTranslations();
|
||||
// mockEnableEmailFeature();
|
||||
enableEmailFeature();
|
||||
globalThis.testEmails = [];
|
||||
fetchMock.resetMocks();
|
||||
});
|
||||
afterEach(() => {
|
||||
//@ts-expect-error - It is a readonly variable
|
||||
delete process.env.CALENDSO_ENCRYPTION_KEY;
|
||||
//@ts-expect-error - It is a readonly variable
|
||||
delete process.env.STRIPE_WEBHOOK_SECRET;
|
||||
delete process.env.DAILY_API_KEY;
|
||||
globalThis.testEmails = [];
|
||||
fetchMock.resetMocks();
|
||||
// process.env.DAILY_API_KEY = "MOCK_DAILY_API_KEY";
|
||||
});
|
||||
}
|
||||
81
calcom/apps/web/test/utils/bookingScenario/test.ts
Normal file
81
calcom/apps/web/test/utils/bookingScenario/test.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { createOrganization } from "@calcom/web/test/utils/bookingScenario/bookingScenario";
|
||||
|
||||
import type { TestFunction } from "vitest";
|
||||
|
||||
import { WEBSITE_URL } from "@calcom/lib/constants";
|
||||
import { test } from "@calcom/web/test/fixtures/fixtures";
|
||||
import type { Fixtures } from "@calcom/web/test/fixtures/fixtures";
|
||||
|
||||
const WEBSITE_PROTOCOL = new URL(WEBSITE_URL).protocol;
|
||||
const _testWithAndWithoutOrg = (
|
||||
description: Parameters<typeof testWithAndWithoutOrg>[0],
|
||||
fn: Parameters<typeof testWithAndWithoutOrg>[1],
|
||||
timeout: Parameters<typeof testWithAndWithoutOrg>[2],
|
||||
mode: "only" | "skip" | "run" = "run"
|
||||
) => {
|
||||
const t = mode === "only" ? test.only : mode === "skip" ? test.skip : test;
|
||||
t(
|
||||
`${description} - With org`,
|
||||
async ({ emails, sms, meta, task, onTestFailed, expect, skip }) => {
|
||||
const org = await createOrganization({
|
||||
name: "Test Org",
|
||||
slug: "testorg",
|
||||
});
|
||||
|
||||
await fn({
|
||||
meta,
|
||||
task,
|
||||
onTestFailed,
|
||||
expect,
|
||||
emails,
|
||||
sms,
|
||||
skip,
|
||||
org: {
|
||||
organization: org,
|
||||
urlOrigin: `${WEBSITE_PROTOCOL}//${org.slug}.cal.local:3000`,
|
||||
},
|
||||
});
|
||||
},
|
||||
timeout
|
||||
);
|
||||
|
||||
t(
|
||||
`${description}`,
|
||||
async ({ emails, sms, meta, task, onTestFailed, expect, skip }) => {
|
||||
await fn({
|
||||
emails,
|
||||
sms,
|
||||
meta,
|
||||
task,
|
||||
onTestFailed,
|
||||
expect,
|
||||
skip,
|
||||
org: null,
|
||||
});
|
||||
},
|
||||
timeout
|
||||
);
|
||||
};
|
||||
|
||||
export const testWithAndWithoutOrg = (
|
||||
description: string,
|
||||
fn: TestFunction<
|
||||
Fixtures & {
|
||||
org: {
|
||||
organization: { id: number | null };
|
||||
urlOrigin?: string;
|
||||
} | null;
|
||||
}
|
||||
>,
|
||||
timeout?: number
|
||||
) => {
|
||||
_testWithAndWithoutOrg(description, fn, timeout, "run");
|
||||
};
|
||||
|
||||
testWithAndWithoutOrg.only = ((description, fn, timeout) => {
|
||||
_testWithAndWithoutOrg(description, fn, timeout, "only");
|
||||
}) as typeof _testWithAndWithoutOrg;
|
||||
|
||||
testWithAndWithoutOrg.skip = ((description, fn, timeout) => {
|
||||
_testWithAndWithoutOrg(description, fn, timeout, "skip");
|
||||
}) as typeof _testWithAndWithoutOrg;
|
||||
Reference in New Issue
Block a user