Skip to content

Commit 8027a10

Browse files
authored
Merge pull request #3113 from perspective-dev/fix-workspace-table-menu
Fix `perspective-workspace` context submenu for tables
2 parents c8db8b7 + 5b5428a commit 8027a10

File tree

2 files changed

+141
-7
lines changed

2 files changed

+141
-7
lines changed

packages/workspace/src/ts/workspace/workspace.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -815,13 +815,11 @@ export class PerspectiveWorkspace extends SplitPanel {
815815
);
816816

817817
(async () => {
818-
for (const table of (
819-
await Promise.all(
820-
this.client.map((client) =>
821-
client.get_hosted_table_names(),
822-
),
823-
)
824-
).map((x) => x.flatMap((x: any) => x))) {
818+
const names = await Promise.all(
819+
this.client.map((c) => c.get_hosted_table_names()),
820+
).then((x) => x.flat());
821+
822+
for (const table of names) {
825823
let args;
826824
if (widget !== null) {
827825
args = {
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
8+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
10+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12+
13+
import { test, expect } from "@perspective-dev/test";
14+
15+
test.beforeEach(async ({ page }) => {
16+
await page.goto("/tools/test/src/html/workspace-test.html");
17+
await page.evaluate(async () => {
18+
while (!window["__TEST_PERSPECTIVE_READY__"]) {
19+
await new Promise((x) => setTimeout(x, 10));
20+
}
21+
});
22+
});
23+
24+
test.describe("Context menu", () => {
25+
test("shows tables in the New Table submenu", async ({ page }) => {
26+
await page.evaluate(async () => {
27+
await window.__WORKER__.table("x\n1\n2\n", {
28+
name: "test_table_1",
29+
});
30+
31+
await window.__WORKER__.table("y\n3\n4\n", {
32+
name: "test_table_2",
33+
});
34+
});
35+
36+
// Right-click on the workspace to open context menu
37+
const workspace = page.locator("perspective-workspace");
38+
await workspace.click({
39+
button: "right",
40+
position: { x: 100, y: 100 },
41+
});
42+
43+
// Wait for the context menu to appear in the shadow DOM
44+
const shadowHost = page.locator("perspective-workspace");
45+
const menu = shadowHost.locator(".lm-Menu").first();
46+
await expect(menu).toBeVisible();
47+
48+
// Click on "New Table" to open the submenu
49+
const newTableItem = menu.locator(
50+
".lm-Menu-item:has(.lm-Menu-itemLabel:text('New Table'))",
51+
);
52+
await newTableItem.hover();
53+
54+
// Wait for submenu to appear
55+
const submenu = shadowHost.locator(".lm-Menu").nth(1);
56+
await expect(submenu).toBeVisible();
57+
58+
// Get the submenu content with table entries
59+
const submenuContent = submenu.locator(".lm-Menu-content");
60+
61+
// Wait for the table items to be populated (they are added asynchronously)
62+
// We expect at least our two test tables plus the default "superstore" table
63+
await expect(submenuContent.locator("> .lm-Menu-item")).toHaveCount(3, {
64+
timeout: 5000,
65+
});
66+
67+
const menuItems = submenuContent.locator("> .lm-Menu-item");
68+
const itemCount = await menuItems.count();
69+
70+
// Get the labels of the first items (the tables)
71+
const labels = [];
72+
for (let i = 0; i < itemCount; i++) {
73+
const label = await menuItems
74+
.nth(i)
75+
.locator(".lm-Menu-itemLabel")
76+
.textContent();
77+
labels.push(label);
78+
}
79+
80+
// Verify our test tables appear in the menu
81+
expect(labels).toContain("test_table_1");
82+
expect(labels).toContain("test_table_2");
83+
expect(labels).toContain("superstore");
84+
});
85+
86+
test("context menu table entries have correct structure", async ({
87+
page,
88+
}) => {
89+
// Create two tables and load the workspace
90+
await page.evaluate(async () => {
91+
await window.__WORKER__.table("a\n1\n", { name: "alpha" });
92+
await window.__WORKER__.table("b\n2\n", { name: "beta" });
93+
});
94+
95+
// Right-click on the workspace
96+
const workspace = page.locator("perspective-workspace");
97+
await workspace.click({
98+
button: "right",
99+
position: { x: 100, y: 100 },
100+
});
101+
102+
// Open the "New Table" submenu
103+
const shadowHost = page.locator("perspective-workspace");
104+
const menu = shadowHost.locator(".lm-Menu").first();
105+
await expect(menu).toBeVisible();
106+
107+
const newTableItem = menu.locator(
108+
".lm-Menu-item:has(.lm-Menu-itemLabel:text('New Table'))",
109+
);
110+
await newTableItem.hover();
111+
112+
const submenu = shadowHost.locator(".lm-Menu").nth(1);
113+
await expect(submenu).toBeVisible();
114+
115+
// Verify the DOM structure of table entries
116+
const submenuContent = submenu.locator(".lm-Menu-content");
117+
118+
// Wait for table items to be populated
119+
await expect(submenuContent.locator("> .lm-Menu-item")).toHaveCount(3, {
120+
timeout: 5000,
121+
});
122+
123+
const firstItem = submenuContent.locator("> .lm-Menu-item").first();
124+
125+
// Check that the menu item has the expected Lumino classes
126+
await expect(firstItem).toHaveClass(/lm-Menu-item/);
127+
128+
// Check that it contains a label element
129+
const labelElement = firstItem.locator(".lm-Menu-itemLabel");
130+
await expect(labelElement).toBeVisible();
131+
132+
// Verify the label contains one of our table names
133+
const labelText = await labelElement.textContent();
134+
expect(["alpha", "beta", "superstore"]).toContain(labelText);
135+
});
136+
});

0 commit comments

Comments
 (0)