diff --git a/desktop/integration-test/menus.test.ts b/desktop/integration-test/menus.test.ts index 0b4c64b7f14..5cae2ecf762 100644 --- a/desktop/integration-test/menus.test.ts +++ b/desktop/integration-test/menus.test.ts @@ -4,43 +4,44 @@ import { signal } from "@foxglove/den/async"; -import { launchApp } from "./launchApp"; +import { AppType, launchApp } from "./launchApp"; describe("menus", () => { - it("should display the data source dialog when clicking File > Open", async () => { - await using app = await launchApp(); - // The Open dialog shows up automatically; close it + const closeDataSourceDialogAfterAppLaunch = async (app: AppType) => { await expect(app.renderer.getByTestId("DataSourceDialog").isVisible()).resolves.toBe(true); await app.renderer.getByTestId("DataSourceDialog").getByTestId("CloseIcon").click(); - await expect(app.renderer.getByTestId("DataSourceDialog").count()).resolves.toBe(0); + await expect(app.renderer.getByTestId("DataSourceDialog").isVisible()).resolves.toBe(false); + }; - // Click "File > Open" and the dialog should appear again - await app.main.evaluate(async ({ Menu }) => { - const menu = Menu.getApplicationMenu(); - menu?.getMenuItemById("fileMenu")?.submenu?.getMenuItemById("open")?.click(); - }); - await app.renderer.waitForSelector('[data-testid="DataSourceDialog"]', { state: "visible" }); - }, 15_000); + it("should display the data source dialog when clicking File > Open", async () => { + await using app = await launchApp(); + + await closeDataSourceDialogAfterAppLaunch(app); + + await app.renderer.getByTestId("AppMenuButton").click(); + await app.renderer.getByTestId("app-menu-file").click(); + await app.renderer.getByTestId("menu-item-open").click(); + + await expect(app.renderer.getByTestId("DataSourceDialog").isVisible()).resolves.toBe(true); + }); it("should display the Open Connection screen when clicking File > Open Connection", async () => { await using app = await launchApp(); - // The Open dialog shows up automatically; close it - await expect(app.renderer.getByTestId("DataSourceDialog").isVisible()).resolves.toBe(true); - await expect(app.renderer.getByTestId("OpenConnection").count()).resolves.toBe(0); - await app.renderer.getByTestId("DataSourceDialog").getByTestId("CloseIcon").click(); - await expect(app.renderer.getByTestId("DataSourceDialog").count()).resolves.toBe(0); - // Click "File > Open Connection" and the Open Connection screen should appear - await app.main.evaluate(async ({ Menu }) => { - const menu = Menu.getApplicationMenu(); - menu?.getMenuItemById("fileMenu")?.submenu?.getMenuItemById("openConnection")?.click(); - }); - await app.renderer.waitForSelector('[data-testid="OpenConnection"]', { state: "visible" }); - }, 15_000); + await closeDataSourceDialogAfterAppLaunch(app); + + await app.renderer.getByTestId("AppMenuButton").click(); + await app.renderer.getByTestId("app-menu-file").click(); + await app.renderer.getByTestId("menu-item-open-connection").click(); + + await expect(app.renderer.getByTestId("OpenConnection").count()).resolves.toBe(1); + }); it("should open the file chooser when clicking File > Open Local File", async () => { await using app = await launchApp(); + await closeDataSourceDialogAfterAppLaunch(app); + // The page is loaded as a file:// URL in the test, so showOpenFilePicker is not available and we need to mock it. // If it were available we could use `app.renderer.waitForEvent("filechooser")` instead. const openFilePickerCalled = signal(); @@ -49,12 +50,10 @@ describe("menus", () => { return []; }); - // Click "File > Open Connection" and the Open Connection screen should appear - await app.main.evaluate(async ({ Menu }) => { - const menu = Menu.getApplicationMenu(); - menu?.getMenuItemById("fileMenu")?.submenu?.getMenuItemById("openLocalFile")?.click(); - }); + await app.renderer.getByTestId("AppMenuButton").click(); + await app.renderer.getByTestId("app-menu-file").click(); + await app.renderer.getByTestId("menu-item-open-local-file").click(); await expect(openFilePickerCalled).resolves.toBe(true); - }, 15_000); + }); }); diff --git a/packages/studio-base/src/components/AppBar/AppMenu.tsx b/packages/studio-base/src/components/AppBar/AppMenu.tsx index 09e1b713974..2f527fc6b05 100644 --- a/packages/studio-base/src/components/AppBar/AppMenu.tsx +++ b/packages/studio-base/src/components/AppBar/AppMenu.tsx @@ -70,6 +70,7 @@ export function AppMenu(props: AppMenuProps): JSX.Element { type: "item", label: t("open"), key: "open", + dataTestId: "menu-item-open", onClick: () => { dialogActions.dataSource.open("start"); handleNestedMenuClose(); @@ -79,6 +80,7 @@ export function AppMenu(props: AppMenuProps): JSX.Element { type: "item", label: t("openLocalFile"), key: "open-file", + dataTestId: "menu-item-open-local-file", onClick: () => { handleNestedMenuClose(); dialogActions.openFile.open().catch(console.error); @@ -88,6 +90,7 @@ export function AppMenu(props: AppMenuProps): JSX.Element { type: "item", label: t("openConnection"), key: "open-connection", + dataTestId: "menu-item-open-connection", onClick: () => { dialogActions.dataSource.open("connection"); handleNestedMenuClose(); diff --git a/packages/studio-base/src/components/AppBar/NestedMenuItem.tsx b/packages/studio-base/src/components/AppBar/NestedMenuItem.tsx index 2ae5c80a882..d24331ef854 100644 --- a/packages/studio-base/src/components/AppBar/NestedMenuItem.tsx +++ b/packages/studio-base/src/components/AppBar/NestedMenuItem.tsx @@ -104,6 +104,7 @@ export function NestedMenuItem( className={classes.menuItem} key={item.key} onClick={item.onClick} + data-testid={item.dataTestId} disabled={item.disabled} > {item.label} diff --git a/packages/studio-base/src/components/AppBar/index.tsx b/packages/studio-base/src/components/AppBar/index.tsx index 95e80b6db65..7bed6be3a33 100644 --- a/packages/studio-base/src/components/AppBar/index.tsx +++ b/packages/studio-base/src/components/AppBar/index.tsx @@ -198,6 +198,7 @@ export function AppBar(props: AppBarProps): JSX.Element { className={cx(classes.logo, { "Mui-selected": appMenuOpen })} color="inherit" id="app-menu-button" + data-testid="AppMenuButton" title="Menu" aria-controls={appMenuOpen ? "app-menu" : undefined} aria-haspopup="true" diff --git a/packages/studio-base/src/components/AppBar/types.ts b/packages/studio-base/src/components/AppBar/types.ts index 5da5c38f6d2..d89d08a2009 100644 --- a/packages/studio-base/src/components/AppBar/types.ts +++ b/packages/studio-base/src/components/AppBar/types.ts @@ -17,6 +17,7 @@ export type AppBarMenuItem = onClick?: MouseEventHandler; external?: boolean; icon?: ReactNode; + dataTestId?: string; } | { type: "subheader"; label: ReactNode; key: string } | { type: "divider" }; diff --git a/packages/studio-base/src/components/DataSourceDialog/DataSourceDialog.tsx b/packages/studio-base/src/components/DataSourceDialog/DataSourceDialog.tsx index 934c6fe3cd5..1f8dce0eb84 100644 --- a/packages/studio-base/src/components/DataSourceDialog/DataSourceDialog.tsx +++ b/packages/studio-base/src/components/DataSourceDialog/DataSourceDialog.tsx @@ -135,7 +135,7 @@ export function DataSourceDialog(props: DataSourceDialogProps): JSX.Element { }} > - +