test(editor): move blocksuite test to tests folder (#10917)
This commit is contained in:
412
tests/blocksuite/e2e/clipboard/clipboard.spec.ts
Normal file
412
tests/blocksuite/e2e/clipboard/clipboard.spec.ts
Normal file
@@ -0,0 +1,412 @@
|
||||
import '../utils/declare-test-window.js';
|
||||
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
import {
|
||||
captureHistory,
|
||||
copyByKeyboard,
|
||||
dragBetweenCoords,
|
||||
dragOverTitle,
|
||||
enterPlaygroundRoom,
|
||||
focusRichText,
|
||||
focusTitle,
|
||||
getClipboardHTML,
|
||||
getClipboardSnapshot,
|
||||
getClipboardText,
|
||||
getCurrentEditorDocId,
|
||||
getEditorLocator,
|
||||
getPageSnapshot,
|
||||
initEmptyParagraphState,
|
||||
mockParseDocUrlService,
|
||||
pasteByKeyboard,
|
||||
pasteContent,
|
||||
pressEnter,
|
||||
pressShiftTab,
|
||||
pressTab,
|
||||
resetHistory,
|
||||
setInlineRangeInSelectedRichText,
|
||||
setSelection,
|
||||
SHORT_KEY,
|
||||
type,
|
||||
undoByClick,
|
||||
waitNextFrame,
|
||||
} from '../utils/actions/index.js';
|
||||
import {
|
||||
assertBlockTypes,
|
||||
assertClipItems,
|
||||
assertRichTexts,
|
||||
assertText,
|
||||
assertTitle,
|
||||
} from '../utils/asserts.js';
|
||||
import { scoped, test } from '../utils/playwright.js';
|
||||
|
||||
test(scoped`clipboard copy paste`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
|
||||
await type(page, 'test');
|
||||
await setInlineRangeInSelectedRichText(page, 0, 3);
|
||||
await waitNextFrame(page);
|
||||
await copyByKeyboard(page);
|
||||
await focusRichText(page);
|
||||
await page.keyboard.press(`${SHORT_KEY}+v`);
|
||||
await assertText(page, 'testtes');
|
||||
});
|
||||
|
||||
test(scoped`clipboard copy paste title`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusTitle(page);
|
||||
|
||||
await type(page, 'test');
|
||||
await dragOverTitle(page);
|
||||
await waitNextFrame(page);
|
||||
await copyByKeyboard(page);
|
||||
await focusTitle(page);
|
||||
await page.keyboard.press(`${SHORT_KEY}+v`);
|
||||
await assertTitle(page, 'testtest');
|
||||
});
|
||||
|
||||
test(scoped`clipboard paste html`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
|
||||
// set up clipboard data using html
|
||||
const clipData = {
|
||||
'text/html': `<span>aaa</span><span>bbb</span><span>ccc</span><bdi>ddd</bdi>`,
|
||||
};
|
||||
await waitNextFrame(page);
|
||||
await page.evaluate(
|
||||
({ clipData }) => {
|
||||
const dT = new DataTransfer();
|
||||
const e = new ClipboardEvent('paste', { clipboardData: dT });
|
||||
Object.defineProperty(e, 'target', {
|
||||
writable: false,
|
||||
value: document,
|
||||
});
|
||||
e.clipboardData?.setData('text/html', clipData['text/html']);
|
||||
document.dispatchEvent(e);
|
||||
},
|
||||
{ clipData }
|
||||
);
|
||||
await assertText(page, 'aaabbbcccddd');
|
||||
});
|
||||
|
||||
test(scoped`split block when paste`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
await resetHistory(page);
|
||||
|
||||
const clipData = {
|
||||
'text/plain': `# text
|
||||
# h1
|
||||
`,
|
||||
};
|
||||
await type(page, 'abc');
|
||||
await captureHistory(page);
|
||||
|
||||
await setInlineRangeInSelectedRichText(page, 1, 1);
|
||||
await pasteContent(page, clipData);
|
||||
await waitNextFrame(page);
|
||||
|
||||
await assertRichTexts(page, ['atext', 'h1c']);
|
||||
|
||||
await undoByClick(page);
|
||||
await assertRichTexts(page, ['abc']);
|
||||
|
||||
await type(page, 'aa');
|
||||
await pressEnter(page);
|
||||
await type(page, 'bb');
|
||||
const topLeft123 = await getEditorLocator(page)
|
||||
.locator('[data-block-id="2"] .inline-editor')
|
||||
.boundingBox();
|
||||
const bottomRight789 = await getEditorLocator(page)
|
||||
.locator('[data-block-id="4"] .inline-editor')
|
||||
.boundingBox();
|
||||
if (!topLeft123) {
|
||||
throw new Error('topLeft123 is not found');
|
||||
}
|
||||
if (!bottomRight789) {
|
||||
throw new Error('bottomRight789 is not found');
|
||||
}
|
||||
await dragBetweenCoords(page, topLeft123, bottomRight789);
|
||||
|
||||
// FIXME see https://github.com/toeverything/blocksuite/pull/878
|
||||
// await pasteContent(page, clipData);
|
||||
// await assertRichTexts(page, ['aaa', 'bbc', 'text', 'h1']);
|
||||
});
|
||||
|
||||
test(scoped`copy clipItems format`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
await captureHistory(page);
|
||||
|
||||
const clipData = `
|
||||
- aa
|
||||
- bb
|
||||
- cc
|
||||
- dd
|
||||
`;
|
||||
|
||||
await pasteContent(page, { 'text/plain': clipData });
|
||||
await page.waitForTimeout(100);
|
||||
await setSelection(page, 4, 1, 5, 1);
|
||||
assertClipItems(page, 'text/plain', 'bc');
|
||||
assertClipItems(page, 'text/html', '<ul><li>b<ul><li>c</li></ul></li></ul>');
|
||||
await undoByClick(page);
|
||||
await assertRichTexts(page, ['']);
|
||||
});
|
||||
|
||||
test(scoped`copy partially selected text`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
|
||||
await type(page, '123 456 789');
|
||||
|
||||
// select 456
|
||||
await setInlineRangeInSelectedRichText(page, 4, 3);
|
||||
await copyByKeyboard(page);
|
||||
assertClipItems(page, 'text/plain', '456');
|
||||
|
||||
// move to line end
|
||||
await setInlineRangeInSelectedRichText(page, 11, 0);
|
||||
await pressEnter(page);
|
||||
await pasteByKeyboard(page);
|
||||
await waitNextFrame(page);
|
||||
|
||||
await assertRichTexts(page, ['123 456 789', '456']);
|
||||
});
|
||||
|
||||
test(scoped`copy & paste outside editor`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await page.evaluate(() => {
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('id', 'input-test');
|
||||
input.value = '123';
|
||||
document.body.querySelector('#app')?.append(input);
|
||||
});
|
||||
await page.focus('#input-test');
|
||||
await page.dblclick('#input-test');
|
||||
await copyByKeyboard(page);
|
||||
await focusRichText(page);
|
||||
await pasteByKeyboard(page);
|
||||
await waitNextFrame(page);
|
||||
await assertRichTexts(page, ['123']);
|
||||
});
|
||||
|
||||
test('should keep first line format when pasted into a new line', async ({
|
||||
page,
|
||||
}) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
|
||||
const clipData = `
|
||||
- [ ] aaa
|
||||
`;
|
||||
|
||||
await pasteContent(page, { 'text/plain': clipData });
|
||||
await waitNextFrame(page);
|
||||
await assertRichTexts(page, ['aaa']);
|
||||
await assertBlockTypes(page, ['todo']);
|
||||
});
|
||||
|
||||
test(scoped`auto identify url`, async ({ page }, testInfo) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
|
||||
// set up clipboard data using html
|
||||
const clipData = {
|
||||
'text/plain': `test https://www.google.com`,
|
||||
};
|
||||
await waitNextFrame(page);
|
||||
await page.evaluate(
|
||||
({ clipData }) => {
|
||||
const dT = new DataTransfer();
|
||||
const e = new ClipboardEvent('paste', { clipboardData: dT });
|
||||
Object.defineProperty(e, 'target', {
|
||||
writable: false,
|
||||
value: document,
|
||||
});
|
||||
e.clipboardData?.setData('text/plain', clipData['text/plain']);
|
||||
document.dispatchEvent(e);
|
||||
},
|
||||
{ clipData }
|
||||
);
|
||||
expect(await getPageSnapshot(page, true)).toMatchSnapshot(
|
||||
`${testInfo.title}_final.json`
|
||||
);
|
||||
});
|
||||
|
||||
test(scoped`pasting internal url`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusTitle(page);
|
||||
await type(page, 'test page');
|
||||
|
||||
await focusRichText(page);
|
||||
const docId = await getCurrentEditorDocId(page);
|
||||
await mockParseDocUrlService(page, {
|
||||
'http://workspace/doc-id': docId,
|
||||
});
|
||||
await pasteContent(page, {
|
||||
'text/plain': 'http://workspace/doc-id',
|
||||
});
|
||||
await expect(page.locator('affine-reference')).toContainText('test page');
|
||||
});
|
||||
|
||||
test(scoped`pasting internal url with params`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusTitle(page);
|
||||
await type(page, 'test page');
|
||||
|
||||
await focusRichText(page);
|
||||
const docId = await getCurrentEditorDocId(page);
|
||||
await mockParseDocUrlService(page, {
|
||||
'http://workspace/doc-id?mode=page&blockIds=rL2_GXbtLU2SsJVfCSmh_': docId,
|
||||
});
|
||||
await pasteContent(page, {
|
||||
'text/plain':
|
||||
'http://workspace/doc-id?mode=page&blockIds=rL2_GXbtLU2SsJVfCSmh_',
|
||||
});
|
||||
await expect(page.locator('affine-reference')).toContainText('test page');
|
||||
});
|
||||
|
||||
test(
|
||||
scoped`pasting an external URL from clipboard to automatically creating a link from selection`,
|
||||
async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusTitle(page);
|
||||
await type(page, 'test page');
|
||||
|
||||
await focusRichText(page);
|
||||
await type(page, 'title alias');
|
||||
await setSelection(page, 1, 6, 1, 11);
|
||||
|
||||
await pasteContent(page, {
|
||||
'text/plain': 'https://affine.pro/',
|
||||
});
|
||||
await expect(page.locator('affine-link')).toContainText('alias');
|
||||
}
|
||||
);
|
||||
|
||||
test(
|
||||
scoped`pasting an internal URL from clipboard to automatically creating a link from selection`,
|
||||
async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusTitle(page);
|
||||
await type(page, 'test page');
|
||||
|
||||
await focusRichText(page);
|
||||
await type(page, 'title alias');
|
||||
await setSelection(page, 1, 6, 1, 11);
|
||||
|
||||
const docId = await getCurrentEditorDocId(page);
|
||||
await mockParseDocUrlService(page, {
|
||||
'http://workspace/doc-id': docId,
|
||||
});
|
||||
await pasteContent(page, {
|
||||
'text/plain': 'http://workspace/doc-id',
|
||||
});
|
||||
await expect(page.locator('affine-reference')).toContainText('alias');
|
||||
}
|
||||
);
|
||||
|
||||
test(scoped`paste parent block`, async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/toeverything/blocksuite/issues/3153',
|
||||
});
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
await type(page, 'This is parent');
|
||||
await page.keyboard.press('Enter');
|
||||
await page.keyboard.press('Tab');
|
||||
await type(page, 'This is child 1');
|
||||
await page.keyboard.press('Enter');
|
||||
await page.keyboard.press('Tab');
|
||||
await type(page, 'This is child 2');
|
||||
await setInlineRangeInSelectedRichText(page, 0, 3);
|
||||
await copyByKeyboard(page);
|
||||
await focusRichText(page, 2);
|
||||
await page.keyboard.press(`${SHORT_KEY}+v`);
|
||||
await assertRichTexts(page, [
|
||||
'This is parent',
|
||||
'This is child 1',
|
||||
'This is child 2Thi',
|
||||
]);
|
||||
});
|
||||
|
||||
test(scoped`clipboard copy multi selection`, async ({ page }) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
|
||||
await type(page, 'abc');
|
||||
await pressEnter(page);
|
||||
await type(page, 'def');
|
||||
await setSelection(page, 2, 1, 3, 1);
|
||||
await waitNextFrame(page);
|
||||
await copyByKeyboard(page);
|
||||
await waitNextFrame(page);
|
||||
await focusRichText(page, 1);
|
||||
await pasteByKeyboard(page);
|
||||
await waitNextFrame(page);
|
||||
await type(page, 'cursor');
|
||||
await waitNextFrame(page);
|
||||
await assertRichTexts(page, ['abc', 'defbc', 'dcursor']);
|
||||
});
|
||||
|
||||
test(scoped`clipboard copy nested items`, async ({ page }, testInfo) => {
|
||||
await enterPlaygroundRoom(page);
|
||||
await initEmptyParagraphState(page);
|
||||
await focusRichText(page);
|
||||
|
||||
await type(page, 'abc');
|
||||
await pressEnter(page);
|
||||
await pressTab(page);
|
||||
await type(page, 'def');
|
||||
await pressEnter(page);
|
||||
await pressTab(page);
|
||||
await type(page, 'ghi');
|
||||
await pressEnter(page);
|
||||
await pressShiftTab(page);
|
||||
await pressShiftTab(page);
|
||||
await type(page, 'jkl');
|
||||
await setSelection(page, 2, 1, 3, 1);
|
||||
await waitNextFrame(page);
|
||||
await copyByKeyboard(page);
|
||||
|
||||
const text = await getClipboardText(page);
|
||||
const html = await getClipboardHTML(page);
|
||||
const snapshot = await getClipboardSnapshot(page);
|
||||
expect(text).toMatchSnapshot(`${testInfo.title}-clipboard.md`);
|
||||
expect(JSON.stringify(snapshot.snapshot.content, null, 2)).toMatchSnapshot(
|
||||
`${testInfo.title}-clipboard.json`
|
||||
);
|
||||
expect(html).toMatchSnapshot(`${testInfo.title}-clipboard.html`);
|
||||
|
||||
await setSelection(page, 4, 1, 5, 1);
|
||||
await waitNextFrame(page);
|
||||
await copyByKeyboard(page);
|
||||
|
||||
const text2 = await getClipboardText(page);
|
||||
const html2 = await getClipboardHTML(page);
|
||||
const snapshot2 = await getClipboardSnapshot(page);
|
||||
expect(text2).toMatchSnapshot(`${testInfo.title}-clipboard2.md`);
|
||||
expect(JSON.stringify(snapshot2.snapshot.content, null, 2)).toMatchSnapshot(
|
||||
`${testInfo.title}-clipboard2.json`
|
||||
);
|
||||
expect(html2).toMatchSnapshot(`${testInfo.title}-clipboard2.html`);
|
||||
});
|
||||
Reference in New Issue
Block a user