fix: Fix React cal api namespaced usage (#15834)
* fix: Fix React cal api namespaced usage * Update e2e
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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": ({
|
||||
|
||||
@@ -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"]');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user