mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-06-08 13:37:29 +01:00
added playwright tests
This commit is contained in:
@@ -91,6 +91,7 @@ function TabNav({ tab, active, tabKind }: { tab?: Tab; active: boolean; tabKind?
|
|||||||
<Menu openOnContext>
|
<Menu openOnContext>
|
||||||
<MenuTrigger disableButtonEnhancement>
|
<MenuTrigger disableButtonEnhancement>
|
||||||
<li
|
<li
|
||||||
|
data-test={`TabNav:${tab !== undefined ? tab.tabId : ReactTabKind[tabKind!]}`}
|
||||||
onMouseOver={() => setHovering(true)}
|
onMouseOver={() => setHovering(true)}
|
||||||
onMouseLeave={() => setHovering(false)}
|
onMouseLeave={() => setHovering(false)}
|
||||||
className={active ? "active tabList" : "tabList"}
|
className={active ? "active tabList" : "tabList"}
|
||||||
|
|||||||
+10
@@ -616,6 +616,16 @@ export class DataExplorer {
|
|||||||
await page.goto(url);
|
await page.goto(url);
|
||||||
return DataExplorer.waitForExplorer(page);
|
return DataExplorer.waitForExplorer(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the tab navigation <li> element for the given tab ID or React tab name (e.g. "tab0", "Home") */
|
||||||
|
tabNavHeader(tabId: string): Locator {
|
||||||
|
return this.frame.getByTestId(`TabNav:${tabId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a context menu item in the tab right-click menu by visible label */
|
||||||
|
tabContextMenuItem(label: string): Locator {
|
||||||
|
return this.frame.getByRole("menuitem", { name: label });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function waitForApiResponse(
|
export async function waitForApiResponse(
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
import { expect, test } from "@playwright/test";
|
||||||
|
|
||||||
|
import { DataExplorer, TestAccount } from "../fx";
|
||||||
|
import { createTestSQLContainer, TestContainerContext } from "../testData";
|
||||||
|
|
||||||
|
let context: TestContainerContext = null!;
|
||||||
|
let explorer: DataExplorer = null!;
|
||||||
|
|
||||||
|
test.beforeAll("Create Test Database", async () => {
|
||||||
|
context = await createTestSQLContainer({ includeTestData: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.afterAll("Delete Test Database", async () => {
|
||||||
|
await context?.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
test.beforeEach("Open Data Explorer", async ({ page }) => {
|
||||||
|
explorer = await DataExplorer.open(page, TestAccount.SQL);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Duplicate Items tab opens a second Items tab", async () => {
|
||||||
|
// Open Items tab
|
||||||
|
const containerNode = await explorer.waitForContainerNode(context.database.id, context.container.id);
|
||||||
|
await containerNode.expand();
|
||||||
|
const itemsNode = await explorer.waitForContainerItemsNode(context.database.id, context.container.id);
|
||||||
|
await itemsNode.element.click();
|
||||||
|
|
||||||
|
const documentsTab = explorer.documentsTab("tab0");
|
||||||
|
await documentsTab.documentsFilter.waitFor({ timeout: 30_000 });
|
||||||
|
|
||||||
|
// Right-click the tab nav header
|
||||||
|
await explorer.tabNavHeader("tab0").click({ button: "right" });
|
||||||
|
|
||||||
|
// "Duplicate tab" should be visible in the context menu
|
||||||
|
const duplicateMenuItem = explorer.tabContextMenuItem("Duplicate tab");
|
||||||
|
await expect(duplicateMenuItem).toBeVisible();
|
||||||
|
await duplicateMenuItem.click();
|
||||||
|
|
||||||
|
// A second tab should appear
|
||||||
|
const tab1 = explorer.tab("tab1");
|
||||||
|
await expect(tab1).toBeAttached({ timeout: 30_000 });
|
||||||
|
|
||||||
|
// The duplicated tab should also show the Documents content
|
||||||
|
const duplicatedTab = explorer.documentsTab("tab1");
|
||||||
|
await duplicatedTab.documentsFilter.waitFor({ timeout: 30_000 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Duplicate Query tab preserves query text in new tab", async () => {
|
||||||
|
// Open a new SQL query tab via container context menu
|
||||||
|
const containerNode = await explorer.waitForContainerNode(context.database.id, context.container.id);
|
||||||
|
await containerNode.openContextMenu();
|
||||||
|
await containerNode.contextMenuItem("New SQL Query").click();
|
||||||
|
|
||||||
|
const queryTab = explorer.queryTab("tab0");
|
||||||
|
const editor = queryTab.editor();
|
||||||
|
await editor.locator.waitFor({ timeout: 30_000 });
|
||||||
|
|
||||||
|
// Type a custom query
|
||||||
|
const customQuery = 'SELECT * FROM c WHERE c.id = "duplicate-query-test"';
|
||||||
|
await editor.setText(customQuery);
|
||||||
|
|
||||||
|
// Right-click the tab nav header
|
||||||
|
await explorer.tabNavHeader("tab0").click({ button: "right" });
|
||||||
|
|
||||||
|
const duplicateMenuItem = explorer.tabContextMenuItem("Duplicate tab");
|
||||||
|
await expect(duplicateMenuItem).toBeVisible();
|
||||||
|
await duplicateMenuItem.click();
|
||||||
|
|
||||||
|
// Second query tab should appear
|
||||||
|
const tab1 = explorer.tab("tab1");
|
||||||
|
await expect(tab1).toBeAttached({ timeout: 30_000 });
|
||||||
|
|
||||||
|
// The duplicated tab should contain the same query text
|
||||||
|
const duplicatedQueryTab = explorer.queryTab("tab1");
|
||||||
|
await duplicatedQueryTab.editor().locator.waitFor({ timeout: 30_000 });
|
||||||
|
const editorText = await duplicatedQueryTab.editor().text();
|
||||||
|
expect(editorText).toContain("duplicate-query-test");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Duplicate Scale & Settings tab opens a second settings tab", async () => {
|
||||||
|
await explorer.openScaleAndSettings(context);
|
||||||
|
|
||||||
|
// Wait for the settings tab pane to be attached
|
||||||
|
const tab0 = explorer.tab("tab0");
|
||||||
|
await expect(tab0).toBeAttached({ timeout: 30_000 });
|
||||||
|
|
||||||
|
// Right-click the tab nav header
|
||||||
|
await explorer.tabNavHeader("tab0").click({ button: "right" });
|
||||||
|
|
||||||
|
const duplicateMenuItem = explorer.tabContextMenuItem("Duplicate tab");
|
||||||
|
await expect(duplicateMenuItem).toBeVisible();
|
||||||
|
await duplicateMenuItem.click();
|
||||||
|
|
||||||
|
// A second settings tab should appear
|
||||||
|
const tab1 = explorer.tab("tab1");
|
||||||
|
await expect(tab1).toBeAttached({ timeout: 30_000 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Duplicate tab menu item is not shown for the Home tab", async () => {
|
||||||
|
// The Home tab (ReactTabKind) is never duplicable
|
||||||
|
await explorer.tabNavHeader("Home").click({ button: "right" });
|
||||||
|
|
||||||
|
// "Close tab" should always appear
|
||||||
|
await expect(explorer.tabContextMenuItem("Close tab")).toBeVisible();
|
||||||
|
|
||||||
|
// "Duplicate tab" must NOT appear
|
||||||
|
await expect(explorer.tabContextMenuItem("Duplicate tab")).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Close tab from right-click menu closes the tab", async () => {
|
||||||
|
// Open Items tab
|
||||||
|
const containerNode = await explorer.waitForContainerNode(context.database.id, context.container.id);
|
||||||
|
await containerNode.expand();
|
||||||
|
const itemsNode = await explorer.waitForContainerItemsNode(context.database.id, context.container.id);
|
||||||
|
await itemsNode.element.click();
|
||||||
|
|
||||||
|
const documentsTab = explorer.documentsTab("tab0");
|
||||||
|
await documentsTab.documentsFilter.waitFor({ timeout: 30_000 });
|
||||||
|
|
||||||
|
// Right-click the tab nav header and close the tab
|
||||||
|
await explorer.tabNavHeader("tab0").click({ button: "right" });
|
||||||
|
await explorer.tabContextMenuItem("Close tab").click();
|
||||||
|
|
||||||
|
// The tab pane should be removed
|
||||||
|
await expect(explorer.tab("tab0")).not.toBeAttached({ timeout: 15_000 });
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user