From 002b9e80f8937cace707b3479cdf1612c8927dec Mon Sep 17 00:00:00 2001 From: pengx17 Date: Fri, 31 May 2024 10:28:42 +0000 Subject: [PATCH] feat: e2e tests for peek view (#7112) fix AFF-1163 --- .../block-suite-editor/lit-adaper.tsx | 13 +- .../block-suite-mode-switch/switch-items.tsx | 1 + .../favorite/favourite-nav-item.tsx | 1 + .../core/src/components/workspace/index.tsx | 1 + .../peek-view/view/peek-view-manager.tsx | 2 +- .../modules/workbench/view/workbench-link.tsx | 4 +- tests/affine-local/e2e/peek-view.spec.ts | 198 ++++++++++++++++++ tests/kit/utils/editor.ts | 12 +- tests/kit/utils/page-logic.ts | 6 +- 9 files changed, 226 insertions(+), 12 deletions(-) create mode 100644 tests/affine-local/e2e/peek-view.spec.ts diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/lit-adaper.tsx b/packages/frontend/core/src/components/blocksuite/block-suite-editor/lit-adaper.tsx index 5c04d6274a..18b6e0c99a 100644 --- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/lit-adaper.tsx +++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/lit-adaper.tsx @@ -86,9 +86,18 @@ const usePatchSpecs = (page: Doc, specs: BlockSpec[]) => { patchReferenceRenderer(patched, reactToLit, referenceRenderer), confirmModal ); - patched = patchPeekViewService(patched, peekViewService); + if (!page.readonly) { + patched = patchPeekViewService(patched, peekViewService); + } return patched; - }, [confirmModal, peekViewService, reactToLit, referenceRenderer, specs]); + }, [ + confirmModal, + page.readonly, + peekViewService, + reactToLit, + referenceRenderer, + specs, + ]); return [ patchedSpecs, diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-mode-switch/switch-items.tsx b/packages/frontend/core/src/components/blocksuite/block-suite-mode-switch/switch-items.tsx index cb9f4b20f6..c293225cc5 100644 --- a/packages/frontend/core/src/components/blocksuite/block-suite-mode-switch/switch-items.tsx +++ b/packages/frontend/core/src/components/blocksuite/block-suite-mode-switch/switch-items.tsx @@ -26,6 +26,7 @@ const HoverAnimateController = ({ { setStartAnimate(true); diff --git a/packages/frontend/core/src/components/pure/workspace-slider-bar/favorite/favourite-nav-item.tsx b/packages/frontend/core/src/components/pure/workspace-slider-bar/favorite/favourite-nav-item.tsx index 48b58248f4..cea313e4c1 100644 --- a/packages/frontend/core/src/components/pure/workspace-slider-bar/favorite/favourite-nav-item.tsx +++ b/packages/frontend/core/src/components/pure/workspace-slider-bar/favorite/favourite-nav-item.tsx @@ -100,6 +100,7 @@ export const FavouriteDocSidebarNavItem = ({ {children} diff --git a/packages/frontend/core/src/modules/peek-view/view/peek-view-manager.tsx b/packages/frontend/core/src/modules/peek-view/view/peek-view-manager.tsx index ef8d026d07..c64f217f00 100644 --- a/packages/frontend/core/src/modules/peek-view/view/peek-view-manager.tsx +++ b/packages/frontend/core/src/modules/peek-view/view/peek-view-manager.tsx @@ -42,7 +42,7 @@ export const PeekViewManagerModal = () => { return ( ) => { + event.preventDefault(); + event.stopPropagation(); if (onClick?.(event)) { return; } - event.preventDefault(); - event.stopPropagation(); if (event.ctrlKey || event.metaKey) { if (appSettings.enableMultiView && environment.isDesktop) { diff --git a/tests/affine-local/e2e/peek-view.spec.ts b/tests/affine-local/e2e/peek-view.spec.ts new file mode 100644 index 0000000000..0cea451fe8 --- /dev/null +++ b/tests/affine-local/e2e/peek-view.spec.ts @@ -0,0 +1,198 @@ +import { test } from '@affine-test/kit/playwright'; +import { + clickEdgelessModeButton, + clickPageModeButton, +} from '@affine-test/kit/utils/editor'; +import { openHomePage } from '@affine-test/kit/utils/load-page'; +import { + clickNewPageButton, + createLinkedPage, + waitForEmptyEditor, +} from '@affine-test/kit/utils/page-logic'; +import { expect } from '@playwright/test'; + +test.beforeEach(async ({ page }) => { + await openHomePage(page); + await clickNewPageButton(page); + await waitForEmptyEditor(page); +}); + +test('can open peek view via link popover', async ({ page }) => { + await page.keyboard.press('Enter'); + await createLinkedPage(page, 'Test Page'); + + await page.locator('affine-reference').hover(); + await expect( + page.locator('.affine-reference-popover-container') + ).toBeVisible(); + + // click more button + await page + .locator('.affine-reference-popover-container') + .locator('icon-button') + .last() + .click(); + await page.locator('icon-button:has-text("center peek")').click(); + + // verify peek view is opened + await expect(page.getByTestId('peek-view-modal')).toBeVisible(); + await expect(page.getByTestId('peek-view-modal')).toContainText('Test Page'); + + // can use 'esc' to close peek view + await page.keyboard.press('Escape'); + await expect(page.getByTestId('peek-view-modal')).not.toBeVisible(); +}); + +test('can open peek view via shift+click link', async ({ page }) => { + await page.keyboard.press('Enter'); + await createLinkedPage(page, 'Test Page'); + + await page.locator('affine-reference').click({ modifiers: ['Shift'] }); + + // verify peek view is opened + await expect(page.getByTestId('peek-view-modal')).toBeVisible(); + await expect(page.getByTestId('peek-view-modal')).toContainText('Test Page'); + + // can use 'esc' to close peek view + await page.keyboard.press('Escape'); + await expect(page.getByTestId('peek-view-modal')).not.toBeVisible(); +}); + +test('can open peek view via db+click link card', async ({ page }) => { + await page.keyboard.press('Enter'); + await createLinkedPage(page, 'Test Page'); + + await page.locator('affine-reference').hover(); + await expect( + page.locator('.affine-reference-popover-container') + ).toBeVisible(); + + await page + .locator('.affine-reference-popover-container') + .locator('.affine-reference-popover-view-selector-button.embed.card-view') + .click(); + + await expect( + page.locator('affine-embed-linked-doc-block:has-text("Test Page")') + ).toBeVisible(); + + // double click to open peek view + await page.locator('affine-embed-linked-doc-block').dblclick(); + + // verify peek view is opened + await expect(page.getByTestId('peek-view-modal')).toBeVisible(); + await expect(page.getByTestId('peek-view-modal')).toContainText('Test Page'); + + // verify peek view can be closed by clicking close button + await page + .locator('[data-testid="peek-view-control"][data-action-name="close"]') + .click(); + + await expect(page.getByTestId('peek-view-modal')).not.toBeVisible(); + + // double click to open peek view + await page.locator('affine-embed-linked-doc-block').dblclick(); + + // check if open-in-new button works + await page + .locator('[data-testid="peek-view-control"][data-action-name="open"]') + .click(); + + // verify page is routed to the linked page + await expect( + page + .getByTestId('main-container') + .locator('doc-title:has-text("Test Page")') + ).toBeVisible(); +}); + +test('can open peek view for embedded frames', async ({ page }) => { + await page.keyboard.press('Enter'); + + // create a frame + await page.keyboard.insertText('```frame\nTest Frame\n```'); + + await clickEdgelessModeButton(page); + + // select the note + await page + .locator('affine-note:has-text("Test Frame")') + .click({ force: true }); + // enter F to create a frame + await page.keyboard.press('f'); + + // insert the frame to page + await page + .locator('edgeless-change-frame-button:has-text("Insert into Page")') + .click(); + + // switch back to page mode + await clickPageModeButton(page); + + // hover the frame to trigger surface-ref-toolbar + await page.locator('affine-surface-ref .affine-surface-ref').hover(); + + await page + .locator('.surface-ref-toolbar-container') + .locator('icon-button:has-text("center peek")') + .click(); + + // verify peek view is opened + await expect(page.getByTestId('peek-view-modal')).toBeVisible(); + + // check if page is in edgeless mode + await expect( + page.locator('edgeless-editor').locator('edgeless-block-portal-frame') + ).toBeInViewport(); + + // close peek view + await page.keyboard.press('Escape'); + + // check if can open peek view by shift+click + await page + .locator('affine-surface-ref .affine-surface-ref') + .click({ modifiers: ['Shift'] }); + + // check if page is in edgeless mode + await expect( + page.locator('edgeless-editor').locator('edgeless-block-portal-frame') + ).toBeInViewport(); + + // close peek view + await page.keyboard.press('Escape'); + + // check if can open peek view by double click + await page.locator('affine-surface-ref .affine-surface-ref').dblclick(); + // check if page is in edgeless mode + await expect( + page.locator('edgeless-editor').locator('edgeless-block-portal-frame') + ).toBeInViewport(); + + // can close modal when navigate + await openHomePage(page); + await expect(page.getByTestId('peek-view-modal')).not.toBeVisible(); +}); + +test.skip('can open peek view for fav link', async ({ page }) => { + // give current page a title + await page.keyboard.insertText('test page title'); + await page.getByTestId('pin-button').click(); + await expect(page.locator('[data-testid="pin-button"].active')).toBeVisible(); + + await page + .getByTestId('favourites') + .locator('[data-favourite-page-item]:has-text("test page title")') + .click({ + modifiers: ['Shift'], + }); + + // verify peek view is opened + await expect(page.getByTestId('peek-view-modal')).toBeVisible(); + await expect(page.getByTestId('peek-view-modal')).toContainText( + 'test page title' + ); + + // can close modal when navigate + await openHomePage(page); + await expect(page.getByTestId('peek-view-modal')).not.toBeVisible(); +}); diff --git a/tests/kit/utils/editor.ts b/tests/kit/utils/editor.ts index d10c73e2cc..1ce5feaee0 100644 --- a/tests/kit/utils/editor.ts +++ b/tests/kit/utils/editor.ts @@ -1,13 +1,21 @@ -import type { Page } from '@playwright/test'; +import { expect, type Page } from '@playwright/test'; export async function clickEdgelessModeButton(page: Page) { await page.getByTestId('switch-edgeless-mode-button').click({ delay: 50, }); + await expect( + page.locator( + '[data-testid="switch-edgeless-mode-button"][data-active="true"]' + ) + ).toBeVisible(); } export async function clickPageModeButton(page: Page) { - return page.getByTestId('switch-page-mode-button').click({ + page.getByTestId('switch-page-mode-button').click({ delay: 50, }); + await expect( + page.locator('[data-testid="switch-page-mode-button"][data-active="true"]') + ).toBeVisible(); } diff --git a/tests/kit/utils/page-logic.ts b/tests/kit/utils/page-logic.ts index 1807b5f842..bc4fe57aff 100644 --- a/tests/kit/utils/page-logic.ts +++ b/tests/kit/utils/page-logic.ts @@ -45,11 +45,7 @@ export const createLinkedPage = async (page: Page, pageName?: string) => { await page.keyboard.type('@', { delay: 50 }); const linkedPagePopover = page.locator('.linked-doc-popover'); await expect(linkedPagePopover).toBeVisible(); - if (pageName) { - await type(page, pageName); - } else { - pageName = 'Untitled'; - } + await type(page, pageName || 'Untitled'); await page.keyboard.press('ArrowUp'); await page.keyboard.press('ArrowUp');