Skip to content

Commit f94e464

Browse files
authored
fix(tests): stabilize webkit keyboard handler tests with programmatic cursor positioning (#2746)
ArrowUp in WebKit (especially Linux) can position the cursor incorrectly when crossing blocks with different indentation levels, causing Delete/ Backspace tests to fail intermittently. Replace unreliable keyboard navigation (ArrowUp, Control+ArrowLeft, ControlOrMeta+ArrowLeft/Right) with programmatic cursor positioning via BlockNote's setTextCursorPosition API.
1 parent d5bad9d commit f94e464

2 files changed

Lines changed: 41 additions & 5 deletions

File tree

tests/src/end-to-end/keyboardhandlers/keyboardhandlers.test.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ import {
55
ITALIC_BUTTON_SELECTOR,
66
} from "../../utils/const.js";
77
import { insertHeading, insertParagraph } from "../../utils/copypaste.js";
8-
import { compareDocToSnapshot, focusOnEditor } from "../../utils/editor.js";
8+
import {
9+
compareDocToSnapshot,
10+
focusOnEditor,
11+
moveCursorToBlockEnd,
12+
moveCursorToBlockStart,
13+
} from "../../utils/editor.js";
914
import { executeSlashCommand } from "../../utils/slashmenu.js";
1015

1116
test.describe.configure({ mode: "serial" });
@@ -96,7 +101,7 @@ test.describe("Check Keyboard Handlers' Behaviour", () => {
96101
await focusOnEditor(page);
97102
await insertHeading(page, 1);
98103

99-
await page.keyboard.press("Control+ArrowLeft");
104+
await moveCursorToBlockStart(page);
100105
await page.keyboard.press("Backspace");
101106

102107
await compareDocToSnapshot(page, "backspaceStartOfBlock.json");
@@ -143,7 +148,7 @@ test.describe("Check Keyboard Handlers' Behaviour", () => {
143148
await page.keyboard.press("ArrowUp");
144149
}
145150

146-
await page.keyboard.press("Control+ArrowLeft");
151+
await moveCursorToBlockStart(page);
147152
await page.keyboard.press("Backspace");
148153

149154
await compareDocToSnapshot(page, "backspacePreservesNestedBlocks.json");
@@ -283,6 +288,7 @@ test.describe("Check Keyboard Handlers' Behaviour", () => {
283288

284289
await page.keyboard.press("ArrowUp");
285290
await page.keyboard.press("ArrowUp");
291+
await moveCursorToBlockEnd(page);
286292
await page.keyboard.press("Delete");
287293

288294
await compareDocToSnapshot(page, "deleteMultipleChildren.json");
@@ -299,6 +305,7 @@ test.describe("Check Keyboard Handlers' Behaviour", () => {
299305

300306
await page.keyboard.press("ArrowUp");
301307
await page.keyboard.press("ArrowUp");
308+
await moveCursorToBlockEnd(page);
302309
await page.keyboard.press("Delete");
303310

304311
await compareDocToSnapshot(page, "deleteNestedChildren.json");
@@ -314,6 +321,7 @@ test.describe("Check Keyboard Handlers' Behaviour", () => {
314321
await insertParagraph(page);
315322

316323
await page.keyboard.press("ArrowUp");
324+
await moveCursorToBlockEnd(page);
317325
await page.keyboard.press("Delete");
318326

319327
await compareDocToSnapshot(page, "deleteShallowerBlock.json");
@@ -335,8 +343,7 @@ test.describe("Check Keyboard Handlers' Behaviour", () => {
335343

336344
await page.keyboard.press("ArrowUp");
337345
await page.keyboard.press("ArrowUp");
338-
await page.keyboard.press("ControlOrMeta+ArrowLeft");
339-
await page.keyboard.press("ControlOrMeta+ArrowRight");
346+
await moveCursorToBlockEnd(page);
340347
await page.keyboard.press("Delete");
341348

342349
await compareDocToSnapshot(page, "deleteShallowerBlockWithChildren.json");

tests/src/utils/editor.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,32 @@ export async function compareDocToSnapshot(page: Page, name: string) {
4646
const doc = JSON.stringify(await getDoc(page), null, 2);
4747
expect(doc).toMatchSnapshot(`${name}.json`);
4848
}
49+
50+
/**
51+
* Programmatically move cursor to end of the current block content.
52+
* This avoids relying on keyboard navigation (ArrowUp/End) which can
53+
* position the cursor incorrectly in WebKit when crossing blocks with
54+
* different indentation levels.
55+
*/
56+
export async function moveCursorToBlockEnd(page: Page) {
57+
await page.evaluate(() => {
58+
const tiptap = (window as any).ProseMirror;
59+
const bnEditor = tiptap.schema.cached.blockNoteEditor;
60+
const block = bnEditor.getTextCursorPosition().block;
61+
bnEditor.setTextCursorPosition(block, "end");
62+
});
63+
}
64+
65+
/**
66+
* Programmatically move cursor to start of the current block content.
67+
* This avoids relying on keyboard navigation which can be unreliable
68+
* in WebKit.
69+
*/
70+
export async function moveCursorToBlockStart(page: Page) {
71+
await page.evaluate(() => {
72+
const tiptap = (window as any).ProseMirror;
73+
const bnEditor = tiptap.schema.cached.blockNoteEditor;
74+
const block = bnEditor.getTextCursorPosition().block;
75+
bnEditor.setTextCursorPosition(block, "start");
76+
});
77+
}

0 commit comments

Comments
 (0)