snapshot of https://github.com/makeplane/plane.git @ d868349a55de79979eb8b98701bf1702c67ad634 (2026-09-15)
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 16s
CodeQL / Analyze (python) (push) Failing after 3s
i18n sync check / check:sync (push) Failing after 3s
React Doctor / react-doctor (push) Failing after 16s
Branch Build CE / Build-Push Admin Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Admin Manifest (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Web Manifest (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Proxy Manifest (push) Has been cancelled
Branch Build CE / Merge Space Manifest (push) Has been cancelled
Branch Build CE / Prepare AIO Assets (push) Has been cancelled
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Live Collaboration Manifest (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge API Server Manifest (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge AIO Manifest (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:14:58 +05:00
commit 23059a1de3
5252 changed files with 573834 additions and 0 deletions

View File

@@ -0,0 +1,572 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { describe, it, expect } from "vitest";
import { applyTransform } from "@hypermod/utils";
import * as transformer from "../function-declaration";
describe("function-declaration", () => {
it("should convert arrow function components to function declarations", async () => {
const result = await applyTransform(
transformer,
`
import React from "react";
export const MyComponent: React.FC<{}> = () => {
return <div>Hello, world!</div>;
};
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import React from "react";
export function MyComponent() {
return <div>Hello, world!</div>;
}"
`);
});
it("should handle components with props", async () => {
const result = await applyTransform(
transformer,
`
import React from "react";
interface IMyComponentProps {
name: string;
}
export const MyComponent: React.FC<IMyComponentProps> = ({ name }) => {
return <div>Hello, {name}!</div>;
};
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import React from "react";
interface IMyComponentProps {
name: string;
}
export function MyComponent(
{
name
}: IMyComponentProps
) {
return <div>Hello, {name}!</div>;
}"
`);
});
it("should preserve default props", async () => {
const result = await applyTransform(
transformer,
`
import React from "react";
interface IMyComponentProps {
name?: string;
}
export const MyComponent: React.FC<IMyComponentProps> = ({ name = "world" }) => {
return <div>Hello, {name}!</div>;
};
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import React from "react";
interface IMyComponentProps {
name?: string;
}
export function MyComponent(
{
name = "world"
}: IMyComponentProps
) {
return <div>Hello, {name}!</div>;
}"
`);
});
it("should not transform non-component arrow functions", async () => {
const result = await applyTransform(
transformer,
`
const myFunction = () => {
return "hello";
};
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"const myFunction = () => {
return "hello";
};"
`);
});
it("should handle observer-wrapped components", async () => {
const result = await applyTransform(
transformer,
`
import { observer } from "mobx-react";
export const WorkspaceAnalyticsHeader = observer(() => {
return <div>Analytics</div>;
});
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import { observer } from "mobx-react";
export const WorkspaceAnalyticsHeader = observer(function WorkspaceAnalyticsHeader() {
return <div>Analytics</div>;
});"
`);
});
it("should handle inline arrow function components", async () => {
const result = await applyTransform(
transformer,
`
export const StarUsOnGitHubLink = () => {
return <a href="https://github.com">Star us</a>;
};
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"export function StarUsOnGitHubLink() {
return <a href="https://github.com">Star us</a>;
}"
`);
});
it("should handle React.FC type without generics", async () => {
const result = await applyTransform(
transformer,
`
import type { FC } from "react";
export const ProjectAppSidebar: FC = observer(() => {
return <div>Sidebar</div>;
});
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import type { FC } from "react";
export const ProjectAppSidebar = observer(function ProjectAppSidebar() {
return <div>Sidebar</div>;
});"
`);
});
it("should handle inline JSX arrow function", async () => {
const result = await applyTransform(
transformer,
`
export const DateAlert = (props: TDateAlertProps) => <></>;
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"export function DateAlert(props: TDateAlertProps) {
return <></>;
}"
`);
});
it("should handle observer with generic type parameters", async () => {
const result = await applyTransform(
transformer,
`
import { observer } from "mobx-react";
export const InstanceProvider = observer<React.FC<React.PropsWithChildren>>((props) => {
const { children } = props;
return <>{children}</>;
});
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import { observer } from "mobx-react";
export const InstanceProvider = observer(function InstanceProvider(props: React.PropsWithChildren) {
const { children } = props;
return <>{children}</>;
});"
`);
});
it("should not add double semicolons after use client directive", async () => {
const result = await applyTransform(
transformer,
`
"use client";
import { observer } from "mobx-react";
export const MyComponent = observer(() => {
return <div>Hello</div>;
});
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
""use client";
import { observer } from "mobx-react";
export const MyComponent = observer(function MyComponent() {
return <div>Hello</div>;
});"
`);
});
it("should preserve generic type parameters in wrapper functions", async () => {
const result = await applyTransform(
transformer,
`
import React from "react";
export const ScatterChart = React.memo(<K extends string, T extends string>(props: TScatterChartProps<K, T>) => {
return <div>Chart</div>;
});
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import React from "react";
export const ScatterChart = React.memo(
function ScatterChart<K extends string, T extends string>(props: TScatterChartProps<K, T>) {
return <div>Chart</div>;
}
);"
`);
});
it("should preserve generic type parameters on React.forwardRef", async () => {
const result = await applyTransform(
transformer,
`
import React from "react";
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
return <button ref={ref}>Click me</button>;
});
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import React from "react";
const Button = React.forwardRef(
function Button(props: ButtonProps, ref: React.ForwardedRef<HTMLButtonElement>) {
return <button ref={ref}>Click me</button>;
}
);"
`);
});
it("should prefix unused props parameter with underscore", async () => {
const result = await applyTransform(
transformer,
`
import type { TCallbackMentionComponentProps } from "@plane/editor";
export const EditorAdditionalMentionsRoot: React.FC<TCallbackMentionComponentProps> = () => null;
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import type { TCallbackMentionComponentProps } from "@plane/editor";
export function EditorAdditionalMentionsRoot(_props: TCallbackMentionComponentProps) {
return null;
}"
`);
});
it("should add Record<string, unknown> type for React.forwardRef with only element type", async () => {
const result = await applyTransform(
transformer,
`
import { forwardRef } from "react";
const ListLoaderItemRow = forwardRef<HTMLDivElement>((props, ref) => (
<div ref={ref}>Content</div>
));
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import { forwardRef } from "react";
const ListLoaderItemRow = forwardRef(
function ListLoaderItemRow(props: Record<string, unknown>, ref: React.ForwardedRef<HTMLDivElement>) {
return (<div ref={ref}>Content</div>);
}
);"
`);
});
it("should preserve comments in function body", async () => {
const result = await applyTransform(
transformer,
`
export const PreloadResources = () => (
// usePreloadResources();
null
);
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"export function PreloadResources() {
return (
// usePreloadResources();
(null)
);
}"
`);
});
it("should preserve leading comments before export declaration", async () => {
const result = await applyTransform(
transformer,
`
"use client";
// TODO: Check if we need this
// https://nextjs.org/docs/app/api-reference/functions/generate-metadata#link-relpreload
// export const usePreloadResources = () => {
// useEffect(() => {
// const preloadItem = (url: string) => {
// ReactDOM.preload(url, { as: "fetch", crossOrigin: "use-credentials" });
// };
//
// const urls = [
// \`\${process.env.VITE_API_BASE_URL}/api/instances/\`,
// \`\${process.env.VITE_API_BASE_URL}/api/users/me/\`,
// \`\${process.env.VITE_API_BASE_URL}/api/users/me/profile/\`,
// \`\${process.env.VITE_API_BASE_URL}/api/users/me/settings/\`,
// \`\${process.env.VITE_API_BASE_URL}/api/users/me/workspaces/?v=\${Date.now()}\`,
// ];
//
// urls.forEach((url) => preloadItem(url));
// }, []);
// };
export const PreloadResources = () =>
// usePreloadResources();
null;
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
""use client";
// TODO: Check if we need this
// https://nextjs.org/docs/app/api-reference/functions/generate-metadata#link-relpreload
// export const usePreloadResources = () => {
// useEffect(() => {
// const preloadItem = (url: string) => {
// ReactDOM.preload(url, { as: "fetch", crossOrigin: "use-credentials" });
// };
//
// const urls = [
// \`\${process.env.VITE_API_BASE_URL}/api/instances/\`,
// \`\${process.env.VITE_API_BASE_URL}/api/users/me/\`,
// \`\${process.env.VITE_API_BASE_URL}/api/users/me/profile/\`,
// \`\${process.env.VITE_API_BASE_URL}/api/users/me/settings/\`,
// \`\${process.env.VITE_API_BASE_URL}/api/users/me/workspaces/?v=\${Date.now()}\`,
// ];
//
// urls.forEach((url) => preloadItem(url));
// }, []);
// };
export function PreloadResources() {
return (
// usePreloadResources();
null
);
}"
`);
});
it("should preserve leading comments before wrapped export declaration", async () => {
const result = await applyTransform(
transformer,
`
// This is a wrapped component
// It uses observer for reactivity
export const MyObserverComponent = observer(() => {
return <div>Observer component</div>;
});
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"// This is a wrapped component
// It uses observer for reactivity
export const MyObserverComponent = observer(function MyObserverComponent() {
return <div>Observer component</div>;
});"
`);
});
it("should preserve trailing comments on exported variable declaration", async () => {
const result = await applyTransform(
transformer,
`
export const Foo = () => <div />; // trailing comment
`,
{ parser: "tsx" }
);
expect(result).toContain("// trailing comment");
});
it("should preserve leading comments on exported variable declaration inside export", async () => {
const result = await applyTransform(
transformer,
`
export /* leading comment */ const Foo = () => <div />;
`,
{ parser: "tsx" }
);
expect(result).toContain("/* leading comment */");
});
it("should preserve dependency arrays when transforming wrapped components", async () => {
const result = await applyTransform(
transformer,
`
import { useMemo } from "react";
const MyComponent = useMemo(() => {
return () => <div>Hello</div>;
}, [dep]);
`,
{ parser: "tsx", path: "file.tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import { useMemo } from "react";
const MyComponent = useMemo(function MyComponent() {
return () => <div>Hello</div>;
}, [dep]);"
`);
});
it("should preserve dependency arrays for constants that look like components", async () => {
const result = await applyTransform(
transformer,
`
import { useMemo } from "react";
const ACTION_HANDLERS = useMemo(function ACTION_HANDLERS() {
return {
archived: () => {},
};
}, []);
`,
{ parser: "tsx", path: "file.tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import { useMemo } from "react";
const ACTION_HANDLERS = useMemo(function ACTION_HANDLERS() {
return {
archived: () => {},
};
}, []);"
`);
});
it("should handle memo with generic type arguments correctly", async () => {
const result = await applyTransform(
transformer,
`
import { memo } from "react";
type TAccessMenuProps = {
currentAccess: number;
};
export const AccessMenu = memo<TAccessMenuProps>(
({ currentAccess }) => {
return <div>{currentAccess}</div>;
}
);
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"import { memo } from "react";
type TAccessMenuProps = {
currentAccess: number;
};
export const AccessMenu = memo(function AccessMenu(
{
currentAccess
}: TAccessMenuProps
) {
return <div>{currentAccess}</div>;
});"
`);
});
it("should not transform CONSTANT_CASE variables", async () => {
const result = await applyTransform(
transformer,
`
export const MY_CONSTANT = () => {
return "value";
};
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"export const MY_CONSTANT = () => {
return "value";
};"
`);
});
});

View File

@@ -0,0 +1,201 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { describe, it, expect } from "vitest";
import { applyTransform } from "@hypermod/utils";
import * as transformer from "../headlessui-v2-default-tags";
const apply = (source: string) =>
applyTransform(transformer, source, { parser: "tsx" });
describe("headlessui-v2-default-tags", () => {
it("pins a bare <Transition> to the v1 div default", async () => {
const result = await apply(`
import { Transition } from "@headlessui/react";
export const Panel = () => (
<Transition show={open} className="grid">
<div>body</div>
</Transition>
);
`);
expect(result).toContain(
`<Transition as="div" show={open} className="grid">`
);
});
it("pins Combobox.Options to ul and Combobox.Option to li", async () => {
const result = await apply(`
import { Combobox } from "@headlessui/react";
export const Select = () => (
<Combobox.Options className="list">
<Combobox.Option value="a">A</Combobox.Option>
</Combobox.Options>
);
`);
expect(result).toContain(`<Combobox.Options as="ul" className="list">`);
expect(result).toContain(`<Combobox.Option as="li" value="a">`);
});
it("pins Listbox.Options to ul and Listbox.Option to li", async () => {
const result = await apply(`
import { Listbox } from "@headlessui/react";
export const Select = () => (
<Listbox.Options>
<Listbox.Option value="a">A</Listbox.Option>
</Listbox.Options>
);
`);
expect(result).toContain(`<Listbox.Options as="ul">`);
expect(result).toContain(`<Listbox.Option as="li" value="a">`);
});
it("pins Tab.Group to Fragment and imports Fragment", async () => {
const result = await apply(`
import { useState } from "react";
import { Tab } from "@headlessui/react";
export const Tabs = () => (
<Tab.Group>
<Tab.List>
<Tab>One</Tab>
</Tab.List>
</Tab.Group>
);
`);
expect(result).toContain("<Tab.Group as={Fragment}>");
expect(result).toMatch(/import \{ useState, Fragment \} from "react"/);
// Tab.List and Tab are unchanged between v1 and v2.
expect(result).toContain("<Tab.List>");
expect(result).toContain("<Tab>One</Tab>");
});
it("adds a value Fragment import alongside an existing type-only one", async () => {
const result = await apply(`
import type { Fragment } from "react";
import { Tab } from "@headlessui/react";
export const Tabs = () => <Tab.Group><Tab.List /></Tab.Group>;
`);
expect(result).toContain("<Tab.Group as={Fragment}>");
// The type-only specifier binds no runtime value, so a real value import must appear.
expect(result).toMatch(/import \{ Fragment \} from "react"/);
});
it("does not mistake an aliased Fragment import for a local Fragment binding", async () => {
const result = await apply(`
import { Fragment as ReactFragment } from "react";
import { Tab } from "@headlessui/react";
export const Tabs = () => <Tab.Group><Tab.List /></Tab.Group>;
`);
expect(result).toContain("<Tab.Group as={Fragment}>");
expect(result).toMatch(
/import \{ Fragment as ReactFragment, Fragment \} from "react"/
);
});
it("adds a react import when the file has none", async () => {
const result = await apply(`
import { Tab } from "@headlessui/react";
export const Tabs = () => <Tab.Group><Tab.List /></Tab.Group>;
`);
expect(result).toMatch(/import \{ Fragment \} from "react"/);
});
it("leaves an existing explicit as= alone", async () => {
const result = await apply(`
import { Transition, Combobox } from "@headlessui/react";
export const Panel = () => (
<Transition
as={Fragment}
show={open}
>
<Combobox.Options as="div">x</Combobox.Options>
</Transition>
);
`);
expect(result).toContain("as={Fragment}");
expect(result).not.toContain(`as="div" as={Fragment}`);
expect(result).toContain(`<Combobox.Options as="div">`);
// exactly one `as` per element
expect(result.match(/as=/g)).toHaveLength(2);
});
it("skips elements carrying a spread that could supply as", async () => {
const result = await apply(`
import { Transition } from "@headlessui/react";
export const Panel = (props) => <Transition {...props}>x</Transition>;
`);
expect(result).not.toContain("as=");
});
it("ignores same-named components not imported from Headless UI", async () => {
const result = await apply(`
import { Transition } from "@/components/transition";
export const Panel = () => <Transition show>x</Transition>;
`);
expect(result).not.toContain("as=");
});
it("does not touch Menu, Dialog, Disclosure or Popover subcomponents", async () => {
const result = await apply(`
import { Menu, Dialog, Disclosure, Popover } from "@headlessui/react";
export const All = () => (
<>
<Menu.Items><Menu.Item>a</Menu.Item></Menu.Items>
<Dialog.Panel><Dialog.Title>t</Dialog.Title></Dialog.Panel>
<Disclosure.Button /><Disclosure.Panel />
<Popover.Button /><Popover.Panel />
</>
);
`);
expect(result).not.toContain("as=");
});
it("resolves aliased Headless UI imports by their imported name", async () => {
const result = await apply(`
import { Transition as HeadlessTransition } from "@headlessui/react";
export const Panel = () => <HeadlessTransition show>x</HeadlessTransition>;
`);
expect(result).toContain(`<HeadlessTransition as="div" show>`);
});
it("resolves aliased member expressions too", async () => {
const result = await apply(`
import { Combobox as HeadlessCombobox } from "@headlessui/react";
export const Select = () => (
<HeadlessCombobox.Options>
<HeadlessCombobox.Option value="a">A</HeadlessCombobox.Option>
</HeadlessCombobox.Options>
);
`);
expect(result).toContain(`<HeadlessCombobox.Options as="ul">`);
expect(result).toContain(`<HeadlessCombobox.Option as="li" value="a">`);
});
});

View File

@@ -0,0 +1,296 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { describe, it, expect } from "vitest";
import { applyTransform } from "@hypermod/utils";
import * as transformer from "../remove-directives";
describe("remove-directives", () => {
it("should remove 'use client' directive", async () => {
const result = await applyTransform(
transformer,
`
"use client";
import React from "react";
export const MyComponent = () => {
return <div>Hello, world!</div>;
};
`,
{ parser: "tsx" },
);
expect(result).toMatchInlineSnapshot(`
"import React from "react";
export const MyComponent = () => {
return <div>Hello, world!</div>;
};"
`);
});
it("should remove 'use server' directive", async () => {
const result = await applyTransform(
transformer,
`
"use server";
import db from "./db";
export const getData = async () => {
return db.query("SELECT * FROM users");
};
`,
{ parser: "ts" },
);
expect(result).toMatchInlineSnapshot(`
"import db from "./db";
export const getData = async () => {
return db.query("SELECT * FROM users");
};"
`);
});
it("should remove 'use client' directive with single quotes", async () => {
const result = await applyTransform(
transformer,
`
'use client';
import React from "react";
export const MyComponent = () => {
return <div>Hello, world!</div>;
};
`,
{ parser: "tsx" },
);
expect(result).toMatchInlineSnapshot(`
"import React from "react";
export const MyComponent = () => {
return <div>Hello, world!</div>;
};"
`);
});
it("should remove multiple directives", async () => {
const result = await applyTransform(
transformer,
`
"use client";
"use strict";
import React from "react";
export const MyComponent = () => {
return <div>Hello, world!</div>;
};
`,
{ parser: "tsx" },
);
expect(result).toMatchInlineSnapshot(`
""use strict";;
import React from "react";
export const MyComponent = () => {
return <div>Hello, world!</div>;
};"
`);
});
it("should ignore directives inside functions", async () => {
const result = await applyTransform(
transformer,
`
import React from "react";
export const MyComponent = () => {
"use client";
return <div>Hello, world!</div>;
};
`,
{ parser: "tsx" },
);
expect(result).toMatchInlineSnapshot(`
"import React from "react";
export const MyComponent = () => {
"use client";
return <div>Hello, world!</div>;
};"
`);
});
it("should preserve comments", async () => {
const result = await applyTransform(
transformer,
`
// comment before
"use client";
// comment after
import React from "react";
`,
{ parser: "tsx" }
);
expect(result).toMatchInlineSnapshot(`
"// comment before
// comment after
import React from "react";"
`);
});
it("should remove 'use-client' directive with hyphen", async () => {
const result = await applyTransform(
transformer,
`
"use-client";
import type { FC } from "react";
// types
import type { TDeDupeIssue } from "@plane/types";
type TDuplicateModalRootProps = {
workspaceSlug: string;
issues: TDeDupeIssue[];
handleDuplicateIssueModal: (value: boolean) => void;
};
export function DuplicateModalRoot(props: TDuplicateModalRootProps) {
const { workspaceSlug, issues, handleDuplicateIssueModal } = props;
return <></>;
}
`,
{ parser: "tsx" },
);
expect(result).toMatchInlineSnapshot(`
"import type { FC } from "react";
// types
import type { TDeDupeIssue } from "@plane/types";
type TDuplicateModalRootProps = {
workspaceSlug: string;
issues: TDeDupeIssue[];
handleDuplicateIssueModal: (value: boolean) => void;
};
export function DuplicateModalRoot(props: TDuplicateModalRootProps) {
const { workspaceSlug, issues, handleDuplicateIssueModal } = props;
return <></>;
}"
`);
});
it("should remove 'use-client' directive with hyphen and single quotes", async () => {
const result = await applyTransform(
transformer,
`
'use-client';
import type { FC } from "react";
import { useState } from "react";
// plane imports
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
export function MyComponent() {
return <div>Hello</div>;
}
`,
{ parser: "tsx" },
);
expect(result).toMatchInlineSnapshot(`
"import type { FC } from "react";
import { useState } from "react";
// plane imports
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
export function MyComponent() {
return <div>Hello</div>;
}"
`);
});
it("should remove 'use-server' directive with hyphen", async () => {
const result = await applyTransform(
transformer,
`
"use-server";
import db from "./db";
export const getData = async () => {
return db.query("SELECT * FROM users");
};
`,
{ parser: "ts" },
);
expect(result).toMatchInlineSnapshot(`
"import db from "./db";
export const getData = async () => {
return db.query("SELECT * FROM users");
};"
`);
});
it("should handle 'use-client' in modal component structure", async () => {
const result = await applyTransform(
transformer,
`
"use-client";
import type { FC } from "react";
import { useState } from "react";
// plane imports
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
// hooks
import useKeypress from "@/hooks/use-keypress";
// local imports
import { InboxIssueCreateRoot } from "./create-root";
type TInboxIssueCreateModalRoot = {
workspaceSlug: string;
projectId: string;
modalState: boolean;
handleModalClose: () => void;
};
export function InboxIssueCreateModalRoot(props: TInboxIssueCreateModalRoot) {
const { workspaceSlug, projectId, modalState, handleModalClose } = props;
return <></>;
}
`,
{ parser: "tsx" },
);
expect(result).toMatchInlineSnapshot(`
"import type { FC } from "react";
import { useState } from "react";
// plane imports
import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
// hooks
import useKeypress from "@/hooks/use-keypress";
// local imports
import { InboxIssueCreateRoot } from "./create-root";
type TInboxIssueCreateModalRoot = {
workspaceSlug: string;
projectId: string;
modalState: boolean;
handleModalClose: () => void;
};
export function InboxIssueCreateModalRoot(props: TInboxIssueCreateModalRoot) {
const { workspaceSlug, projectId, modalState, handleModalClose } = props;
return <></>;
}"
`);
});
});