Skip to content

Commit 3da9337

Browse files
fix(e2e): create fresh page in navigateToEditorPage to prevent parallel test interference (#187) (#190)
Co-authored-by: Ona <no-reply@ona.com>
1 parent 359c32b commit 3da9337

1 file changed

Lines changed: 17 additions & 29 deletions

File tree

e2e/fixtures/editor-helpers.ts

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,30 @@ import type { Page } from "@playwright/test";
22
import { expect } from "@playwright/test";
33

44
/**
5-
* Navigate to a page that has an editor. Waits for the sidebar page tree to
6-
* load, then clicks an existing page. If no pages exist, creates one via the
7-
* sidebar "New Page" button.
5+
* Navigate to a page that has an editor. Always creates a fresh page via the
6+
* sidebar "New Page" button so each test gets its own isolated page. This
7+
* prevents parallel tests (e.g. the delete test) from interfering by deleting
8+
* a shared page mid-test.
89
*
910
* Returns once `[contenteditable="true"]` is visible.
1011
*/
1112
export async function navigateToEditorPage(page: Page): Promise<void> {
1213
const sidebar = page.getByRole("complementary");
1314

14-
// The page tree loads asynchronously: fetches workspace ID, then pages.
15-
// While loading it shows skeleton pulse divs. Once loaded it renders either
16-
// role="tree" with role="treeitem" children (pages exist) or "No pages yet".
17-
// Wait for tree items to appear — this is the most reliable signal that
18-
// the async data has loaded and the sidebar is interactive.
19-
const treeItem = sidebar.locator('[role="treeitem"]').first();
20-
try {
21-
await expect(treeItem).toBeVisible({ timeout: 10_000 });
22-
} catch {
23-
// Tree loaded but has no pages, or workspace has no pages yet
24-
}
15+
// The page tree loads asynchronously: workspace ID lookup → page fetch.
16+
// The "New Page" button silently no-ops if the workspace ID hasn't resolved
17+
// yet, so we must wait for the tree to finish loading before clicking it.
18+
// The tree renders either treeitem elements (pages exist) or "No pages yet"
19+
// once loading completes. Wait for either signal.
20+
const treeLoaded = sidebar
21+
.locator('[role="treeitem"], :text("No pages yet")')
22+
.first();
23+
await expect(treeLoaded).toBeVisible({ timeout: 10_000 });
2524

26-
if ((await treeItem.count()) > 0) {
27-
// The tree item row contains: grip icon, expand button, file icon, title button, action buttons.
28-
// The title button has class "flex-1 truncate text-left" and triggers navigation.
29-
// Use text-left as a more specific selector since it's unique to the title button.
30-
const titleBtn = treeItem.locator("button.text-left");
31-
if ((await titleBtn.count()) > 0) {
32-
await titleBtn.click();
33-
} else {
34-
// Fallback: click the last button in the tree item (the title button)
35-
await treeItem.locator("button").last().click();
36-
}
37-
} else {
38-
// No pages exist — create one via the sidebar "New Page" button
39-
await sidebar.getByRole("button", { name: /new page/i }).click();
40-
}
25+
// Create a fresh page so this test owns it and parallel tests cannot
26+
// delete or modify it underneath us.
27+
const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
28+
await newPageBtn.click();
4129

4230
// Wait for the editor to appear (works for both hard and soft navigation)
4331
const editor = page.locator('[contenteditable="true"]');

0 commit comments

Comments
 (0)