diff --git a/packages/frontend/core/src/components/affine/reference-link/index.tsx b/packages/frontend/core/src/components/affine/reference-link/index.tsx
index c936e89dc..94f1a90df 100644
--- a/packages/frontend/core/src/components/affine/reference-link/index.tsx
+++ b/packages/frontend/core/src/components/affine/reference-link/index.tsx
@@ -30,6 +30,7 @@ import * as styles from './styles.css';
interface AffinePageReferenceProps {
pageId: string;
params?: URLSearchParams;
+ title?: string | null; // title alias
className?: string;
Icon?: ComponentType;
onClick?: (e: MouseEvent) => void;
@@ -38,20 +39,21 @@ interface AffinePageReferenceProps {
function AffinePageReferenceInner({
pageId,
params,
+ title,
Icon: UserIcon,
}: AffinePageReferenceProps) {
const docDisplayMetaService = useService(DocDisplayMetaService);
const docsService = useService(DocsService);
const i18n = useI18n();
- let linkWithMode: DocMode | null = null;
- let linkToNode = false;
+ let referenceWithMode: DocMode | null = null;
+ let referenceToNode = false;
if (params) {
const m = params.get('mode');
if (m && (m === 'page' || m === 'edgeless')) {
- linkWithMode = m as DocMode;
+ referenceWithMode = m as DocMode;
}
- linkToNode = params.has('blockIds') || params.has('elementIds');
+ referenceToNode = params.has('blockIds') || params.has('elementIds');
}
const Icon = useLiveData(
@@ -61,25 +63,33 @@ function AffinePageReferenceInner({
}
return get(
docDisplayMetaService.icon$(pageId, {
- mode: linkWithMode ?? undefined,
+ mode: referenceWithMode ?? undefined,
reference: true,
- referenceToNode: linkToNode,
+ referenceToNode,
+ hasTitleAlias: Boolean(title),
})
);
})
);
+
const notFound = !useLiveData(docsService.list.doc$(pageId));
- let title = useLiveData(
+ const docTitle = useLiveData(
docDisplayMetaService.title$(pageId, { reference: true })
);
- title = notFound ? i18n.t('com.affine.notFoundPage.title') : title;
+ if (notFound) {
+ title = i18n.t('com.affine.notFoundPage.title');
+ }
+
+ if (!title) {
+ title = i18n.t(docTitle);
+ }
return (
- {i18n.t(title)}
+ {title}
);
}
@@ -87,6 +97,7 @@ function AffinePageReferenceInner({
export function AffinePageReference({
pageId,
params,
+ title,
className,
Icon,
onClick: userOnClick,
@@ -152,7 +163,12 @@ export function AffinePageReference({
onClick={onClick}
className={clsx(styles.pageReferenceLink, className)}
>
-
+
);
}
@@ -161,6 +177,7 @@ export function AffineSharedPageReference({
pageId,
docCollection,
params,
+ title,
Icon,
onClick: userOnClick,
}: AffinePageReferenceProps & {
@@ -213,7 +230,12 @@ export function AffineSharedPageReference({
onClick={onClick}
className={styles.pageReferenceLink}
>
-
+
);
}
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 a2891cdf7..5e677123e 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
@@ -56,6 +56,7 @@ import {
patchEmbedLinkedDocBlockConfig,
patchForMobile,
patchForSharedPage,
+ patchGenerateDocUrlExtension,
patchNotificationService,
patchParseDocUrlExtension,
patchPeekViewService,
@@ -112,6 +113,8 @@ const usePatchSpecs = (shared: boolean, mode: DocMode) => {
const pageId = data.pageId;
if (!pageId) return ;
+ // title alias
+ const title = data.title;
const params = toURLSearchParams(data.params);
if (workspaceService.workspace.openOptions.isSharedMode) {
@@ -120,11 +123,14 @@ const usePatchSpecs = (shared: boolean, mode: DocMode) => {
docCollection={workspaceService.workspace.docCollection}
pageId={pageId}
params={params}
+ title={title}
/>
);
}
- return ;
+ return (
+
+ );
};
}, [workspaceService]);
@@ -147,6 +153,7 @@ const usePatchSpecs = (shared: boolean, mode: DocMode) => {
patched = patched.concat(patchPeekViewService(peekViewService));
patched = patched.concat(patchEdgelessClipboard());
patched = patched.concat(patchParseDocUrlExtension(framework));
+ patched = patched.concat(patchGenerateDocUrlExtension(framework));
patched = patched.concat(patchQuickSearchService(framework));
patched = patched.concat(patchEmbedLinkedDocBlockConfig(framework));
if (shared) {
diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/database-block.ts b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/database-block.ts
index 0306861ca..416515968 100644
--- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/database-block.ts
+++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/database-block.ts
@@ -52,7 +52,7 @@ function createCopyLinkToBlockMenuItem(
const options: UseSharingUrl = {
workspaceId,
pageId,
- shareMode: mode,
+ mode,
blockIds: [model.id],
};
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 d34022db3..489d4fd0e 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
@@ -7,6 +7,7 @@ import {
toReactNode,
type useConfirmModal,
} from '@affine/component';
+import { WorkspaceServerService } from '@affine/core/modules/cloud';
import type { EditorService } from '@affine/core/modules/editor';
import { EditorSettingService } from '@affine/core/modules/editor-setting';
import { resolveLinkToDoc } from '@affine/core/modules/navigation';
@@ -47,6 +48,7 @@ import {
EdgelessRootBlockComponent,
EmbedLinkedDocBlockComponent,
EmbedLinkedDocBlockConfigExtension,
+ GenerateDocUrlExtension,
MobileSpecsPatches,
NotificationExtension,
ParseDocUrlExtension,
@@ -55,6 +57,7 @@ import {
ReferenceNodeConfigExtension,
} from '@blocksuite/affine/blocks';
import { type BlockSnapshot, Text } from '@blocksuite/affine/store';
+import type { ReferenceParams } from '@blocksuite/affine-model';
import {
AIChatBlockSchema,
type DocProps,
@@ -68,6 +71,7 @@ import { customElement } from 'lit/decorators.js';
import { literal } from 'lit/static-html.js';
import { pick } from 'lodash-es';
+import { generateUrl } from '../../../../hooks/affine/use-share-url';
import { createKeyboardToolbarConfig } from './widgets/keyboard-toolbar';
export type ReferenceReactRenderer = (
@@ -110,13 +114,13 @@ export function patchReferenceRenderer(
reactToLit: (element: ElementOrFactory) => TemplateResult,
reactRenderer: ReferenceReactRenderer
): ExtensionType {
- const litRenderer = (reference: AffineReference) => {
+ const customContent = (reference: AffineReference) => {
const node = reactRenderer(reference);
return reactToLit(node);
};
return ReferenceNodeConfigExtension({
- customContent: litRenderer,
+ customContent,
});
}
@@ -463,18 +467,32 @@ export function patchParseDocUrlExtension(framework: FrameworkProvider) {
const info = resolveLinkToDoc(url);
if (!info || info.workspaceId !== workspaceService.workspace.id) return;
- return {
- docId: info.docId,
- blockIds: info.blockIds,
- elementIds: info.elementIds,
- mode: info.mode,
- };
+ delete info.refreshKey;
+
+ return info;
},
});
return [ParseDocUrl];
}
+export function patchGenerateDocUrlExtension(framework: FrameworkProvider) {
+ const workspaceService = framework.get(WorkspaceService);
+ const workspaceServerService = framework.get(WorkspaceServerService);
+ const GenerateDocUrl = GenerateDocUrlExtension({
+ generateDocUrl(pageId: string, params?: ReferenceParams) {
+ return generateUrl({
+ ...params,
+ pageId,
+ workspaceId: workspaceService.workspace.id,
+ baseUrl: workspaceServerService.server?.baseUrl ?? location.origin,
+ });
+ },
+ });
+
+ return [GenerateDocUrl];
+}
+
export function patchEdgelessClipboard() {
class EdgelessClipboardWatcher extends BlockServiceWatcher {
static override readonly flavour = 'affine:page';
diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/widgets/toolbar.ts b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/widgets/toolbar.ts
index 610c98cb3..1afbe6b03 100644
--- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/widgets/toolbar.ts
+++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/widgets/toolbar.ts
@@ -93,7 +93,7 @@ function createCopyLinkToBlockMenuItem(
const mode = editor.mode$.value;
const pageId = editor.doc.id;
const workspaceId = editor.doc.workspace.id;
- const options: UseSharingUrl = { workspaceId, pageId, shareMode: mode };
+ const options: UseSharingUrl = { workspaceId, pageId, mode };
let type = '';
if (mode === 'page') {
diff --git a/packages/frontend/core/src/components/hooks/affine/use-share-url.ts b/packages/frontend/core/src/components/hooks/affine/use-share-url.ts
index 4e9024506..0e4abca87 100644
--- a/packages/frontend/core/src/components/hooks/affine/use-share-url.ts
+++ b/packages/frontend/core/src/components/hooks/affine/use-share-url.ts
@@ -13,7 +13,7 @@ import { useCallback } from 'react';
export type UseSharingUrl = {
workspaceId: string;
pageId: string;
- shareMode?: DocMode;
+ mode?: DocMode;
blockIds?: string[];
elementIds?: string[];
xywh?: string; // not needed currently
@@ -30,7 +30,7 @@ export const generateUrl = ({
pageId,
blockIds,
elementIds,
- shareMode: mode,
+ mode,
xywh, // not needed currently
}: UseSharingUrl & { baseUrl: string }) => {
try {
@@ -38,23 +38,24 @@ export const generateUrl = ({
const search = toURLSearchParams({ mode, blockIds, elementIds, xywh });
if (search?.size) url.search = search.toString();
return url.toString();
- } catch {
- return null;
+ } catch (err) {
+ console.error(err);
+ return undefined;
}
};
const getShareLinkType = ({
- shareMode,
+ mode,
blockIds,
elementIds,
}: {
- shareMode?: DocMode;
+ mode?: DocMode;
blockIds?: string[];
elementIds?: string[];
}) => {
- if (shareMode === 'page') {
+ if (mode === 'page') {
return 'doc';
- } else if (shareMode === 'edgeless') {
+ } else if (mode === 'edgeless') {
return 'whiteboard';
} else if (blockIds && blockIds.length > 0) {
return 'block';
@@ -131,17 +132,17 @@ export const useSharingUrl = ({ workspaceId, pageId }: UseSharingUrl) => {
const serverService = useService(ServerService);
const onClickCopyLink = useCallback(
- (shareMode?: DocMode, blockIds?: string[], elementIds?: string[]) => {
+ (mode?: DocMode, blockIds?: string[], elementIds?: string[]) => {
const sharingUrl = generateUrl({
baseUrl: serverService.server.baseUrl,
workspaceId,
pageId,
blockIds,
elementIds,
- shareMode, // if view is not provided, use the current view
+ mode, // if view is not provided, use the current view
});
const type = getShareLinkType({
- shareMode,
+ mode,
blockIds,
elementIds,
});
diff --git a/packages/frontend/core/src/modules/doc-display-meta/services/doc-display-meta.ts b/packages/frontend/core/src/modules/doc-display-meta/services/doc-display-meta.ts
index 5c46e8935..8cd617a1e 100644
--- a/packages/frontend/core/src/modules/doc-display-meta/services/doc-display-meta.ts
+++ b/packages/frontend/core/src/modules/doc-display-meta/services/doc-display-meta.ts
@@ -1,6 +1,7 @@
import { extractEmojiIcon } from '@affine/core/utils';
import { i18nTime } from '@affine/i18n';
import {
+ AliasIcon as LitAliasIcon,
BlockLinkIcon as LitBlockLinkIcon,
EdgelessIcon as LitEdgelessIcon,
LinkedEdgelessIcon as LitLinkedEdgelessIcon,
@@ -11,6 +12,7 @@ import {
YesterdayIcon as LitYesterdayIcon,
} from '@blocksuite/icons/lit';
import {
+ AliasIcon,
BlockLinkIcon,
EdgelessIcon,
LinkedEdgelessIcon,
@@ -42,6 +44,7 @@ interface DocDisplayIconOptions {
mode?: 'edgeless' | 'page';
reference?: boolean;
referenceToNode?: boolean;
+ hasTitleAlias?: boolean;
/**
* @default true
*/
@@ -57,6 +60,7 @@ interface DocDisplayTitleOptions {
}
const rcIcons = {
+ AliasIcon,
BlockLinkIcon,
EdgelessIcon,
LinkedEdgelessIcon,
@@ -67,6 +71,7 @@ const rcIcons = {
YesterdayIcon,
};
const litIcons = {
+ AliasIcon: LitAliasIcon,
BlockLinkIcon: LitBlockLinkIcon,
EdgelessIcon: LitEdgelessIcon,
LinkedEdgelessIcon: LitLinkedEdgelessIcon,
@@ -130,6 +135,12 @@ export class DocDisplayMetaService extends Service {
const mode = doc ? get(doc.primaryMode$) : undefined;
const finalMode = options?.mode ?? mode ?? 'page';
const referenceToNode = !!(options?.reference && options.referenceToNode);
+ const hasTitleAlias = !!(options?.reference && options?.hasTitleAlias);
+
+ // increases block link priority with title alias
+ if (hasTitleAlias) {
+ return iconSet.AliasIcon;
+ }
// increases block link priority
if (referenceToNode) {
diff --git a/tests/affine-local/e2e/links.spec.ts b/tests/affine-local/e2e/links.spec.ts
index 449d7bcc5..9b91b3191 100644
--- a/tests/affine-local/e2e/links.spec.ts
+++ b/tests/affine-local/e2e/links.spec.ts
@@ -580,3 +580,305 @@ test('should show edgeless content when switching card view of linked mode doc i
edgelessText.y + edgelessText.height
);
});
+
+// Aliases & Copy link
+test.describe('Customize linked doc title and description', () => {
+ // Inline View
+ test('should set a custom title for inline link', async ({ page }) => {
+ await page.keyboard.press('Enter');
+ await createLinkedPage(page, 'Test Page');
+
+ const link = page.locator('affine-reference');
+ const title = link.locator('.affine-reference-title');
+ await link.hover();
+
+ const toolbar = page.locator('reference-popup');
+
+ // Copies link
+ await toolbar.getByRole('button', { name: 'Copy link' }).click();
+ const url0 = await link.locator('a').getAttribute('href');
+ const url1 = await (
+ await page.evaluateHandle(() => navigator.clipboard.readText())
+ ).jsonValue();
+ expect(url0).not.toBeNull();
+ expect(new URL(url0!, coreUrl).pathname).toBe(new URL(url1).pathname);
+
+ // Edits title
+ await toolbar.getByRole('button', { name: 'Edit' }).click();
+
+ // Title alias
+ await page.keyboard.type('Test Page Alias');
+ await page.keyboard.press('Enter');
+
+ await expect(title).toHaveText('Test Page Alias');
+
+ // Original title
+ await link.hover();
+ const docTitle = toolbar.getByRole('button', { name: 'Doc title' });
+ await expect(docTitle).toHaveText('Test Page', { useInnerText: true });
+
+ // Edits title
+ await toolbar.getByRole('button', { name: 'Edit' }).click();
+
+ const aliasPopup = page.locator('reference-alias-popup');
+
+ // Input
+ await expect(aliasPopup.locator('input')).toHaveValue('Test Page Alias');
+
+ // Reset
+ await aliasPopup.getByRole('button', { name: 'Reset' }).click();
+
+ await expect(title).toHaveText('Test Page');
+
+ await link.hover();
+ await expect(docTitle).toBeHidden();
+ });
+
+ // Card View
+ test('should set a custom title and description for card link', async ({
+ page,
+ }) => {
+ await page.keyboard.press('Enter');
+ await createLinkedPage(page, 'Test Page');
+
+ const inlineLink = page.locator('affine-reference');
+ const inlineToolbar = page.locator('reference-popup');
+
+ await inlineLink.hover();
+
+ // Copies link
+ await inlineToolbar.getByRole('button', { name: 'Copy link' }).click();
+ const url0 = await (
+ await page.evaluateHandle(() => navigator.clipboard.readText())
+ ).jsonValue();
+
+ // Edits title
+ await inlineToolbar.getByRole('button', { name: 'Edit' }).click();
+
+ // Title alias
+ await page.keyboard.type('Test Page Alias');
+ await page.keyboard.press('Enter');
+
+ await inlineLink.hover();
+
+ // Switches to card view
+ await inlineToolbar.getByRole('button', { name: 'Switch view' }).click();
+ await inlineToolbar.getByRole('button', { name: 'Card view' }).click();
+
+ const cardLink = page.locator('affine-embed-linked-doc-block');
+ const cardTitle = cardLink.locator(
+ '.affine-embed-linked-doc-content-title-text'
+ );
+ const cardDescription = cardLink.locator(
+ '.affine-embed-linked-doc-content-note.alias'
+ );
+ const cardToolbar = page.locator('affine-embed-card-toolbar');
+
+ await cardLink.click();
+
+ // Copies link
+ await cardToolbar.getByRole('button', { name: 'Copy link' }).click();
+ const url1 = await (
+ await page.evaluateHandle(() => navigator.clipboard.readText())
+ ).jsonValue();
+
+ expect(url0).not.toBeNull();
+ expect(url1).not.toBeNull();
+ expect(url0).toBe(url1);
+
+ const docTitle = cardToolbar.getByRole('button', { name: 'Doc title' });
+ await expect(docTitle).toHaveText('Test Page', { useInnerText: true });
+ await expect(cardTitle).toHaveText('Test Page Alias');
+
+ // Edits title & description
+ await cardToolbar.getByRole('button', { name: 'Edit' }).click();
+
+ const cardEditPopup = page.locator('embed-card-edit-modal');
+
+ // Title alias
+ await page.keyboard.type('Test Page Alias Again');
+ await page.keyboard.press('Tab');
+ // Description alias
+ await page.keyboard.type('This is a new description');
+
+ // Saves aliases
+ await cardEditPopup.getByRole('button', { name: 'Save' }).click();
+ await expect(cardTitle).toHaveText('Test Page Alias Again');
+ await expect(cardDescription).toHaveText('This is a new description');
+
+ await cardLink.click();
+
+ // Switches to inline view
+ {
+ await cardToolbar.getByRole('button', { name: 'Switch view' }).click();
+ await cardToolbar.getByRole('button', { name: 'Inline view' }).click();
+
+ // Focuses inline editor
+ const bounds = (await inlineLink.boundingBox())!;
+ await page.mouse.click(
+ bounds.x + bounds.width + 30,
+ bounds.y + bounds.height / 2
+ );
+
+ await inlineLink.hover();
+
+ const title = inlineLink.locator('.affine-reference-title');
+ await expect(title).toHaveText('Test Page Alias Again');
+
+ // Switches to card view
+ await inlineToolbar.getByRole('button', { name: 'Switch view' }).click();
+ await inlineToolbar.getByRole('button', { name: 'Card view' }).click();
+ }
+
+ await cardLink.click();
+
+ await cardToolbar.getByRole('button', { name: 'Edit' }).click();
+
+ // Resets
+ await cardEditPopup.getByRole('button', { name: 'Reset' }).click();
+
+ await expect(cardTitle).toHaveText('Test Page');
+ await expect(cardDescription).toBeHidden();
+ });
+
+ // Embed View
+ test('should automatically switch to card view and set a custom title and description', async ({
+ page,
+ }) => {
+ await page.keyboard.press('Enter');
+ await createLinkedPage(page, 'Test Page');
+
+ const inlineLink = page.locator('affine-reference');
+ const inlineToolbar = page.locator('reference-popup');
+
+ await inlineLink.hover();
+
+ // Copies link
+ await inlineToolbar.getByRole('button', { name: 'Copy link' }).click();
+ const url0 = await (
+ await page.evaluateHandle(() => navigator.clipboard.readText())
+ ).jsonValue();
+
+ // Switches to card view
+ await inlineToolbar.getByRole('button', { name: 'Switch view' }).click();
+ await inlineToolbar.getByRole('button', { name: 'Card view' }).click();
+
+ const cardLink = page.locator('affine-embed-linked-doc-block');
+ const cardTitle = cardLink.locator(
+ '.affine-embed-linked-doc-content-title-text'
+ );
+ const cardDescription = cardLink.locator(
+ '.affine-embed-linked-doc-content-note.alias'
+ );
+ const cardToolbar = page.locator('affine-embed-card-toolbar');
+
+ await cardLink.click();
+
+ // Copies link
+ await cardToolbar.getByRole('button', { name: 'Copy link' }).click();
+ const url1 = await (
+ await page.evaluateHandle(() => navigator.clipboard.readText())
+ ).jsonValue();
+
+ // Switches to embed view
+ await cardToolbar.getByRole('button', { name: 'Switch view' }).click();
+ await cardToolbar.getByRole('button', { name: 'Embed view' }).click();
+
+ const embedLink = page.locator('affine-embed-synced-doc-block');
+ const embedTitle = embedLink.locator('.affine-embed-synced-doc-title');
+ const embedToolbar = page.locator('affine-embed-card-toolbar');
+
+ await embedLink.click();
+
+ // Copies link
+ await embedToolbar.getByRole('button', { name: 'Copy link' }).click();
+ const url2 = await (
+ await page.evaluateHandle(() => navigator.clipboard.readText())
+ ).jsonValue();
+
+ expect(url0).not.toBeNull();
+ expect(url1).not.toBeNull();
+ expect(url2).not.toBeNull();
+ expect(url0).toBe(url1);
+ expect(url1).toBe(url2);
+
+ // Edits title & description
+ await embedToolbar.getByRole('button', { name: 'Edit' }).click();
+
+ const embedEditPopup = page.locator('embed-card-edit-modal');
+
+ // Title alias
+ await page.keyboard.type('Test Page Alias Again');
+ await page.keyboard.press('Tab');
+ // Description alias
+ await page.keyboard.type('This is a new description');
+
+ // Cancels
+ await embedEditPopup.getByRole('button', { name: 'Cancel' }).click();
+ await expect(embedEditPopup).toBeHidden();
+
+ await embedLink.click();
+
+ // Edits title & description
+ await embedToolbar.getByRole('button', { name: 'Edit' }).click();
+
+ // Title alias
+ await page.keyboard.type('Test Page Alias');
+ await page.keyboard.press('Tab');
+ // Description alias
+ await page.keyboard.type('This is a new description');
+
+ // Saves aliases
+ await embedEditPopup.getByRole('button', { name: 'Save' }).click();
+
+ // Automatically switch to card view
+ await expect(embedLink).toBeHidden();
+
+ await expect(cardTitle).toHaveText('Test Page Alias');
+ await expect(cardDescription).toHaveText('This is a new description');
+
+ await cardLink.click();
+
+ const docTitle = cardToolbar.getByRole('button', { name: 'Doc title' });
+ await expect(docTitle).toHaveText('Test Page', { useInnerText: true });
+ await expect(cardTitle).toHaveText('Test Page Alias');
+
+ // Switches to embed view
+ await cardToolbar.getByRole('button', { name: 'Switch view' }).click();
+ await cardToolbar.getByRole('button', { name: 'Embed view' }).click();
+
+ await expect(embedTitle).toHaveText('Test Page');
+
+ await embedLink.click();
+
+ // Switches to inline view
+ {
+ await embedToolbar.getByRole('button', { name: 'Switch view' }).click();
+ await embedToolbar.getByRole('button', { name: 'Inline view' }).click();
+
+ // Focuses inline editor
+ const bounds = (await inlineLink.boundingBox())!;
+ await page.mouse.click(
+ bounds.x + bounds.width + 30,
+ bounds.y + bounds.height / 2
+ );
+
+ await inlineLink.hover();
+
+ // Upstreams: https://github.com/toeverything/blocksuite/pull/8884
+ // const title = inlineLink.locator('.affine-reference-title');
+ // await expect(title).toHaveText('Test Page');
+
+ // Switches to embed view
+ await inlineToolbar.getByRole('button', { name: 'Switch view' }).click();
+ await inlineToolbar.getByRole('button', { name: 'Embed view' }).click();
+ }
+
+ await embedLink.click();
+
+ await expect(embedTitle).toHaveText('Test Page');
+ await expect(
+ embedToolbar.getByRole('button', { name: 'Doc title' })
+ ).toBeHidden();
+ });
+});