fix: Fix React cal api namespaced usage (#15834)

* fix: Fix React cal api namespaced usage

* Update e2e
This commit is contained in:
Hariom Balhara
2024-07-22 12:01:05 +02:00
committed by GitHub
parent c870df7027
commit 35110892c1
5 changed files with 66 additions and 14 deletions
@@ -424,6 +424,10 @@ async function expectValidHtmlEmbedSnippet(
expect(embedCode).toContain(orgSlug);
}
// Html/VanillaJS embed needs namespace to call an instruction
// Verify Cal.ns.abc("ui") or Cal.ns["abc"]("ui")
expect(embedCode).toMatch(/.*Cal\.ns[^(]+\("ui/);
const dom = parse(embedCode);
const scripts = dom.getElementsByTagName("script");
assertThatCodeIsValidVanillaJsCode(scripts[0].innerText);
@@ -492,6 +496,8 @@ async function expectValidReactEmbedSnippet(
expect(embedCode).toContain(
embedType === "floating-popup" ? "floatingButton" : embedType === "inline" ? `<Cal` : "data-cal-link"
);
// React embed doesn't need to access .ns to call an instruction
expect(embedCode).toContain('cal("ui"');
if (orgSlug) {
expect(embedCode).toContain(orgSlug);
}
+7 -4
View File
@@ -2,7 +2,7 @@ import { WEBSITE_URL, IS_SELF_HOSTED, WEBAPP_URL } from "@calcom/lib/constants";
import type { PreviewState } from "../types";
import { embedLibUrl } from "./constants";
import { getApiName } from "./getApiName";
import { getApiNameForReactSnippet, getApiNameForVanillaJsSnippet } from "./getApiName";
import { getDimension } from "./getDimension";
export const doWeNeedCalOriginProp = (embedCalOrigin: string) => {
@@ -67,7 +67,7 @@ export const Codes = {
useEffect(()=>{
(async function () {
const cal = await getCalApi(${argumentForGetCalApi ? JSON.stringify(argumentForGetCalApi) : ""});
${getApiName({ namespace, mainApiName: "cal" })}("floatingButton", ${floatingButtonArg});
${getApiNameForReactSnippet({ mainApiName: "cal" })}("floatingButton", ${floatingButtonArg});
${uiInstructionCode}
})();
}, [])
@@ -119,7 +119,7 @@ export const Codes = {
previewState: PreviewState;
namespace: string;
}) => {
return code`${getApiName({ namespace })}("inline", {
return code`${getApiNameForVanillaJsSnippet({ namespace, mainApiName: "Cal" })}("inline", {
elementOrSelector:"#my-cal-inline",
calLink: "${calLink}",
layout: "${previewState.layout}"
@@ -137,7 +137,10 @@ export const Codes = {
uiInstructionCode: string;
namespace: string;
}) => {
return code`${getApiName({ namespace, mainApiName: "Cal" })}("floatingButton", ${floatingButtonArg});
return code`${getApiNameForVanillaJsSnippet({
namespace,
mainApiName: "Cal",
})}("floatingButton", ${floatingButtonArg});
${uiInstructionCode}`;
},
"element-click": ({
+3 -3
View File
@@ -10,7 +10,7 @@ import { TextArea } from "@calcom/ui";
import type { EmbedFramework, EmbedType, PreviewState } from "../types";
import { Codes, doWeNeedCalOriginProp } from "./EmbedCodes";
import { embedLibUrl, EMBED_PREVIEW_HTML_URL } from "./constants";
import { getApiName } from "./getApiName";
import { getApiNameForReactSnippet, getApiNameForVanillaJsSnippet } from "./getApiName";
import { getDimension } from "./getDimension";
import { useEmbedCalOrigin } from "./hooks";
@@ -181,7 +181,7 @@ const getEmbedTypeSpecificString = ({
};
if (embedFramework === "react") {
uiInstructionStringArg = {
apiName: getApiName({ namespace, mainApiName: "cal" }),
apiName: getApiNameForReactSnippet({ mainApiName: "cal" }),
theme: previewState.theme,
brandColor: previewState.palette.brandColor,
hideEventTypeDetails: previewState.hideEventTypeDetails,
@@ -189,7 +189,7 @@ const getEmbedTypeSpecificString = ({
};
} else {
uiInstructionStringArg = {
apiName: getApiName({ namespace, mainApiName: "Cal" }),
apiName: getApiNameForVanillaJsSnippet({ namespace, mainApiName: "Cal" }),
theme: previewState.theme,
brandColor: previewState.palette.brandColor,
hideEventTypeDetails: previewState.hideEventTypeDetails,
@@ -0,0 +1,28 @@
import { describe, it, expect } from "vitest";
import { getApiNameWithNamespace } from "./getApiName";
describe("getApiNameWithNamespace", () => {
describe("when namespace is a valid variable", () => {
it("should return the correct API name with namespace for a non-hyphenated namespace", () => {
const result = getApiNameWithNamespace({ namespace: "first", mainApiName: "cal" });
expect(result).toBe("cal.ns.first");
});
it("should return the correct API name with namespace for a$b", () => {
const result = getApiNameWithNamespace({ namespace: "a$b", mainApiName: "cal" });
expect(result).toBe("cal.ns.a$b");
});
});
describe("when namespace is not a valid variable", () => {
it("should return the correct API name with namespace for a hyphenated namespace", () => {
const result = getApiNameWithNamespace({ namespace: "first-one", mainApiName: "cal" });
expect(result).toBe('cal.ns["first-one"]');
});
it("should return the correct API name with namespace for a&n", () => {
const result = getApiNameWithNamespace({ namespace: "a&n", mainApiName: "cal" });
expect(result).toBe('cal.ns["a&n"]');
});
});
});
+22 -7
View File
@@ -1,14 +1,29 @@
export function getApiName({
export function getApiNameWithNamespace({
namespace,
mainApiName = "Cal",
mainApiName,
}: {
namespace: string | null;
mainApiName?: string;
namespace: string;
mainApiName: string;
}) {
if (!namespace) {
return mainApiName;
}
const isAValidVariableName = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(namespace);
// Try to use dot notation if possible because it's more readable otherwise use bracket notation
return isAValidVariableName ? `${mainApiName}.ns.${namespace}` : `${mainApiName}.ns["${namespace}"]`;
}
function getApiNameWithoutNamespace({ mainApiName }: { mainApiName: string }) {
return mainApiName;
}
export function getApiNameForReactSnippet({ mainApiName }: { mainApiName: string }) {
return getApiNameWithoutNamespace({ mainApiName });
}
export function getApiNameForVanillaJsSnippet({
namespace,
mainApiName,
}: {
namespace: string;
mainApiName: string;
}) {
return getApiNameWithNamespace({ mainApiName, namespace });
}