refactor: apply biome formatting to several packages (#27439)

* refactor: apply biome formatting to Phase 1 packages

Packages formatted:
- packages/app-store-cli
- packages/config
- packages/dayjs
- packages/debugging
- packages/embeds/embed-react
- packages/embeds/embed-snippet
- packages/kysely
- packages/platform/constants
- packages/platform/utils
- packages/testing
- packages/tsconfig

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: restore non-null assertions in embed-snippet to fix type error

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: remove ESM import from CommonJS config file

Biome incorrectly added 'import process from node:process' to a CommonJS
file that uses require(). This breaks Jest which expects CommonJS syntax.
The process global is already available in Node.js without explicit import.

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: exclude packages/embeds from Phase 1 formatting

Per user request, reverting all biome formatting changes in packages/embeds
to handle separately.

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: restore const enum for BookingLocations

Biome changed 'const enum' to 'enum' which is a semantic change.
Reverting to keep the PR purely formatting-only.

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Eunjae LeeandDevin AI authored and GitHub committed 2026-02-05 07:24:34 -03:00
1 parent c652c61e0c
commit 357c2882ad
50 files changed
+349 -452

No files matched your search

+2 -3
View File
@@ -1,6 +1,5 @@
import React, { FC } from "react";
import { SupportedCommands } from "src/types";
import type { FC } from "react";
import type { SupportedCommands } from "src/types";
import Create from "./commandViews/Create";
import CreateTemplate from "./commandViews/Create";
import Delete from "./commandViews/Delete";
+25 -85
View File
@@ -1,12 +1,12 @@
import chokidar from "chokidar";
import fs from "node:fs"
// eslint-disable-next-line no-restricted-imports
import { debounce } from "lodash";
import { spawnSync } from "node:child_process";
import path from "node:path"
import fs from "node:fs";
import path from "node:path";
import process from "node:process";
import type { AppMeta } from "@calcom/types/App";
import { AppMetaSchema } from "@calcom/types/AppMetaSchema";
import chokidar from "chokidar";
// eslint-disable-next-line no-restricted-imports
import { debounce } from "lodash";
import { APP_STORE_PATH } from "./constants";
import { getAppName } from "./utils/getAppName";
@@ -37,8 +37,7 @@ const formatOutput = (source: string) => source;
const getVariableName = (appName: string) => appName.replace(/[-./]/g, "_");
// INFO: Handle stripe separately as it's an old app with different dirName than slug/appId
const getAppId = (app: { name: string }) =>
app.name === "stripepayment" ? "stripe" : app.name;
const getAppId = (app: { name: string }) => (app.name === "stripepayment" ? "stripe" : app.name);
type App = Partial<AppMeta> & {
name: string;
@@ -79,21 +78,10 @@ function generateFiles() {
}
});
function forEachAppDir(
callback: (arg: App) => void,
filter: (arg: App) => boolean = () => true
) {
function forEachAppDir(callback: (arg: App) => void, filter: (arg: App) => boolean = () => true) {
for (let i = 0; i < appDirs.length; i++) {
const configPath = path.join(
APP_STORE_PATH,
appDirs[i].path,
"config.json"
);
const metadataPath = path.join(
APP_STORE_PATH,
appDirs[i].path,
"_metadata.ts"
);
const configPath = path.join(APP_STORE_PATH, appDirs[i].path, "config.json");
const metadataPath = path.join(APP_STORE_PATH, appDirs[i].path, "_metadata.ts");
let app: AppMetaSchema;
if (fs.existsSync(configPath)) {
@@ -102,16 +90,8 @@ function generateFiles() {
const parsedConfig = JSON.parse(rawConfig);
app = AppMetaSchema.parse(parsedConfig);
} catch (error) {
const prefix = `Config error in ${path.join(
APP_STORE_PATH,
appDirs[i].path,
"config.json"
)}`;
throw new Error(
`${prefix}: ${
error instanceof Error ? error.message : String(error)
}`
);
const prefix = `Config error in ${path.join(APP_STORE_PATH, appDirs[i].path, "config.json")}`;
throw new Error(`${prefix}: ${error instanceof Error ? error.message : String(error)}`);
}
} else if (fs.existsSync(metadataPath)) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -156,7 +136,7 @@ function generateFiles() {
{
fileToBeImported: string;
importName: string;
}
},
];
/**
@@ -180,18 +160,12 @@ function generateFiles() {
const getLocalImportName = (
app: { name: string },
chosenConfig: ReturnType<typeof getChosenImportConfig>
) =>
`${getVariableName(app.name)}_${getVariableName(
chosenConfig.fileToBeImported
)}`;
) => `${getVariableName(app.name)}_${getVariableName(chosenConfig.fileToBeImported)}`;
const fileToBeImportedExists = (
app: { path: string },
chosenConfig: ReturnType<typeof getChosenImportConfig>
) =>
fs.existsSync(
path.join(APP_STORE_PATH, app.path, chosenConfig.fileToBeImported)
);
) => fs.existsSync(path.join(APP_STORE_PATH, app.path, chosenConfig.fileToBeImported));
addImportStatements();
createExportObject();
@@ -201,19 +175,13 @@ function generateFiles() {
function addImportStatements() {
forEachAppDir((app) => {
const chosenConfig = getChosenImportConfig(importConfig, app);
if (
fileToBeImportedExists(app, chosenConfig) &&
chosenConfig.importName
) {
if (fileToBeImportedExists(app, chosenConfig) && chosenConfig.importName) {
const importName = chosenConfig.importName;
if (!lazyImport) {
if (importName !== "default") {
// Import with local alias that will be used by createExportObject
output.push(
`import { ${importName} as ${getLocalImportName(
app,
chosenConfig
)} } from "${getModulePath(
`import { ${importName} as ${getLocalImportName(app, chosenConfig)} } from "${getModulePath(
app.path,
chosenConfig.fileToBeImported
)}"`
@@ -221,10 +189,7 @@ function generateFiles() {
} else {
// Default Import
output.push(
`import ${getLocalImportName(
app,
chosenConfig
)} from "${getModulePath(
`import ${getLocalImportName(app, chosenConfig)} from "${getModulePath(
app.path,
chosenConfig.fileToBeImported
)}"`
@@ -255,12 +220,7 @@ function generateFiles() {
)}")),`
);
} else {
output.push(
`"${key}": import("${getModulePath(
app.path,
chosenConfig.fileToBeImported
)}"),`
);
output.push(`"${key}": import("${getModulePath(app.path, chosenConfig.fileToBeImported)}"),`);
}
}
}
@@ -269,24 +229,13 @@ function generateFiles() {
output.push(`};`);
}
function getChosenImportConfig(
importConfig: ImportConfig,
app: { path: string }
) {
function getChosenImportConfig(importConfig: ImportConfig, app: { path: string }) {
let chosenConfig: ImportConfig;
if (!Array.isArray(importConfig)) {
chosenConfig = importConfig;
} else {
if (
fs.existsSync(
path.join(
APP_STORE_PATH,
app.path,
importConfig[0].fileToBeImported
)
)
) {
if (fs.existsSync(path.join(APP_STORE_PATH, app.path, importConfig[0].fileToBeImported))) {
chosenConfig = importConfig[0];
} else {
chosenConfig = importConfig[1];
@@ -472,10 +421,7 @@ function generateFiles() {
);
if (analyticsExportLineIndex !== -1) {
const exportLine = analyticsServices[analyticsExportLineIndex];
const objectContent = analyticsServices.slice(
analyticsExportLineIndex + 1,
-1
);
const objectContent = analyticsServices.slice(analyticsExportLineIndex + 1, -1);
analyticsOutput.push(
exportLine.replace(
@@ -500,9 +446,7 @@ function generateFiles() {
lazyImport: true,
},
(app: App) => {
const hasPaymentService = fs.existsSync(
path.join(APP_STORE_PATH, app.path, "lib/PaymentService.ts")
);
const hasPaymentService = fs.existsSync(path.join(APP_STORE_PATH, app.path, "lib/PaymentService.ts"));
return hasPaymentService;
}
);
@@ -520,9 +464,7 @@ function generateFiles() {
lazyImport: true,
},
(app: App) => {
return fs.existsSync(
path.join(APP_STORE_PATH, app.path, "lib/VideoApiAdapter.ts")
);
return fs.existsSync(path.join(APP_STORE_PATH, app.path, "lib/VideoApiAdapter.ts"));
}
);
@@ -568,9 +510,7 @@ function generateFiles() {
fs.writeFileSync(filePath, formatOutput(`${banner}${output.join("\n")}`));
formatFileWithBiome(filePath);
});
console.log(
`Generated ${filesToGenerate.map(([fileName]) => fileName).join(", ")}`
);
console.log(`Generated ${filesToGenerate.map(([fileName]) => fileName).join(", ")}`);
}
const debouncedGenerateFiles = debounce(generateFiles);
+1 -3
View File
@@ -1,10 +1,8 @@
#!/usr/bin/env node
import { render } from "ink";
import meow from "meow";
import React from "react";
import App from "./App";
import { SupportedCommands } from "./types";
import type { SupportedCommands } from "./types";
const cli = meow(
`
@@ -1,5 +1,4 @@
import React from "react";
import type React from "react";
import { AppForm } from "../components/AppCreateUpdateForm";
export default function Create(props: Omit<React.ComponentProps<typeof AppForm>, "action">) {
@@ -1,5 +1,4 @@
import React from "react";
import type React from "react";
import { AppForm } from "../components/AppCreateUpdateForm";
export default function CreateTemplate(props: Omit<React.ComponentProps<typeof AppForm>, "action">) {
@@ -1,5 +1,3 @@
import React from "react";
import DeleteForm from "../components/DeleteForm";
export default function Delete({ slug }: { slug: string }) {
@@ -1,5 +1,3 @@
import React from "react";
import DeleteForm from "../components/DeleteForm";
export default function Delete({ slug }: { slug: string }) {
@@ -1,5 +1,4 @@
import React from "react";
import type React from "react";
import { AppForm } from "../components/AppCreateUpdateForm";
export default function Edit(props: Omit<React.ComponentProps<typeof AppForm>, "action">) {
@@ -1,5 +1,4 @@
import React from "react";
import type React from "react";
import { AppForm } from "../components/AppCreateUpdateForm";
export default function Edit(props: Omit<React.ComponentProps<typeof AppForm>, "action">) {
@@ -1,12 +1,10 @@
import fs from "node:fs"
import fs from "node:fs";
import type { AppMeta } from "@calcom/types/App";
import { Box, Newline, Text, useApp } from "ink";
import SelectInput from "ink-select-input";
import TextInput from "ink-text-input";
import React, { useEffect, useState } from "react";
import type { AppMeta } from "@calcom/types/App";
import { getSlugFromAppName, BaseAppFork, generateAppFiles, getAppDirPath } from "../core";
import { useEffect, useState } from "react";
import { BaseAppFork, generateAppFiles, getAppDirPath, getSlugFromAppName } from "../core";
import { getApp } from "../utils/getApp";
import Templates from "../utils/templates";
import Label from "./Label";
@@ -46,7 +44,7 @@ export const AppForm = ({
category: config.categories[0],
template: config.__template,
};
} catch (e) {}
} catch (_e) {}
const fields = [
{
@@ -130,7 +128,7 @@ export const AppForm = ({
const formCompleted = inputIndex === fields.length;
if (field?.name === "appCategory") {
// Use template category as the default category
fieldValue = Templates.find((t) => t.value === appInputData["template"])?.category || "";
fieldValue = Templates.find((t) => t.value === appInputData.template)?.category || "";
}
const slug = getSlugFromAppName(name) || givenSlug;
@@ -158,7 +156,19 @@ export const AppForm = ({
setStatus("done");
}
})();
}, [formCompleted]);
}, [
formCompleted,
category,
description,
email,
givenSlug,
isEditAction,
isTemplate,
name,
publisher,
slug,
template,
]);
if (action === "edit" || action === "edit-template") {
if (!slug) {
@@ -291,7 +301,7 @@ export const AppForm = ({
)}
<Box>
<Label>{`${fieldLabel}`}</Label>
{field?.type == "text" ? (
{field?.type === "text" ? (
<TextInput
value={fieldValue}
placeholder={field?.defaultValue}
@@ -1,7 +1,6 @@
import { Text } from "ink";
import TextInput from "ink-text-input";
import React, { useEffect, useState } from "react";
import { useEffect, useState } from "react";
import { ImportantText } from "../components/ImportantText";
import { Message } from "../components/Message";
import { BaseAppFork, generateAppFiles } from "../core";
@@ -22,7 +21,7 @@ export default function DeleteForm({ slug, action }: { slug: string; action: "de
if (!app) {
setState("APP_NOT_EXISTS");
}
}, []);
}, [app]);
useEffect(() => {
if (state === "DELETION_CONFIRMATION_SUCCESSFUL") {
@@ -33,7 +32,7 @@ export default function DeleteForm({ slug, action }: { slug: string; action: "de
setState("DELETION_COMPLETED");
})();
}
}, [slug, state]);
}, [slug, state, isTemplate]);
if (state === "INITIALIZED") {
return (
@@ -1,5 +1,5 @@
import { Text } from "ink";
import React from "react";
import type React from "react";
export function ImportantText({ children }: { children: React.ReactNode }) {
return <Text color="red">{children}</Text>;
@@ -1,5 +1,5 @@
import { Box, Text } from "ink";
import React from "react";
import type React from "react";
export default function Label({ children }: { children: React.ReactNode }) {
return (
@@ -1,5 +1,5 @@
import { Text } from "ink";
import React, { useEffect, useState } from "react";
import { useEffect, useState } from "react";
export function Message({
message,
+1 -1
View File
@@ -1,5 +1,5 @@
import os from "node:os";
import path from "node:path"
import path from "node:path";
export const APP_STORE_PATH = path.join(__dirname, "..", "..", "app-store");
export const TEMPLATES_PATH = path.join(APP_STORE_PATH, "templates");
+7 -8
View File
@@ -1,7 +1,6 @@
import fs from "node:fs"
import path from "node:path"
import { APP_STORE_PATH, TEMPLATES_PATH, IS_WINDOWS_PLATFORM } from "./constants";
import fs from "node:fs";
import path from "node:path";
import { APP_STORE_PATH, IS_WINDOWS_PLATFORM, TEMPLATES_PATH } from "./constants";
import execSync from "./utils/execSync";
const slugify = (str: string) => {
@@ -41,10 +40,10 @@ const updatePackageJson = ({
fs.writeFileSync(`${appDirPath}/package.json`, JSON.stringify(packageJsonConfig, null, 2));
};
const workspaceDir = path.resolve(__dirname, "..", "..", "..");
const _workspaceDir = path.resolve(__dirname, "..", "..", "..");
export const BaseAppFork = {
create: async function ({
create: async ({
category,
editMode = false,
description,
@@ -66,7 +65,7 @@ export const BaseAppFork = {
template: string;
isTemplate: boolean;
oldSlug?: string;
}) {
}) => {
const appDirPath = getAppDirPath(slug, isTemplate);
if (!editMode) {
await execSync(IS_WINDOWS_PLATFORM ? `mkdir ${appDirPath}` : `mkdir -p ${appDirPath}`);
@@ -129,7 +128,7 @@ export const BaseAppFork = {
await execSync("yarn");
},
delete: async function ({ slug, isTemplate }: { slug: string; isTemplate: boolean }) {
delete: async ({ slug, isTemplate }: { slug: string; isTemplate: boolean }) => {
const appDirPath = getAppDirPath(slug, isTemplate);
await execSync(IS_WINDOWS_PLATFORM ? `rd /s /q ${appDirPath}` : `rm -rf ${appDirPath}`);
},
+2 -1
View File
@@ -1,7 +1,8 @@
import child_process from "node:child_process";
import process from "node:process";
const execSync = async (cmd: string) => {
const silent = process.env.DEBUG === "1" ? false : true;
const silent = process.env.DEBUG !== "1";
if (!silent) {
console.log(`${process.cwd()}$: ${cmd}`);
}
+3 -4
View File
@@ -1,6 +1,5 @@
import fs from "node:fs"
import path from "node:path"
import fs from "node:fs";
import path from "node:path";
import { APP_STORE_PATH, TEMPLATES_PATH } from "../constants";
import { getAppName } from "./getAppName";
@@ -18,7 +17,7 @@ export const getApp = (slug: string, isTemplate: boolean) => {
if (foundApp) {
try {
return JSON.parse(fs.readFileSync(path.join(base, foundApp, "config.json")).toString());
} catch (e) {
} catch (_e) {
return {};
}
}
@@ -1,5 +1,4 @@
import path from "node:path"
import path from "node:path";
import { APP_STORE_PATH } from "../constants";
export function getAppName(candidatePath) {
@@ -1,6 +1,5 @@
import fs from "node:fs"
import path from "node:path"
import fs from "node:fs";
import path from "node:path";
import { TEMPLATES_PATH } from "../constants";
import { getAppName } from "./getAppName";
@@ -20,7 +19,7 @@ const Templates = fs
value: dir,
category: config.categories[0],
};
} catch (e) {
} catch (_e) {
// config.json might not exist
return null;
}
+2 -2
View File
@@ -14,7 +14,7 @@ const hexToHSL = (hex: string): HSL => {
s,
// eslint-disable-next-line prefer-const
l = (max + min) / 2;
if (max == min) {
if (max === min) {
h = s = 0; // achromatic
} else {
const d = max - min;
@@ -37,7 +37,7 @@ const hexToHSL = (hex: string): HSL => {
HSL.s = Math.round(s * 100);
HSL.l = Math.round(l * 100);
return HSL;
} catch (error) {
} catch (_error) {
console.log(hex);
return { h: 0, s: 0, l: 0 };
}
+1 -1
View File
@@ -1,6 +1,6 @@
@source "../../../apps/web/pages/**/*.{js,ts,jsx,tsx}";
@source "../../../apps/web/app/**/*.{js,ts,jsx,tsx}";
@source "../../../apps/web/modules/**/*.{js,ts,jsx,tsx}";
@source "../../../apps/web/modules/**/*.{js,ts,jsx,tsx}";
@source "../../../apps/web/components/**/*.{js,ts,jsx,tsx}";
@source "../../../packages/app-store/**/*{components,pages}/**/*.{js,ts,jsx,tsx}";
@source "../../../packages/features/**/*.{js,ts,jsx,tsx}";
+9 -7
View File
@@ -1,17 +1,19 @@
import dayjs from "@calcom/dayjs";
import timezone from "dayjs/plugin/timezone";
import utc from "dayjs/plugin/utc";
import { vi } from "vitest";
import dayjs from "@calcom/dayjs";
dayjs.extend(utc);
dayjs.extend(timezone);
// biome-ignore lint/nursery/useExplicitType: mock function
const mockDayjs = Object.assign(vi.fn((date: Parameters<typeof dayjs>[0]) => dayjs(date)), {
utc: vi.fn((date: Parameters<typeof dayjs.utc>[0]) => dayjs.utc(date)),
tz: vi.fn(),
extend: vi.fn(),
});
const mockDayjs = Object.assign(
vi.fn((date: Parameters<typeof dayjs>[0]) => dayjs(date)),
{
utc: vi.fn((date: Parameters<typeof dayjs.utc>[0]) => dayjs.utc(date)),
tz: vi.fn(),
extend: vi.fn(),
}
);
export default mockDayjs;
-1
View File
@@ -10,7 +10,6 @@ import relativeTime from "dayjs/plugin/relativeTime";
import timeZone from "dayjs/plugin/timezone";
import toArray from "dayjs/plugin/toArray";
import utc from "dayjs/plugin/utc";
import BusinessDaysPlugin from "./plugins/business-days-plugin";
dayjs.extend(customParseFormat);
+10 -20
View File
@@ -15,43 +15,33 @@ const BusinessDaysPlugin: PluginFunc<BusinessDaysPluginOptions> = (
) => {
const defaultWorkingWeekdays = [1, 2, 3, 4, 5];
dayjsFactory.getWorkingWeekdays = function (): number[] {
return options.workingWeekdays || defaultWorkingWeekdays;
};
dayjsFactory.getWorkingWeekdays = (): number[] => options.workingWeekdays || defaultWorkingWeekdays;
dayjsFactory.setWorkingWeekdays = function (workingWeekdays: number[]): void {
dayjsFactory.setWorkingWeekdays = (workingWeekdays: number[]): void => {
options.workingWeekdays = workingWeekdays;
};
dayjsFactory.getHolidays = function (): string[] {
return options.holidays || [];
};
dayjsFactory.getHolidays = (): string[] => options.holidays || [];
dayjsFactory.setHolidays = function (holidays: string[]): void {
dayjsFactory.setHolidays = (holidays: string[]): void => {
options.holidays = holidays;
};
dayjsFactory.getHolidayFormat = function (): string | undefined {
return options.holidayFormat;
};
dayjsFactory.getHolidayFormat = (): string | undefined => options.holidayFormat;
dayjsFactory.setHolidayFormat = function (holidayFormat: string): void {
dayjsFactory.setHolidayFormat = (holidayFormat: string): void => {
options.holidayFormat = holidayFormat;
};
dayjsFactory.getAdditionalWorkingDays = function (): string[] {
return options.additionalWorkingDays || [];
};
dayjsFactory.getAdditionalWorkingDays = (): string[] => options.additionalWorkingDays || [];
dayjsFactory.setAdditionalWorkingDays = function (additionalWorkingDays: string[]): void {
dayjsFactory.setAdditionalWorkingDays = (additionalWorkingDays: string[]): void => {
options.additionalWorkingDays = additionalWorkingDays;
};
dayjsFactory.getAdditionalWorkingDayFormat = function (): string | undefined {
return options.additionalWorkingDayFormat;
};
dayjsFactory.getAdditionalWorkingDayFormat = (): string | undefined => options.additionalWorkingDayFormat;
dayjsFactory.setAdditionalWorkingDayFormat = function (additionalWorkingDayFormat: string): void {
dayjsFactory.setAdditionalWorkingDayFormat = (additionalWorkingDayFormat: string): void => {
options.additionalWorkingDayFormat = additionalWorkingDayFormat;
};
+3 -3
View File
@@ -1,7 +1,7 @@
import { Kysely, ParseJSONResultsPlugin, PostgresDialect, DeduplicateJoinsPlugin } from "kysely";
import process from "node:process";
import { DeduplicateJoinsPlugin, Kysely, ParseJSONResultsPlugin, PostgresDialect } from "kysely";
import { Pool } from "pg";
import type { DB, Booking } from "./types";
import type { Booking, DB } from "./types";
export type { DB, Booking };
+1 -1
View File
@@ -2,7 +2,7 @@ import type { ExpressionBuilder, StringReference } from "kysely";
import { sql } from "kysely";
export function traverseJSON<DB, TB extends keyof DB>(
eb: ExpressionBuilder<DB, TB>,
_eb: ExpressionBuilder<DB, TB>,
column: StringReference<DB, TB>,
path: string | [string, ...string[]]
) {
+1 -1
View File
@@ -1,3 +1,3 @@
export * from "./permissions";
export * from "./api";
export * from "./apps";
export * from "./permissions";
+4 -4
View File
@@ -1,15 +1,15 @@
import {
APPS_READ,
APPS_WRITE,
BOOKING_READ,
BOOKING_WRITE,
EVENT_TYPE_READ,
EVENT_TYPE_WRITE,
PERMISSIONS,
SCHEDULE_READ,
SCHEDULE_WRITE,
APPS_READ,
APPS_WRITE,
PROFILE_READ,
PROFILE_WRITE,
SCHEDULE_READ,
SCHEDULE_WRITE,
} from "@calcom/platform-constants";
import type { PLATFORM_PERMISSION } from "@calcom/platform-types";
@@ -6,7 +6,6 @@ import {
SCHEDULE_READ,
SCHEDULE_WRITE,
} from "@calcom/platform-constants";
import { hasPermission, hasPermissions, listPermissions } from "../permissions";
describe("Permissions Function: hasPermission", () => {
@@ -1,5 +1,4 @@
import { sleep } from "k6";
import { THRESHOLDS } from "../utils/config.js";
import { viewBookingPage } from "../utils/helpers.js";
@@ -1,5 +1,4 @@
import { sleep } from "k6";
import { THRESHOLDS } from "../utils/config.js";
import { viewBookingPage } from "../utils/helpers.js";
@@ -1,5 +1,4 @@
import { sleep } from "k6";
import { THRESHOLDS } from "../utils/config.js";
import { viewBookingPage } from "../utils/helpers.js";
@@ -1,5 +1,4 @@
import { sleep } from "k6";
import { THRESHOLDS } from "../utils/config.js";
import { viewBookingPage } from "../utils/helpers.js";
+4 -6
View File
@@ -35,12 +35,10 @@ export const THRESHOLDS = {
},
};
export const TEST_USERS = new SharedArray("users", function () {
return [
{ username: __ENV.TEST_USER_FREE || "free", password: __ENV.TEST_PASSWORD_FREE || "free" },
{ username: __ENV.TEST_USER_PRO || "pro", password: __ENV.TEST_PASSWORD_PRO || "pro" },
];
});
export const TEST_USERS = new SharedArray("users", () => [
{ username: __ENV.TEST_USER_FREE || "free", password: __ENV.TEST_PASSWORD_FREE || "free" },
{ username: __ENV.TEST_USER_PRO || "pro", password: __ENV.TEST_PASSWORD_PRO || "pro" },
]);
export function getRandomUser() {
return TEST_USERS[Math.floor(Math.random() * TEST_USERS.length)];
@@ -1,7 +1,6 @@
import { check, group } from "k6";
import http from "k6/http";
import { randomSleep, BASE_URL, randomQueryParam } from "./config.js";
import { BASE_URL, randomQueryParam, randomSleep } from "./config.js";
export function viewBookingPage(username, eventSlug) {
return group("View Booking Page", () => {
@@ -1,7 +1,6 @@
import { beforeEach, vi } from "vitest";
import { mockReset, mockDeep } from "vitest-mock-extended";
import type * as i18n from "@calcom/lib/server/i18n";
import { beforeEach, vi } from "vitest";
import { mockDeep, mockReset } from "vitest-mock-extended";
vi.mock("@calcom/lib/server/i18n", () => i18nMock);
+6 -7
View File
@@ -1,12 +1,11 @@
import { type DMMF } from "@prisma/client/runtime/client";
import { getDMMF } from "@prisma/internals";
import { readFileSync } from "node:fs";
import { beforeEach, vi } from "vitest";
import { createPrismock } from "prismock/build/main/lib/client";
import logger from "@calcom/lib/logger";
import type { PrismaClient } from "@calcom/prisma";
import * as selects from "@calcom/prisma/selects";
import type { DMMF } from "@prisma/client/runtime/client";
import { getDMMF } from "@prisma/internals";
import { createPrismock } from "prismock/build/main/lib/client";
import { beforeEach, vi } from "vitest";
vi.stubEnv("DATABASE_URL", "postgresql://user:password@localhost:5432/testdb");
@@ -56,7 +55,7 @@ const prismaMockProxy = new Proxy(proxyTarget, {
}
return prop in prismockInstance;
},
ownKeys(target) {
ownKeys(_target) {
if (!prismockInstance) {
return [];
}
@@ -68,7 +67,7 @@ const prismaMockProxy = new Proxy(proxyTarget, {
}
(target as any)[prop] = value;
return true;
}
},
});
vi.mock("@calcom/prisma", async (importOriginal) => {
@@ -1,8 +1,7 @@
import type { PrismaClient } from "@calcom/prisma";
import { beforeEach, vi } from "vitest";
import { type DeepMockProxy, mockDeep, mockReset } from "vitest-mock-extended";
import type { PrismaClient } from "@calcom/prisma";
const prisma = mockDeep<PrismaClient>() as unknown as DeepMockProxy<PrismaClient>;
vi.mock("@calcom/prisma", () => ({
@@ -4,7 +4,7 @@ import "vitest-fetch-mock";
import { sendAwaitingPaymentEmailAndSMS } from "@calcom/emails/email-manager";
import logger from "@calcom/lib/logger";
import type { Payment, Prisma, PaymentOption, Booking } from "@calcom/prisma/client";
import type { Booking, Payment, PaymentOption, Prisma } from "@calcom/prisma/client";
import type { CalendarEvent } from "@calcom/types/Calendar";
import type { IAbstractPaymentService } from "@calcom/types/PaymentService";
@@ -23,10 +23,10 @@ export function getMockPaymentService() {
async create(
payment: Pick<Prisma.PaymentUncheckedCreateInput, "amount" | "currency">,
bookingId: Booking["id"],
userId: Booking["userId"],
username: string | null,
bookerName: string | null,
bookerEmail: string,
_userId: Booking["userId"],
_username: string | null,
_bookerName: string | null,
_bookerEmail: string,
paymentOption: PaymentOption
) {
const paymentCreateData = {
@@ -59,7 +59,7 @@ export function getMockPaymentService() {
}
async afterPayment(
event: CalendarEvent,
booking: {
_booking: {
user: { email: string | null; name: string | null; timeZone: string } | null;
id: number;
startTime: { toISOString: () => string };
@@ -71,12 +71,14 @@ export function getMockPaymentService() {
await sendAwaitingPaymentEmailAndSMS({
...event,
paymentInfo: {
link: createPaymentLink(/*{
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,
@@ -1,45 +1,52 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import i18nMock from "../__mocks__/libServerI18n";
import prismock from "../__mocks__/prisma";
import { v4 as uuidv4 } from "uuid";
import { vi } from "vitest";
import "vitest-fetch-mock";
import type { z } from "zod";
import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData";
import { weekdayToWeekIndex, type WeekDays } from "@calcom/lib/dayjs";
import { type WeekDays, weekdayToWeekIndex } from "@calcom/lib/dayjs";
import type { IntervalLimit } from "@calcom/lib/intervalLimits/intervalLimitSchema";
import logger from "@calcom/lib/logger";
import { safeStringify } from "@calcom/lib/safeStringify";
import type { BookingReference, Attendee, Booking, Membership } from "@calcom/prisma/client";
import type { Prisma } from "@calcom/prisma/client";
import type { WebhookTriggerEvents } from "@calcom/prisma/client";
import type {
Attendee,
Booking,
BookingReference,
Membership,
Prisma,
WebhookTriggerEvents,
WorkflowActions,
WorkflowMethods,
WorkflowTemplates,
WorkflowTriggerEvents,
WorkflowMethods,
} from "@calcom/prisma/client";
import type { PaymentOption, SchedulingType, SMSLockState, TimeUnit } 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";
import type { eventTypeBookingFields } from "@calcom/prisma/zod-utils";
import type { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import type {
BookingStatus,
PaymentOption,
SchedulingType,
SMSLockState,
TimeUnit,
} from "@calcom/prisma/enums";
import type {
EventTypeMetaDataSchema,
eventTypeBookingFields,
teamMetadataSchema,
userMetadataType,
} from "@calcom/prisma/zod-utils";
import type { AppMeta } from "@calcom/types/App";
import type {
Calendar,
CalendarEvent,
EventBusyDate,
IntegrationCalendar,
NewCalendarEventType,
EventBusyDate,
} from "@calcom/types/Calendar";
import type { CredentialPayload } from "@calcom/types/Credential";
import type { VideoApiAdapter } from "@calcom/types/VideoApiAdapter";
import { getMockPaymentService } from "./MockPaymentService";
import type { z } from "zod";
import type { getMockRequestDataForBooking } from "./getMockRequestDataForBooking";
import { getMockPaymentService } from "./MockPaymentService";
type NonNullableVideoApiAdapter = NonNullable<VideoApiAdapter>;
vi.mock("@calcom/app-store/calendar.services.generated", () => ({
@@ -57,7 +64,7 @@ vi.mock("@calcom/app-store/video.adapters.generated", () => ({
VideoApiAdapterMap: new Proxy(
{},
{
get(target, prop) {
get(_target, prop) {
if (typeof prop === "string" && mockVideoAdapterRegistry[prop]) {
return mockVideoAdapterRegistry[prop];
}
@@ -578,7 +585,7 @@ export async function addEventTypes(eventTypes: InputEventType[], usersStore: In
data: eventType.restrictionSchedule.create.availability.createMany.data,
},
},
user: { connect: { id: eventType.userId || (eventType.users && eventType.users[0]?.id) || 1 } },
user: { connect: { id: eventType.userId || eventType.users?.[0]?.id || 1 } },
},
}
: undefined,
@@ -1131,12 +1138,7 @@ export async function createCredentials(
* use vi.setSystemTime to fix the date and time and then use hardcoded days instead of dynamic date calculation.
*/
export const getDate = (
param: {
dateIncrement?: number;
monthIncrement?: number;
yearIncrement?: number;
fromDate?: Date;
} = {}
param: { dateIncrement?: number; monthIncrement?: number; yearIncrement?: number; fromDate?: Date } = {}
) => {
let { dateIncrement, monthIncrement, yearIncrement, fromDate } = param;
@@ -1837,163 +1839,154 @@ export async function mockCalendar(
if (calendarServicePromise) {
const resolvedService = await calendarServicePromise;
vi.mocked(resolvedService.default).mockImplementation(function MockCalendarService(credential) {
return {
createEvent: async function (
...rest: Parameters<Calendar["createEvent"]>
): Promise<NewCalendarEventType> {
if (calendarData?.creationCrash) {
throw new Error("MockCalendarService.createEvent fake error");
}
const [calEvent, credentialId, externalCalendarId] = rest;
log.debug(
"mockCalendar.createEvent",
JSON.stringify({ calEvent, credentialId, externalCalendarId })
);
createEventCalls.push({
args: {
calEvent,
credentialId,
externalCalendarId,
},
calendarServiceConstructorArgs: {
credential,
},
});
const isGoogleMeetLocation = calEvent?.location === BookingLocations.GoogleMeet;
if (app.type === "google_calendar") {
return Promise.resolve({
type: app.type,
additionalInfo: {
hangoutLink:
normalizedCalendarData.create?.appSpecificData?.googleCalendar?.hangoutLink ||
"https://GOOGLE_MEET_URL_IN_CALENDAR_EVENT",
},
return {
createEvent: async (...rest: Parameters<Calendar["createEvent"]>): Promise<NewCalendarEventType> => {
if (calendarData?.creationCrash) {
throw new Error("MockCalendarService.createEvent fake error");
}
const [calEvent, credentialId, externalCalendarId] = rest;
log.debug(
"mockCalendar.createEvent",
JSON.stringify({ calEvent, credentialId, externalCalendarId })
);
createEventCalls.push({
args: {
calEvent,
credentialId,
externalCalendarId,
},
calendarServiceConstructorArgs: {
credential,
},
});
const isGoogleMeetLocation = calEvent?.location === BookingLocations.GoogleMeet;
if (app.type === "google_calendar") {
return Promise.resolve({
type: app.type,
additionalInfo: {
hangoutLink:
normalizedCalendarData.create?.appSpecificData?.googleCalendar?.hangoutLink ||
"https://GOOGLE_MEET_URL_IN_CALENDAR_EVENT",
uid: normalizedCalendarData.create?.uid || "GOOGLE_CALENDAR_EVENT_ID",
id: normalizedCalendarData.create?.id || "GOOGLE_CALENDAR_EVENT_ID",
iCalUID:
normalizedCalendarData.create?.iCalUID || calEvent.iCalUID || "GOOGLE_CALENDAR_EVENT_ID",
password: "MOCK_PASSWORD",
url:
normalizedCalendarData.create?.appSpecificData?.googleCalendar?.hangoutLink ||
"https://GOOGLE_MEET_URL_IN_CALENDAR_EVENT",
});
} else if (app.type === "office365_calendar") {
return Promise.resolve({
type: app.type,
additionalInfo: {},
uid: normalizedCalendarData.create?.uid || "OFFICE_365_CALENDAR_EVENT_ID",
id: normalizedCalendarData.create?.id || "OFFICE_365_CALENDAR_EVENT_ID",
iCalUID:
normalizedCalendarData.create?.iCalUID ||
calEvent.iCalUID ||
"OFFICE_365_CALENDAR_EVENT_ID",
password: "MOCK_PASSWORD",
url:
normalizedCalendarData.create?.appSpecificData?.office365Calendar?.url ||
"https://UNUSED_URL",
});
} else {
return Promise.resolve({
type: app.type,
additionalInfo: {},
uid: "PROBABLY_UNUSED_UID",
hangoutLink:
(isGoogleMeetLocation
? normalizedCalendarData.create?.appSpecificData?.googleCalendar?.hangoutLink
: null) || "https://UNUSED_URL",
// A Calendar is always expected to return an id.
id: normalizedCalendarData.create?.id || "FALLBACK_MOCK_CALENDAR_EVENT_ID",
iCalUID: normalizedCalendarData.create?.iCalUID,
// Password and URL seems useless for CalendarService, plan to remove them if that's the case
password: "MOCK_PASSWORD",
url: "https://UNUSED_URL",
});
}
},
updateEvent: async function (
...rest: Parameters<Calendar["updateEvent"]>
): Promise<NewCalendarEventType> {
if (calendarData?.updationCrash) {
throw new Error("MockCalendarService.updateEvent fake error");
}
const [uid, event, externalCalendarId] = rest;
log.silly("mockCalendar.updateEvent", JSON.stringify({ uid, event, externalCalendarId }));
updateEventCalls.push({
args: {
uid,
event,
externalCalendarId,
},
calendarServiceConstructorArgs: {
credential,
},
hangoutLink:
normalizedCalendarData.create?.appSpecificData?.googleCalendar?.hangoutLink ||
"https://GOOGLE_MEET_URL_IN_CALENDAR_EVENT",
uid: normalizedCalendarData.create?.uid || "GOOGLE_CALENDAR_EVENT_ID",
id: normalizedCalendarData.create?.id || "GOOGLE_CALENDAR_EVENT_ID",
iCalUID:
normalizedCalendarData.create?.iCalUID || calEvent.iCalUID || "GOOGLE_CALENDAR_EVENT_ID",
password: "MOCK_PASSWORD",
url:
normalizedCalendarData.create?.appSpecificData?.googleCalendar?.hangoutLink ||
"https://GOOGLE_MEET_URL_IN_CALENDAR_EVENT",
});
const isGoogleMeetLocation = event.location === BookingLocations.GoogleMeet;
} else if (app.type === "office365_calendar") {
return Promise.resolve({
type: app.type,
additionalInfo: {},
uid: normalizedCalendarData.create?.uid || "OFFICE_365_CALENDAR_EVENT_ID",
id: normalizedCalendarData.create?.id || "OFFICE_365_CALENDAR_EVENT_ID",
iCalUID:
normalizedCalendarData.create?.iCalUID || calEvent.iCalUID || "OFFICE_365_CALENDAR_EVENT_ID",
password: "MOCK_PASSWORD",
url:
normalizedCalendarData.create?.appSpecificData?.office365Calendar?.url ||
"https://UNUSED_URL",
});
} else {
return Promise.resolve({
type: app.type,
additionalInfo: {},
uid: "PROBABLY_UNUSED_UID",
iCalUID: normalizedCalendarData.update?.iCalUID,
id: normalizedCalendarData.update?.uid || "FALLBACK_MOCK_ID",
hangoutLink:
(isGoogleMeetLocation
? normalizedCalendarData.create?.appSpecificData?.googleCalendar?.hangoutLink
: null) || "https://UNUSED_URL",
// A Calendar is always expected to return an id.
id: normalizedCalendarData.create?.id || "FALLBACK_MOCK_CALENDAR_EVENT_ID",
iCalUID: normalizedCalendarData.create?.iCalUID,
// Password and URL seems useless for CalendarService, plan to remove them if that's the case
password: "MOCK_PASSWORD",
url: "https://UNUSED_URL",
location: isGoogleMeetLocation ? "https://UNUSED_URL" : undefined,
hangoutLink:
(isGoogleMeetLocation
? normalizedCalendarData.update?.appSpecificData?.googleCalendar?.hangoutLink
: null) || "https://UNUSED_URL",
conferenceData: isGoogleMeetLocation ? event.conferenceData : undefined,
});
},
deleteEvent: async (...rest: Parameters<Calendar["deleteEvent"]>) => {
log.silly("mockCalendar.deleteEvent", JSON.stringify({ rest }));
deleteEventCalls.push({
args: {
uid: rest[0],
event: rest[1],
externalCalendarId: rest[2],
},
calendarServiceConstructorArgs: {
credential,
},
});
},
getAvailability: async (params: {
dateFrom: string;
dateTo: string;
selectedCalendars: IntegrationCalendar[];
mode: "slots" | "overlay" | "booking";
fallbackToPrimary?: boolean;
}): Promise<EventBusyDate[]> => {
const { dateFrom, dateTo, selectedCalendars, mode } = params;
if (calendarData?.getAvailabilityCrash) {
throw new Error("MockCalendarService.getAvailability fake error");
}
getAvailabilityCalls.push({
args: {
dateFrom,
dateTo,
selectedCalendars,
mode,
},
calendarServiceConstructorArgs: {
credential,
},
});
return new Promise((resolve) => {
resolve(calendarData?.busySlots || []);
});
},
listCalendars: async function (): Promise<IntegrationCalendar[]> {
return Promise.resolve([]);
},
} as Calendar;
}
);
}
},
updateEvent: async (...rest: Parameters<Calendar["updateEvent"]>): Promise<NewCalendarEventType> => {
if (calendarData?.updationCrash) {
throw new Error("MockCalendarService.updateEvent fake error");
}
const [uid, event, externalCalendarId] = rest;
log.silly("mockCalendar.updateEvent", JSON.stringify({ uid, event, externalCalendarId }));
updateEventCalls.push({
args: {
uid,
event,
externalCalendarId,
},
calendarServiceConstructorArgs: {
credential,
},
});
const isGoogleMeetLocation = event.location === BookingLocations.GoogleMeet;
return Promise.resolve({
type: app.type,
additionalInfo: {},
uid: "PROBABLY_UNUSED_UID",
iCalUID: normalizedCalendarData.update?.iCalUID,
id: normalizedCalendarData.update?.uid || "FALLBACK_MOCK_ID",
// Password and URL seems useless for CalendarService, plan to remove them if that's the case
password: "MOCK_PASSWORD",
url: "https://UNUSED_URL",
location: isGoogleMeetLocation ? "https://UNUSED_URL" : undefined,
hangoutLink:
(isGoogleMeetLocation
? normalizedCalendarData.update?.appSpecificData?.googleCalendar?.hangoutLink
: null) || "https://UNUSED_URL",
conferenceData: isGoogleMeetLocation ? event.conferenceData : undefined,
});
},
deleteEvent: async (...rest: Parameters<Calendar["deleteEvent"]>) => {
log.silly("mockCalendar.deleteEvent", JSON.stringify({ rest }));
deleteEventCalls.push({
args: {
uid: rest[0],
event: rest[1],
externalCalendarId: rest[2],
},
calendarServiceConstructorArgs: {
credential,
},
});
},
getAvailability: async (params: {
dateFrom: string;
dateTo: string;
selectedCalendars: IntegrationCalendar[];
mode: "slots" | "overlay" | "booking";
fallbackToPrimary?: boolean;
}): Promise<EventBusyDate[]> => {
const { dateFrom, dateTo, selectedCalendars, mode } = params;
if (calendarData?.getAvailabilityCrash) {
throw new Error("MockCalendarService.getAvailability fake error");
}
getAvailabilityCalls.push({
args: {
dateFrom,
dateTo,
selectedCalendars,
mode,
},
calendarServiceConstructorArgs: {
credential,
},
});
return new Promise((resolve) => {
resolve(calendarData?.busySlots || []);
});
},
listCalendars: async (): Promise<IntegrationCalendar[]> => Promise.resolve([]),
} as Calendar;
});
}
return {
@@ -1,5 +1,4 @@
import { createMocks } from "node-mocks-http";
import type { CustomNextApiRequest, CustomNextApiResponse } from "./types";
export function createMockNextJsRequest(...args: Parameters<typeof createMocks>) {
@@ -1,7 +1,5 @@
import prismaMock from "../__mocks__/prisma";
import type { InputEventType, getOrganizer, CalendarServiceMethodMock } from "./bookingScenario";
import type { CalendarServiceMethodMock, getOrganizer, InputEventType } from "./bookingScenario";
import { parse } from "node-html-parser";
import type { VEvent } from "node-ical";
import ical from "node-ical";
@@ -9,22 +7,20 @@ import { expect, vi } from "vitest";
import "vitest-fetch-mock";
import dayjs from "@calcom/dayjs";
import type { Tracking } from "../types";
import { WEBSITE_URL } from "@calcom/lib/constants";
import logger from "@calcom/lib/logger";
import { safeStringify } from "@calcom/lib/safeStringify";
import type {
WebhookTriggerEvents,
Booking,
BookingReference,
DestinationCalendar,
WebhookTriggerEvents,
} from "@calcom/prisma/client";
import { BookingStatus } from "@calcom/prisma/enums";
import type { AppsStatus } from "@calcom/types/Calendar";
import type { CalendarEvent } from "@calcom/types/Calendar";
import type { AppsStatus, CalendarEvent } from "@calcom/types/Calendar";
import type { CredentialForCalendarService } from "@calcom/types/Credential";
import type { Fixtures } from "../fixtures/fixtures";
import type { Tracking } from "../types";
import { DEFAULT_TIMEZONE_BOOKER } from "./getMockRequestDataForBooking";
// This is too complex at the moment, I really need to simplify this.
@@ -123,10 +119,9 @@ expect.extend({
let isToAddressExpected = true;
const isIcsFilenameExpected = expectedEmail.ics ? ics?.filename === expectedEmail.ics.filename : true;
const isIcsUIDExpected =
expectedEmail.ics && expectedEmail.ics.iCalUID
? !!(icsObject ? icsObject[expectedEmail.ics.iCalUID] : null)
: true;
const isIcsUIDExpected = expectedEmail.ics?.iCalUID
? !!(icsObject ? icsObject[expectedEmail.ics.iCalUID] : null)
: true;
const emailDom = parse(testEmail.html);
const actualEmailContent = {
@@ -1242,7 +1237,7 @@ export function expectSuccessfulCalendarEventCreationInCalendar(
| ExpectedForSuccessfulCalendarEventCreationInCalendar
| ExpectedForSuccessfulCalendarEventCreationInCalendar[]
) {
const expecteds = expected instanceof Array ? expected : [expected];
const expecteds = Array.isArray(expected) ? expected : [expected];
expect(calendarMock.createEventCalls.length).toBe(expecteds.length);
for (let i = 0; i < calendarMock.createEventCalls.length; i++) {
@@ -1,8 +1,7 @@
import { getDate } from "./bookingScenario";
import type { Tracking } from "../types";
import type { SchedulingType } from "@calcom/prisma/client";
import type { CreationSource } from "@calcom/prisma/enums";
import type { Tracking } from "../types";
export const DEFAULT_TIMEZONE_BOOKER = "Asia/Kolkata";
export function getBasicMockRequestDataForBooking() {
@@ -1,6 +1,5 @@
import type z from "zod";
import type { bookingCancelSchema } from "@calcom/prisma/zod-utils";
import type z from "zod";
export function getMockRequestDataForCancelBooking(data: z.infer<typeof bookingCancelSchema>) {
return data;
@@ -1,45 +1,43 @@
import { IdentityProvider, UserPermissionRole } 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",
export const getSampleUserInSession = () => ({
locale: "",
avatar: "",
organization: {
isOrgAdmin: false,
metadata: null,
role: UserPermissionRole.USER,
disableImpersonation: false,
organizationId: null,
theme: "",
appTheme: "",
createdDate: new Date(),
trialEndsAt: new Date(),
completedOnboarding: false,
allowSEOIndexing: false,
receiveMonthlyDigestEmail: false,
};
};
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,
});
@@ -1,6 +1,6 @@
import { enableEmailFeature, mockNoTranslations } from "./bookingScenario";
import { beforeEach, afterEach } from "vitest";
import process from "node:process";
import { afterEach, beforeEach } from "vitest";
export function setupAndTeardown() {
beforeEach(() => {
@@ -1,8 +1,7 @@
import { createOrganization } from "./bookingScenario";
import { WEBSITE_URL } from "@calcom/lib/constants";
import { test } from "../fixtures/fixtures";
import type { Fixtures } from "../fixtures/fixtures";
import { test } from "../fixtures/fixtures";
type OrgContext = {
org: {
@@ -1,8 +1,8 @@
// my-test.ts
import { test as base } from "vitest";
import { getTestEmails } from "@calcom/lib/testEmails";
import { getTestSMS } from "@calcom/lib/testSMS";
import { test as base } from "vitest";
export interface Fixtures {
emails: ReturnType<typeof getEmailsFixture>;
+3 -5
View File
@@ -1,10 +1,10 @@
import process from "node:process";
import type { CalendarService } from "@calcom/types/Calendar";
import matchers from "@testing-library/jest-dom/matchers";
import ResizeObserver from "resize-observer-polyfill";
import { vi, expect } from "vitest";
import { expect, vi } from "vitest";
import createFetchMock from "vitest-fetch-mock";
import type { CalendarService } from "@calcom/types/Calendar";
global.ResizeObserver = ResizeObserver;
if (typeof window !== "undefined") {
@@ -32,7 +32,6 @@ fetchMocker.enableMocks();
expect.extend(matchers);
class MockExchangeCalendarService implements CalendarService {
constructor() {}
async createEvent() {
return {
uid: "mock",
@@ -181,7 +180,6 @@ vi.mock("@calcom/app-store/payment.services.generated", () => ({
}));
class MockCrmService {
constructor() {}
async createEvent() {
return [];
}