diff --git a/blocksuite/affine/block-table/src/add-button.ts b/blocksuite/affine/block-table/src/add-button.ts index 6fbbde780..48e01602f 100644 --- a/blocksuite/affine/block-table/src/add-button.ts +++ b/blocksuite/affine/block-table/src/add-button.ts @@ -246,6 +246,7 @@ export class AddButton extends SignalWatcher( this.hoverColumnIndex$.value === this.columns$.value.length - 1; const dragging = this.columnDragging$.value; return html`
{ + await openHomePage(pageA); + await clickNewPageButton(pageA); + await waitForEditorLoad(pageA); + await pageA.keyboard.press('Enter'); + + /** + * | Cell1 | Cell2 | + * | Cell3 | Cell4 | + */ + await createTable(pageA); + const cellsInA = pageA.locator('affine-table-cell'); + const cellCountInA = await cellsInA.count(); + expect(cellCountInA).toBe(4); + + const currentUrl = pageA.url(); + + const pageB = await context.newPage(); + await pageB.goto(currentUrl); + await waitForEditorLoad(pageB); + await pageB.keyboard.press('Enter'); + + const tableInB = pageB.locator('affine-table'); + await expect(tableInB).toBeVisible(); + const cellsInB = tableInB.locator('affine-table-cell'); + expect(await cellsInB.count()).toBe(cellCountInA); + + expect(await getCellText(pageB, 0)).toBe('Cell1'); + expect(await getCellText(pageB, 3)).toBe('Cell4'); + + await cellsInB.last().hover(); + const addColumnButton = tableInB.locator('data-testid=add-column-button'); + expect(await addColumnButton.isVisible()).toBe(true); + await addColumnButton.click(); + + expect(await cellsInA.count()).toBe(6); + expect(await cellsInB.count()).toBe(6); + + // new created cells should be synced to both page + /** + * | Cell1 | Cell2 | Cell5 | + * | Cell3 | Cell4 | Cell6 | + */ + await inputToCell(pageA, 2, 'Cell5'); + await inputToCell(pageA, 5, 'Cell6'); + expect(await getCellText(pageB, 2)).toBe('Cell5'); + expect(await getCellText(pageB, 5)).toBe('Cell6'); + + await cellsInB.last().hover(); + const addRowButton = tableInB.locator('data-testid=add-row-button'); + expect(await addRowButton.isVisible()).toBe(true); + await addRowButton.click(); + + expect(await cellsInA.count()).toBe(9); + expect(await cellsInB.count()).toBe(9); + + // new created cells should be synced to both page + /** + * | Cell1 | Cell2 | Cell5 | + * | Cell3 | Cell4 | Cell6 | + * | Cell7 | Cell8 | Cell9 | + */ + await inputToCell(pageA, 6, 'Cell7'); + await inputToCell(pageA, 7, 'Cell8'); + await inputToCell(pageA, 8, 'Cell9'); + expect(await getCellText(pageB, 6)).toBe('Cell7'); + expect(await getCellText(pageB, 7)).toBe('Cell8'); + expect(await getCellText(pageB, 8)).toBe('Cell9'); + + // delete a column + await cellsInA.nth(1).hover(); + const dragColumnHandle = cellsInA + .nth(1) + .locator('data-testid=drag-column-handle'); + expect(await dragColumnHandle.isVisible()).toBe(true); + await dragColumnHandle.click(); + + await clickDeleteButtonInTableMenu(pageA); + /** + * | Cell1 | Cell5 | + * | Cell3 | Cell6 | + * | Cell7 | Cell9 | + */ + expect(await cellsInA.count()).toBe(6); + expect(await cellsInB.count()).toBe(6); + + expect(await getCellText(pageB, 0)).toBe('Cell1'); + expect(await getCellText(pageB, 1)).toBe('Cell5'); + expect(await getCellText(pageB, 2)).toBe('Cell3'); + expect(await getCellText(pageB, 3)).toBe('Cell6'); + expect(await getCellText(pageB, 4)).toBe('Cell7'); + expect(await getCellText(pageB, 5)).toBe('Cell9'); + + // delete a row + await cellsInB.nth(0).hover(); + const dragRowHandle = cellsInB.nth(0).locator('data-testid=drag-row-handle'); + expect(await dragRowHandle.isVisible()).toBe(true); + await dragRowHandle.click(); + + await clickDeleteButtonInTableMenu(pageB); + /** + * | Cell3 | Cell6 | + * | Cell7 | Cell9 | + */ + expect(await cellsInA.count()).toBe(4); + expect(await cellsInB.count()).toBe(4); + + expect(await getCellText(pageB, 0)).toBe('Cell3'); + expect(await getCellText(pageB, 1)).toBe('Cell6'); + expect(await getCellText(pageB, 2)).toBe('Cell7'); + expect(await getCellText(pageB, 3)).toBe('Cell9'); +}); diff --git a/tests/kit/package.json b/tests/kit/package.json index 47718e922..9be18de96 100644 --- a/tests/kit/package.json +++ b/tests/kit/package.json @@ -7,7 +7,8 @@ "./electron": "./src/electron.ts", "./mobile": "./src/mobile.ts", "./playwright": "./src/playwright.ts", - "./utils/*": "./src/utils/*.ts" + "./utils/*": "./src/utils/*.ts", + "./bs/*": "./src/bs/*.ts" }, "devDependencies": { "@affine-tools/utils": "workspace:*", diff --git a/tests/kit/src/bs/misc.ts b/tests/kit/src/bs/misc.ts new file mode 100644 index 000000000..b321102f8 --- /dev/null +++ b/tests/kit/src/bs/misc.ts @@ -0,0 +1,7 @@ +import type { Page } from '@playwright/test'; + +export async function waitNextFrame(page: Page) { + await page.evaluate( + () => new Promise(resolve => requestAnimationFrame(resolve)) + ); +} diff --git a/tests/kit/src/bs/table.ts b/tests/kit/src/bs/table.ts new file mode 100644 index 000000000..bdd368bcb --- /dev/null +++ b/tests/kit/src/bs/table.ts @@ -0,0 +1,53 @@ +import { expect, type Locator, type Page } from '@playwright/test'; + +import { waitNextFrame } from './misc'; + +export async function createTable(page: Page) { + await page.keyboard.press('/'); + await expect(page.locator('affine-slash-menu .slash-menu')).toBeVisible(); + await page.keyboard.type('table'); + await page.keyboard.press('Enter'); + await waitNextFrame(page); + const table = page.locator('affine-table'); + + await expect(table).toBeVisible(); + const cells = table.locator('affine-table-cell'); + const cellCount = await cells.count(); + expect(cellCount).toBe(4); + + for (let i = 0; i < cellCount; i++) { + await inputToCell(page, i, `Cell${i + 1}`); + } +} + +export async function getCellText(page: Page, nth: number, table?: Locator) { + table = table ?? page.locator('affine-table'); + const cell = table.locator('affine-table-cell').nth(nth); + await cell.hover(); + await waitNextFrame(page); + return cell.locator('v-line').innerText(); +} + +export async function inputToCell( + page: Page, + nth: number, + text: string, + table?: Locator +) { + table = table ?? page.locator('affine-table'); + const cell = table.locator('affine-table-cell').nth(nth); + await cell.hover(); + await waitNextFrame(page); + await cell.click(); + await cell.click(); + await waitNextFrame(page); + await page.keyboard.type(text, { delay: 20 }); +} + +export async function clickDeleteButtonInTableMenu(page: Page) { + const menu = page.locator('affine-menu'); + await expect(menu).toBeVisible(); + const deleteButton = menu.getByText('Delete'); + await expect(deleteButton).toBeVisible(); + await deleteButton.click(); +}