diff --git a/src/Explorer/Tabs/Tabs.tsx b/src/Explorer/Tabs/Tabs.tsx index e36a7da04..40966d04f 100644 --- a/src/Explorer/Tabs/Tabs.tsx +++ b/src/Explorer/Tabs/Tabs.tsx @@ -1,4 +1,4 @@ -import { Spinner, SpinnerSize, TooltipHost } from "@fluentui/react"; +import { ITooltipHost, Spinner, SpinnerSize, TooltipHost } from "@fluentui/react"; import { Menu, MenuItem, MenuList, MenuPopover, MenuTrigger } from "@fluentui/react-components"; import { CollectionTabKind } from "Contracts/ViewModels"; import Explorer from "Explorer/Explorer"; @@ -74,6 +74,7 @@ export const Tabs = ({ explorer }: TabsProps): JSX.Element => { function TabNav({ tab, active, tabKind }: { tab?: Tab; active: boolean; tabKind?: ReactTabKind }) { const [hovering, setHovering] = useState(false); const focusTab = useRef() as MutableRefObject; + const tabTooltip = useRef(null); const tabId = tab ? tab.tabId : ""; const getReactTabTitle = (): ko.Observable => { @@ -85,6 +86,7 @@ function TabNav({ tab, active, tabKind }: { tab?: Tab; active: boolean; tabKind? useEffect(() => { if (active && focusTab.current) { focusTab.current.focus(); + tabTooltip.current?.dismiss(); } }, [active]); const liElement = ( @@ -98,7 +100,7 @@ function TabNav({ tab, active, tabKind }: { tab?: Tab; active: boolean; tabKind? >
- + { diff --git a/src/Explorer/Tabs/useTabs.test.ts b/src/Explorer/Tabs/useTabs.test.ts index 9d4925a2c..1093fccd2 100644 --- a/src/Explorer/Tabs/useTabs.test.ts +++ b/src/Explorer/Tabs/useTabs.test.ts @@ -1,11 +1,69 @@ +import { act, cleanup, fireEvent, render } from "@testing-library/react"; import { DocumentsTabV2 } from "Explorer/Tabs/DocumentsTabV2/DocumentsTabV2"; import * as ko from "knockout"; +import React from "react"; import * as ViewModels from "../../Contracts/ViewModels"; import { updateUserContext } from "../../UserContext"; import { useTabs } from "../../hooks/useTabs"; import { container } from "../Controls/Settings/TestUtils"; import DocumentId from "../Tree/DocumentId"; import { NewQueryTab } from "./QueryTab/QueryTab"; +import { Tabs } from "./Tabs"; +import TabsBase from "./TabsBase"; + +describe("Tab path tooltips", () => { + const renderActiveTab = () => { + const tab = Object.assign( + new TabsBase({ tabKind: ViewModels.CollectionTabKind.Query, title: "Query 1", tabPath: "" }), + { render: () => React.createElement("button", null, "Execute Query") }, + ); + tab.tabPath = ko.observable("t_34646986695_1_dbc3_1789160465183>testcontainer>Query 1"); + useTabs.setState({ openedTabs: [tab], activeTab: tab }); + return render(React.createElement(Tabs, { explorer: container })); + }; + + beforeEach(() => { + jest.useFakeTimers(); + useTabs.setState({ openedTabs: [], openedReactTabs: [], activeTab: undefined, activeReactTab: undefined }); + }); + + afterEach(() => { + cleanup(); + jest.clearAllTimers(); + jest.useRealTimers(); + useTabs.setState({ openedTabs: [], activeTab: undefined }); + }); + + it("focuses an activated tab without opening its path tooltip", () => { + const view = renderActiveTab(); + expect(document.activeElement).toBe(view.getByRole("tab", { name: "Query 1" })); + + act(() => jest.advanceTimersByTime(1000)); + expect(document.querySelector(".ms-Tooltip")).toBeNull(); + }); + + it.each(["hover", "focus"])("keeps the path tooltip available on later %s and dismissible with Escape", (trigger) => { + const view = renderActiveTab(); + const tab = view.getByRole("tab", { name: "Query 1" }); + act(() => jest.advanceTimersByTime(1000)); + + if (trigger === "hover") { + fireEvent.mouseEnter(tab); + } else { + act(() => { + view.getByRole("button", { name: "Execute Query" }).focus(); + tab.focus(); + }); + } + + act(() => jest.advanceTimersByTime(1000)); + expect(document.querySelector(".ms-Tooltip")?.textContent).toContain("testcontainer>Query 1"); + + fireEvent.keyDown(tab, { key: "Escape", keyCode: 27, which: 27 }); + expect(document.querySelector(".ms-Tooltip")).toBeNull(); + expect(document.activeElement).toBe(tab); + }); +}); describe("useTabs tests", () => { let database: ViewModels.Database; diff --git a/test/sql/indexAdvisor.spec.ts b/test/sql/indexAdvisor.spec.ts index dc6ee978c..09489d080 100644 --- a/test/sql/indexAdvisor.spec.ts +++ b/test/sql/indexAdvisor.spec.ts @@ -1,6 +1,6 @@ import { expect, test, type Page } from "@playwright/test"; -import { CommandBarButton, DataExplorer, TestAccount } from "../fx"; +import { CommandBarButton, DataExplorer, generateUniqueName, TestAccount } from "../fx"; import { createTestSQLContainer, TestContainerContext } from "../testData"; // Test container context for setup and cleanup @@ -10,7 +10,10 @@ let CONTAINER_ID: string; // Set up test database and container with data before all tests test.beforeAll(async () => { - testContainer = await createTestSQLContainer({ includeTestData: true }); + testContainer = await createTestSQLContainer({ + includeTestData: true, + databaseName: generateUniqueName("db_tab_tooltip_with_a_long_resource_name"), + }); DATABASE_ID = testContainer.database.id; CONTAINER_ID = testContainer.container.id; });