diff --git a/packages/frontend/core/src/modules/peek-view/entities/peek-view.ts b/packages/frontend/core/src/modules/peek-view/entities/peek-view.ts index 9dfe4935d6280..2ce82f61d8801 100644 --- a/packages/frontend/core/src/modules/peek-view/entities/peek-view.ts +++ b/packages/frontend/core/src/modules/peek-view/entities/peek-view.ts @@ -119,34 +119,25 @@ function resolvePeekInfoFromPeekTarget( if (element instanceof AffineReference) { const referenceInfo = element.referenceInfo; if (referenceInfo) { - const { pageId: docId } = referenceInfo; + const { pageId: docId, params } = referenceInfo; const info: DocPeekViewInfo = { type: 'doc', - docRef: { - docId, - }, + docRef: { docId, ...params }, }; - Object.assign(info, referenceInfo.params); return info; } } else if ('model' in element) { const blockModel = element.model; - if (isEmbedLinkedDocModel(blockModel)) { + if ( + isEmbedLinkedDocModel(blockModel) || + isEmbedSyncedDocModel(blockModel) + ) { + const { pageId: docId, params } = blockModel; const info: DocPeekViewInfo = { type: 'doc', - docRef: { - docId: blockModel.pageId, - }, + docRef: { docId, ...params }, }; - Object.assign(info, blockModel.params); return info; - } else if (isEmbedSyncedDocModel(blockModel)) { - return { - type: 'doc', - docRef: { - docId: blockModel.pageId, - }, - }; } else if (isSurfaceRefModel(blockModel)) { const refModel = (element as SurfaceRefBlockComponent).referenceModel; // refModel can be null if the reference is invalid diff --git a/tests/affine-local/e2e/links.spec.ts b/tests/affine-local/e2e/links.spec.ts new file mode 100644 index 0000000000000..42429687f8d1b --- /dev/null +++ b/tests/affine-local/e2e/links.spec.ts @@ -0,0 +1,246 @@ +import { test } from '@affine-test/kit/playwright'; +import { + pasteByKeyboard, + writeTextToClipboard, +} from '@affine-test/kit/utils/keyboard'; +import { openHomePage } from '@affine-test/kit/utils/load-page'; +import { + clickNewPageButton, + createLinkedPage, + waitForEmptyEditor, +} from '@affine-test/kit/utils/page-logic'; +import { expect, type Locator } from '@playwright/test'; + +test.beforeEach(async ({ page }) => { + await openHomePage(page); + await clickNewPageButton(page); + await waitForEmptyEditor(page); +}); + +async function notClickable(locator: Locator) { + await expect(locator).toHaveAttribute('disabled', ''); +} + +async function clickable(locator: Locator) { + await expect(locator).not.toHaveAttribute('disabled', ''); +} + +test('not allowed to switch to embed view when linking to the same document', async ({ + page, +}) => { + await page.keyboard.press('Enter'); + + const url0 = new URL(page.url()); + + await writeTextToClipboard(page, url0.toString()); + await pasteByKeyboard(page); + + const switchViewBtn = page.locator('Switch view'); + const linkToInlineBtn = page.getByTestId('link-to-inline'); + const linkToCardBtn = page.getByTestId('link-to-card'); + const linkToEmbedBtn = page.getByTestId('link-to-embed'); + + // Inline + await page.locator('affine-reference').hover(); + await page.waitForTimeout(300); + await switchViewBtn.click(); + + await notClickable(linkToInlineBtn); + await clickable(linkToCardBtn); + await notClickable(linkToEmbedBtn); + + // Switches to card view + await linkToCardBtn.click(); + + // Card + await page.locator('affine-embed-linked-doc-block').click(); + // await switchViewBtn.click(); + + await clickable(linkToInlineBtn); + await notClickable(linkToCardBtn); + await notClickable(linkToEmbedBtn); +}); + +test('not allowed to switch to embed view when linking to block', async ({ + page, +}) => { + await page.keyboard.press('Enter'); + await createLinkedPage(page, 'Test Page'); + + await page.locator('affine-reference').hover(); +}); + +test('allow switching to embed view when linking to the other document without mode', async ({ + page, +}) => { + await page.keyboard.press('Enter'); + await createLinkedPage(page, 'Test Page'); + + const switchViewBtn = page.locator('Switch view'); + const linkToInlineBtn = page.getByTestId('link-to-inline'); + const linkToCardBtn = page.getByTestId('link-to-card'); + const linkToEmbedBtn = page.getByTestId('link-to-embed'); + + // Inline + await page.locator('affine-reference').hover(); + await switchViewBtn.click(); + + await notClickable(linkToInlineBtn); + await clickable(linkToCardBtn); + await clickable(linkToEmbedBtn); + + // Switches to card view + await linkToCardBtn.click(); + + // Card + await page.locator('affine-embed-linked-doc-block').click(); + await switchViewBtn.click(); + + await clickable(linkToInlineBtn); + await notClickable(linkToCardBtn); + await clickable(linkToEmbedBtn); + + // Switches to embed view + await linkToEmbedBtn.click(); + + // Embed + await page.locator('affine-embed-synced-doc-block').click(); + await switchViewBtn.click(); + + await clickable(linkToInlineBtn); + await clickable(linkToCardBtn); + await notClickable(linkToEmbedBtn); + + // Closes + await switchViewBtn.click(); + await expect( + page.locator('.affine-embed-synced-doc-container.page') + ).toBeVisible(); + + // Opens in peek view + await page.locator('affine-embed-synced-doc-block').dblclick(); + + const peekViewModel = page.getByTestId('peek-view-modal'); + await expect(peekViewModel).toBeVisible(); + await expect(peekViewModel.locator('page-editor')).toBeVisible(); + await page.keyboard.press('Escape'); + await expect(peekViewModel).not.toBeVisible(); + await page.waitForTimeout(300); + + await page.locator('affine-embed-synced-doc-block').click(); + await switchViewBtn.click(); + + await clickable(linkToInlineBtn); + await clickable(linkToCardBtn); + await notClickable(linkToEmbedBtn); + + // Switches to card view + await linkToCardBtn.click(); + + await page.locator('affine-embed-linked-doc-block').click(); + await switchViewBtn.click(); + + await clickable(linkToInlineBtn); + await notClickable(linkToCardBtn); + await clickable(linkToEmbedBtn); + + // Switches to inline view + await linkToInlineBtn.click(); + + await expect(page.locator('affine-reference')).toBeVisible(); +}); + +test('allow switching to embed view when linking to the other document with mode', async ({ + page, +}) => { + await page.keyboard.press('Enter'); + await createLinkedPage(page, 'Test Page'); + + const switchViewBtn = page.locator('Switch view'); + const linkToInlineBtn = page.getByTestId('link-to-inline'); + const linkToCardBtn = page.getByTestId('link-to-card'); + const linkToEmbedBtn = page.getByTestId('link-to-embed'); + + const url = new URL(page.url()); + url.searchParams.append('mode', 'edgeless'); + + await page.locator('affine-reference').click(); + await page.waitForTimeout(300); + await page.keyboard.press('Enter'); + + await writeTextToClipboard(page, url.toString()); + await pasteByKeyboard(page); + + // Inline + await page.locator('affine-reference').hover(); + await switchViewBtn.click(); + + await notClickable(linkToInlineBtn); + await clickable(linkToCardBtn); + await clickable(linkToEmbedBtn); + + // Switches to card view + await linkToCardBtn.click(); + + // Card + await page.locator('affine-embed-linked-doc-block').click(); + await switchViewBtn.click(); + + await clickable(linkToInlineBtn); + await notClickable(linkToCardBtn); + await clickable(linkToEmbedBtn); + + // Switches to embed view + await linkToEmbedBtn.click(); + + // Embed + await page.locator('affine-embed-synced-doc-block').click(); + await switchViewBtn.click(); + + await clickable(linkToInlineBtn); + await clickable(linkToCardBtn); + await notClickable(linkToEmbedBtn); + + // Closes + await switchViewBtn.click(); + await expect( + page.locator('.affine-embed-synced-doc-container.edgeless') + ).toBeVisible(); + + // Opens in peek view + await page.locator('affine-embed-synced-doc-block').dblclick(); + + const peekViewModel = page.getByTestId('peek-view-modal'); + await expect(peekViewModel).toBeVisible(); + await expect(peekViewModel.locator('edgeless-editor')).toBeVisible(); + await page.keyboard.press('Escape'); + await expect(peekViewModel).not.toBeVisible(); + await page.waitForTimeout(300); + + await page.locator('affine-embed-synced-doc-block').click(); + await switchViewBtn.click(); + + await clickable(linkToInlineBtn); + await clickable(linkToCardBtn); + await notClickable(linkToEmbedBtn); + + // Switches to card view + await linkToCardBtn.click(); + + await page.locator('affine-embed-linked-doc-block').click(); + await switchViewBtn.click(); + + await clickable(linkToInlineBtn); + await notClickable(linkToCardBtn); + await clickable(linkToEmbedBtn); + + // Switches to inline view + await linkToInlineBtn.click(); + + await page.locator('affine-reference').click(); + + // Checks the url + const url2 = new URL(page.url()); + url2.searchParams.delete('refreshKey'); + expect(url.toJSON()).toStrictEqual(url2.toJSON()); +}); diff --git a/tests/affine-local/e2e/quick-search.spec.ts b/tests/affine-local/e2e/quick-search.spec.ts index 799e1d43bd5e1..a8b87bb3ad36f 100644 --- a/tests/affine-local/e2e/quick-search.spec.ts +++ b/tests/affine-local/e2e/quick-search.spec.ts @@ -1,6 +1,9 @@ import { test } from '@affine-test/kit/playwright'; import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor'; -import { withCtrlOrMeta } from '@affine-test/kit/utils/keyboard'; +import { + withCtrlOrMeta, + writeTextToClipboard, +} from '@affine-test/kit/utils/keyboard'; import { openHomePage } from '@affine-test/kit/utils/load-page'; import { clickNewPageButton, @@ -510,25 +513,7 @@ test('can paste a doc link to create link reference', async ({ page }) => { await page.keyboard.press('Enter'); // paste the url - await page.evaluate( - async ([url]) => { - const clipData = { - 'text/plain': url, - }; - const e = new ClipboardEvent('paste', { - clipboardData: new DataTransfer(), - }); - Object.defineProperty(e, 'target', { - writable: false, - value: document, - }); - Object.entries(clipData).forEach(([key, value]) => { - e.clipboardData?.setData(key, value); - }); - document.dispatchEvent(e); - }, - [url] - ); + await writeTextToClipboard(page, url); // check the link reference await page.waitForTimeout(500); diff --git a/tests/kit/utils/keyboard.ts b/tests/kit/utils/keyboard.ts index 8da69c9818f00..a51dd816645fc 100644 --- a/tests/kit/utils/keyboard.ts +++ b/tests/kit/utils/keyboard.ts @@ -63,3 +63,26 @@ export async function pasteByKeyboard(page: Page) { await page.keyboard.press('v', { delay: 50 }); await keyUpCtrlOrMeta(page); } + +export async function writeTextToClipboard(page: Page, text: string) { + // paste the url + await page.evaluate( + async ([text]) => { + const clipData = { + 'text/plain': text, + }; + const e = new ClipboardEvent('paste', { + clipboardData: new DataTransfer(), + }); + Object.defineProperty(e, 'target', { + writable: false, + value: document, + }); + Object.entries(clipData).forEach(([key, value]) => { + e.clipboardData?.setData(key, value); + }); + document.dispatchEvent(e); + }, + [text] + ); +}