mirror of
https://github.com/toeverything/AFFiNE.git
synced 2025-01-02 01:53:34 +03:00
fix: reference parameters and add test cases (#8740)
Upstreams: https://github.com/toeverything/blocksuite/pull/8689 Closes: AF-1650
This commit is contained in:
parent
68573aa35e
commit
a5bcfb0b14
@ -14,7 +14,7 @@
|
||||
"@affine/core": "workspace:*",
|
||||
"@affine/i18n": "workspace:*",
|
||||
"@blocksuite/affine": "0.17.28",
|
||||
"@blocksuite/icons": "^2.1.67",
|
||||
"@blocksuite/icons": "^2.1.69",
|
||||
"@capacitor/android": "^6.1.2",
|
||||
"@capacitor/core": "^6.1.2",
|
||||
"@sentry/react": "^8.0.0",
|
||||
|
@ -14,7 +14,7 @@
|
||||
"@affine/core": "workspace:*",
|
||||
"@affine/i18n": "workspace:*",
|
||||
"@blocksuite/affine": "0.17.28",
|
||||
"@blocksuite/icons": "^2.1.67",
|
||||
"@blocksuite/icons": "^2.1.69",
|
||||
"@capacitor/app": "^6.0.1",
|
||||
"@capacitor/browser": "^6.0.3",
|
||||
"@capacitor/core": "^6.1.2",
|
||||
|
@ -14,7 +14,7 @@
|
||||
"@affine/core": "workspace:*",
|
||||
"@affine/i18n": "workspace:*",
|
||||
"@blocksuite/affine": "0.17.28",
|
||||
"@blocksuite/icons": "^2.1.67",
|
||||
"@blocksuite/icons": "^2.1.69",
|
||||
"@sentry/react": "^8.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
@ -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
|
||||
|
333
tests/affine-local/e2e/links.spec.ts
Normal file
333
tests/affine-local/e2e/links.spec.ts
Normal file
@ -0,0 +1,333 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import {
|
||||
pasteByKeyboard,
|
||||
writeTextToClipboard,
|
||||
} from '@affine-test/kit/utils/keyboard';
|
||||
import { coreUrl, 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');
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const url0 = new URL(page.url());
|
||||
|
||||
await writeTextToClipboard(page, url0.toString());
|
||||
await pasteByKeyboard(page);
|
||||
|
||||
// Inline
|
||||
await page.locator('affine-reference').hover();
|
||||
await page.getByLabel('Switch view').click();
|
||||
|
||||
const linkToInlineBtn = page.getByTestId('link-to-inline');
|
||||
const linkToCardBtn = page.getByTestId('link-to-card');
|
||||
const linkToEmbedBtn = page.getByTestId('link-to-embed');
|
||||
|
||||
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').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.locator('affine-embed-linked-doc-block').click();
|
||||
await page.getByLabel('Switch view').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();
|
||||
await page.getByLabel('Switch view').click();
|
||||
|
||||
const linkToInlineBtn = page.getByTestId('link-to-inline');
|
||||
const linkToCardBtn = page.getByTestId('link-to-card');
|
||||
const linkToEmbedBtn = page.getByTestId('link-to-embed');
|
||||
|
||||
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').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.locator('affine-embed-linked-doc-block').click();
|
||||
|
||||
await page.locator('affine-embed-card-toolbar').getByLabel('More').click();
|
||||
await page.getByLabel('Copy link to block').click();
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
await pasteByKeyboard(page);
|
||||
|
||||
const href0 = await page
|
||||
.locator('affine-reference')
|
||||
.locator('a')
|
||||
.getAttribute('href');
|
||||
|
||||
await page.locator('affine-reference').hover();
|
||||
await page.getByLabel('Switch view').click();
|
||||
|
||||
await notClickable(linkToInlineBtn);
|
||||
await clickable(linkToCardBtn);
|
||||
await notClickable(linkToEmbedBtn);
|
||||
|
||||
// Switches to card view
|
||||
await linkToCardBtn.click();
|
||||
|
||||
await page.locator('affine-embed-linked-doc-block').nth(1).dblclick();
|
||||
|
||||
await expect(peekViewModel).toBeVisible();
|
||||
await expect(peekViewModel.locator('page-editor')).toBeVisible();
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(peekViewModel).not.toBeVisible();
|
||||
|
||||
await page.locator('affine-embed-linked-doc-block').nth(1).click();
|
||||
await page.getByLabel('Switch view').click();
|
||||
|
||||
await clickable(linkToInlineBtn);
|
||||
await notClickable(linkToCardBtn);
|
||||
await notClickable(linkToEmbedBtn);
|
||||
|
||||
// Switches to inline view
|
||||
await linkToInlineBtn.click();
|
||||
|
||||
const href1 = await page
|
||||
.locator('affine-reference')
|
||||
.locator('a')
|
||||
.getAttribute('href');
|
||||
|
||||
expect(href0).not.toBeNull();
|
||||
expect(href1).not.toBeNull();
|
||||
|
||||
const url0 = new URL(href0!, coreUrl);
|
||||
const url1 = new URL(href1!, coreUrl);
|
||||
|
||||
url0.searchParams.delete('refreshKey');
|
||||
url1.searchParams.delete('refreshKey');
|
||||
expect(url0.toJSON()).toStrictEqual(url1.toJSON());
|
||||
});
|
||||
|
||||
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');
|
||||
|
||||
// Inline
|
||||
await page.locator('affine-reference').hover();
|
||||
await page.getByLabel('Switch view').click();
|
||||
|
||||
const linkToInlineBtn = page.getByTestId('link-to-inline');
|
||||
const linkToCardBtn = page.getByTestId('link-to-card');
|
||||
const linkToEmbedBtn = page.getByTestId('link-to-embed');
|
||||
|
||||
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 page.getByLabel('Switch view').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 page.waitForTimeout(300);
|
||||
await page.locator('affine-embed-synced-doc-block').click();
|
||||
await page.getByLabel('Switch view').click();
|
||||
|
||||
await clickable(linkToInlineBtn);
|
||||
await clickable(linkToCardBtn);
|
||||
await notClickable(linkToEmbedBtn);
|
||||
|
||||
// Closes
|
||||
await page.getByLabel('Switch view').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 page.getByLabel('Switch view').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 page.waitForTimeout(300);
|
||||
await page.locator('affine-embed-linked-doc-block').click();
|
||||
await page.getByLabel('Switch view').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 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 page.getByLabel('Switch view').click();
|
||||
|
||||
const linkToInlineBtn = page.getByTestId('link-to-inline');
|
||||
const linkToCardBtn = page.getByTestId('link-to-card');
|
||||
const linkToEmbedBtn = page.getByTestId('link-to-embed');
|
||||
|
||||
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 page.getByLabel('Switch view').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 page.waitForTimeout(300);
|
||||
await page.locator('affine-embed-synced-doc-block').click();
|
||||
await page.getByLabel('Switch view').click();
|
||||
|
||||
await clickable(linkToInlineBtn);
|
||||
await clickable(linkToCardBtn);
|
||||
await notClickable(linkToEmbedBtn);
|
||||
|
||||
// Closes
|
||||
await page.getByLabel('Switch view').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 page.getByLabel('Switch view').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 page.getByLabel('Switch view').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());
|
||||
});
|
@ -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);
|
||||
|
@ -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]
|
||||
);
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ __metadata:
|
||||
"@affine/core": "workspace:*"
|
||||
"@affine/i18n": "workspace:*"
|
||||
"@blocksuite/affine": "npm:0.17.28"
|
||||
"@blocksuite/icons": "npm:^2.1.67"
|
||||
"@blocksuite/icons": "npm:^2.1.69"
|
||||
"@capacitor/android": "npm:^6.1.2"
|
||||
"@capacitor/cli": "npm:^6.1.2"
|
||||
"@capacitor/core": "npm:^6.1.2"
|
||||
@ -620,7 +620,7 @@ __metadata:
|
||||
"@affine/core": "workspace:*"
|
||||
"@affine/i18n": "workspace:*"
|
||||
"@blocksuite/affine": "npm:0.17.28"
|
||||
"@blocksuite/icons": "npm:^2.1.67"
|
||||
"@blocksuite/icons": "npm:^2.1.69"
|
||||
"@capacitor/app": "npm:^6.0.1"
|
||||
"@capacitor/browser": "npm:^6.0.3"
|
||||
"@capacitor/cli": "npm:^6.1.2"
|
||||
@ -646,7 +646,7 @@ __metadata:
|
||||
"@affine/core": "workspace:*"
|
||||
"@affine/i18n": "workspace:*"
|
||||
"@blocksuite/affine": "npm:0.17.28"
|
||||
"@blocksuite/icons": "npm:^2.1.67"
|
||||
"@blocksuite/icons": "npm:^2.1.69"
|
||||
"@sentry/react": "npm:^8.0.0"
|
||||
"@types/react": "npm:^18.2.75"
|
||||
"@types/react-dom": "npm:^18.2.24"
|
||||
@ -2812,7 +2812,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/icons@npm:2.1.69, @blocksuite/icons@npm:^2.1.67, @blocksuite/icons@npm:^2.1.68":
|
||||
"@blocksuite/icons@npm:2.1.69, @blocksuite/icons@npm:^2.1.68, @blocksuite/icons@npm:^2.1.69":
|
||||
version: 2.1.69
|
||||
resolution: "@blocksuite/icons@npm:2.1.69"
|
||||
peerDependencies:
|
||||
|
Loading…
Reference in New Issue
Block a user