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 7f602b57bc..43c027fc8a 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 @@ -97,9 +97,7 @@ const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => { patchReferenceRenderer(patched, reactToLit, referenceRenderer), confirmModal ); - if (!page.readonly) { - patched = patchPeekViewService(patched, peekViewService); - } + patched = patchPeekViewService(patched, peekViewService); if (!page.readonly) { patched = patchQuickSearchService(patched, framework); } diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx index 69089f834b..7473ffc1d8 100644 --- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx +++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/spec-patchers.tsx @@ -514,7 +514,7 @@ export function patchQuickSearchService( @customElement('affine-linked-doc-ref-block') // @ts-expect-error ignore private warning for overriding _load export class LinkedDocBlockComponent extends EmbedLinkedDocBlockComponent { - override _load() { + override async _load() { this.isBannerEmpty = true; } } diff --git a/packages/frontend/core/src/modules/peek-view/view/image-preview/index.tsx b/packages/frontend/core/src/modules/peek-view/view/image-preview/index.tsx index d97f32328d..8a7c6959e8 100644 --- a/packages/frontend/core/src/modules/peek-view/view/image-preview/index.tsx +++ b/packages/frontend/core/src/modules/peek-view/view/image-preview/index.tsx @@ -419,14 +419,18 @@ const ImagePreviewModalImpl = ({ icon={} onClick={copyHandler} /> -
- } - disabled={blocks.length === 0} - onClick={() => deleteHandler(cursor)} - /> + {blockModel && !blockModel.doc.readonly && ( + <> +
+ } + disabled={blocks.length === 0} + onClick={() => deleteHandler(cursor)} + /> + + )} diff --git a/packages/frontend/core/src/pages/share/share-detail-page.tsx b/packages/frontend/core/src/pages/share/share-detail-page.tsx index 33aa80eaf7..c9bd0fd1e2 100644 --- a/packages/frontend/core/src/pages/share/share-detail-page.tsx +++ b/packages/frontend/core/src/pages/share/share-detail-page.tsx @@ -33,6 +33,7 @@ import { AppContainer } from '../../components/affine/app-container'; import { PageDetailEditor } from '../../components/page-detail-editor'; import { SharePageNotFoundError } from '../../components/share-page-not-found-error'; import { MainContainer } from '../../components/workspace'; +import { PeekViewManagerModal } from '../../modules/peek-view'; import { CloudBlobStorage } from '../../modules/workspace-engine/impls/engine/blob-cloud'; import * as styles from './share-detail-page.css'; import { ShareFooter } from './share-footer'; @@ -253,6 +254,7 @@ export const Component = () => { + diff --git a/tests/affine-cloud/e2e/collaboration.spec.ts b/tests/affine-cloud/e2e/collaboration.spec.ts index a1adb7f23f..d9b355ef00 100644 --- a/tests/affine-cloud/e2e/collaboration.spec.ts +++ b/tests/affine-cloud/e2e/collaboration.spec.ts @@ -5,10 +5,8 @@ import { addUserToWorkspace, createRandomUser, enableCloudWorkspace, - enableCloudWorkspaceFromShareButton, loginUser, } from '@affine-test/kit/utils/cloud'; -import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor'; import { clickNewPageButton, getBlockSuiteEditorTitle, @@ -37,89 +35,6 @@ test.beforeEach(async ({ page }) => { await loginUser(page, user.email); }); -test('can enable share page', 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('TEST CONTENT', { delay: 50 }); - await page.getByTestId('cloud-share-menu-button').click(); - await page.getByTestId('share-menu-create-link-button').click(); - await page.getByTestId('share-menu-copy-link-button').click(); - - // check share page is accessible - { - 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 title = getBlockSuiteEditorTitle(page2); - await expect(title).toContainText('TEST TITLE'); - expect(page2.locator('affine-paragraph').first()).toContainText( - 'TEST CONTENT' - ); - } -}); - -test('share page with default edgeless', 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('TEST CONTENT', { delay: 50 }); - await clickEdgelessModeButton(page); - await expect(page.locator('affine-edgeless-root')).toBeVisible({ - timeout: 1000, - }); - await page.getByTestId('cloud-share-menu-button').click(); - await page.getByTestId('share-menu-create-link-button').click(); - await page.getByTestId('share-menu-copy-link-button').click(); - - // check share page is accessible - { - 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); - await expect(page.locator('affine-edgeless-root')).toBeVisible({ - timeout: 1000, - }); - expect(page2.locator('affine-paragraph').first()).toContainText( - 'TEST CONTENT' - ); - const editButton = page2.getByTestId('share-page-edit-button'); - await expect(editButton).not.toBeVisible(); - } -}); - // SKIP until BS-671 fix test.skip('can collaborate with other user and name should display when editing', async ({ page, diff --git a/tests/affine-cloud/e2e/share-page.spec.ts b/tests/affine-cloud/e2e/share-page.spec.ts new file mode 100644 index 0000000000..ed56b40adb --- /dev/null +++ b/tests/affine-cloud/e2e/share-page.spec.ts @@ -0,0 +1,151 @@ +import { skipOnboarding, test } from '@affine-test/kit/playwright'; +import { + createRandomUser, + enableCloudWorkspaceFromShareButton, + loginUser, +} from '@affine-test/kit/utils/cloud'; +import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor'; +import { importImage } from '@affine-test/kit/utils/image'; +import { + getBlockSuiteEditorTitle, + waitForEditorLoad, +} from '@affine-test/kit/utils/page-logic'; +import { createLocalWorkspace } from '@affine-test/kit/utils/workspace'; +import { expect } from '@playwright/test'; + +let user: { + id: string; + name: string; + email: string; + password: string; +}; + +test.beforeEach(async () => { + user = await createRandomUser(); +}); + +test.beforeEach(async ({ page }) => { + await loginUser(page, user.email); +}); + +test('can enable share page', 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('TEST CONTENT', { delay: 50 }); + await page.getByTestId('cloud-share-menu-button').click(); + await page.getByTestId('share-menu-create-link-button').click(); + await page.getByTestId('share-menu-copy-link-button').click(); + + // check share page is accessible + { + 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 title = getBlockSuiteEditorTitle(page2); + await expect(title).toContainText('TEST TITLE'); + expect(page2.locator('affine-paragraph').first()).toContainText( + 'TEST CONTENT' + ); + } +}); + +test('share page with default edgeless', 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('TEST CONTENT', { delay: 50 }); + await clickEdgelessModeButton(page); + await expect(page.locator('affine-edgeless-root')).toBeVisible({ + timeout: 1000, + }); + await page.getByTestId('cloud-share-menu-button').click(); + await page.getByTestId('share-menu-create-link-button').click(); + await page.getByTestId('share-menu-copy-link-button').click(); + + // check share page is accessible + { + 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); + await expect(page.locator('affine-edgeless-root')).toBeVisible({ + timeout: 1000, + }); + expect(page2.locator('affine-paragraph').first()).toContainText( + 'TEST CONTENT' + ); + const editButton = page2.getByTestId('share-page-edit-button'); + await expect(editButton).not.toBeVisible(); + } +}); + +test('image preview should should be shown', async ({ page, browser }) => { + await page.reload(); + await waitForEditorLoad(page); + await createLocalWorkspace( + { + name: 'test', + }, + page + ); + await enableCloudWorkspaceFromShareButton(page); + const title = getBlockSuiteEditorTitle(page); + await title.click(); + await page.keyboard.press('Enter'); + await importImage(page, 'http://localhost:8081/large-image.png'); + + await page.getByTestId('cloud-share-menu-button').click(); + await page.getByTestId('share-menu-create-link-button').click(); + await page.getByTestId('share-menu-copy-link-button').click(); + + // check share page is accessible + { + 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); + + await page.locator('affine-page-image').first().dblclick(); + const locator = page.getByTestId('image-preview-modal'); + await expect(locator).toBeVisible(); + await page.getByTestId('image-preview-close-button').first().click(); + await page.waitForTimeout(500); + await expect(locator).not.toBeVisible(); + } +}); diff --git a/tests/affine-cloud/playwright.config.ts b/tests/affine-cloud/playwright.config.ts index 75c1775e2f..ed072898d8 100644 --- a/tests/affine-cloud/playwright.config.ts +++ b/tests/affine-cloud/playwright.config.ts @@ -10,7 +10,7 @@ const config: PlaywrightTestConfig = { timeout: 120_000, outputDir: testResultDir, use: { - baseURL: 'http://localhost:8081/', + baseURL: 'http://localhost:8080/', browserName: (process.env.BROWSER as PlaywrightWorkerOptions['browserName']) ?? 'chromium', @@ -26,6 +26,16 @@ const config: PlaywrightTestConfig = { retries: 1, reporter: process.env.CI ? 'github' : 'list', webServer: [ + { + command: 'yarn run serve:test-static', + port: 8081, + timeout: 120 * 1000, + reuseExistingServer: !process.env.CI, + env: { + COVERAGE: process.env.COVERAGE || 'false', + ENABLE_DEBUG_PAGE: '1', + }, + }, // Intentionally not building the web, reminds you to run it by yourself. { command: 'yarn -T run start:web-static', diff --git a/tests/affine-local/e2e/image-preview.spec.ts b/tests/affine-local/e2e/image-preview.spec.ts index 8448cb6f7b..4a4bcb333a 100644 --- a/tests/affine-local/e2e/image-preview.spec.ts +++ b/tests/affine-local/e2e/image-preview.spec.ts @@ -2,41 +2,16 @@ import fs from 'node:fs'; import { test } from '@affine-test/kit/playwright'; +import { importImage } from '@affine-test/kit/utils/image'; import { openHomePage } from '@affine-test/kit/utils/load-page'; import { clickNewPageButton, - focusInlineEditor, getBlockSuiteEditorTitle, waitForEditorLoad, } from '@affine-test/kit/utils/page-logic'; import type { Page } from '@playwright/test'; import { expect } from '@playwright/test'; -async function importImage(page: Page, url: string) { - await focusInlineEditor(page); - await page.evaluate( - ([url]) => { - const clipData = { - 'text/html': `{'Sample`, - }; - 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] - ); - // TODO(@catsjuice): wait for image to be loaded more reliably - await page.waitForTimeout(1000); -} - async function closeImagePreviewModal(page: Page) { await page.getByTestId('image-preview-close-button').first().click(); await page.waitForTimeout(500); diff --git a/tests/kit/utils/image.ts b/tests/kit/utils/image.ts new file mode 100644 index 0000000000..931f603849 --- /dev/null +++ b/tests/kit/utils/image.ts @@ -0,0 +1,28 @@ +import type { Page } from '@playwright/test'; + +import { focusInlineEditor } from './page-logic'; + +export async function importImage(page: Page, url: string) { + await focusInlineEditor(page); + await page.evaluate( + ([url]) => { + const clipData = { + 'text/html': `{'Sample`, + }; + 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] + ); + // TODO(@catsjuice): wait for image to be loaded more reliably + await page.waitForTimeout(1000); +}