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() && (
}
{...rh.propsOpenButton()}
onClick={() => openSandboxPopup(ensure(sandboxInfo).id)}
>
Open in new tab
)}
Code scheme
onSwitchCodeScheme("blackbox")}
/>
onSwitchCodeScheme("direct")}
/>
>
}
/>
{rh.childStrH1u3gI8vG()}
{rh.showCreateHint() && (
{rh.showCreateHint2() && (
{rh.childStrCreateHint2()}
)}
)}
{rh.showCreateButton() && (
}
{...rh.propsCreateButton()}
onClick={onCreateOrUpdateSandbox}
>
{rh.childStrCreateButton()}
)}
{rh.showUpdateHint() && (
{rh.childStrCreateHint22()}
)}
{rh.showNmdHeAjEx() && (
setEmail(e.target.value)}
value={email}
/>
{rh.show$kdxH_yN6() && (
{rh.showUpdateButton() && (
)
}
{...rh.propsUpdateButton()}
onClick={onCreateOrUpdateSandbox}
>
{rh.childStrUpdateButton()}
)}
{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() && (
}
{...rh.propsOpenButton()}
onClick={() => openSandboxPopup(ensure(sandboxInfo).id)}
>
Open in new tab
)}
Code scheme
onSwitchCodeScheme("blackbox")}
/>
onSwitchCodeScheme("direct")}
/>
>
}
/>
{rh.childStrH1u3gI8vG()}
{rh.showCreateHint() && (
{rh.showCreateHint2() && (
{rh.childStrCreateHint2()}
)}
)}
{rh.showCreateButton() && (
}
{...rh.propsCreateButton()}
onClick={onCreateOrUpdateSandbox}
>
{rh.childStrCreateButton()}
)}
{rh.showUpdateHint() && (
{rh.childStrCreateHint22()}
)}
{rh.showNmdHeAjEx() && (
setEmail(e.target.value)}
value={email}
/>
{rh.show$kdxH_yN6() && (
{rh.showUpdateButton() && (
)
}
{...rh.propsUpdateButton()}
onClick={onCreateOrUpdateSandbox}
>
{rh.childStrUpdateButton()}
)}
{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}]
*/
`
);
});
});