From a2f879066f3a9797ba8e137d3ad1d7ff1e8a9408 Mon Sep 17 00:00:00 2001 From: Saul-Mirone Date: Thu, 10 Apr 2025 16:52:15 +0000 Subject: [PATCH] ci(editor): enable cross platform test (#11566) --- .github/workflows/build-test.yml | 39 ++- .../playground/examples/inline/test-page.ts | 7 + .../e2e/inline/inline-editor.spec.ts | 256 ++++++++++-------- 3 files changed, 190 insertions(+), 112 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index a2416376e6..dd40158035 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -218,7 +218,43 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: test-results-e2e-legacy-bs-${{ matrix.shard }} + name: test-results-e2e-bs-${{ matrix.shard }} + path: ./test-results + if-no-files-found: ignore + + e2e-blocksuite-cross-browser-test: + name: E2E BlockSuite Cross Browser Test + runs-on: ubuntu-latest + needs: optimize_ci + if: needs.optimize_ci.outputs.skip == 'false' + strategy: + fail-fast: false + matrix: + shard: [1, 2] + browser: ['chromium', 'firefox', 'webkit'] + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js + uses: ./.github/actions/setup-node + with: + playwright-install: true + playwright-platform: ${{ matrix.browser }} + electron-install: false + full-cache: true + + - name: Run playground build + run: yarn workspace @blocksuite/playground build + + - name: Run playwright tests + env: + BROWSER: ${{ matrix.browser }} + run: yarn workspace @affine-test/blocksuite test "inline-editor.spec.ts" --forbid-only --shard=${{ matrix.shard }}/${{ strategy.job-total }} + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-e2e-bs-cross-browser-${{ matrix.browser }}-${{ matrix.shard }} path: ./test-results if-no-files-found: ignore @@ -1141,6 +1177,7 @@ jobs: - check-yarn-binary - e2e-test - e2e-blocksuite-test + - e2e-blocksuite-cross-browser-test - e2e-mobile-test - unit-test - build-native diff --git a/blocksuite/playground/examples/inline/test-page.ts b/blocksuite/playground/examples/inline/test-page.ts index 626a27854a..58bb4aef75 100644 --- a/blocksuite/playground/examples/inline/test-page.ts +++ b/blocksuite/playground/examples/inline/test-page.ts @@ -227,6 +227,13 @@ export class CustomToolbar extends ShadowlessElement { } `; + override connectedCallback() { + super.connectedCallback(); + this.addEventListener('pointerdown', e => { + e.preventDefault(); + }); + } + override firstUpdated() { const boldButton = this.querySelector('.bold'); const italicButton = this.querySelector('.italic'); diff --git a/tests/blocksuite/e2e/inline/inline-editor.spec.ts b/tests/blocksuite/e2e/inline/inline-editor.spec.ts index e086163273..2ea45ffc16 100644 --- a/tests/blocksuite/e2e/inline/inline-editor.spec.ts +++ b/tests/blocksuite/e2e/inline/inline-editor.spec.ts @@ -2,7 +2,13 @@ import type { InlineEditor, InlineRange } from '@blocksuite/affine/std/inline'; import type { DeltaInsert } from '@blocksuite/affine/store'; import { expect, type Page, test } from '@playwright/test'; -import { pressArrowLeft, pressEnter } from '../utils/actions/keyboard.js'; +import { press } from '../database/actions.js'; +import { + pressArrowLeft, + pressBackspace, + pressEnter, + type, +} from '../utils/actions/keyboard.js'; import { enterPlaygroundRoom, focusRichText, @@ -15,15 +21,6 @@ const defaultPlaygroundURL = new URL( `http://localhost:${process.env.CI ? 4173 : 5173}/` ); -async function type(page: Page, content: string) { - await page.keyboard.type(content, { delay: 50 }); -} - -async function press(page: Page, content: string) { - await page.keyboard.press(content, { delay: 50 }); - await page.waitForTimeout(50); -} - async function enterInlineEditorPlayground(page: Page) { const url = new URL('examples/inline/index.html', defaultPlaygroundURL); await page.goto(url.toString()); @@ -158,7 +155,7 @@ async function assertSelection( expect(actual).toEqual({ index: rangeIndex, length: rangeLength }); } -test('basic input', async ({ page }) => { +test('basic input', async ({ page, browserName }) => { await enterInlineEditorPlayground(page); await focusInlineRichText(page); @@ -168,43 +165,43 @@ test('basic input', async ({ page }) => { const editorAUndo = page.getByText('undo').nth(0); const editorARedo = page.getByText('redo').nth(0); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); - expect(await editorB.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); + await expect(editorB).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); await type(page, 'abcd😃efg👨‍👨‍👧‍👦hj'); - expect(await editorA.innerText()).toBe('abcd😃efg👨‍👨‍👧‍👦hj'); - expect(await editorB.innerText()).toBe('abcd😃efg👨‍👨‍👧‍👦hj'); + await expect(editorA).toHaveText('abcd😃efg👨‍👨‍👧‍👦hj'); + await expect(editorB).toHaveText('abcd😃efg👨‍👨‍👧‍👦hj'); await editorAUndo.click(); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); - expect(await editorB.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); + await expect(editorB).toHaveText(ZERO_WIDTH_SPACE); await editorARedo.click(); - expect(await editorA.innerText()).toBe('abcd😃efg👨‍👨‍👧‍👦hj'); - expect(await editorB.innerText()).toBe('abcd😃efg👨‍👨‍👧‍👦hj'); + await expect(editorA).toHaveText('abcd😃efg👨‍👨‍👧‍👦hj'); + await expect(editorB).toHaveText('abcd😃efg👨‍👨‍👧‍👦hj'); await focusInlineRichText(page); - await press(page, 'Backspace'); - await press(page, 'Backspace'); - await press(page, 'Backspace'); + await pressBackspace(page, 2); // remove j and h + // see https://github.com/microsoft/vscode/issues/99629#issuecomment-831565509 + await pressBackspace(page, browserName === 'firefox' ? 5 : 1); - expect(await editorA.innerText()).toBe('abcd😃efg'); - expect(await editorB.innerText()).toBe('abcd😃efg'); + await expect(editorA).toHaveText('abcd😃efg'); + await expect(editorB).toHaveText('abcd😃efg'); await editorAUndo.click(); - expect(await editorA.innerText()).toBe('abcd😃efg👨‍👨‍👧‍👦hj'); - expect(await editorB.innerText()).toBe('abcd😃efg👨‍👨‍👧‍👦hj'); + await expect(editorA).toHaveText('abcd😃efg👨‍👨‍👧‍👦hj'); + await expect(editorB).toHaveText('abcd😃efg👨‍👨‍👧‍👦hj'); await editorARedo.click(); - expect(await editorA.innerText()).toBe('abcd😃efg'); - expect(await editorB.innerText()).toBe('abcd😃efg'); + await expect(editorA).toHaveText('abcd😃efg'); + await expect(editorB).toHaveText('abcd😃efg'); await focusInlineRichText(page); await press(page, 'ArrowLeft'); @@ -216,8 +213,8 @@ test('basic input', async ({ page }) => { await press(page, 'Delete'); await type(page, '🥰👨‍👨‍👧‍👦'); - expect(await editorA.innerText()).toBe('abc🥰👨‍👨‍👧‍👦efg'); - expect(await editorB.innerText()).toBe('abc🥰👨‍👨‍👧‍👦efg'); + await expect(editorA).toHaveText('abc🥰👨‍👨‍👧‍👦efg'); + await expect(editorB).toHaveText('abc🥰👨‍👨‍👧‍👦efg'); await setInlineRichTextRange(page, { index: 3, @@ -226,18 +223,18 @@ test('basic input', async ({ page }) => { await page.waitForTimeout(100); await press(page, 'Delete'); - expect(await editorA.innerText()).toBe('abc'); - expect(await editorA.innerText()).toBe('abc'); + await expect(editorA).toHaveText('abc'); + await expect(editorB).toHaveText('abc'); await editorAUndo.click(); - expect(await editorA.innerText()).toBe('abcd😃efg'); - expect(await editorB.innerText()).toBe('abcd😃efg'); + await expect(editorA).toHaveText('abcd😃efg'); + await expect(editorB).toHaveText('abcd😃efg'); await editorARedo.click(); - expect(await editorA.innerText()).toBe('abc'); - expect(await editorB.innerText()).toBe('abc'); + await expect(editorA).toHaveText('abc'); + await expect(editorB).toHaveText('abc'); await focusInlineRichText(page); await page.waitForTimeout(100); @@ -247,38 +244,47 @@ test('basic input', async ({ page }) => { await page.waitForTimeout(100); - expect(await editorA.innerText()).toBe('abc\n' + ZERO_WIDTH_SPACE + '\nbbb'); - expect(await editorB.innerText()).toBe('abc\n' + ZERO_WIDTH_SPACE + '\nbbb'); + await expect(editorA).toHaveText('abc\n' + ZERO_WIDTH_SPACE + '\nbbb', { + useInnerText: true, // for multi-line text + }); + await expect(editorB).toHaveText('abc\n' + ZERO_WIDTH_SPACE + '\nbbb', { + useInnerText: true, // for multi-line text + }); await editorAUndo.click(); - expect(await editorA.innerText()).toBe('abc'); - expect(await editorB.innerText()).toBe('abc'); + await expect(editorA).toHaveText('abc'); + await expect(editorB).toHaveText('abc'); await editorARedo.click(); - expect(await editorA.innerText()).toBe('abc\n' + ZERO_WIDTH_SPACE + '\nbbb'); - expect(await editorB.innerText()).toBe('abc\n' + ZERO_WIDTH_SPACE + '\nbbb'); + await expect(editorA).toHaveText('abc\n' + ZERO_WIDTH_SPACE + '\nbbb', { + useInnerText: true, // for multi-line text + }); + await expect(editorB).toHaveText('abc\n' + ZERO_WIDTH_SPACE + '\nbbb', { + useInnerText: true, // for multi-line text + }); await focusInlineRichText(page); await page.waitForTimeout(100); - await press(page, 'Backspace'); - await press(page, 'Backspace'); - await press(page, 'Backspace'); - await press(page, 'Backspace'); - await press(page, 'Backspace'); + await pressBackspace(page, 5); - expect(await editorA.innerText()).toBe('abc'); - expect(await editorB.innerText()).toBe('abc'); + await expect(editorA).toHaveText('abc'); + await expect(editorB).toHaveText('abc'); await editorAUndo.click(); - expect(await editorA.innerText()).toBe('abc\n' + ZERO_WIDTH_SPACE + '\nbbb'); - expect(await editorB.innerText()).toBe('abc\n' + ZERO_WIDTH_SPACE + '\nbbb'); + await expect(editorA).toHaveText('abc\n' + ZERO_WIDTH_SPACE + '\nbbb', { + useInnerText: true, // for multi-line text + }); + await expect(editorB).toHaveText('abc\n' + ZERO_WIDTH_SPACE + '\nbbb', { + useInnerText: true, // for multi-line text + }); await editorARedo.click(); - expect(await editorA.innerText()).toBe('abc'); + await expect(editorA).toHaveText('abc'); + await expect(editorB).toHaveText('abc'); await focusInlineRichText(page); await page.waitForTimeout(100); @@ -289,17 +295,17 @@ test('basic input', async ({ page }) => { await press(page, 'ArrowRight'); await type(page, 'dd'); - expect(await editorA.innerText()).toBe('abbbcdd'); - expect(await editorB.innerText()).toBe('abbbcdd'); + await expect(editorA).toHaveText('abbbcdd'); + await expect(editorB).toHaveText('abbbcdd'); await editorAUndo.click(); - expect(await editorA.innerText()).toBe('abc'); + await expect(editorA).toHaveText('abc'); await editorARedo.click(); - expect(await editorA.innerText()).toBe('abbbcdd'); - expect(await editorB.innerText()).toBe('abbbcdd'); + await expect(editorA).toHaveText('abbbcdd'); + await expect(editorB).toHaveText('abbbcdd'); await focusInlineRichText(page); await page.waitForTimeout(100); @@ -308,29 +314,42 @@ test('basic input', async ({ page }) => { await press(page, 'Enter'); await press(page, 'Enter'); - expect(await editorA.innerText()).toBe('abbbc\n' + ZERO_WIDTH_SPACE + '\ndd'); - expect(await editorB.innerText()).toBe('abbbc\n' + ZERO_WIDTH_SPACE + '\ndd'); + await expect(editorA).toHaveText('abbbc\n' + ZERO_WIDTH_SPACE + '\ndd', { + useInnerText: true, // for multi-line text + }); + await expect(editorB).toHaveText('abbbc\n' + ZERO_WIDTH_SPACE + '\ndd', { + useInnerText: true, // for multi-line text + }); await editorAUndo.click(); - expect(await editorA.innerText()).toBe('abbbcdd'); - expect(await editorB.innerText()).toBe('abbbcdd'); + await expect(editorA).toHaveText('abbbcdd'); + await expect(editorB).toHaveText('abbbcdd'); await editorARedo.click(); - expect(await editorA.innerText()).toBe('abbbc\n' + ZERO_WIDTH_SPACE + '\ndd'); - expect(await editorB.innerText()).toBe('abbbc\n' + ZERO_WIDTH_SPACE + '\ndd'); + await expect(editorA).toHaveText('abbbc\n' + ZERO_WIDTH_SPACE + '\ndd', { + useInnerText: true, // for multi-line text + }); + await expect(editorB).toHaveText('abbbc\n' + ZERO_WIDTH_SPACE + '\ndd', { + useInnerText: true, // for multi-line text + }); }); -test('chinese input', async ({ page }) => { +test('chinese input', async ({ page, browserName }) => { + test.skip( + browserName !== 'chromium', + 'CDPSession is only supported in chromium' + ); + await enterInlineEditorPlayground(page); await focusInlineRichText(page); const editorA = page.locator('[data-v-root="true"]').nth(0); const editorB = page.locator('[data-v-root="true"]').nth(1); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); - expect(await editorB.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); + await expect(editorB).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); const client = await page.context().newCDPSession(page); @@ -347,8 +366,8 @@ test('chinese input', async ({ page }) => { await client.send('Input.insertText', { text: '你', }); - expect(await editorA.innerText()).toBe('你'); - expect(await editorB.innerText()).toBe('你'); + await expect(editorA).toHaveText('你'); + await expect(editorB).toHaveText('你'); }); test('type many times in one moment', async ({ page }) => { @@ -377,15 +396,15 @@ test('readonly mode', async ({ page }) => { const editorA = page.locator('[data-v-root="true"]').nth(0); const editorB = page.locator('[data-v-root="true"]').nth(1); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); - expect(await editorB.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); + await expect(editorB).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); await type(page, 'abcdefg'); - expect(await editorA.innerText()).toBe('abcdefg'); - expect(await editorB.innerText()).toBe('abcdefg'); + await expect(editorA).toHaveText('abcdefg'); + await expect(editorB).toHaveText('abcdefg'); await page.evaluate(() => { const richTextA = document @@ -402,8 +421,8 @@ test('readonly mode', async ({ page }) => { await type(page, 'aaaa'); - expect(await editorA.innerText()).toBe('abcdefg'); - expect(await editorB.innerText()).toBe('abcdefg'); + await expect(editorA).toHaveText('abcdefg'); + await expect(editorB).toHaveText('abcdefg'); }); test('basic styles', async ({ page }) => { @@ -422,18 +441,18 @@ test('basic styles', async ({ page }) => { const editorAUndo = page.getByText('undo').nth(0); const editorARedo = page.getByText('redo').nth(0); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); - expect(await editorB.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); + await expect(editorB).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); await type(page, 'abcdefg'); - expect(await editorA.innerText()).toBe('abcdefg'); - expect(await editorB.innerText()).toBe('abcdefg'); + await expect(editorA).toHaveText('abcdefg'); + await expect(editorB).toHaveText('abcdefg'); let delta = await getDeltaFromInlineRichText(page); - expect(delta).toEqual([ + await expect(delta).toEqual([ { insert: 'abcdefg', }, @@ -677,15 +696,15 @@ test('overlapping styles', async ({ page }) => { const editorAUndo = page.getByText('undo').nth(0); const editorARedo = page.getByText('redo').nth(0); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); - expect(await editorB.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); + await expect(editorB).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); await type(page, 'abcdefghijk'); - expect(await editorA.innerText()).toBe('abcdefghijk'); - expect(await editorB.innerText()).toBe('abcdefghijk'); + await expect(editorA).toHaveText('abcdefghijk'); + await expect(editorB).toHaveText('abcdefghijk'); let delta = await getDeltaFromInlineRichText(page); expect(delta).toEqual([ @@ -849,15 +868,15 @@ test('input continuous spaces', async ({ page }) => { const editorA = page.locator('[data-v-root="true"]').nth(0); const editorB = page.locator('[data-v-root="true"]').nth(1); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); - expect(await editorB.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); + await expect(editorB).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); await type(page, 'abc def'); - expect(await editorA.innerText()).toBe('abc def'); - expect(await editorB.innerText()).toBe('abc def'); + await expect(editorA).toHaveText('abc def'); + await expect(editorB).toHaveText('abc def'); await focusInlineRichText(page); await page.waitForTimeout(100); @@ -868,8 +887,12 @@ test('input continuous spaces', async ({ page }) => { await press(page, 'Enter'); - expect(await editorA.innerText()).toBe('abc \n' + ' def'); - expect(await editorB.innerText()).toBe('abc \n' + ' def'); + await expect(editorA).toHaveText('abc \n' + ' def', { + useInnerText: true, // for multi-line text + }); + await expect(editorB).toHaveText('abc \n' + ' def', { + useInnerText: true, // for multi-line text + }); }); test('select from the start of line using shift+arrow', async ({ page }) => { @@ -879,8 +902,8 @@ test('select from the start of line using shift+arrow', async ({ page }) => { const editorA = page.locator('[data-v-root="true"]').nth(0); const editorB = page.locator('[data-v-root="true"]').nth(1); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); - expect(await editorB.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); + await expect(editorB).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); @@ -890,8 +913,12 @@ test('select from the start of line using shift+arrow', async ({ page }) => { await press(page, 'Enter'); await type(page, 'ghi'); - expect(await editorA.innerText()).toBe('abc\ndef\nghi'); - expect(await editorB.innerText()).toBe('abc\ndef\nghi'); + await expect(editorB).toHaveText('abc\ndef\nghi', { + useInnerText: true, // for multi-line text + }); + await expect(editorA).toHaveText('abc\ndef\nghi', { + useInnerText: true, // for multi-line text + }); /** * abc @@ -920,11 +947,11 @@ test('select from the start of line using shift+arrow', async ({ page }) => { */ await press(page, 'ArrowRight'); await assertSelection(page, 0, 1, 7); - await press(page, 'Backspace'); + await pressBackspace(page); await page.waitForTimeout(100); - expect(await editorA.innerText()).toBe('aghi'); - expect(await editorB.innerText()).toBe('aghi'); + await expect(editorA).toHaveText('aghi'); + await expect(editorB).toHaveText('aghi'); }); test('getLine', async ({ page }) => { @@ -934,15 +961,19 @@ test('getLine', async ({ page }) => { const editorA = page.locator('[data-v-root="true"]').nth(0); const editorB = page.locator('[data-v-root="true"]').nth(1); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); - expect(await editorB.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); + await expect(editorB).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); await type(page, 'abc\ndef\nghi'); - expect(await editorA.innerText()).toBe('abc\ndef\nghi'); - expect(await editorB.innerText()).toBe('abc\ndef\nghi'); + await expect(editorA).toHaveText('abc\ndef\nghi', { + useInnerText: true, // for multi-line text + }); + await expect(editorB).toHaveText('abc\ndef\nghi', { + useInnerText: true, // for multi-line text + }); const [line1, offset1] = await getInlineRichTextLine(page, 0); const [line2, offset2] = await getInlineRichTextLine(page, 1); @@ -1001,14 +1032,13 @@ test('embed', async ({ page }) => { const editorA = page.locator('[data-v-root="true"]').nth(0); const editorAEmbed = page.getByText('embed').nth(0); - - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); await type(page, 'abcde'); - expect(await editorA.innerText()).toBe('abcde'); + await expect(editorA).toHaveText('abcde'); await press(page, 'ArrowLeft'); await page.waitForTimeout(100); @@ -1022,7 +1052,7 @@ test('embed', async ({ page }) => { await editorAEmbed.click(); const embedCount = await page.locator('[data-v-embed="true"]').count(); - expect(embedCount).toBe(3); + await expect(embedCount).toBe(3); // try to update cursor position using arrow keys await assertSelection(page, 0, 1, 3); @@ -1071,10 +1101,10 @@ test('delete embed when pressing backspace after embed', async ({ page }) => { const editorA = page.locator('[data-v-root="true"]').nth(0); const editorAEmbed = page.getByText('embed').nth(0); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); await type(page, 'ab'); - expect(await editorA.innerText()).toBe('ab'); + await expect(editorA).toHaveText('ab'); await page.keyboard.down('Shift'); await press(page, 'ArrowLeft'); @@ -1100,7 +1130,7 @@ test('delete embed when pressing backspace after embed', async ({ page }) => { // use click to select right side of the embed instead of use arrow key await page.mouse.click(rect.x + 3, rect.y); await assertSelection(page, 0, 2, 0); - await press(page, 'Backspace'); + await pressBackspace(page); delta = await getDeltaFromInlineRichText(page); expect(delta).toEqual([ @@ -1116,11 +1146,13 @@ test('triple click to select line', async ({ page }) => { const editorA = page.locator('[data-v-root="true"]').nth(0); - expect(await editorA.innerText()).toBe(ZERO_WIDTH_SPACE); + await expect(editorA).toHaveText(ZERO_WIDTH_SPACE); await page.waitForTimeout(100); await type(page, 'abc\nabc abc abc\nabc'); - expect(await editorA.innerText()).toBe('abc\nabc abc abc\nabc'); + await expect(editorA).toHaveText('abc\nabc abc abc\nabc', { + useInnerText: true, // for multi-line text + }); const rect = await getInlineRangeIndexRect(page, [0, 10]); await page.mouse.click(rect.x, rect.y, { @@ -1128,8 +1160,10 @@ test('triple click to select line', async ({ page }) => { }); await assertSelection(page, 0, 4, 11); - await press(page, 'Backspace'); - expect(await editorA.innerText()).toBe('abc\n' + ZERO_WIDTH_SPACE + '\nabc'); + await pressBackspace(page); + await expect(editorA).toHaveText('abc\n' + ZERO_WIDTH_SPACE + '\nabc', { + useInnerText: true, // for multi-line text + }); }); test('caret should move correctly when inline elements are exist', async ({