mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-20 09:20:16 +00:00
Redesign resource tree (#1865)
* start redesign work * add left padding to all tree nodes * fiddling with padding * align tab bar line with first item in resource tree * final touch ups * fix a strange password manager autofill prompt * add keyboard shortcuts * revert testing change * nudge messagebar to layout row height * tidy up * switch to Allotment to stop ResizeObserver issues with monaco * refmt and fix lints * fabric touch-ups * update snapshots * remove explicit react-icons dependency * reinstall packages * remove background from FluentProvider * fix alignment of message bar * undo temporary workaround * restore refresh button * fix e2e tests and reformat * fix compiler error * remove uiw/react-split * uncomment selection change on expand
This commit is contained in:
committed by
GitHub
parent
3d1f280378
commit
31773ee73b
@@ -8,7 +8,7 @@ test("Cassandra keyspace and table CRUD", async ({ page }) => {
|
||||
|
||||
const explorer = await DataExplorer.open(page, TestAccount.Cassandra);
|
||||
|
||||
await explorer.commandBarButton("New Table").click();
|
||||
await explorer.globalCommandButton("New Table").click();
|
||||
await explorer.whilePanelOpen("Add Table", async (panel, okButton) => {
|
||||
await panel.getByPlaceholder("Type a new keyspace id").fill(keyspaceId);
|
||||
await panel.getByPlaceholder("Enter table Id").fill(tableId);
|
||||
@@ -16,9 +16,9 @@ test("Cassandra keyspace and table CRUD", async ({ page }) => {
|
||||
await okButton.click();
|
||||
});
|
||||
|
||||
const keyspaceNode = explorer.treeNode(`DATA/${keyspaceId}`);
|
||||
const keyspaceNode = explorer.treeNode(keyspaceId);
|
||||
await keyspaceNode.expand();
|
||||
const tableNode = explorer.treeNode(`DATA/${keyspaceId}/${tableId}`);
|
||||
const tableNode = explorer.treeNode(`${keyspaceId}/${tableId}`);
|
||||
|
||||
await tableNode.openContextMenu();
|
||||
await tableNode.contextMenuItem("Delete Table").click();
|
||||
|
||||
30
test/fx.ts
30
test/fx.ts
@@ -63,11 +63,21 @@ export async function getTestExplorerUrl(accountType: TestAccount, iframeSrc?: s
|
||||
// We can't retrieve AZ CLI credentials from the browser so we get them here.
|
||||
const token = await getAzureCLICredentialsToken();
|
||||
const accountName = getAccountName(accountType);
|
||||
const baseUrl = `https://localhost:1234/testExplorer.html?accountName=${accountName}&resourceGroup=${resourceGroupName}&subscriptionId=${subscriptionId}&token=${token}`;
|
||||
const params = new URLSearchParams();
|
||||
params.set("accountName", accountName);
|
||||
params.set("resourceGroup", resourceGroupName);
|
||||
params.set("subscriptionId", subscriptionId);
|
||||
params.set("token", token);
|
||||
|
||||
// There seem to be occasional CORS issues with calling the copilot APIs (/api/tokens/sampledataconnection/v2, for example)
|
||||
// For now, since we don't test copilot, we can disable the copilot APIs by setting the feature flag to false.
|
||||
params.set("feature.enableCopilot", "false");
|
||||
|
||||
if (iframeSrc) {
|
||||
return `${baseUrl}&iframeSrc=${iframeSrc}`;
|
||||
params.set("iframeSrc", iframeSrc);
|
||||
}
|
||||
return baseUrl;
|
||||
|
||||
return `https://localhost:1234/testExplorer.html?${params.toString()}`;
|
||||
}
|
||||
|
||||
/** Helper class that provides locator methods for TreeNode elements, on top of a Locator */
|
||||
@@ -106,18 +116,30 @@ class TreeNode {
|
||||
export class DataExplorer {
|
||||
constructor(public frame: Frame) {}
|
||||
|
||||
/** Select the primary global command button.
|
||||
*
|
||||
* There's only a single "primary" button, but we still require you to pass the label to confirm you're selecting the right button.
|
||||
*/
|
||||
globalCommandButton(label: string): Locator {
|
||||
return this.frame.getByTestId("GlobalCommands").getByText(label);
|
||||
}
|
||||
|
||||
/** Select the command bar button with the specified label */
|
||||
commandBarButton(label: string): Locator {
|
||||
return this.frame.getByTestId(`CommandBar/Button:${label}`).and(this.frame.locator("css=button"));
|
||||
}
|
||||
|
||||
/** Select the side panel with the specified title */
|
||||
panel(title: string): Locator {
|
||||
return this.frame.getByTestId(`Panel:${title}`);
|
||||
}
|
||||
|
||||
/** Select the tree node with the specified id */
|
||||
treeNode(id: string): TreeNode {
|
||||
return new TreeNode(this.frame.getByTestId(`TreeNode:${id}`), this.frame, id);
|
||||
}
|
||||
|
||||
/** Waits for the panel with the specified title to be open, then runs the provided callback. After the callback completes, waits for the panel to close. */
|
||||
async whilePanelOpen(title: string, action: (panel: Locator, okButton: Locator) => Promise<void>): Promise<void> {
|
||||
const panel = this.panel(title);
|
||||
await panel.waitFor();
|
||||
@@ -126,6 +148,7 @@ export class DataExplorer {
|
||||
await panel.waitFor({ state: "detached" });
|
||||
}
|
||||
|
||||
/** Waits for the Data Explorer app to load */
|
||||
static async waitForExplorer(page: Page) {
|
||||
const iframeElement = await page.getByTestId("DataExplorerFrame").elementHandle();
|
||||
if (iframeElement === null) {
|
||||
@@ -143,6 +166,7 @@ export class DataExplorer {
|
||||
return new DataExplorer(explorerFrame);
|
||||
}
|
||||
|
||||
/** Opens the Data Explorer app using the specified test account (and optionally, the provided IFRAME src url). */
|
||||
static async open(page: Page, testAccount: TestAccount, iframeSrc?: string): Promise<DataExplorer> {
|
||||
const url = await getTestExplorerUrl(testAccount, iframeSrc);
|
||||
await page.goto(url);
|
||||
|
||||
@@ -9,7 +9,7 @@ test("Gremlin graph CRUD", async ({ page }) => {
|
||||
const explorer = await DataExplorer.open(page, TestAccount.Gremlin);
|
||||
|
||||
// Create new database and graph
|
||||
await explorer.commandBarButton("New Graph").click();
|
||||
await explorer.globalCommandButton("New Graph").click();
|
||||
await explorer.whilePanelOpen("New Graph", async (panel, okButton) => {
|
||||
await panel.getByPlaceholder("Type a new database id").fill(databaseId);
|
||||
await panel.getByRole("textbox", { name: "Graph id, Example Graph1" }).fill(graphId);
|
||||
@@ -18,9 +18,9 @@ test("Gremlin graph CRUD", async ({ page }) => {
|
||||
await okButton.click();
|
||||
});
|
||||
|
||||
const databaseNode = explorer.treeNode(`DATA/${databaseId}`);
|
||||
const databaseNode = explorer.treeNode(databaseId);
|
||||
await databaseNode.expand();
|
||||
const graphNode = explorer.treeNode(`DATA/${databaseId}/${graphId}`);
|
||||
const graphNode = explorer.treeNode(`${databaseId}/${graphId}`);
|
||||
|
||||
await graphNode.openContextMenu();
|
||||
await graphNode.contextMenuItem("Delete Graph").click();
|
||||
|
||||
@@ -14,7 +14,7 @@ import { DataExplorer, TestAccount, generateDatabaseNameWithTimestamp, generateU
|
||||
|
||||
const explorer = await DataExplorer.open(page, accountType);
|
||||
|
||||
await explorer.commandBarButton("New Collection").click();
|
||||
await explorer.globalCommandButton("New Collection").click();
|
||||
await explorer.whilePanelOpen("New Collection", async (panel, okButton) => {
|
||||
await panel.getByPlaceholder("Type a new database id").fill(databaseId);
|
||||
await panel.getByRole("textbox", { name: "Collection id, Example Collection1" }).fill(collectionId);
|
||||
@@ -23,9 +23,9 @@ import { DataExplorer, TestAccount, generateDatabaseNameWithTimestamp, generateU
|
||||
await okButton.click();
|
||||
});
|
||||
|
||||
const databaseNode = explorer.treeNode(`DATA/${databaseId}`);
|
||||
const databaseNode = explorer.treeNode(databaseId);
|
||||
await databaseNode.expand();
|
||||
const collectionNode = explorer.treeNode(`DATA/${databaseId}/${collectionId}`);
|
||||
const collectionNode = explorer.treeNode(`${databaseId}/${collectionId}`);
|
||||
|
||||
await collectionNode.openContextMenu();
|
||||
await collectionNode.contextMenuItem("Delete Collection").click();
|
||||
|
||||
@@ -8,7 +8,7 @@ test("SQL database and container CRUD", async ({ page }) => {
|
||||
|
||||
const explorer = await DataExplorer.open(page, TestAccount.SQL);
|
||||
|
||||
await explorer.commandBarButton("New Container").click();
|
||||
await explorer.globalCommandButton("New Container").click();
|
||||
await explorer.whilePanelOpen("New Container", async (panel, okButton) => {
|
||||
await panel.getByPlaceholder("Type a new database id").fill(databaseId);
|
||||
await panel.getByRole("textbox", { name: "Container id, Example Container1" }).fill(containerId);
|
||||
@@ -17,9 +17,9 @@ test("SQL database and container CRUD", async ({ page }) => {
|
||||
await okButton.click();
|
||||
});
|
||||
|
||||
const databaseNode = explorer.treeNode(`DATA/${databaseId}`);
|
||||
const databaseNode = explorer.treeNode(databaseId);
|
||||
await databaseNode.expand();
|
||||
const containerNode = explorer.treeNode(`DATA/${databaseId}/${containerId}`);
|
||||
const containerNode = explorer.treeNode(`${databaseId}/${containerId}`);
|
||||
|
||||
await containerNode.openContextMenu();
|
||||
await containerNode.contextMenuItem("Delete Container").click();
|
||||
|
||||
@@ -47,7 +47,7 @@ test("SQL account using Resource token", async ({ page }) => {
|
||||
|
||||
const explorer = await DataExplorer.waitForExplorer(page);
|
||||
|
||||
const collectionNode = explorer.treeNode(`DATA/${collectionId}`);
|
||||
const collectionNode = explorer.treeNode(`${collectionId}`);
|
||||
await collectionNode.element.waitFor();
|
||||
await expect(collectionNode.element).toBeAttached();
|
||||
|
||||
|
||||
@@ -7,17 +7,17 @@ test("Tables CRUD", async ({ page }) => {
|
||||
|
||||
const explorer = await DataExplorer.open(page, TestAccount.Tables);
|
||||
|
||||
await explorer.commandBarButton("New Table").click();
|
||||
await explorer.globalCommandButton("New Table").click();
|
||||
await explorer.whilePanelOpen("New Table", async (panel, okButton) => {
|
||||
await panel.getByRole("textbox", { name: "Table id, Example Table1" }).fill(tableId);
|
||||
await panel.getByLabel("Table Max RU/s").fill("1000");
|
||||
await okButton.click();
|
||||
});
|
||||
|
||||
const databaseNode = explorer.treeNode("DATA/TablesDB");
|
||||
const databaseNode = explorer.treeNode("TablesDB");
|
||||
await databaseNode.expand();
|
||||
|
||||
const tableNode = explorer.treeNode(`DATA/TablesDB/${tableId}`);
|
||||
const tableNode = explorer.treeNode(`TablesDB/${tableId}`);
|
||||
await expect(tableNode.element).toBeAttached();
|
||||
|
||||
await tableNode.openContextMenu();
|
||||
|
||||
Reference in New Issue
Block a user