diff --git a/src/renderer/components/+extensions/__tests__/extensions.test.tsx b/src/renderer/components/+extensions/__tests__/extensions.test.tsx index e56e88aed9..0b4dde307c 100644 --- a/src/renderer/components/+extensions/__tests__/extensions.test.tsx +++ b/src/renderer/components/+extensions/__tests__/extensions.test.tsx @@ -4,7 +4,7 @@ */ import "@testing-library/jest-dom/extend-expect"; -import { fireEvent, waitFor } from "@testing-library/react"; +import { fireEvent, screen, waitFor } from "@testing-library/react"; import fse from "fs-extra"; import React from "react"; import { UserStore } from "../../../../common/user-store"; @@ -97,43 +97,43 @@ describe("Extensions", () => { it("disables uninstall and disable buttons while uninstalling", async () => { extensionDiscovery.isLoaded = true; - const res = render(( + render(( <> )); - const table = res.getByTestId("extensions-table"); - const menuTrigger = table.querySelector("div[role=row]:first-of-type .actions .Icon"); + + const table = await screen.findByTestId("extensions-table"); + const menuTrigger = table.querySelector(".table div[role='rowgroup'] .actions .Icon"); assert(menuTrigger); - fireEvent.click(menuTrigger); - expect(res.getByText("Disable")).toHaveAttribute("aria-disabled", "false"); - expect(res.getByText("Uninstall")).toHaveAttribute("aria-disabled", "false"); + expect(await screen.findByText("Disable")).toHaveAttribute("aria-disabled", "false"); + expect(await screen.findByText("Uninstall")).toHaveAttribute("aria-disabled", "false"); - fireEvent.click(res.getByText("Uninstall")); + fireEvent.click(await screen.findByText("Uninstall")); // Approve confirm dialog - fireEvent.click(res.getByText("Yes")); + fireEvent.click(await screen.findByText("Yes")); await waitFor(() => { expect(extensionDiscovery.uninstallExtension).toHaveBeenCalled(); fireEvent.click(menuTrigger); - expect(res.getByText("Disable")).toHaveAttribute("aria-disabled", "true"); - expect(res.getByText("Uninstall")).toHaveAttribute("aria-disabled", "true"); + expect(screen.getByText("Disable")).toHaveAttribute("aria-disabled", "true"); + expect(screen.getByText("Uninstall")).toHaveAttribute("aria-disabled", "true"); }, { timeout: 30000, }); }); it("disables install button while installing", async () => { - const res = render(); + render(); (fse.unlink as jest.MockedFunction).mockReturnValue(Promise.resolve()); - fireEvent.change(res.getByPlaceholderText("File path or URL", { + fireEvent.change(await screen.findByPlaceholderText("File path or URL", { exact: false, }), { target: { @@ -141,8 +141,8 @@ describe("Extensions", () => { }, }); - fireEvent.click(res.getByText("Install")); - expect(res.getByText("Install").closest("button")).toBeDisabled(); + fireEvent.click(await screen.findByText("Install")); + expect((await screen.findByText("Install")).closest("button")).toBeDisabled(); }); it("displays spinner while extensions are loading", () => { diff --git a/src/renderer/components/+extensions/installed-extensions.tsx b/src/renderer/components/+extensions/installed-extensions.tsx index 8bde9c344b..2de88642e2 100644 --- a/src/renderer/components/+extensions/installed-extensions.tsx +++ b/src/renderer/components/+extensions/installed-extensions.tsx @@ -81,63 +81,61 @@ const NonInjectedInstalledExtensions = observer(({ extensionDiscovery, extension ); const data = useMemo( - () => { - return extensions.map(extension => { - const { id, isEnabled, isCompatible, manifest } = extension; - const { name, description, version } = manifest; - const isUninstalling = extensionInstallationStateStore.isExtensionUninstalling(id); + () => extensions.map(extension => { + const { id, isEnabled, isCompatible, manifest } = extension; + const { name, description, version } = manifest; + const isUninstalling = extensionInstallationStateStore.isExtensionUninstalling(id); - return { - extension: ( -
-
-
{name}
-
{description}
-
+ return { + extension: ( +
+
+
{name}
+
{description}
- ), - version, - status: ( -
- {getStatus(extension)} -
- ), - actions: ( - - { isCompatible && ( - <> - {isEnabled ? ( - disable(id)} - > - - Disable - - ) : ( - enable(id)} - > - - Enable - - )} - - )} +
+ ), + version, + status: ( +
+ {getStatus(extension)} +
+ ), + actions: ( + + {isCompatible && ( + <> + {isEnabled ? ( + disable(id)} + > + + Disable + + ) : ( + enable(id)} + > + + Enable + + )} + + )} - uninstall(extension)} - > - - Uninstall - - - ), - }; - }); - }, [extensions, extensionInstallationStateStore.anyUninstalling], + uninstall(extension)} + > + + Uninstall + + + ), + }; + }), [extensions, extensionInstallationStateStore.anyUninstalling], ); if (!extensionDiscovery.isLoaded) { diff --git a/src/renderer/components/table/react-table.tsx b/src/renderer/components/table/react-table.tsx index 92ff70875f..e1dcc59ab9 100644 --- a/src/renderer/components/table/react-table.tsx +++ b/src/renderer/components/table/react-table.tsx @@ -10,11 +10,11 @@ import { useFlexLayout, useSortBy, useTable } from "react-table"; import { Icon } from "../icon"; import { cssNames } from "../../utils"; -export interface ReactTableProps extends UseTableOptions { +export interface ReactTableProps extends UseTableOptions { headless?: boolean; } -export function ReactTable({ columns, data, headless }: ReactTableProps) { +export function ReactTable({ columns, data, headless }: ReactTableProps) { const defaultColumn = useMemo( () => ({ minWidth: 20, @@ -40,11 +40,11 @@ export function ReactTable({ columns, data, headless }: ReactTableProps) { ); const renderRow = useCallback( - (row: Row) => { + (row: Row) => { prepareRow(row); return ( -
+
{row.cells.map((cell, index) => (
; +export type IgnoredClassNames = number | symbol | Function; -export function cssNames(...args: IClassName[]): string { - const map: IClassNameMap = {}; +export type IClassName = string | string[] | IClassNameMap | undefined | null | false | IgnoredClassNames; +export type IClassNameMap = Record; - args.forEach(className => { - if (typeof className === "string" || Array.isArray(className)) { - [className].flat().forEach(name => map[name] = true); +export function cssNames(...classNames: IClassName[]): string { + const classNamesEnabled: IClassNameMap = {}; + + for (const className of classNames) { + if (typeof className === "string") { + classNamesEnabled[className] = true; + } else if (Array.isArray(className)) { + for (const name of className) { + classNamesEnabled[name] = true; + } + } else if (className && typeof className === "object") { + Object.assign(classNamesEnabled, className); } - else { - Object.assign(map, className); - } - }); + } - return Object.entries(map) + return Object.entries(classNamesEnabled) .filter(([, isActive]) => !!isActive) .map(([className]) => className.trim()) .join(" ");