import { ensureNextjsGlobalCssFileImports, formatScript, mkFixImportContext, replaceImports, tsxToJsx, } from "../utils/code-utils"; import { readFileText } from "../utils/file-utils"; describe("code-utils", function () { it("typescript to javascript should work", async function () { const code = ` // This is a skeleton starter React component generated by Plasmic. // @jsx helper import React, { ReactNode } from "react"; import { PlasmicCodeSandboxDialogContent__RenderHelper, PlasmicCodeSandboxDialogContent__VariantsArgs, PlasmicCodeSandboxDialogContent__ArgsType, PlasmicCodeSandboxDialogContent__VariantsType, PlasmicCodeSandboxDialogContent__TriggerStateType } from "./PP__CodeSandboxDialogContent"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/render import Button from "../Button"; // plasmic-import: 4SYnkOQLd5/component import { PlasmicButton__VariantsArgs } from "../../../plasmic/PlasmicButton"; // plasmic-import: 4SYnkOQLd5/renderer import Dropdown from "./Dropdown"; // plasmic-import: a200b79f-288d-4306-be99-e5fd221b8ba6/component import { PlasmicDropdown__VariantsArgs } from "./PP__Dropdown"; // plasmic-import: a200b79f-288d-4306-be99-e5fd221b8ba6/renderer import DropdownItem from "./DropdownItem"; // plasmic-import: f4c2f0bb-8dce-49c7-a106-65abe9e70e51/component import { PlasmicDropdownItem__VariantsArgs } from "./PP__DropdownItem"; // plasmic-import: f4c2f0bb-8dce-49c7-a106-65abe9e70e51/renderer import IconButton from "../../IconButton"; // plasmic-import: cfe92-5RW/component import { PlasmicIconButton__VariantsArgs } from "../../../plasmic/PlasmicIconButton"; // plasmic-import: cfe92-5RW/renderer import { hasVariant, DefaultFlexStack, FlexStack } from "@plasmicapp/react-web"; import { StudioCtx } from "../../../StudioCtx"; import { ensure, asOne, isValidEmail } from "../../../../common"; import { CodeSandboxInfo } from "../../../../shared/db-json-blobs"; import { createSandboxUrl } from "../../../../codesandbox/url"; import { Tooltip } from "antd"; import { observer } from "mobx-react-lite"; interface CodeSandboxDialogContentProps { sc: StudioCtx; onClose: () => void; // Required className prop is used for positioning this component className?: string; } function _CodeSandboxDialogContent(props: CodeSandboxDialogContentProps) { const sc = props.sc; const [inviting, setInviting] = React.useState(false); const [submitting, setSubmitting] = React.useState(false); const [email, setEmail] = React.useState(""); const [sandboxInfo, setSandboxInfo] = React.useState< CodeSandboxInfo | undefined >(asOne(sc.siteInfo.codeSandboxInfos)); const [codeScheme, setCodeScheme] = React.useState<"blackbox" | "direct">( sandboxInfo ? sandboxInfo.code.scheme : "blackbox" ); const openSandboxPopup = (sandboxId: string) => { const url = createSandboxUrl({ id: sandboxId }); if (sc.popupCodesandboxWindow && !sc.popupCodesandboxWindow.closed) { sc.popupCodesandboxWindow.location.href = url; sc.popupCodesandboxWindow.focus(); } else { sc.popupCodesandboxWindow = window.open(url); } }; const onCreateOrUpdateSandbox = async () => { setSubmitting(true); const { id } = await sc.appCtx.api.publishCodeSandbox( sc.siteInfo.id, sandboxInfo ? { ...sandboxInfo } : { code: { lang: "ts", scheme: codeScheme } } ); await sc.refreshSiteInfo(); setSubmitting(false); setSandboxInfo((sc.siteInfo.codeSandboxInfos || []).find(x => x.id === id)); openSandboxPopup(id); }; const onInvite = () => { setInviting(true); sc.appCtx.api .shareCodeSandbox(sc.siteInfo.id, ensure(sandboxInfo).id, email) .then(() => { setInviting(false); }); setEmail(""); }; const onSwitchCodeScheme = (scheme: "blackbox" | "direct") => { setCodeScheme(scheme); setSandboxInfo( (sc.siteInfo.codeSandboxInfos || []).find(x => x.code.scheme === scheme) ); }; const onDeleteSandbox = async () => { setSubmitting(true); await sc.appCtx.api.detachCodeSandbox( sc.siteInfo.id, ensure(sandboxInfo).id ); await sc.refreshSiteInfo(); setSubmitting(false); setSandboxInfo(undefined); }; const variants: PlasmicCodeSandboxDialogContent__VariantsArgs = { state: inviting ? "inviting" : submitting ? "submitting" : undefined, hasSandbox: !!sandboxInfo ? "yes" : "no", invalidEmail: !isValidEmail(email) ? "yes" : undefined, canEdit: !sc.canEditProject() ? "no" : undefined, scheme: codeScheme === "direct" ? "direct" : "blackbox" }; const args: PlasmicCodeSandboxDialogContent__ArgsType = {}; // The following code block is fully managed by Plasmic. Don't edit - it will // be overwritten after every "plasmic sync". // plasmic-managed-start const rh = new PlasmicCodeSandboxDialogContent__RenderHelper( variants, args, props.className ); // plasmic-managed-end // plasmic-managed-jsx/5487 return (
CodeSandbox
{rh.showOpenButton() && ( )}
Code scheme
onSwitchCodeScheme("blackbox")} /> onSwitchCodeScheme("direct")} /> } />
{rh.childStrH1u3gI8vG()}
{rh.showCreateHint() && (
{rh.showCreateHint2() && (
{rh.childStrCreateHint2()}
)}
)} {rh.showCreateButton() && ( )} {rh.showUpdateHint() && (
{rh.childStrCreateHint22()}
)} {rh.showNmdHeAjEx() && ( setEmail(e.target.value)} value={email} />
{rh.show$kdxH_yN6() && (
{rh.showUpdateButton() && ( )} {rh.showDeleteButton() && ( )}
)} )}
); } export const CodeSandboxDialogContent = observer( _CodeSandboxDialogContent as React.FunctionComponent< CodeSandboxDialogContentProps > );`; expect((await formatScript(tsxToJsx(code))).trim()).toEqual( ` // This is a skeleton starter React component generated by Plasmic. // @jsx helper import React from "react"; import { PlasmicCodeSandboxDialogContent__RenderHelper } from "./PP__CodeSandboxDialogContent"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/render import Button from "../Button"; // plasmic-import: 4SYnkOQLd5/component import Dropdown from "./Dropdown"; // plasmic-import: a200b79f-288d-4306-be99-e5fd221b8ba6/component import DropdownItem from "./DropdownItem"; // plasmic-import: f4c2f0bb-8dce-49c7-a106-65abe9e70e51/component import IconButton from "../../IconButton"; // plasmic-import: cfe92-5RW/component import { DefaultFlexStack } from "@plasmicapp/react-web"; import { ensure, asOne, isValidEmail } from "../../../../common"; import { createSandboxUrl } from "../../../../codesandbox/url"; import { Tooltip } from "antd"; import { observer } from "mobx-react-lite"; function _CodeSandboxDialogContent(props) { const sc = props.sc; const [inviting, setInviting] = React.useState(false); const [submitting, setSubmitting] = React.useState(false); const [email, setEmail] = React.useState(""); const [sandboxInfo, setSandboxInfo] = React.useState( asOne(sc.siteInfo.codeSandboxInfos) ); const [codeScheme, setCodeScheme] = React.useState( sandboxInfo ? sandboxInfo.code.scheme : "blackbox" ); const openSandboxPopup = (sandboxId) => { const url = createSandboxUrl({ id: sandboxId }); if (sc.popupCodesandboxWindow && !sc.popupCodesandboxWindow.closed) { sc.popupCodesandboxWindow.location.href = url; sc.popupCodesandboxWindow.focus(); } else { sc.popupCodesandboxWindow = window.open(url); } }; const onCreateOrUpdateSandbox = async () => { setSubmitting(true); const { id } = await sc.appCtx.api.publishCodeSandbox( sc.siteInfo.id, sandboxInfo ? { ...sandboxInfo } : { code: { lang: "ts", scheme: codeScheme } } ); await sc.refreshSiteInfo(); setSubmitting(false); setSandboxInfo( (sc.siteInfo.codeSandboxInfos || []).find((x) => x.id === id) ); openSandboxPopup(id); }; const onInvite = () => { setInviting(true); sc.appCtx.api .shareCodeSandbox(sc.siteInfo.id, ensure(sandboxInfo).id, email) .then(() => { setInviting(false); }); setEmail(""); }; const onSwitchCodeScheme = (scheme) => { setCodeScheme(scheme); setSandboxInfo( (sc.siteInfo.codeSandboxInfos || []).find((x) => x.code.scheme === scheme) ); }; const onDeleteSandbox = async () => { setSubmitting(true); await sc.appCtx.api.detachCodeSandbox( sc.siteInfo.id, ensure(sandboxInfo).id ); await sc.refreshSiteInfo(); setSubmitting(false); setSandboxInfo(undefined); }; const variants = { state: inviting ? "inviting" : submitting ? "submitting" : undefined, hasSandbox: !!sandboxInfo ? "yes" : "no", invalidEmail: !isValidEmail(email) ? "yes" : undefined, canEdit: !sc.canEditProject() ? "no" : undefined, scheme: codeScheme === "direct" ? "direct" : "blackbox" }; const args = {}; // The following code block is fully managed by Plasmic. Don't edit - it will // be overwritten after every "plasmic sync". // plasmic-managed-start const rh = new PlasmicCodeSandboxDialogContent__RenderHelper( variants, args, props.className ); // plasmic-managed-end // plasmic-managed-jsx/5487 return (
CodeSandbox
{rh.showOpenButton() && ( )}
Code scheme
onSwitchCodeScheme("blackbox")} /> onSwitchCodeScheme("direct")} /> } />
{rh.childStrH1u3gI8vG()}
{rh.showCreateHint() && (
{rh.showCreateHint2() && (
{rh.childStrCreateHint2()}
)}
)} {rh.showCreateButton() && ( )} {rh.showUpdateHint() && (
{rh.childStrCreateHint22()}
)} {rh.showNmdHeAjEx() && ( setEmail(e.target.value)} value={email} />
{rh.show$kdxH_yN6() && (
{rh.showUpdateButton() && ( )} {rh.showDeleteButton() && ( )}
)} )}
); } export const CodeSandboxDialogContent = observer(_CodeSandboxDialogContent); `.trim() ); }); it("fix imports for file should work", async function () { const code = `// This is a skeleton starter React component generated by Plasmic. import React, { ReactNode } from "react"; import { PlasmicCodeSandboxDialogContent__RenderHelper, PlasmicCodeSandboxDialogContent__VariantsArgs, PlasmicCodeSandboxDialogContent__ArgsType, PlasmicCodeSandboxDialogContent__TriggerStateType } from "./PP__CodeSandboxDialogContent"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/render import Button from "./Button"; // plasmic-import: 4SYnkOQLd5/component import CloseIcon from "./PlasmicIcon__Close"; // plasmic-import: rFn9Vj2p9/icon import "@plasmicapp/react-web/lib/plasmic.css"; import "./PP__plasmic__default_style.css"; // plasmic-import: global/defaultcss import "./PP__plasmic_kit.css"; // plasmic-import: aBwbYpvCqht4V3F8CJNJX3/projectcss import "./PP__CodeSandboxDialogContent.css"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/css import { hasVariant, DefaultFlexStack, Stack, PlasmicIcon } from "@plasmicapp/react-web"; import { StudioCtx } from "../../../StudioCtx"; import { observer } from "mobx-react-lite"; function _CodeSandboxDialogContent(props) { return null; } `; const configJson = readFileText( "./testData/fixImports_plasmic.json" ).toString(); const config = JSON.parse(configJson); const context = { config, cliArgs: {}, } as any; const fixImportContext = mkFixImportContext(config); const replaced = await replaceImports( context, code, "/tmp/CodeSandbox.tsx", fixImportContext, false ); const expectedCode = `// This is a skeleton starter React component generated by Plasmic. import React, { ReactNode } from "react"; import { PlasmicCodeSandboxDialogContent__RenderHelper, PlasmicCodeSandboxDialogContent__VariantsArgs, PlasmicCodeSandboxDialogContent__ArgsType, PlasmicCodeSandboxDialogContent__TriggerStateType } from "./newDir/PP__CodeSandboxDialogContent"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/render import Button from "./newDir/Button"; // plasmic-import: 4SYnkOQLd5/component import CloseIcon from "./newDir/PlasmicIcon__Close"; // plasmic-import: rFn9Vj2p9/icon import "@plasmicapp/react-web/lib/plasmic.css"; import "./newDir/PP__plasmic__default_style.css"; // plasmic-import: global/defaultcss import "./newDir/PP__plasmic_kit.css"; // plasmic-import: aBwbYpvCqht4V3F8CJNJX3/projectcss import "./newDir/PP__CodeSandboxDialogContent.css"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/css import { hasVariant, DefaultFlexStack, Stack, PlasmicIcon } from "@plasmicapp/react-web"; import { StudioCtx } from "../../../StudioCtx"; import { observer } from "mobx-react-lite"; function _CodeSandboxDialogContent(props) { return null; } `; expect(replaced).toEqual(expectedCode); }); it("fix imports should remove directives", async function () { const code = `// This is a skeleton starter React component generated by Plasmic. import React, { ReactNode } from "react"; import { PlasmicCodeSandboxDialogContent__RenderHelper, PlasmicCodeSandboxDialogContent__VariantsArgs, PlasmicCodeSandboxDialogContent__ArgsType, PlasmicCodeSandboxDialogContent__TriggerStateType } from "./PP__CodeSandboxDialogContent"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/render import Button from "./Button"; // plasmic-import: 4SYnkOQLd5/component import CloseIcon from "./PlasmicIcon__Close"; // plasmic-import: rFn9Vj2p9/icon import "@plasmicapp/react-web/lib/plasmic.css"; import "./PP__plasmic__default_style.css"; // plasmic-import: global/defaultcss import "./PP__plasmic_kit.css"; // plasmic-import: aBwbYpvCqht4V3F8CJNJX3/projectcss import "./PP__CodeSandboxDialogContent.css"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/css import { hasVariant, DefaultFlexStack, Stack, PlasmicIcon } from "@plasmicapp/react-web"; import { StudioCtx } from "../../../StudioCtx"; import { observer } from "mobx-react-lite"; function _CodeSandboxDialogContent(props) { return null; } `; const configJson = readFileText( "./testData/fixImports_plasmic.json" ).toString(); const config = JSON.parse(configJson); const fixImportContext = mkFixImportContext(config); const context = { config, cliArgs: {}, } as any; const replaced = await replaceImports( context, code, "/tmp/CodeSandbox.tsx", fixImportContext, true ); const expectedCode = `// This is a skeleton starter React component generated by Plasmic. import React, { ReactNode } from "react"; import { PlasmicCodeSandboxDialogContent__RenderHelper, PlasmicCodeSandboxDialogContent__VariantsArgs, PlasmicCodeSandboxDialogContent__ArgsType, PlasmicCodeSandboxDialogContent__TriggerStateType } from "./newDir/PP__CodeSandboxDialogContent"; import Button from "./newDir/Button"; import CloseIcon from "./newDir/PlasmicIcon__Close"; import "@plasmicapp/react-web/lib/plasmic.css"; import "./newDir/PP__plasmic__default_style.css"; import "./newDir/PP__plasmic_kit.css"; import "./newDir/PP__CodeSandboxDialogContent.css"; import { hasVariant, DefaultFlexStack, Stack, PlasmicIcon } from "@plasmicapp/react-web"; import { StudioCtx } from "../../../StudioCtx"; import { observer } from "mobx-react-lite"; function _CodeSandboxDialogContent(props) { return null; } `; expect(replaced).toEqual(expectedCode); }); it("fix imports for file should work when the code has no semicolon", async function () { const code = `// This is a skeleton starter React component generated by Plasmic. import React, { ReactNode } from "react"; import { PlasmicCodeSandboxDialogContent__RenderHelper, PlasmicCodeSandboxDialogContent__VariantsArgs, PlasmicCodeSandboxDialogContent__ArgsType, PlasmicCodeSandboxDialogContent__TriggerStateType } from "./PP__CodeSandboxDialogContent" // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/render import Button from "./Button" // plasmic-import: 4SYnkOQLd5/component import CloseIcon from "./PlasmicIcon__Close" // plasmic-import: rFn9Vj2p9/icon import "@plasmicapp/react-web/lib/plasmic.css" import "./PP__plasmic__default_style.css" // plasmic-import: global/defaultcss import "./PP__plasmic_kit.css" // plasmic-import: aBwbYpvCqht4V3F8CJNJX3/projectcss import "./PP__CodeSandboxDialogContent.css" // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/css import { hasVariant, DefaultFlexStack, Stack, PlasmicIcon } from "@plasmicapp/react-web"; import { StudioCtx } from "../../../StudioCtx" import { observer } from "mobx-react-lite" function _CodeSandboxDialogContent(props) { return null } `; const configJson = readFileText( "./testData/fixImports_plasmic.json" ).toString(); const config = JSON.parse(configJson); const fixImportContext = mkFixImportContext(config); const context = { config, cliArgs: {}, } as any; const replaced = await replaceImports( context, code, "/tmp/CodeSandbox.tsx", fixImportContext, false ); const expectedCode = `// This is a skeleton starter React component generated by Plasmic. import React, { ReactNode } from "react"; import { PlasmicCodeSandboxDialogContent__RenderHelper, PlasmicCodeSandboxDialogContent__VariantsArgs, PlasmicCodeSandboxDialogContent__ArgsType, PlasmicCodeSandboxDialogContent__TriggerStateType } from "./newDir/PP__CodeSandboxDialogContent"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/render import Button from "./newDir/Button"; // plasmic-import: 4SYnkOQLd5/component import CloseIcon from "./newDir/PlasmicIcon__Close"; // plasmic-import: rFn9Vj2p9/icon import "@plasmicapp/react-web/lib/plasmic.css"; import "./newDir/PP__plasmic__default_style.css"; // plasmic-import: global/defaultcss import "./newDir/PP__plasmic_kit.css"; // plasmic-import: aBwbYpvCqht4V3F8CJNJX3/projectcss import "./newDir/PP__CodeSandboxDialogContent.css"; // plasmic-import: f68b061e-0f85-41c1-8707-3ba9f634f1af/css import { hasVariant, DefaultFlexStack, Stack, PlasmicIcon } from "@plasmicapp/react-web"; import { StudioCtx } from "../../../StudioCtx"; import { observer } from "mobx-react-lite"; function _CodeSandboxDialogContent(props) { return null; } `; expect(replaced).toEqual(expectedCode); }); it("Ts to js should not remove unused React", function () { const input = ` /* eslint-disable */ /* tslint:disable */ /* prettier-ignore-start */ /** @jsx createPlasmicElementProxy */ // This class is auto-generated by Plasmic; please do not edit! // Plasmic Project: aBwbYpvCqht4V3F8CJNJX3 // Component: 4SYnkOQLd5 import React, { ReactNode } from "react"; import { hasVariant, createPlasmicElement, RenderOpts, Override, classNames, Flex, RenderFunc, RenderFuncOverrides, wrapWithClassName, Renderer, NodeRenderer, createPlasmicElementProxy, makeFragment, PlasmicIcon, PlasmicSlot, MultiChoiceArg, SingleBooleanChoiceArg, SingleChoiceArg } from "@plasmicapp/react-web"; import "@plasmicapp/react-web/lib/plasmic.css"; import "../plasmic__default_style.css"; // plasmic-import: global/defaultcss import "./plasmic_plasmic_kit.css"; // plasmic-import: aBwbYpvCqht4V3F8CJNJX3/projectcss import "./PlasmicButton.css"; // plasmic-import: 4SYnkOQLd5/css import TrashIcon from "./PlasmicIcon__Trash"; // plasmic-import: wibhDXsBy/icon export type PlasmicButton__VariantsArgs = { type?: SingleChoiceArg< | "primary" | "secondary" | "link" | "backlitError" | "backlitInfo" | "chip" | "toggleOn" | "toggleOff" | "clear" >; size?: SingleChoiceArg<"small" | "stretch" | "wide">; withIcons?: SingleChoiceArg<"startIcon">; disabled?: SingleBooleanChoiceArg<"disabled">; font?: SingleChoiceArg<"bold">; }; export type PlasmicButton__ArgsType = { children?: ReactNode; startIcon?: ReactNode; }; function PlasmicButton(props: {}): ReactNode { return ; } function PlasmicButton2(props: {}): React.ReactNode { return ; } export default PlasmicButton; /* prettier-ignore-end */ `; expect(tsxToJsx(input).trim()).toEqual( ` /* eslint-disable */ /* tslint:disable */ /* prettier-ignore-start */ /** @jsx createPlasmicElementProxy */ // This class is auto-generated by Plasmic; please do not edit! // Plasmic Project: aBwbYpvCqht4V3F8CJNJX3 // Component: 4SYnkOQLd5 import React from "react"; import { createPlasmicElementProxy } from "@plasmicapp/react-web"; import "@plasmicapp/react-web/lib/plasmic.css"; import "../plasmic__default_style.css"; // plasmic-import: global/defaultcss import "./plasmic_plasmic_kit.css"; // plasmic-import: aBwbYpvCqht4V3F8CJNJX3/projectcss import "./PlasmicButton.css"; // plasmic-import: 4SYnkOQLd5/css function PlasmicButton(props) { return ; } function PlasmicButton2(props) { return ; } export default PlasmicButton; /* prettier-ignore-end */`.trim() ); }); describe("ensureNextjsGlobalCssFileImports", () => { const cssImports = [ { projectId: "abc123", importPath: "../components/plasmic/website_starter/plasmic.css", }, ]; it("inserts a marker import when none exists", async () => { const input = `import "@/styles/globals.css"; import { PlasmicRootProvider } from "@plasmicapp/react-web"; export default function MyApp({ Component, pageProps }) { return ; } `; const out = await ensureNextjsGlobalCssFileImports( input, cssImports, "/tmp/_app.tsx" ); expect(out).toContain( `import "../components/plasmic/website_starter/plasmic.css"; // plasmic-import: abc123/projectcss` ); expect(out).toContain(`import "@/styles/globals.css"`); }); it("updates the path of an existing marker import", async () => { const input = `import "../old/path/plasmic.css"; // plasmic-import: abc123/projectcss import { PlasmicRootProvider } from "@plasmicapp/react-web"; export default function MyApp({ Component, pageProps }) { return ; } `; const out = await ensureNextjsGlobalCssFileImports( input, cssImports, "/tmp/_app.tsx" ); expect(out).toContain( `import "../components/plasmic/website_starter/plasmic.css"; // plasmic-import: abc123/projectcss` ); expect(out).not.toContain("../old/path/plasmic.css"); }); it("inserts one marker import per top-level project", async () => { const multi = [ { projectId: "marketing-id", importPath: "../components/plasmic/marketing/plasmic.css", }, { projectId: "dashboard-id", importPath: "../components/plasmic/dashboard/plasmic.css", }, ]; const input = `import "@/styles/globals.css"; import { PlasmicRootProvider } from "@plasmicapp/react-web"; export default function MyApp({ Component, pageProps }) { return ; } `; const out = await ensureNextjsGlobalCssFileImports( input, multi, "/tmp/_app.tsx" ); expect(out).toContain( `import "../components/plasmic/marketing/plasmic.css"; // plasmic-import: marketing-id/projectcss` ); expect(out).toContain( `import "../components/plasmic/dashboard/plasmic.css"; // plasmic-import: dashboard-id/projectcss` ); }); it("is idempotent on repeated runs", async () => { const input = `import "@/styles/globals.css"; import { PlasmicRootProvider } from "@plasmicapp/react-web"; export default function MyApp({ Component, pageProps }) { return ; } `; const first = await ensureNextjsGlobalCssFileImports( input, cssImports, "/tmp/_app.tsx" ); const second = await ensureNextjsGlobalCssFileImports( first, cssImports, "/tmp/_app.tsx" ); expect(second).toEqual(first); }); it("removes unmarked plasmic.css imports and adds marker'd version", async () => { const input = `import "./components/plasmic/website_starter/plasmic.css"; import "@/styles/globals.css"; import { PlasmicRootProvider } from "@plasmicapp/react-web"; export default function MyApp({ Component, pageProps }) { return ; } `; const out = await ensureNextjsGlobalCssFileImports( input, cssImports, "/tmp/_app.tsx" ); // The unmarked import should be removed expect(out).not.toContain( `import "./components/plasmic/website_starter/plasmic.css";` ); // The marker'd import should be added expect(out).toContain( `import "../components/plasmic/website_starter/plasmic.css"; // plasmic-import: abc123/projectcss` ); }); it("computes correct relative paths for import statements", async () => { const input = `import "@/styles/globals.css"; import { PlasmicRootProvider } from "@plasmicapp/react-web"; export default function MyApp({ Component, pageProps }) { return ; } `; const out = await ensureNextjsGlobalCssFileImports( input, cssImports, "/tmp/_app.tsx" ); // Should compute relative path correctly (from parent dir to the CSS file) expect(out).toContain( `import "../components/plasmic/website_starter/plasmic.css"; // plasmic-import: abc123/projectcss` ); expect(out).not.toContain( `import "components/plasmic/website_starter/plasmic.css";` ); expect(out).not.toContain( `import "./components/plasmic/website_starter/plasmic.css";` ); }); }); it("formatJs should not add spaces to comment block", async function () { const input = ` import React, { ReactNode } from "react"; import "@plasmicapp/react-web/lib/plasmic.css"; function PlasmicButton(props: {}): React.ReactNode { return ; } function forNode(name: keyof typeof PlasmicButton) { const x = [1, 2].map(v => v > 1); return null; } export default PlasmicButton; // For debugging /* plasmic-nameInIdToUuid/123 [{"1": 1""}, {"2" : "2}] */ `; expect(await formatScript(input)).toEqual( `import React, { ReactNode } from "react"; import "@plasmicapp/react-web/lib/plasmic.css"; function PlasmicButton(props: {}): React.ReactNode { return ; } function forNode(name: keyof typeof PlasmicButton) { const x = [1, 2].map((v) => v > 1); return null; } export default PlasmicButton; // For debugging /* plasmic-nameInIdToUuid/123 [{"1": 1""}, {"2" : "2}] */ ` ); }); });