mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 22:37:04 +08:00
@@ -97,9 +97,7 @@ const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => {
|
|||||||
patchReferenceRenderer(patched, reactToLit, referenceRenderer),
|
patchReferenceRenderer(patched, reactToLit, referenceRenderer),
|
||||||
confirmModal
|
confirmModal
|
||||||
);
|
);
|
||||||
if (!page.readonly) {
|
patched = patchPeekViewService(patched, peekViewService);
|
||||||
patched = patchPeekViewService(patched, peekViewService);
|
|
||||||
}
|
|
||||||
if (!page.readonly) {
|
if (!page.readonly) {
|
||||||
patched = patchQuickSearchService(patched, framework);
|
patched = patchQuickSearchService(patched, framework);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -514,7 +514,7 @@ export function patchQuickSearchService(
|
|||||||
@customElement('affine-linked-doc-ref-block')
|
@customElement('affine-linked-doc-ref-block')
|
||||||
// @ts-expect-error ignore private warning for overriding _load
|
// @ts-expect-error ignore private warning for overriding _load
|
||||||
export class LinkedDocBlockComponent extends EmbedLinkedDocBlockComponent {
|
export class LinkedDocBlockComponent extends EmbedLinkedDocBlockComponent {
|
||||||
override _load() {
|
override async _load() {
|
||||||
this.isBannerEmpty = true;
|
this.isBannerEmpty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -419,14 +419,18 @@ const ImagePreviewModalImpl = ({
|
|||||||
icon={<CopyIcon />}
|
icon={<CopyIcon />}
|
||||||
onClick={copyHandler}
|
onClick={copyHandler}
|
||||||
/>
|
/>
|
||||||
<div className={styles.dividerStyle}></div>
|
{blockModel && !blockModel.doc.readonly && (
|
||||||
<ButtonWithTooltip
|
<>
|
||||||
data-testid="delete-button"
|
<div className={styles.dividerStyle}></div>
|
||||||
tooltip="Delete"
|
<ButtonWithTooltip
|
||||||
icon={<DeleteIcon />}
|
data-testid="delete-button"
|
||||||
disabled={blocks.length === 0}
|
tooltip="Delete"
|
||||||
onClick={() => deleteHandler(cursor)}
|
icon={<DeleteIcon />}
|
||||||
/>
|
disabled={blocks.length === 0}
|
||||||
|
onClick={() => deleteHandler(cursor)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import { AppContainer } from '../../components/affine/app-container';
|
|||||||
import { PageDetailEditor } from '../../components/page-detail-editor';
|
import { PageDetailEditor } from '../../components/page-detail-editor';
|
||||||
import { SharePageNotFoundError } from '../../components/share-page-not-found-error';
|
import { SharePageNotFoundError } from '../../components/share-page-not-found-error';
|
||||||
import { MainContainer } from '../../components/workspace';
|
import { MainContainer } from '../../components/workspace';
|
||||||
|
import { PeekViewManagerModal } from '../../modules/peek-view';
|
||||||
import { CloudBlobStorage } from '../../modules/workspace-engine/impls/engine/blob-cloud';
|
import { CloudBlobStorage } from '../../modules/workspace-engine/impls/engine/blob-cloud';
|
||||||
import * as styles from './share-detail-page.css';
|
import * as styles from './share-detail-page.css';
|
||||||
import { ShareFooter } from './share-footer';
|
import { ShareFooter } from './share-footer';
|
||||||
@@ -253,6 +254,7 @@ export const Component = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</MainContainer>
|
</MainContainer>
|
||||||
|
<PeekViewManagerModal />
|
||||||
</AppContainer>
|
</AppContainer>
|
||||||
</FrameworkScope>
|
</FrameworkScope>
|
||||||
</FrameworkScope>
|
</FrameworkScope>
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ import {
|
|||||||
addUserToWorkspace,
|
addUserToWorkspace,
|
||||||
createRandomUser,
|
createRandomUser,
|
||||||
enableCloudWorkspace,
|
enableCloudWorkspace,
|
||||||
enableCloudWorkspaceFromShareButton,
|
|
||||||
loginUser,
|
loginUser,
|
||||||
} from '@affine-test/kit/utils/cloud';
|
} from '@affine-test/kit/utils/cloud';
|
||||||
import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor';
|
|
||||||
import {
|
import {
|
||||||
clickNewPageButton,
|
clickNewPageButton,
|
||||||
getBlockSuiteEditorTitle,
|
getBlockSuiteEditorTitle,
|
||||||
@@ -37,89 +35,6 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await loginUser(page, user.email);
|
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
|
// SKIP until BS-671 fix
|
||||||
test.skip('can collaborate with other user and name should display when editing', async ({
|
test.skip('can collaborate with other user and name should display when editing', async ({
|
||||||
page,
|
page,
|
||||||
|
|||||||
151
tests/affine-cloud/e2e/share-page.spec.ts
Normal file
151
tests/affine-cloud/e2e/share-page.spec.ts
Normal file
@@ -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();
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -10,7 +10,7 @@ const config: PlaywrightTestConfig = {
|
|||||||
timeout: 120_000,
|
timeout: 120_000,
|
||||||
outputDir: testResultDir,
|
outputDir: testResultDir,
|
||||||
use: {
|
use: {
|
||||||
baseURL: 'http://localhost:8081/',
|
baseURL: 'http://localhost:8080/',
|
||||||
browserName:
|
browserName:
|
||||||
(process.env.BROWSER as PlaywrightWorkerOptions['browserName']) ??
|
(process.env.BROWSER as PlaywrightWorkerOptions['browserName']) ??
|
||||||
'chromium',
|
'chromium',
|
||||||
@@ -26,6 +26,16 @@ const config: PlaywrightTestConfig = {
|
|||||||
retries: 1,
|
retries: 1,
|
||||||
reporter: process.env.CI ? 'github' : 'list',
|
reporter: process.env.CI ? 'github' : 'list',
|
||||||
webServer: [
|
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.
|
// Intentionally not building the web, reminds you to run it by yourself.
|
||||||
{
|
{
|
||||||
command: 'yarn -T run start:web-static',
|
command: 'yarn -T run start:web-static',
|
||||||
|
|||||||
@@ -2,41 +2,16 @@
|
|||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
|
||||||
import { test } from '@affine-test/kit/playwright';
|
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 { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||||
import {
|
import {
|
||||||
clickNewPageButton,
|
clickNewPageButton,
|
||||||
focusInlineEditor,
|
|
||||||
getBlockSuiteEditorTitle,
|
getBlockSuiteEditorTitle,
|
||||||
waitForEditorLoad,
|
waitForEditorLoad,
|
||||||
} from '@affine-test/kit/utils/page-logic';
|
} from '@affine-test/kit/utils/page-logic';
|
||||||
import type { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
import { expect } 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': `<img alt={'Sample image'} src=${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]
|
|
||||||
);
|
|
||||||
// TODO(@catsjuice): wait for image to be loaded more reliably
|
|
||||||
await page.waitForTimeout(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function closeImagePreviewModal(page: Page) {
|
async function closeImagePreviewModal(page: Page) {
|
||||||
await page.getByTestId('image-preview-close-button').first().click();
|
await page.getByTestId('image-preview-close-button').first().click();
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|||||||
28
tests/kit/utils/image.ts
Normal file
28
tests/kit/utils/image.ts
Normal file
@@ -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': `<img alt={'Sample image'} src=${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]
|
||||||
|
);
|
||||||
|
// TODO(@catsjuice): wait for image to be loaded more reliably
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user