Skip to content

Commit 1873535

Browse files
committed
feat(e2e): 10_new_ui.spec.ts — Playwright coverage for new bb0 UI surface
Adds end-to-end scenarios for every component shipped by bb0 epic v2 that previously had only vitest (jsdom + mocked fetch) coverage: vbgui/e2e/scenarios/10_new_ui.spec.ts (NEW, 12 tests): - Sidebar exposes Dimensions + Ablations tabs (E7-2 / E7-11-UI) - DimensionsTab populates after preset drop (inference_log >0 rows) - DimensionsTab source filter narrows rows - AblationsTab axis dropdown + variants render - AblationsTab axis switch reveals new variant list (optimizer → lion/muon) - AblationsTab Run on empty canvas surfaces error - ScheduleEditor toggle in OptimTab reveals editor (E7-9) - ScheduleEditor cosine selection reveals total_steps + sparkline - AutoGroupButton visible + disabled with empty canvas (E7-4) - AutoGroupButton emits banner after preset drop + click - BrickContextPanel opens on brick node click + shows activation dropdown (E7-5/E7-6) - Roundtrip badge surfaces per-row OK/FAIL in DataInspector (E7-3-UI) Full Playwright matrix (all 10 spec files) wall-clock 9.1 min: - 1178 passed - 3 flaky cells passed on retry-1 (arcee_trinity / llama3_8b T1 cppmega P1 minimal, tokenizer 3-panel compare — known timing sensitivity under workers=4 contention, identical to pa3 baseline) - 0 hard failures Total e2e cells: 6 (canvas smoke) + 912 (preset matrix) + 192 (train matrix) + 2 (tokenizer playground) + 18 (data inspector) + 3 (sharding) + 2 (gotchas) + 28 (manual drag-drop) + 8 (manual cross- product) + 12 (new UI) = 1183, all retry-pass.
1 parent a632708 commit 1873535

1 file changed

Lines changed: 170 additions & 0 deletions

