diff --git a/tests/affine-cloud/e2e/share-page.spec.ts b/tests/affine-cloud/e2e/share-page.spec.ts index 46a3b5072..fb9edab07 100644 --- a/tests/affine-cloud/e2e/share-page.spec.ts +++ b/tests/affine-cloud/e2e/share-page.spec.ts @@ -5,13 +5,18 @@ import { enableShare, loginUser, } from '@affine-test/kit/utils/cloud'; -import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor'; +import { + clickEdgelessModeButton, + getParagraphIds, +} from '@affine-test/kit/utils/editor'; import { importImage } from '@affine-test/kit/utils/image'; +import { copyByKeyboard } from '@affine-test/kit/utils/keyboard'; import { clickNewPageButton, getBlockSuiteEditorTitle, waitForEditorLoad, } from '@affine-test/kit/utils/page-logic'; +import { setSelection } from '@affine-test/kit/utils/selection'; import { createLocalWorkspace } from '@affine-test/kit/utils/workspace'; import { expect } from '@playwright/test'; @@ -405,3 +410,48 @@ test('Inline latex modal should be not shown in shared mode when clicking', asyn await expect(modalLocator).not.toBeVisible(); } }); + +test('share page should support copying content', async ({ page, browser }) => { + await page.reload(); + await waitForEditorLoad(page); + await createLocalWorkspace( + { + name: 'test', + }, + page + ); + await enableCloudWorkspaceFromShareButton(page); + const title = getBlockSuiteEditorTitle(page); + await title.pressSequentially('TEST TITLE', { + delay: 50, + }); + await page.keyboard.press('Enter', { delay: 50 }); + await page.keyboard.type('Hello World'); + + // enable share page and copy page link + await enableShare(page); + await page.getByTestId('share-menu-copy-link-button').click(); + await page.getByTestId('share-link-menu-copy-page').click(); + + // check share page is accessible and content can be copied + { + const context = await browser.newContext(); + await skipOnboarding(context); + const url: string = await page.evaluate(() => + navigator.clipboard.readText() + ); + const page2 = await context.newPage(); + await page2.goto(url); + await waitForEditorLoad(page2); + + const { blockIds: paragraphIds } = await getParagraphIds(page2); + await setSelection(page2, paragraphIds[0], 0, paragraphIds[0], 11); + await copyByKeyboard(page2); + + // Verify copied content + const copiedText = await page2.evaluate(() => + navigator.clipboard.readText() + ); + expect(copiedText).toContain('Hello World'); + } +}); diff --git a/tests/affine-local/e2e/blocksuite/clipboard/clipboard.spec.ts b/tests/affine-local/e2e/blocksuite/clipboard/clipboard.spec.ts index 416575b0a..4dce82296 100644 --- a/tests/affine-local/e2e/blocksuite/clipboard/clipboard.spec.ts +++ b/tests/affine-local/e2e/blocksuite/clipboard/clipboard.spec.ts @@ -3,6 +3,8 @@ import { pasteContent } from '@affine-test/kit/utils/clipboard'; import { clickEdgelessModeButton, clickPageModeButton, + getCodeBlockIds, + getParagraphIds, locateEditorContainer, } from '@affine-test/kit/utils/editor'; import { @@ -84,28 +86,6 @@ async function verifyCodeBlockContent( ); } -// Helper function to get block ids -async function getBlockIds( - page: Page, - selector: string -) { - const blocks = page.locator(selector); - const blockIds = await blocks.evaluateAll((blocks: T[]) => - blocks.map(block => block.model.id) - ); - return { blockIds }; -} - -// Helper functions using the generic getBlockIds -async function getParagraphIds(page: Page) { - return getBlockIds(page, paragraphLocator); -} - -// Helper functions using the generic getBlockIds -async function getCodeBlockIds(page: Page) { - return getBlockIds(page, codeBlockLocator); -} - test.beforeEach(async ({ page }) => { await openHomePage(page); await clickNewPageButton(page, 'Clipboard Test'); diff --git a/tests/kit/src/utils/editor.ts b/tests/kit/src/utils/editor.ts index a45437ac1..fb059281c 100644 --- a/tests/kit/src/utils/editor.ts +++ b/tests/kit/src/utils/editor.ts @@ -1,5 +1,8 @@ import type * as BlocksuiteEffects from '@blocksuite/affine/effects'; import type { IVec, XYWH } from '@blocksuite/affine/global/gfx'; +import type { CodeBlockComponent } from '@blocksuite/affine-block-code'; +import type { ParagraphBlockComponent } from '@blocksuite/affine-block-paragraph'; +import type { BlockComponent } from '@blocksuite/std'; import { expect, type Locator, type Page } from '@playwright/test'; declare type _GLOBAL_ = typeof BlocksuiteEffects; @@ -11,6 +14,9 @@ export function inlineEditorInnerTextToString(innerText: string): string { return innerText.replace(ZERO_WIDTH_SPACE, '').trim(); } +const PARAGRAPH_BLOCK_LOCATOR = 'affine-paragraph'; +const CODE_BLOCK_LOCATOR = 'affine-code'; + export function locateModeSwitchButton( page: Page, mode: 'page' | 'edgeless', @@ -475,3 +481,25 @@ export async function createEdgelessNoteBlock( await clickView(page, position, editorIndex); } } + +// Helper function to get block ids +export async function getBlockIds( + page: Page, + selector: string +) { + const blocks = page.locator(selector); + const blockIds = await blocks.evaluateAll((blocks: T[]) => + blocks.map(block => block.model.id) + ); + return { blockIds }; +} + +// Helper functions using the generic getBlockIds +export async function getParagraphIds(page: Page) { + return getBlockIds(page, PARAGRAPH_BLOCK_LOCATOR); +} + +// Helper functions using the generic getBlockIds +export async function getCodeBlockIds(page: Page) { + return getBlockIds(page, CODE_BLOCK_LOCATOR); +}