Merge branch 'main' into feat/organizations
This commit is contained in:
commit
ac67e358e4
|
@ -25,7 +25,9 @@ jobs:
|
|||
- uses: ./.github/actions/cache-db
|
||||
- uses: ./.github/actions/cache-build
|
||||
- name: Run Tests
|
||||
run: yarn test-e2e:embed-react
|
||||
run: |
|
||||
yarn test-e2e:embed-react
|
||||
yarn workspace @calcom/embed-react packaged:tests
|
||||
env:
|
||||
DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }}
|
||||
- name: Upload Test Results
|
||||
|
|
|
@ -33,7 +33,7 @@ import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/que
|
|||
* type: integer
|
||||
* example: [2, 3, 4]
|
||||
* - in: query
|
||||
* name: attendeeEmails
|
||||
* name: attendeeEmail
|
||||
* required: false
|
||||
* schema:
|
||||
* oneOf:
|
||||
|
|
|
@ -215,6 +215,11 @@ const nextConfig = {
|
|||
destination: "/new-booker/team/:slug/:type",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
{
|
||||
source: "/d/:link/:slug",
|
||||
destination: "/new-booker/d/:link/:slug",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
];
|
||||
},
|
||||
async headers() {
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
import type { GetServerSidePropsContext } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Booker } from "@calcom/atoms";
|
||||
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
||||
import { getBookingByUidOrRescheduleUid } from "@calcom/features/bookings/lib/get-booking";
|
||||
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import type { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
type PageProps = inferSSRProps<typeof getServerSideProps>;
|
||||
|
||||
export default function Type({ slug, user, booking, away, isBrandingHidden }: PageProps) {
|
||||
return (
|
||||
<main className="flex h-full min-h-[100dvh] items-center justify-center">
|
||||
<BookerSeo
|
||||
username={user}
|
||||
eventSlug={slug}
|
||||
rescheduleUid={booking?.uid}
|
||||
hideBranding={isBrandingHidden}
|
||||
/>
|
||||
<Booker
|
||||
username={user}
|
||||
eventSlug={slug}
|
||||
rescheduleBooking={booking}
|
||||
isAway={away}
|
||||
hideBranding={isBrandingHidden}
|
||||
/>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Type.PageWrapper = PageWrapper;
|
||||
|
||||
async function getUserPageProps(context: GetServerSidePropsContext) {
|
||||
const { link, slug } = paramsSchema.parse(context.params);
|
||||
const { rescheduleUid } = context.query;
|
||||
|
||||
const { ssrInit } = await import("@server/lib/ssr");
|
||||
const ssr = await ssrInit(context);
|
||||
|
||||
const hashedLink = await prisma.hashedLink.findUnique({
|
||||
where: {
|
||||
link,
|
||||
},
|
||||
select: {
|
||||
eventTypeId: true,
|
||||
eventType: {
|
||||
select: {
|
||||
users: {
|
||||
select: {
|
||||
username: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const username = hashedLink?.eventType.users[0]?.username;
|
||||
|
||||
if (!hashedLink || !username) {
|
||||
return {
|
||||
notFound: true,
|
||||
};
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: {
|
||||
username,
|
||||
},
|
||||
select: {
|
||||
away: true,
|
||||
hideBranding: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return {
|
||||
notFound: true,
|
||||
};
|
||||
}
|
||||
|
||||
let booking: GetBookingType | null = null;
|
||||
if (rescheduleUid) {
|
||||
booking = await getBookingByUidOrRescheduleUid(`${rescheduleUid}`);
|
||||
}
|
||||
|
||||
// We use this to both prefetch the query on the server,
|
||||
// as well as to check if the event exist, so we c an show a 404 otherwise.
|
||||
const eventData = await ssr.viewer.public.event.fetch({ username, eventSlug: slug });
|
||||
|
||||
if (!eventData) {
|
||||
return {
|
||||
notFound: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
booking,
|
||||
away: user?.away,
|
||||
user: username,
|
||||
slug,
|
||||
trpcState: ssr.dehydrate(),
|
||||
isBrandingHidden: user?.hideBranding,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const paramsSchema = z.object({ link: z.string(), slug: z.string() });
|
||||
|
||||
// Booker page fetches a tiny bit of data server side, to determine early
|
||||
// whether the page should show an away state or dynamic booking not allowed.
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
return await getUserPageProps(context);
|
||||
};
|
|
@ -1821,5 +1821,18 @@
|
|||
"pop_up_element_click": "ينبثق عبر النقر على العنصر",
|
||||
"open_dialog_with_element_click": "افتح مربع الحوار الخاص بك عندما ينقر شخص على عنصر ما.",
|
||||
"need_help_embedding": "بحاجة إلى مساعدة؟ راجع أدلتنا لإدراج Cal على Wix، Squarespace، أو WordPress، تحقق من أسئلتنا المشتركة، أو استكشف خيارات متقدمة متضمنة.",
|
||||
"book_my_cal": "ثبّت الحجز في رزنامتي"
|
||||
"book_my_cal": "ثبّت الحجز في رزنامتي",
|
||||
"invite_as": "دعوة باسم",
|
||||
"form_updated_successfully": "تم تحديث الاستمارة بنجاح.",
|
||||
"email_not_cal_member_cta": "انضم إلى فريقك",
|
||||
"disable_attendees_confirmation_emails": "تعطيل رسائل التأكيد الافتراضية للحضور",
|
||||
"disable_attendees_confirmation_emails_description": "يوجد مسار عمل واحد على الأقل نشط في هذا النوع من الأحداث يقوم بإرسال رسائل إلكترونية إلى الحاضرين عند حجز الحدث.",
|
||||
"disable_host_confirmation_emails": "تعطيل رسائل التأكيد الافتراضية لمضيف",
|
||||
"disable_host_confirmation_emails_description": "يوجد مسار عمل واحد على الأقل نشط في هذا النوع من الأحداث يقوم بإرسال رسائل إلكترونية إلى المضيف عند حجز الحدث.",
|
||||
"add_an_override": "إضافة تجاوز",
|
||||
"import_from_google_workspace": "استيراد المستخدمين من مساحة عمل Google",
|
||||
"connect_google_workspace": "ربط مساحة عمل Google",
|
||||
"google_workspace_admin_tooltip": "يجب أن تكون مشرفًا على مساحة العمل لاستخدام هذه الميزة",
|
||||
"first_event_type_webhook_description": "قم بإنشاء أول شبكة ويب هوك لهذا النوع من الفعاليات",
|
||||
"create_for": "إنشاء من أجل"
|
||||
}
|
||||
|
|
|
@ -1325,7 +1325,7 @@
|
|||
"exchange_version_2013_SP1": "2013 SP1",
|
||||
"exchange_version_2015": "2015",
|
||||
"exchange_version_2016": "2016",
|
||||
"routing_forms_description": "作成したすべてのフォームとルートをここで確認できます",
|
||||
"routing_forms_description": "出席者を正しい目的地に案内するためのフォームを作成します。",
|
||||
"routing_forms_send_email_owner": "所有者にメールを送信",
|
||||
"routing_forms_send_email_owner_description": "フォームの送信時に所有者にメールを送信します",
|
||||
"add_new_form": "新しいフォームを追加",
|
||||
|
|
|
@ -1749,7 +1749,7 @@
|
|||
"locked_webhooks_description": "Üyeler aktif web kancalarını görebilir, ancak hiçbir web kancası ayarını düzenleyemez",
|
||||
"locked_workflows_description": "Üyeler aktif iş akışlarını görebilir, ancak hiçbir iş akışı ayarını düzenleyemez",
|
||||
"locked_by_admin": "Ekip yöneticisi tarafından kilitlendi",
|
||||
"app_not_connected": "Bir {{appName}} hesabı bağlamadınız.",
|
||||
"app_not_connected": "{{appName}} hesabı bağlamadınız.",
|
||||
"connect_now": "Hemen bağlan",
|
||||
"managed_event_dialog_confirm_button_one": "{{count}} üyeyi değiştirin ve bilgilendirin",
|
||||
"managed_event_dialog_confirm_button_other": "{{count}} üyeyi değiştirin ve bilgilendirin",
|
||||
|
@ -1757,7 +1757,7 @@
|
|||
"managed_event_dialog_title_other": "URL /{{slug}}, {{count}} üye için zaten mevcut. Bunu değiştirmek istiyor musunuz?",
|
||||
"managed_event_dialog_information_one": "<strong>{{names}}</strong> zaten <strong>/{{slug}}</strong> URL'sini kullanıyor.",
|
||||
"managed_event_dialog_information_other": "<strong>{{names}}</strong> zaten <strong>/{{slug}}</strong> URL'sini kullanıyor.",
|
||||
"managed_event_dialog_clarification": "Değiştirmeyi seçmeniz durumunda kullanıcıları bilgilendireceğiz. Üzerine yazmak istemiyorsanız geri dönerek onları kaldırın.",
|
||||
"managed_event_dialog_clarification": "Değiştirmeyi seçmeniz durumunda onları bilgilendiririz. Üzerine yazmak istemiyorsanız geri dönerek onları kaldırın.",
|
||||
"review_event_type": "Etkinlik Türünü inceleyin",
|
||||
"looking_for_more_analytics": "Daha fazla analiz mi arıyorsunuz?",
|
||||
"looking_for_more_insights": "Daha fazla Insights mı arıyorsunuz?",
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
"app-store": "yarn app-store-cli cli",
|
||||
"create-app": "yarn app-store create",
|
||||
"edit-app": "yarn app-store edit",
|
||||
"publish-embed": "yarn workspaces foreach --from=\"@calcom/embed*\" npm publish --access=public",
|
||||
"withEmbedPublishEnv": "NEXT_PUBLIC_EMBED_LIB_URL='https://app.cal.com/embed/embed.js' NEXT_PUBLIC_WEBAPP_URL='https://app.cal.com' yarn",
|
||||
"publish-embed": "yarn withEmbedPublishEnv workspace @calcom/embed-core build && yarn withEmbedPublishEnv workspace @calcom/embed-snippet build && yarn workspaces foreach --from=\"@calcom/embed*\" npm publish --access=public",
|
||||
"delete-app": "yarn app-store delete",
|
||||
"create-app-template": "yarn app-store create-template",
|
||||
"edit-app-template": "yarn app-store edit-template",
|
||||
|
@ -93,7 +94,7 @@
|
|||
"city-timezones": "^1.2.1",
|
||||
"eslint": "^8.34.0",
|
||||
"lucide-react": "^0.171.0",
|
||||
"turbo": "^1.8.3"
|
||||
"turbo": "^1.10.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"@apidevtools/json-schema-ref-parser": "9.0.9",
|
||||
|
|
|
@ -39,7 +39,8 @@ async function* getResponses(
|
|||
if (value instanceof Array) {
|
||||
serializedValue = value.map((val) => escapeCsvText(val)).join(" | ");
|
||||
} else {
|
||||
serializedValue = escapeCsvText(value);
|
||||
// value can be a number as well for type Number field
|
||||
serializedValue = escapeCsvText(String(value));
|
||||
}
|
||||
csvCells.push(serializedValue);
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@ import type { Dispatch, SetStateAction } from "react";
|
|||
import getFieldIdentifier from "../lib/getFieldIdentifier";
|
||||
import { getQueryBuilderConfig } from "../lib/getQueryBuilderConfig";
|
||||
import isRouterLinkedField from "../lib/isRouterLinkedField";
|
||||
import transformResponse from "../lib/transformResponse";
|
||||
import type { SerializableForm, Response } from "../types/types";
|
||||
|
||||
type Props = {
|
||||
|
@ -54,14 +55,14 @@ export default function FormInputFields(props: Props) {
|
|||
required={!!field.required}
|
||||
listValues={options}
|
||||
data-testid={`form-field-${getFieldIdentifier(field)}`}
|
||||
setValue={(value) => {
|
||||
setValue={(value: number | string | string[]) => {
|
||||
setResponse((response) => {
|
||||
response = response || {};
|
||||
return {
|
||||
...response,
|
||||
[field.id]: {
|
||||
label: field.label,
|
||||
value,
|
||||
value: transformResponse({ field, value }),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
@ -43,6 +43,22 @@ const OPERATOR_MAP = {
|
|||
operator: "NOT.equals",
|
||||
secondaryOperand: "",
|
||||
},
|
||||
">": {
|
||||
operator: "gt",
|
||||
secondaryOperand: null,
|
||||
},
|
||||
">=": {
|
||||
operator: "gte",
|
||||
secondaryOperand: null,
|
||||
},
|
||||
"<": {
|
||||
operator: "lt",
|
||||
secondaryOperand: null,
|
||||
},
|
||||
"<=": {
|
||||
operator: "lte",
|
||||
secondaryOperand: null,
|
||||
},
|
||||
all: {
|
||||
operator: "array_contains",
|
||||
secondaryOperand: null,
|
||||
|
@ -58,6 +74,7 @@ const GROUP_OPERATOR_MAP = {
|
|||
"!": "NOT",
|
||||
} as const;
|
||||
|
||||
const NumberOperators = [">", ">=", "<", "<="];
|
||||
const convertSingleQueryToPrismaWhereClause = (
|
||||
operatorName: keyof typeof OPERATOR_MAP,
|
||||
logicData: LogicData,
|
||||
|
@ -71,13 +88,56 @@ const convertSingleQueryToPrismaWhereClause = (
|
|||
logicData[operatorName] instanceof Array ? logicData[operatorName] : [logicData[operatorName]];
|
||||
|
||||
const mainOperand = operatorName !== "in" ? operands[0].var : operands[1].var;
|
||||
|
||||
let secondaryOperand = staticSecondaryOperand || (operatorName !== "in" ? operands[1] : operands[0]) || "";
|
||||
if (operatorName === "all") {
|
||||
secondaryOperand = secondaryOperand.in[1];
|
||||
}
|
||||
const prismaWhere = {
|
||||
response: { path: [mainOperand, "value"], [`${prismaOperator}`]: secondaryOperand },
|
||||
};
|
||||
|
||||
const isNumberOperator = NumberOperators.includes(operatorName);
|
||||
const secondaryOperandAsNumber = typeof secondaryOperand === "string" ? Number(secondaryOperand) : null;
|
||||
|
||||
let prismaWhere;
|
||||
if (secondaryOperandAsNumber) {
|
||||
// We know that it's number operator so Prisma should query number
|
||||
// Note that if we get string values in DB(e.g. '100'), those values can't be filtered with number operators.
|
||||
if (isNumberOperator) {
|
||||
prismaWhere = {
|
||||
response: {
|
||||
path: [mainOperand, "value"],
|
||||
[`${prismaOperator}`]: secondaryOperandAsNumber,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
// We know that it's not number operator but the input field might have been a number and thus stored value in DB as number.
|
||||
// Also, even for input type=number we might accidentally get string value(e.g. '100'). So, let reporting do it's best job with both number and string.
|
||||
prismaWhere = {
|
||||
OR: [
|
||||
{
|
||||
response: {
|
||||
path: [mainOperand, "value"],
|
||||
// Query as string e.g. equals '100'
|
||||
[`${prismaOperator}`]: secondaryOperand,
|
||||
},
|
||||
},
|
||||
{
|
||||
response: {
|
||||
path: [mainOperand, "value"],
|
||||
// Query as number e.g. equals 100
|
||||
[`${prismaOperator}`]: secondaryOperandAsNumber,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
} else {
|
||||
prismaWhere = {
|
||||
response: {
|
||||
path: [mainOperand, "value"],
|
||||
[`${prismaOperator}`]: secondaryOperand,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (isNegation) {
|
||||
return {
|
||||
|
|
|
@ -50,8 +50,14 @@ export function getQueryBuilderConfig(form: RoutingForm, forReporting = false) {
|
|||
|
||||
const initialConfigCopy = { ...InitialConfig, operators: { ...InitialConfig.operators } };
|
||||
if (forReporting) {
|
||||
// Empty and Not empty doesn't work well with JSON querying in prisma. Try to implement these when we desperately need these operators.
|
||||
delete initialConfigCopy.operators.is_empty;
|
||||
delete initialConfigCopy.operators.is_not_empty;
|
||||
|
||||
// Between and Not between aren't directly supported by prisma. So, we need to update jsonLogicToPrisma to generate gte and lte query for between. It can be implemented later.
|
||||
delete initialConfigCopy.operators.between;
|
||||
delete initialConfigCopy.operators.not_between;
|
||||
|
||||
initialConfigCopy.operators.__calReporting = true;
|
||||
}
|
||||
// You need to provide your own config. See below 'Config format'
|
||||
|
|
|
@ -50,13 +50,13 @@ export function processRoute({
|
|||
const jsonLogicQuery = QbUtils.jsonLogicFormat(state.tree, state.config);
|
||||
const logic = jsonLogicQuery.logic;
|
||||
let result = false;
|
||||
const responseValues: Record<string, string | string[]> = {};
|
||||
const responseValues: Record<string, Response[string]["value"]> = {};
|
||||
for (const [uuid, { value }] of Object.entries(response)) {
|
||||
responseValues[uuid] = value;
|
||||
}
|
||||
|
||||
if (logic) {
|
||||
// Leave the logs for easy debugging of routing form logic test.
|
||||
// Leave the logs for debugging of routing form logic test in production
|
||||
console.log("Checking logic with response", logic, responseValues);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
result = jsonLogic.apply(logic as any, responseValues);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import type { Field, Response } from "../types/types";
|
||||
|
||||
export default function transformResponse({
|
||||
field,
|
||||
value,
|
||||
}: {
|
||||
field: Field;
|
||||
value: Response[string]["value"];
|
||||
}) {
|
||||
// type="number" still gives value as a string but we need to store that as number so that number operators can work.
|
||||
return field.type === "number" && typeof value === "string" ? Number(value) : value;
|
||||
}
|
|
@ -7,6 +7,7 @@ import type { inferSSRProps } from "@calcom/types/inferSSRProps";
|
|||
import getFieldIdentifier from "../../lib/getFieldIdentifier";
|
||||
import { getSerializableForm } from "../../lib/getSerializableForm";
|
||||
import { processRoute } from "../../lib/processRoute";
|
||||
import transformResponse from "../../lib/transformResponse";
|
||||
import type { Response } from "../../types/types";
|
||||
|
||||
export default function Router({ form, message }: inferSSRProps<typeof getServerSideProps>) {
|
||||
|
@ -60,12 +61,11 @@ export const getServerSideProps = async function getServerSideProps(
|
|||
|
||||
const response: Record<string, Pick<Response[string], "value">> = {};
|
||||
serializableForm.fields?.forEach((field) => {
|
||||
const rawFieldResponse = fieldsResponses[getFieldIdentifier(field)] || "";
|
||||
console.log(field);
|
||||
const fieldResponse =
|
||||
field.type === "multiselect" ? rawFieldResponse.split(",").map((r) => r.trim()) : rawFieldResponse;
|
||||
const fieldResponse = fieldsResponses[getFieldIdentifier(field)] || "";
|
||||
const value =
|
||||
field.type === "multiselect" ? fieldResponse.split(",").map((r) => r.trim()) : fieldResponse;
|
||||
response[field.id] = {
|
||||
value: fieldResponse,
|
||||
value: transformResponse({ field, value }),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -187,8 +187,10 @@ function getUrlSearchParamsToForward(response: Response, fields: NonNullable<Pro
|
|||
// If for some reason, the field isn't there, let's just
|
||||
return;
|
||||
}
|
||||
const valueAsStringOrStringArray =
|
||||
typeof fieldResponse.value === "number" ? String(fieldResponse.value) : fieldResponse.value;
|
||||
paramsFromResponse[getFieldIdentifier(foundField) as keyof typeof paramsFromResponse] =
|
||||
fieldResponse.value;
|
||||
valueAsStringOrStringArray;
|
||||
});
|
||||
|
||||
// Build query params from current URL. It excludes route params
|
||||
|
|
|
@ -6,89 +6,229 @@ afterEach(() => {
|
|||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
describe("jsonLogicToPrisma - Single Query", () => {
|
||||
it("should support Short 'Equals' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: { and: [{ "==": [{ var: "505d3c3c-aa71-4220-93a9-6fd1e1087939" }, "A"] }] },
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
response: {
|
||||
path: ["505d3c3c-aa71-4220-93a9-6fd1e1087939", "value"],
|
||||
equals: "A",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should support Short 'Not Equals' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: { and: [{ "!=": [{ var: "505d3c3c-aa71-4220-93a9-6fd1e1087939" }, "abc"] }] },
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
NOT: {
|
||||
describe("jsonLogicToPrisma(Reporting)", () => {
|
||||
describe("Text Operand", () => {
|
||||
it("should support 'Equals' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: { and: [{ "==": [{ var: "505d3c3c-aa71-4220-93a9-6fd1e1087939" }, "A"] }] },
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
response: {
|
||||
path: ["505d3c3c-aa71-4220-93a9-6fd1e1087939", "value"],
|
||||
equals: "abc",
|
||||
equals: "A",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should support Short 'Contains' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: { and: [{ in: ["A", { var: "505d3c3c-aa71-4220-93a9-6fd1e1087939" }] }] },
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
response: {
|
||||
path: ["505d3c3c-aa71-4220-93a9-6fd1e1087939", "value"],
|
||||
string_contains: "A",
|
||||
it("should support 'Not Equals' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: { and: [{ "!=": [{ var: "505d3c3c-aa71-4220-93a9-6fd1e1087939" }, "abc"] }] },
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
NOT: {
|
||||
response: {
|
||||
path: ["505d3c3c-aa71-4220-93a9-6fd1e1087939", "value"],
|
||||
equals: "abc",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should support Short 'Not Contains' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: { and: [{ "!": { in: ["a", { var: "505d3c3c-aa71-4220-93a9-6fd1e1087939" }] } }] },
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
NOT: {
|
||||
it("should support 'Contains' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: { and: [{ in: ["A", { var: "505d3c3c-aa71-4220-93a9-6fd1e1087939" }] }] },
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
response: {
|
||||
path: ["505d3c3c-aa71-4220-93a9-6fd1e1087939", "value"],
|
||||
string_contains: "a",
|
||||
string_contains: "A",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should support 'Not Contains' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: { and: [{ "!": { in: ["a", { var: "505d3c3c-aa71-4220-93a9-6fd1e1087939" }] } }] },
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
NOT: {
|
||||
response: {
|
||||
path: ["505d3c3c-aa71-4220-93a9-6fd1e1087939", "value"],
|
||||
string_contains: "a",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
describe("Number Type", () => {
|
||||
it("should support 'greater than' operator", () => {
|
||||
let prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
and: [
|
||||
{
|
||||
">": [
|
||||
{
|
||||
var: "a0d113a8-8e40-49b7-87b1-7f4ab57d226f",
|
||||
},
|
||||
// Giving a string here to test that it is converted to a number
|
||||
"100",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [{ response: { path: ["a0d113a8-8e40-49b7-87b1-7f4ab57d226f", "value"], gt: 100 } }],
|
||||
});
|
||||
|
||||
prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
and: [
|
||||
{
|
||||
">": [
|
||||
{
|
||||
var: "a0d113a8-8e40-49b7-87b1-7f4ab57d226f",
|
||||
},
|
||||
// A number would also work
|
||||
100,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [{ response: { path: ["a0d113a8-8e40-49b7-87b1-7f4ab57d226f", "value"], gt: 100 } }],
|
||||
});
|
||||
});
|
||||
it("should support 'greater than or equal to' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
and: [
|
||||
{
|
||||
">=": [
|
||||
{
|
||||
var: "a0d113a8-8e40-49b7-87b1-7f4ab57d226f",
|
||||
},
|
||||
// Giving a string here to test that it is converted to a number
|
||||
"100",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [{ response: { path: ["a0d113a8-8e40-49b7-87b1-7f4ab57d226f", "value"], gte: 100 } }],
|
||||
});
|
||||
});
|
||||
it("should support 'less than' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
and: [
|
||||
{
|
||||
"<": [
|
||||
{
|
||||
var: "a0d113a8-8e40-49b7-87b1-7f4ab57d226f",
|
||||
},
|
||||
// Giving a string here to test that it is converted to a number
|
||||
"100",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [{ response: { path: ["a0d113a8-8e40-49b7-87b1-7f4ab57d226f", "value"], lt: 100 } }],
|
||||
});
|
||||
});
|
||||
it("should support 'less than or equal to' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
and: [
|
||||
{
|
||||
"<=": [
|
||||
{
|
||||
var: "a0d113a8-8e40-49b7-87b1-7f4ab57d226f",
|
||||
},
|
||||
// Giving a string here to test that it is converted to a number
|
||||
"100",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [{ response: { path: ["a0d113a8-8e40-49b7-87b1-7f4ab57d226f", "value"], lte: 100 } }],
|
||||
});
|
||||
});
|
||||
it("'Equals' operator should query with string as well as number", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: { and: [{ "==": [{ var: "505d3c3c-aa71-4220-93a9-6fd1e1087939" }, "1"] }] },
|
||||
});
|
||||
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
OR: [
|
||||
{
|
||||
response: {
|
||||
path: ["505d3c3c-aa71-4220-93a9-6fd1e1087939", "value"],
|
||||
equals: "1",
|
||||
},
|
||||
},
|
||||
{
|
||||
response: {
|
||||
path: ["505d3c3c-aa71-4220-93a9-6fd1e1087939", "value"],
|
||||
equals: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should support 'MultiSelect' 'Equals' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
and: [{ all: [{ var: "267c7817-81a5-4bef-9d5b-d0faa4cd0d71" }, { in: [{ var: "" }, ["C", "D"]] }] }],
|
||||
},
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{ response: { path: ["267c7817-81a5-4bef-9d5b-d0faa4cd0d71", "value"], array_contains: ["C", "D"] } },
|
||||
],
|
||||
describe("MultiSelect", () => {
|
||||
it("should support 'Equals' operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
and: [
|
||||
{ all: [{ var: "267c7817-81a5-4bef-9d5b-d0faa4cd0d71" }, { in: [{ var: "" }, ["C", "D"]] }] },
|
||||
],
|
||||
},
|
||||
});
|
||||
expect(prismaWhere).toEqual({
|
||||
AND: [
|
||||
{
|
||||
response: { path: ["267c7817-81a5-4bef-9d5b-d0faa4cd0d71", "value"], array_contains: ["C", "D"] },
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("jsonLogicToPrisma - Single Query", () => {
|
||||
|
||||
it("should support where All Match ['Equals', 'Equals'] operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
|
@ -116,6 +256,7 @@ describe("jsonLogicToPrisma - Single Query", () => {
|
|||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should support where Any Match ['Equals', 'Equals'] operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
|
@ -143,6 +284,7 @@ describe("jsonLogicToPrisma - Single Query", () => {
|
|||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should support where None Match ['Equals', 'Equals'] operator", () => {
|
||||
const prismaWhere = jsonLogicToPrisma({
|
||||
logic: {
|
||||
|
|
|
@ -52,9 +52,9 @@ export const reportHandler = async ({ ctx: { prisma }, input }: ReportHandlerOpt
|
|||
});
|
||||
const fields = serializedForm?.fields || [];
|
||||
const headers = fields.map((f) => f.label + (f.deleted ? "(Deleted)" : ""));
|
||||
const responses: string[][] = [];
|
||||
const responses: (string | number)[][] = [];
|
||||
rows.forEach((r) => {
|
||||
const rowResponses: string[] = [];
|
||||
const rowResponses: (string | number)[] = [];
|
||||
responses.push(rowResponses);
|
||||
fields.forEach((field) => {
|
||||
if (!r.response) {
|
||||
|
@ -62,13 +62,13 @@ export const reportHandler = async ({ ctx: { prisma }, input }: ReportHandlerOpt
|
|||
}
|
||||
const response = r.response as Response;
|
||||
const value = response[field.id]?.value || "";
|
||||
let stringValue = "";
|
||||
let transformedValue;
|
||||
if (value instanceof Array) {
|
||||
stringValue = value.join(", ");
|
||||
transformedValue = value.join(", ");
|
||||
} else {
|
||||
stringValue = value;
|
||||
transformedValue = value;
|
||||
}
|
||||
rowResponses.push(stringValue);
|
||||
rowResponses.push(transformedValue);
|
||||
});
|
||||
});
|
||||
const areThereNoResultsOrLessThanAskedFor = !rows.length || rows.length < take;
|
||||
|
|
|
@ -6,7 +6,7 @@ export const ZResponseInputSchema = z.object({
|
|||
response: z.record(
|
||||
z.object({
|
||||
label: z.string(),
|
||||
value: z.union([z.string(), z.array(z.string())]),
|
||||
value: z.union([z.string(), z.number(), z.array(z.string())]),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ export type Response = Record<
|
|||
// Field ID
|
||||
string,
|
||||
{
|
||||
value: string | string[];
|
||||
value: number | string | string[];
|
||||
label: string;
|
||||
}
|
||||
>;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"embed-web-start": "yarn workspace @calcom/web start",
|
||||
"__build": "yarn tailwind && vite build && tsc --emitDeclarationOnly --declarationDir dist && cp -r ../../../apps/web/public/embed ./dist/",
|
||||
"__dev": "yarn tailwind && vite build --mode development",
|
||||
"build": "NEXT_PUBLIC_EMBED_FINGER_PRINT=$(git rev-parse --short HEAD) yarn __build",
|
||||
"build": "rm -rf dist && NEXT_PUBLIC_EMBED_FINGER_PRINT=$(git rev-parse --short HEAD) yarn __build",
|
||||
"build-preview": "PREVIEW_BUILD=1 yarn __build ",
|
||||
"vite": "vite",
|
||||
"tailwind": "yarn tailwindcss -i ./src/styles.css -o ./src/tailwind.generated.css",
|
||||
|
@ -29,7 +29,8 @@
|
|||
"embed-tests": "yarn playwright test --config=playwright/config/playwright.config.ts",
|
||||
"embed-tests-quick": "QUICK=true yarn embed-tests",
|
||||
"embed-tests-update-snapshots:ci": "yarn embed-tests-quick --update-snapshots",
|
||||
"prepack": "NEXT_PUBLIC_WEBAPP_URL='https://app.cal.com' yarn build",
|
||||
"withEmbedPublishEnv": "NEXT_PUBLIC_EMBED_LIB_URL='https://app.cal.com/embed/embed.js' NEXT_PUBLIC_WEBAPP_URL='https://app.cal.com' yarn",
|
||||
"prepack": "yarn withEmbedPublishEnv build",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf ../../../apps/web/public/embed"
|
||||
},
|
||||
"files": [
|
||||
|
|
|
@ -131,9 +131,9 @@ export async function bookFirstEvent(username: string, frame: Frame, page: Page)
|
|||
return booking;
|
||||
}
|
||||
|
||||
export async function rescheduleEvent(username, frame, page) {
|
||||
export async function rescheduleEvent(username: string, frame: Frame, page: Page) {
|
||||
await selectFirstAvailableTimeSlotNextMonth(frame, page);
|
||||
await frame.waitForURL((url) => {
|
||||
await frame.waitForURL((url: { pathname: string | string[] }) => {
|
||||
return url.pathname.includes(`/${username}/book`);
|
||||
});
|
||||
// --- fill form
|
||||
|
|
|
@ -125,7 +125,7 @@ type SingleInstruction = SingleInstructionMap[keyof SingleInstructionMap];
|
|||
export type Instruction = SingleInstruction | SingleInstruction[];
|
||||
export type InstructionQueue = Instruction[];
|
||||
|
||||
type PrefillAndIframeAttrsConfig = Record<string, string | string[] | Record<string, string>> & {
|
||||
export type PrefillAndIframeAttrsConfig = Record<string, string | string[] | Record<string, string>> & {
|
||||
iframeAttrs?: Record<string, string> & {
|
||||
id?: string;
|
||||
};
|
||||
|
@ -551,7 +551,13 @@ class CalApi {
|
|||
this.cal.actionManager.on(action, callback);
|
||||
}
|
||||
|
||||
off({ action, callback }: { action: never; callback: never }) {
|
||||
off<T extends keyof EventDataMap>({
|
||||
action,
|
||||
callback,
|
||||
}: {
|
||||
action: T;
|
||||
callback: (arg0: CustomEvent<EventData<T>>) => void;
|
||||
}) {
|
||||
this.cal.actionManager.off(action, callback);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,16 +3,19 @@ import { useEffect } from "react";
|
|||
import { useState } from "react";
|
||||
import ReactDom from "react-dom";
|
||||
|
||||
// Because we don't import from @calcom/embed-react, this file isn't able to test if the build is successful or not and thus npm package would work or not correctly.
|
||||
// There are tests in test/built which verifiy that the types from built package are correctly generated and exported correctly.
|
||||
import Cal, { getCalApi } from "./src/index";
|
||||
|
||||
const api = getCalApi();
|
||||
|
||||
function App() {
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const [, setLoaded] = useState(false);
|
||||
useEffect(() => {
|
||||
// Simulate state change causing config object to change, causing rerender of Cal
|
||||
setTimeout(setLoaded.bind(true), 1000);
|
||||
const callback = (event) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const callback = (event: any) => {
|
||||
console.log(event.detail);
|
||||
};
|
||||
api.then((api) => {
|
||||
|
|
|
@ -11,16 +11,17 @@
|
|||
},
|
||||
"scripts": {
|
||||
"dev": "vite --port=3101 --open",
|
||||
"build": "vite build && tsc --emitDeclarationOnly --declarationDir dist",
|
||||
"build": "rm -rf dist && vite build && tsc --emitDeclarationOnly --declarationDir dist",
|
||||
"preview": "vite preview",
|
||||
"prepare": "NEXT_PUBLIC_EMBED_LIB_URL='https://app.cal.com/embed/embed.js' NEXT_PUBLIC_WEBAPP_URL='https://app.cal.com' yarn build",
|
||||
"type-check": "tsc --pretty --noEmit",
|
||||
"type-check:ci": "tsc-absolute --pretty --noEmit",
|
||||
"lint": "eslint --ext .ts,.js,.tsx,.jsx ./src",
|
||||
"embed-tests": "yarn playwright test --config=./playwright/config/playwright.config.ts",
|
||||
"embed-tests-quick": "QUICK=true yarn embed-tests",
|
||||
"embed-tests-update-snapshots:ci": "yarn embed-tests-quick --update-snapshots",
|
||||
"prepack": "NEXT_PUBLIC_EMBED_LIB_URL='https://app.cal.com/embed/embed.js' NEXT_PUBLIC_WEBAPP_URL='https://app.cal.com' yarn build",
|
||||
"packaged:tests": "cd test/packaged && yarn tsc --noEmit && yarn run -T test -- --packaged-embed-tests-only",
|
||||
"withEmbedPublishEnv": "NEXT_PUBLIC_EMBED_LIB_URL='https://app.cal.com/embed/embed.js' NEXT_PUBLIC_WEBAPP_URL='https://app.cal.com' yarn",
|
||||
"prepack": "yarn withEmbedPublishEnv build && yarn packaged:tests",
|
||||
"embed-web-start": "yarn workspace @calcom/web start",
|
||||
"embed-dev": "yarn workspace @calcom/embed-react dev",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
||||
|
|
|
@ -3,16 +3,22 @@ import { expect } from "@playwright/test";
|
|||
import { getEmbedIframe } from "@calcom/embed-core/playwright/lib/testUtils";
|
||||
import { test } from "@calcom/web/playwright/lib/fixtures";
|
||||
|
||||
test("Inline Usage Snapshot", async ({ page, getActionFiredDetails, addEmbedListeners }) => {
|
||||
//TODO: Do it with page.goto automatically
|
||||
await addEmbedListeners("");
|
||||
await page.goto("/");
|
||||
const embedIframe = await getEmbedIframe({ page, pathname: "/pro" });
|
||||
expect(embedIframe).toBeEmbedCalLink("", getActionFiredDetails, {
|
||||
pathname: "/pro",
|
||||
searchParams: {
|
||||
theme: "dark",
|
||||
},
|
||||
test.describe("Inline Embed", () => {
|
||||
test("should verify that the iframe got created with correct URL", async ({
|
||||
page,
|
||||
getActionFiredDetails,
|
||||
addEmbedListeners,
|
||||
}) => {
|
||||
//TODO: Do it with page.goto automatically
|
||||
await addEmbedListeners("");
|
||||
await page.goto("/");
|
||||
const embedIframe = await getEmbedIframe({ page, pathname: "/pro" });
|
||||
expect(embedIframe).toBeEmbedCalLink("", getActionFiredDetails, {
|
||||
pathname: "/pro",
|
||||
searchParams: {
|
||||
theme: "dark",
|
||||
},
|
||||
});
|
||||
// expect(await page.screenshot()).toMatchSnapshot("react-component-inline.png");
|
||||
});
|
||||
// expect(await page.screenshot()).toMatchSnapshot("react-component-inline.png");
|
||||
});
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
import type { PrefillAndIframeAttrsConfig } from "@calcom/embed-core";
|
||||
|
||||
import useEmbed from "./useEmbed";
|
||||
|
||||
type CalProps = {
|
||||
|
@ -11,7 +13,7 @@ type CalProps = {
|
|||
debug?: boolean;
|
||||
uiDebug?: boolean;
|
||||
};
|
||||
config?: Record<string, string>;
|
||||
config?: PrefillAndIframeAttrsConfig;
|
||||
embedJsUrl?: string;
|
||||
} & React.HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# Packaged
|
||||
|
||||
The tests in this file are run on the packaged code that is published to npm. The packaged code is different from the source code in atleast the following ways
|
||||
- Not all files go to packaged code.If package.json -> files field is specified then only the files that are specified there would be published. So, one might accidentally miss an important file that's available otherwise.
|
||||
- The packaged code doesn't have .ts files. Those files are actually converted to .js files and .d.ts files are generated separately for TypeScript support. It allows the package to work in both TypeScript and non TypeScript environments.
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* This file tests two things in 2 ways
|
||||
* - It is a vitest test file and thus it tests if the code executes without any error. Thus, it tests that package.json->main/module fields are correctly defined. It obviously verifies the assertions as well.
|
||||
* - It is also validates for it's types and thus verifies that @calcom/embed-react has correctly specified it's types in package.json->types field.
|
||||
*/
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
// This import may show up as an error in your IDE, but it's fine because typings are available only after embed-react is built.
|
||||
import { getCalApi } from "@calcom/embed-react";
|
||||
|
||||
const api = getCalApi();
|
||||
|
||||
test("Check that the API is available", () => {
|
||||
expect(api).toBeDefined()
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "@calcom/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"target": "ES2015",
|
||||
"moduleResolution": "Node",
|
||||
"baseUrl": ".",
|
||||
"declaration": true,
|
||||
"jsx": "preserve",
|
||||
"outDir": "dist",
|
||||
},
|
||||
"include": ["**/*.ts"],
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
"@calcom/embed-snippet": ["../embed-snippet/src"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "env.d.ts"],
|
||||
"exclude": ["dist", "build", "node_modules", "test-cal.tsx"]
|
||||
"include": ["**/*.ts","**/*.tsx", "env.d.ts"],
|
||||
// Exclude "test" because that has `api.test.ts` which imports @calcom/embed-react which needs it to be built using this tsconfig.json first. Excluding it here prevents type-check from validating test folder
|
||||
"exclude": ["node_modules", "test"]
|
||||
}
|
||||
|
|
|
@ -12,11 +12,12 @@
|
|||
"directory": "packages/embeds/embed-snippet"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build && tsc --emitDeclarationOnly --declarationDir dist",
|
||||
"build": "rm -rf dist && vite build && tsc --emitDeclarationOnly --declarationDir dist",
|
||||
"type-check": "tsc --pretty --noEmit",
|
||||
"type-check:ci": "tsc-absolute --pretty --noEmit",
|
||||
"lint": "eslint --ext .ts,.js src",
|
||||
"prepack": "NEXT_PUBLIC_EMBED_LIB_URL='https://app.cal.com/embed/embed.js' NEXT_PUBLIC_WEBAPP_URL='https://app.cal.com' yarn build",
|
||||
"withEmbedPublishEnv": "NEXT_PUBLIC_EMBED_LIB_URL='https://app.cal.com/embed/embed.js' NEXT_PUBLIC_WEBAPP_URL='https://app.cal.com' yarn",
|
||||
"prepack": "yarn withEmbedPublishEnv build",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
||||
},
|
||||
"files": [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { GetServerSidePropsContext, GetServerSidePropsResult } from "next";
|
||||
import { CalendsoSessionUser } from "next-auth";
|
||||
import type { GetServerSidePropsContext, GetServerSidePropsResult } from "next";
|
||||
import type { CalendsoSessionUser } from "next-auth";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import type prisma from "@calcom/prisma";
|
||||
|
||||
import type { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ const config: PlaywrightTestConfig = {
|
|||
{
|
||||
name: "@calcom/embed-core",
|
||||
testDir: "./packages/embeds/embed-core/",
|
||||
testMatch: /.*\.(e2e|test)\.tsx?/,
|
||||
testMatch: /.*\.e2e\.tsx?/,
|
||||
expect: {
|
||||
timeout: DEFAULT_EXPECT_TIMEOUT,
|
||||
},
|
||||
|
@ -116,7 +116,7 @@ const config: PlaywrightTestConfig = {
|
|||
expect: {
|
||||
timeout: DEFAULT_EXPECT_TIMEOUT,
|
||||
},
|
||||
testMatch: /.*\.(e2e|test)\.tsx?/,
|
||||
testMatch: /.*\.e2e\.tsx?/,
|
||||
use: { ...devices["Desktop Chrome"], baseURL: "http://localhost:3101/" },
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,20 +1,32 @@
|
|||
import { defineWorkspace } from "vitest/config";
|
||||
|
||||
const packagedEmbedTestsOnly = process.argv.includes("--packaged-embed-tests-only");
|
||||
// defineWorkspace provides a nice type hinting DX
|
||||
export default defineWorkspace([
|
||||
{
|
||||
test: {
|
||||
include: ["packages/**/*.{test,spec}.{ts,js}", "apps/**/*.{test,spec}.{ts,js}"],
|
||||
// TODO: Ignore the api until tests are fixed
|
||||
exclude: ["apps/api/**/*", "**/node_modules/**/*"],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: "@calcom/closecom",
|
||||
include: ["packages/app-store/closecom/**/*.{test,spec}.{ts,js}"],
|
||||
environment: "jsdom",
|
||||
setupFiles: ["packages/app-store/closecom/test/globals.ts"],
|
||||
},
|
||||
},
|
||||
]);
|
||||
const workspaces = packagedEmbedTestsOnly
|
||||
? [
|
||||
{
|
||||
test: {
|
||||
include: ["packages/embeds/**/*.{test,spec}.{ts,js}"],
|
||||
environment: "jsdom",
|
||||
},
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
test: {
|
||||
include: ["packages/**/*.{test,spec}.{ts,js}", "apps/**/*.{test,spec}.{ts,js}"],
|
||||
// TODO: Ignore the api until tests are fixed
|
||||
exclude: ["apps/api/**/*", "**/node_modules/**/*", "packages/embeds/**/*"],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: {
|
||||
name: "@calcom/closecom",
|
||||
include: ["packages/app-store/closecom/**/*.{test,spec}.{ts,js}"],
|
||||
environment: "jsdom",
|
||||
setupFiles: ["packages/app-store/closecom/test/globals.ts"],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default defineWorkspace(workspaces);
|
||||
|
|
81
yarn.lock
81
yarn.lock
|
@ -5088,7 +5088,7 @@ __metadata:
|
|||
next: ~13.2.1
|
||||
next-auth: ^4.20.1
|
||||
next-i18next: ^11.3.0
|
||||
playwright: ^1.31.2
|
||||
playwright-core: ^1.34.3
|
||||
postcss: ^8.4.18
|
||||
prism-react-renderer: ^1.3.5
|
||||
react: ^18.2.0
|
||||
|
@ -16833,7 +16833,7 @@ __metadata:
|
|||
lucide-react: ^0.171.0
|
||||
prettier: ^2.8.6
|
||||
tsc-absolute: ^1.0.0
|
||||
turbo: ^1.8.3
|
||||
turbo: ^1.10.1
|
||||
typescript: ^4.9.4
|
||||
vitest: ^0.31.1
|
||||
vitest-mock-extended: ^1.1.3
|
||||
|
@ -30849,23 +30849,12 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright-core@npm:1.33.0":
|
||||
version: 1.33.0
|
||||
resolution: "playwright-core@npm:1.33.0"
|
||||
"playwright-core@npm:^1.34.3":
|
||||
version: 1.34.3
|
||||
resolution: "playwright-core@npm:1.34.3"
|
||||
bin:
|
||||
playwright: cli.js
|
||||
checksum: 5fb7bda06a8b73b56b85b5a0b8f711211dde57a375d9379289e22239b2de879c6d93c8fdc9ba44b932bf100914ab1ca1a55697ad88440fdd0a39101fc020b77f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright@npm:^1.31.2":
|
||||
version: 1.33.0
|
||||
resolution: "playwright@npm:1.33.0"
|
||||
dependencies:
|
||||
playwright-core: 1.33.0
|
||||
bin:
|
||||
playwright: cli.js
|
||||
checksum: fb3934c56ed749cf412ea35b82052f013872d7f7b7747ab7042580af473dfc1b038956a31c132ee8c0098f74150c75e2073e9c737fd4c1ed54700a23fffc079f
|
||||
playwright-core: cli.js
|
||||
checksum: eaf9e9b2d77b9726867dcbc641a1c72b0e8f680cdd71ff904366deea1c96141ff7563f6c6fb29f9975309d1b87dead97ea93f6f44953b59946882fb785b34867
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -37147,58 +37136,58 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"turbo-darwin-64@npm:1.8.3":
|
||||
version: 1.8.3
|
||||
resolution: "turbo-darwin-64@npm:1.8.3"
|
||||
"turbo-darwin-64@npm:1.10.1":
|
||||
version: 1.10.1
|
||||
resolution: "turbo-darwin-64@npm:1.10.1"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"turbo-darwin-arm64@npm:1.8.3":
|
||||
version: 1.8.3
|
||||
resolution: "turbo-darwin-arm64@npm:1.8.3"
|
||||
"turbo-darwin-arm64@npm:1.10.1":
|
||||
version: 1.10.1
|
||||
resolution: "turbo-darwin-arm64@npm:1.10.1"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"turbo-linux-64@npm:1.8.3":
|
||||
version: 1.8.3
|
||||
resolution: "turbo-linux-64@npm:1.8.3"
|
||||
"turbo-linux-64@npm:1.10.1":
|
||||
version: 1.10.1
|
||||
resolution: "turbo-linux-64@npm:1.10.1"
|
||||
conditions: os=linux & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"turbo-linux-arm64@npm:1.8.3":
|
||||
version: 1.8.3
|
||||
resolution: "turbo-linux-arm64@npm:1.8.3"
|
||||
"turbo-linux-arm64@npm:1.10.1":
|
||||
version: 1.10.1
|
||||
resolution: "turbo-linux-arm64@npm:1.10.1"
|
||||
conditions: os=linux & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"turbo-windows-64@npm:1.8.3":
|
||||
version: 1.8.3
|
||||
resolution: "turbo-windows-64@npm:1.8.3"
|
||||
"turbo-windows-64@npm:1.10.1":
|
||||
version: 1.10.1
|
||||
resolution: "turbo-windows-64@npm:1.10.1"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"turbo-windows-arm64@npm:1.8.3":
|
||||
version: 1.8.3
|
||||
resolution: "turbo-windows-arm64@npm:1.8.3"
|
||||
"turbo-windows-arm64@npm:1.10.1":
|
||||
version: 1.10.1
|
||||
resolution: "turbo-windows-arm64@npm:1.10.1"
|
||||
conditions: os=win32 & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"turbo@npm:^1.8.3":
|
||||
version: 1.8.3
|
||||
resolution: "turbo@npm:1.8.3"
|
||||
"turbo@npm:^1.10.1":
|
||||
version: 1.10.1
|
||||
resolution: "turbo@npm:1.10.1"
|
||||
dependencies:
|
||||
turbo-darwin-64: 1.8.3
|
||||
turbo-darwin-arm64: 1.8.3
|
||||
turbo-linux-64: 1.8.3
|
||||
turbo-linux-arm64: 1.8.3
|
||||
turbo-windows-64: 1.8.3
|
||||
turbo-windows-arm64: 1.8.3
|
||||
turbo-darwin-64: 1.10.1
|
||||
turbo-darwin-arm64: 1.10.1
|
||||
turbo-linux-64: 1.10.1
|
||||
turbo-linux-arm64: 1.10.1
|
||||
turbo-windows-64: 1.10.1
|
||||
turbo-windows-arm64: 1.10.1
|
||||
dependenciesMeta:
|
||||
turbo-darwin-64:
|
||||
optional: true
|
||||
|
@ -37214,7 +37203,7 @@ __metadata:
|
|||
optional: true
|
||||
bin:
|
||||
turbo: bin/turbo
|
||||
checksum: 4a07d120ef8adf6c8e58a48abd02e075ffa215287cc6c3ef843d4fb08aeb0a566fe810ec9bfc376254468a2aa4f29bae154a60804a83af78dfa86d0e8e995476
|
||||
checksum: 3551c57be67e833583de549d74d5ec991e0f1e38047e25600b8acc085a1a8a4007992259a015eb9f2c0abd68156545800bd34e7b5ad337d1998b32461952d3fb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user