mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 12:28:42 +00:00
770 lines
19 KiB
TypeScript
770 lines
19 KiB
TypeScript
import { sleep } from '@blocksuite/global/utils';
|
|
import { expect, type Page } from '@playwright/test';
|
|
import { switchEditorMode } from 'utils/actions/edgeless.js';
|
|
|
|
import { dragBlockToPoint, popImageMoreMenu } from './utils/actions/drag.js';
|
|
import {
|
|
pressArrowDown,
|
|
pressArrowUp,
|
|
pressBackspace,
|
|
pressEnter,
|
|
pressEscape,
|
|
pressShiftTab,
|
|
pressTab,
|
|
redoByKeyboard,
|
|
SHORT_KEY,
|
|
type,
|
|
undoByKeyboard,
|
|
} from './utils/actions/keyboard.js';
|
|
import {
|
|
captureHistory,
|
|
enterPlaygroundRoom,
|
|
focusRichText,
|
|
initEmptyEdgelessState,
|
|
initEmptyParagraphState,
|
|
resetHistory,
|
|
waitNextFrame,
|
|
} from './utils/actions/misc.js';
|
|
import {
|
|
assertBlockChildrenIds,
|
|
assertBlockCount,
|
|
assertBlockFlavour,
|
|
assertBlockSelections,
|
|
assertKeyboardWorkInInput,
|
|
assertParentBlockFlavour,
|
|
assertRichImage,
|
|
assertRichTextInlineRange,
|
|
assertStoreMatchJSX,
|
|
} from './utils/asserts.js';
|
|
import { test } from './utils/playwright.js';
|
|
|
|
const FILE_NAME = 'test-card-1.png';
|
|
const FILE_PATH = `../playground/public/${FILE_NAME}`;
|
|
const FILE_ID = 'ejImogf-Tb7AuKY-v94uz1zuOJbClqK-tWBxVr_ksGA=';
|
|
const FILE_SIZE = 45801;
|
|
|
|
function getAttachment(page: Page) {
|
|
const attachment = page.locator('affine-attachment');
|
|
const loading = attachment.locator('.affine-attachment-card.loading');
|
|
const toolbar = page.locator('.affine-attachment-toolbar');
|
|
const switchViewButton = toolbar.getByRole('button', { name: 'Switch view' });
|
|
const renameBtn = toolbar.getByRole('button', { name: 'Rename' });
|
|
const renameInput = page.locator('.affine-attachment-rename-container input');
|
|
|
|
const insertAttachment = async () => {
|
|
await page.evaluate(() => {
|
|
// Force fallback to input[type=file] in tests
|
|
// See https://github.com/microsoft/playwright/issues/8850
|
|
window.showOpenFilePicker = undefined;
|
|
});
|
|
|
|
const slashMenu = page.locator(`.slash-menu`);
|
|
await waitNextFrame(page);
|
|
await type(page, '/');
|
|
await resetHistory(page);
|
|
await expect(slashMenu).toBeVisible();
|
|
await type(page, 'file', 100);
|
|
await expect(slashMenu).toBeVisible();
|
|
|
|
const fileChooser = page.waitForEvent('filechooser');
|
|
await pressEnter(page);
|
|
await sleep(100);
|
|
await (await fileChooser).setFiles(FILE_PATH);
|
|
|
|
// Try to break the undo redo test
|
|
await captureHistory(page);
|
|
|
|
await expect(attachment).toBeVisible();
|
|
};
|
|
|
|
const getName = () =>
|
|
attachment.locator('.affine-attachment-content-title-text').innerText();
|
|
|
|
return {
|
|
// locators
|
|
attachment,
|
|
toolbar,
|
|
switchViewButton,
|
|
renameBtn,
|
|
renameInput,
|
|
|
|
// actions
|
|
insertAttachment,
|
|
/**
|
|
* Wait for the attachment upload to finish
|
|
*/
|
|
waitLoading: () => loading.waitFor({ state: 'hidden' }),
|
|
getName,
|
|
getSize: () =>
|
|
attachment.locator('.affine-attachment-content-info').innerText(),
|
|
|
|
turnToEmbed: async () => {
|
|
await expect(switchViewButton).toBeVisible();
|
|
await switchViewButton.click();
|
|
await page.getByRole('button', { name: 'Embed view' }).click();
|
|
await assertRichImage(page, 1);
|
|
},
|
|
rename: async (newName: string) => {
|
|
await attachment.hover();
|
|
await expect(toolbar).toBeVisible();
|
|
await renameBtn.click();
|
|
await page.keyboard.press(`${SHORT_KEY}+a`, { delay: 50 });
|
|
await pressBackspace(page);
|
|
await type(page, newName);
|
|
await pressEnter(page);
|
|
expect(await getName()).toContain(newName);
|
|
},
|
|
|
|
// external
|
|
turnImageToCard: async () => {
|
|
const { turnIntoCardButton } = await popImageMoreMenu(page);
|
|
await turnIntoCardButton.click();
|
|
await expect(attachment).toBeVisible();
|
|
},
|
|
};
|
|
}
|
|
|
|
test('can insert attachment from slash menu', async ({ page }) => {
|
|
await enterPlaygroundRoom(page);
|
|
const { noteId } = await initEmptyParagraphState(page);
|
|
|
|
const { insertAttachment, waitLoading, getName, getSize } =
|
|
getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await insertAttachment();
|
|
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
expect(await getName()).toBe(FILE_NAME);
|
|
expect(await getSize()).toBe('45.8 kB');
|
|
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
`
|
|
<affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:attachment
|
|
prop:embed={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
prop:name="${FILE_NAME}"
|
|
prop:rotate={0}
|
|
prop:size={${FILE_SIZE}}
|
|
prop:sourceId="${FILE_ID}"
|
|
prop:style="horizontalThin"
|
|
prop:type="image/png"
|
|
/>
|
|
</affine:note>`,
|
|
noteId
|
|
);
|
|
});
|
|
|
|
test('should undo/redo works for attachment', async ({ page }) => {
|
|
await enterPlaygroundRoom(page);
|
|
const { noteId } = await initEmptyParagraphState(page);
|
|
|
|
const { insertAttachment, waitLoading } = getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await insertAttachment();
|
|
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
` <affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:attachment
|
|
prop:embed={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
prop:name="${FILE_NAME}"
|
|
prop:rotate={0}
|
|
prop:size={${FILE_SIZE}}
|
|
prop:sourceId="${FILE_ID}"
|
|
prop:style="horizontalThin"
|
|
prop:type="image/png"
|
|
/>
|
|
</affine:note>`,
|
|
noteId
|
|
);
|
|
|
|
await undoByKeyboard(page);
|
|
await waitNextFrame(page);
|
|
// The loading/error state should not be restored after undo
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
`
|
|
<affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:paragraph
|
|
prop:collapsed={false}
|
|
prop:text="/"
|
|
prop:type="text"
|
|
/>
|
|
</affine:note>`,
|
|
noteId
|
|
);
|
|
|
|
await redoByKeyboard(page);
|
|
await waitNextFrame(page);
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
`
|
|
<affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:attachment
|
|
prop:embed={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
prop:name="${FILE_NAME}"
|
|
prop:rotate={0}
|
|
prop:size={${FILE_SIZE}}
|
|
prop:sourceId="${FILE_ID}"
|
|
prop:style="horizontalThin"
|
|
prop:type="image/png"
|
|
/>
|
|
</affine:note>`,
|
|
noteId
|
|
);
|
|
});
|
|
|
|
test('should rename attachment works', async ({ page }) => {
|
|
test.info().annotations.push({
|
|
type: 'issue',
|
|
description: 'https://github.com/toeverything/blocksuite/issues/4534',
|
|
});
|
|
await enterPlaygroundRoom(page);
|
|
await initEmptyParagraphState(page);
|
|
const {
|
|
attachment,
|
|
renameBtn,
|
|
renameInput,
|
|
insertAttachment,
|
|
waitLoading,
|
|
getName,
|
|
rename,
|
|
} = getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await insertAttachment();
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
expect(await getName()).toBe(FILE_NAME);
|
|
|
|
await attachment.hover();
|
|
await expect(renameBtn).toBeVisible();
|
|
await renameBtn.click();
|
|
await assertKeyboardWorkInInput(page, renameInput);
|
|
await pressEscape(page);
|
|
await expect(renameInput).not.toBeVisible();
|
|
|
|
await rename('new-name');
|
|
expect(await getName()).toBe('new-name.png');
|
|
await rename('');
|
|
expect(await getName()).toBe('.png');
|
|
await rename('abc');
|
|
expect(await getName()).toBe('abc');
|
|
});
|
|
|
|
test('should turn attachment to image works', async ({ page }) => {
|
|
await enterPlaygroundRoom(page);
|
|
const { noteId } = await initEmptyParagraphState(page);
|
|
const { insertAttachment, waitLoading, turnToEmbed, turnImageToCard } =
|
|
getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await insertAttachment();
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
await turnToEmbed();
|
|
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
`
|
|
<affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:image
|
|
prop:caption=""
|
|
prop:height={0}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
prop:rotate={0}
|
|
prop:size={${FILE_SIZE}}
|
|
prop:sourceId="${FILE_ID}"
|
|
prop:width={0}
|
|
/>
|
|
</affine:note>`,
|
|
noteId
|
|
);
|
|
await turnImageToCard();
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
`
|
|
<affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:attachment
|
|
prop:caption=""
|
|
prop:embed={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
prop:name="${FILE_NAME}"
|
|
prop:rotate={0}
|
|
prop:size={${FILE_SIZE}}
|
|
prop:sourceId="${FILE_ID}"
|
|
prop:style="horizontalThin"
|
|
prop:type="image/png"
|
|
/>
|
|
</affine:note>`,
|
|
noteId
|
|
);
|
|
});
|
|
|
|
test('should attachment can be deleted', async ({ page }) => {
|
|
await enterPlaygroundRoom(page);
|
|
const { noteId } = await initEmptyParagraphState(page);
|
|
const { attachment, insertAttachment, waitLoading } = getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await insertAttachment();
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
await attachment.click();
|
|
await pressBackspace(page);
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
`
|
|
<affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:paragraph
|
|
prop:collapsed={false}
|
|
prop:type="text"
|
|
/>
|
|
</affine:note>`,
|
|
noteId
|
|
);
|
|
});
|
|
|
|
test.fixme(`support dragging attachment block directly`, async ({ page }) => {
|
|
await enterPlaygroundRoom(page);
|
|
const { noteId } = await initEmptyParagraphState(page);
|
|
|
|
const { insertAttachment, waitLoading, getName, getSize } =
|
|
getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await insertAttachment();
|
|
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
expect(await getName()).toBe(FILE_NAME);
|
|
expect(await getSize()).toBe('45.8 kB');
|
|
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
` <affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:attachment
|
|
prop:embed={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
prop:name="${FILE_NAME}"
|
|
prop:rotate={0}
|
|
prop:size={${FILE_SIZE}}
|
|
prop:sourceId="${FILE_ID}"
|
|
prop:style="horizontalThin"
|
|
prop:type="image/png"
|
|
/>
|
|
</affine:note>`,
|
|
noteId
|
|
);
|
|
|
|
const attachmentBlock = page.locator('affine-attachment');
|
|
const rect = await attachmentBlock.boundingBox();
|
|
if (!rect) {
|
|
throw new Error('image not found');
|
|
}
|
|
|
|
// add new paragraph blocks
|
|
await page.mouse.click(rect.x + 20, rect.y + rect.height + 20);
|
|
await focusRichText(page);
|
|
await type(page, '111');
|
|
await page.waitForTimeout(200);
|
|
await pressEnter(page);
|
|
|
|
await type(page, '222');
|
|
await page.waitForTimeout(200);
|
|
await pressEnter(page);
|
|
|
|
await type(page, '333');
|
|
await page.waitForTimeout(200);
|
|
|
|
await page.waitForTimeout(200);
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
/*xml*/ `<affine:page>
|
|
<affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:attachment
|
|
prop:embed={false}
|
|
prop:index="a0"
|
|
prop:name="${FILE_NAME}"
|
|
prop:rotate={0}
|
|
prop:size={${FILE_SIZE}}
|
|
prop:sourceId="${FILE_ID}"
|
|
prop:style="horizontalThin"
|
|
prop:type="image/png"
|
|
/>
|
|
<affine:paragraph
|
|
prop:collapsed={false}
|
|
prop:text="111"
|
|
prop:type="text"
|
|
/>
|
|
<affine:paragraph
|
|
prop:collapsed={false}
|
|
prop:text="222"
|
|
prop:type="text"
|
|
/>
|
|
<affine:paragraph
|
|
prop:collapsed={false}
|
|
prop:text="333"
|
|
prop:type="text"
|
|
/>
|
|
</affine:note>
|
|
</affine:page>`
|
|
);
|
|
|
|
// drag bookmark block
|
|
await page.mouse.move(rect.x + 20, rect.y + 20);
|
|
await page.mouse.down();
|
|
await page.mouse.move(rect.x + 40, rect.y + rect.height + 80, { steps: 20 });
|
|
await page.mouse.up();
|
|
|
|
const rects = page.locator('affine-block-selection').locator('visible=true');
|
|
await expect(rects).toHaveCount(1);
|
|
|
|
await assertStoreMatchJSX(
|
|
page,
|
|
/*xml*/ `<affine:page>
|
|
<affine:note
|
|
prop:background="--affine-note-background-white"
|
|
prop:displayMode="both"
|
|
prop:edgeless={
|
|
Object {
|
|
"style": Object {
|
|
"borderRadius": 8,
|
|
"borderSize": 4,
|
|
"borderStyle": "none",
|
|
"shadowType": "--affine-note-shadow-box",
|
|
},
|
|
}
|
|
}
|
|
prop:hidden={false}
|
|
prop:index="a0"
|
|
prop:lockedBySelf={false}
|
|
>
|
|
<affine:paragraph
|
|
prop:collapsed={false}
|
|
prop:text="111"
|
|
prop:type="text"
|
|
/>
|
|
<affine:paragraph
|
|
prop:collapsed={false}
|
|
prop:text="222"
|
|
prop:type="text"
|
|
/>
|
|
<affine:attachment
|
|
prop:embed={false}
|
|
prop:index="a0"
|
|
prop:name="${FILE_NAME}"
|
|
prop:rotate={0}
|
|
prop:size={${FILE_SIZE}}
|
|
prop:sourceId="${FILE_ID}"
|
|
prop:style="horizontalThin"
|
|
prop:type="image/png"
|
|
/>
|
|
<affine:paragraph
|
|
prop:collapsed={false}
|
|
prop:text="333"
|
|
prop:type="text"
|
|
/>
|
|
</affine:note>
|
|
</affine:page>`
|
|
);
|
|
});
|
|
|
|
test('press backspace after bookmark block can select bookmark block', async ({
|
|
page,
|
|
}) => {
|
|
await enterPlaygroundRoom(page);
|
|
await initEmptyParagraphState(page);
|
|
const { insertAttachment, waitLoading } = getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await pressEnter(page);
|
|
await pressArrowUp(page);
|
|
await insertAttachment();
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
await focusRichText(page);
|
|
await assertBlockCount(page, 'paragraph', 1);
|
|
await assertRichTextInlineRange(page, 0, 0);
|
|
await pressBackspace(page);
|
|
await assertBlockSelections(page, ['4']);
|
|
await assertBlockCount(page, 'paragraph', 0);
|
|
});
|
|
|
|
test('cancel file picker with input element resolves', async ({ page }) => {
|
|
await enterPlaygroundRoom(page);
|
|
await initEmptyParagraphState(page);
|
|
|
|
const { attachment } = getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await pressEnter(page);
|
|
await pressArrowUp(page);
|
|
|
|
await page.evaluate(() => {
|
|
// Force fallback to input[type=file]
|
|
window.showOpenFilePicker = undefined;
|
|
});
|
|
|
|
const slashMenu = page.locator(`.slash-menu`);
|
|
await waitNextFrame(page);
|
|
await type(page, '/file', 100);
|
|
await expect(slashMenu).toBeVisible();
|
|
|
|
const fileChooser = page.waitForEvent('filechooser');
|
|
await pressEnter(page);
|
|
const inputFile = page.locator("input[type='file']");
|
|
await expect(inputFile).toHaveCount(1);
|
|
|
|
// This does not trigger `cancel` event and,
|
|
// therefore, the test isn't representative.
|
|
// Waiting for https://github.com/microsoft/playwright/issues/27524
|
|
await (await fileChooser).setFiles([]);
|
|
|
|
await expect(attachment).toHaveCount(0);
|
|
await expect(inputFile).toHaveCount(0);
|
|
});
|
|
|
|
test('indent attachment block to paragraph', async ({ page }) => {
|
|
await enterPlaygroundRoom(page);
|
|
await initEmptyParagraphState(page);
|
|
const { insertAttachment, waitLoading } = getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await pressEnter(page);
|
|
await insertAttachment();
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
await assertBlockChildrenIds(page, '1', ['2', '4']);
|
|
await assertBlockFlavour(page, '1', 'affine:note');
|
|
await assertBlockFlavour(page, '2', 'affine:paragraph');
|
|
await assertBlockFlavour(page, '4', 'affine:attachment');
|
|
|
|
await focusRichText(page);
|
|
await pressArrowDown(page);
|
|
await assertBlockSelections(page, ['4']);
|
|
await pressTab(page);
|
|
await assertBlockChildrenIds(page, '1', ['2']);
|
|
await assertBlockChildrenIds(page, '2', ['4']);
|
|
|
|
await pressShiftTab(page);
|
|
await assertBlockChildrenIds(page, '1', ['2', '4']);
|
|
});
|
|
|
|
test('indent attachment block to list', async ({ page }) => {
|
|
await enterPlaygroundRoom(page);
|
|
await initEmptyParagraphState(page);
|
|
const { insertAttachment, waitLoading } = getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await type(page, '- a');
|
|
await pressEnter(page);
|
|
await insertAttachment();
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
await assertBlockChildrenIds(page, '1', ['3', '5']);
|
|
await assertBlockFlavour(page, '1', 'affine:note');
|
|
await assertBlockFlavour(page, '3', 'affine:list');
|
|
await assertBlockFlavour(page, '5', 'affine:attachment');
|
|
|
|
await focusRichText(page);
|
|
await pressArrowDown(page);
|
|
await assertBlockSelections(page, ['5']);
|
|
await pressTab(page);
|
|
await assertBlockChildrenIds(page, '1', ['3']);
|
|
await assertBlockChildrenIds(page, '3', ['5']);
|
|
|
|
await pressShiftTab(page);
|
|
await assertBlockChildrenIds(page, '1', ['3', '5']);
|
|
});
|
|
|
|
test('attachment can be dragged from note to surface top level block', async ({
|
|
page,
|
|
}) => {
|
|
await enterPlaygroundRoom(page);
|
|
await initEmptyEdgelessState(page);
|
|
const { insertAttachment, waitLoading } = getAttachment(page);
|
|
|
|
await focusRichText(page);
|
|
await insertAttachment();
|
|
|
|
// Wait for the attachment to be uploaded
|
|
await waitLoading();
|
|
|
|
await switchEditorMode(page);
|
|
await page.mouse.dblclick(450, 450);
|
|
|
|
await dragBlockToPoint(page, '4', { x: 200, y: 200 });
|
|
|
|
await waitNextFrame(page);
|
|
await assertParentBlockFlavour(page, '4', 'affine:surface');
|
|
});
|