File tree

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// E2E coverage for new UI components added by bb0 epic (v2):
2+
// DimensionsTab, AblationsTab, ScheduleEditor, BrickContextPanel,
3+
// Tooltip + ExplainModal, AutoGroupButton, Roundtrip badge.
4+
5+
import { test, expect } from "@playwright/test";
6+
import {
7+
gotoApp, selectPreset, clickTab, dropBrickViaPalette,
8+
} from "../fixtures";
9+
import { snapshot } from "../utils/screenshot";
10+
import { loadMatrix } from "../utils/matrix";
11+
12+
// ---------------------------------------------------------------------------
13+
// New sidebar tabs (Dimensions / Ablations)
14+
// ---------------------------------------------------------------------------
15+
16+
test.describe("new sidebar tabs (E7-2 / E7-11-UI)", () => {
17+
test("Sidebar exposes Dimensions + Ablations tabs", async ({ page }) => {
18+
await gotoApp(page);
19+
await expect(page.getByTestId("sidebar-tab-dimensions")).toBeVisible();
20+
await expect(page.getByTestId("sidebar-tab-ablations")).toBeVisible();
21+
});
22+
23+
test("DimensionsTab populates after preset drop", async ({ page }) => {
24+
await gotoApp(page);
25+
await selectPreset(page, "llama3_8b");
26+
await page.getByTestId("sidebar-tab-dimensions").click();
27+
await page.getByTestId("dimensions-tab").waitFor();
28+
// Wait for inference_log to populate (after verify completes).
29+
await expect.poll(async () =>
30+
await page.locator("[data-testid^='dim-row-']").count(),
31+
{ timeout: 8_000 },
32+
).toBeGreaterThan(0);
33+
await snapshot(page, "10_new_ui", "dimensions_populated");
34+
});
35+
36+
test("DimensionsTab source filter narrows rows", async ({ page }) => {
37+
await gotoApp(page);
38+
await selectPreset(page, "llama3_8b");
39+
await page.getByTestId("sidebar-tab-dimensions").click();
40+
await page.getByTestId("dimensions-tab").waitFor();
41+
await expect.poll(async () =>
42+
await page.locator("[data-testid^='dim-row-']").count(),
43+
{ timeout: 8_000 },
44+
).toBeGreaterThan(0);
45+
const before = await page.locator("[data-testid^='dim-row-']").count();
46+
await page.getByTestId("dimensions-filter-source")
47+
.selectOption("user");
48+
const after = await page.locator("[data-testid^='dim-row-']").count();
49+
expect(after).toBeLessThanOrEqual(before);
50+
});
51+
52+
test("AblationsTab axis dropdown + variants render", async ({ page }) => {
53+
await gotoApp(page);
54+
await page.getByTestId("sidebar-tab-ablations").click();
55+
await page.getByTestId("ablations-tab").waitFor();
56+
await expect(page.getByTestId("ablation-axis")).toBeVisible();
57+
await expect(page.getByTestId("ablation-run")).toBeVisible();
58+
// Default activation axis exposes glu + swiglu variants pre-ticked.
59+
await expect(page.getByTestId("ablation-variant-glu")).toBeVisible();
60+
await expect(page.getByTestId("ablation-variant-swiglu")).toBeVisible();
61+
});
62+
63+
test("AblationsTab axis switch reveals new variant list", async ({ page }) => {
64+
await gotoApp(page);
65+
await page.getByTestId("sidebar-tab-ablations").click();
66+
await page.getByTestId("ablations-tab").waitFor();
67+
await page.getByTestId("ablation-axis").selectOption("optimizer");
68+
await expect(page.getByTestId("ablation-variant-lion")).toBeVisible();
69+
await expect(page.getByTestId("ablation-variant-muon")).toBeVisible();
70+
});
71+
72+
test("AblationsTab Run with empty canvas surfaces error", async ({ page }) => {
73+
await gotoApp(page);
74+
await page.getByTestId("sidebar-tab-ablations").click();
75+
await page.getByTestId("ablations-tab").waitFor();
76+
await page.getByTestId("ablation-run").click();
77+
await expect(page.getByTestId("ablation-error")).toBeVisible({ timeout: 4_000 });
78+
});
79+
});
80+
81+
// ---------------------------------------------------------------------------
82+
// ScheduleEditor inside OptimTab (E7-9)
83+
// ---------------------------------------------------------------------------
84+
85+
test.describe("ScheduleEditor in OptimTab (E7-9)", () => {
86+
test("schedule toggle button reveals editor", async ({ page }) => {
87+
await gotoApp(page);
88+
await page.getByTestId("sidebar-tab-optim").click();
89+
await page.getByTestId("optim-tab").waitFor();
90+
await page.getByTestId("optim-group-0-schedule-toggle").click();
91+
await expect(page.getByTestId("schedule-editor-0")).toBeVisible();
92+
});
93+
94+
test("selecting cosine reveals total_steps + sparkline", async ({ page }) => {
95+
await gotoApp(page);
96+
await page.getByTestId("sidebar-tab-optim").click();
97+
await page.getByTestId("optim-group-0-schedule-toggle").click();
98+
await page.getByTestId("schedule-kind-0").selectOption("cosine");
99+
await expect(page.getByTestId("schedule-total-0")).toBeVisible();
100+
await expect(page.getByTestId("schedule-sparkline")).toBeVisible();
101+
await snapshot(page, "10_new_ui", "schedule_cosine");
102+
});
103+
});
104+
105+
// ---------------------------------------------------------------------------
106+
// AutoGroupButton in OptimTab (E7-4)
107+
// ---------------------------------------------------------------------------
108+
109+
test.describe("AutoGroupButton (E7-4)", () => {
110+
test("button visible in OptimTab; disabled until canvas has bricks", async ({ page }) => {
111+
await gotoApp(page);
112+
await page.getByTestId("sidebar-tab-optim").click();
113+
const btn = page.getByTestId("optim-auto-group");
114+
await expect(btn).toBeVisible();
115+
await expect(btn).toBeDisabled();
116+
});
117+
118+
test("Auto-group after preset emits banner with grouping", async ({ page }) => {
119+
await gotoApp(page);
120+
await selectPreset(page, "llama3_8b");
121+
await page.getByTestId("sidebar-tab-optim").click();
122+
await page.getByTestId("optim-auto-group").click();
123+
await expect(page.getByTestId("optim-auto-group-banner"))
124+
.toBeVisible({ timeout: 8_000 });
125+
});
126+
});
127+
128+
// ---------------------------------------------------------------------------
129+
// BrickContextPanel (E7-5/E7-6)
130+
// ---------------------------------------------------------------------------
131+
132+
test.describe("BrickContextPanel (E7-5 + E7-6)", () => {
133+
test("clicking a brick opens activation/norm panel", async ({ page }) => {
134+
await gotoApp(page);
135+
await dropBrickViaPalette(page, "mlp");
136+
// pick first brick-node
137+
const firstNode = page.locator("[data-testid^='brick-node-']").first();
138+
await firstNode.click();
139+
// The panel testid uses the node id; locate any brick-context-* root
140+
const panel = page.locator("[data-testid^='brick-context-']").first();
141+
await expect(panel).toBeVisible({ timeout: 4_000 });
142+
// mlp should expose activation dropdown
143+
const actDropdown = page.locator(
144+
"[data-testid$='-activation']").first();
145+
await expect(actDropdown).toBeVisible();
146+
});
147+
});
148+
149+
// ---------------------------------------------------------------------------
150+
// Roundtrip badge (E7-3-UI)
151+
// ---------------------------------------------------------------------------
152+
153+
test("Roundtrip badge surfaces per-row OK/FAIL (E7-3-UI)", async ({ page }) => {
154+
const matrix = loadMatrix();
155+
await gotoApp(page);
156+
await clickTab(page, "data");
157+
await page.getByTestId("data-inspector").waitFor();
158+
await page.getByTestId("data-path")
159+
.fill(matrix.parquets.T2_gpt2_small__P1_minimal.path);
160+
await page.getByTestId("data-load").click();
161+
await page.getByTestId("data-row-0").waitFor({ timeout: 8_000 });
162+
163+
await page.getByTestId("data-tokenizer-path")
164+
.fill(matrix.tokenizers.T2_gpt2_small.path);
165+
await page.getByTestId("data-roundtrip").click();
166+
await page.getByTestId("data-roundtrip-0").waitFor({ timeout: 8_000 });
167+
const text = await page.getByTestId("data-roundtrip-0").textContent();
168+
expect(text).toMatch(/Roundtrip (OK|FAIL)/);
169+
await snapshot(page, "10_new_ui", "roundtrip_badge");
170+
});

0 commit comments

Comments
 (0)