mirror of
https://github.com/facebook/lexical.git
synced 2025-05-17 06:59:17 +08:00
2730 lines
76 KiB
JavaScript
2730 lines
76 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
*/
|
|
|
|
import {
|
|
deleteBackward,
|
|
moveDown,
|
|
moveLeft,
|
|
moveRight,
|
|
moveToEditorBeginning,
|
|
moveUp,
|
|
pressBackspace,
|
|
selectAll,
|
|
} from '../keyboardShortcuts/index.mjs';
|
|
import {
|
|
assertHTML,
|
|
assertSelection,
|
|
click,
|
|
clickSelectors,
|
|
copyToClipboard,
|
|
deleteTableColumns,
|
|
deleteTableRows,
|
|
focusEditor,
|
|
html,
|
|
initialize,
|
|
insertCollapsible,
|
|
insertHorizontalRule,
|
|
insertSampleImage,
|
|
insertTable,
|
|
insertTableColumnBefore,
|
|
insertTableRowBelow,
|
|
IS_COLLAB,
|
|
LEGACY_EVENTS,
|
|
mergeTableCells,
|
|
pasteFromClipboard,
|
|
SAMPLE_IMAGE_URL,
|
|
selectCellsFromTableCords,
|
|
selectFromAdditionalStylesDropdown,
|
|
selectFromAlignDropdown,
|
|
setBackgroundColor,
|
|
test,
|
|
toggleColumnHeader,
|
|
unmergeTableCell,
|
|
waitForSelector,
|
|
} from '../utils/index.mjs';
|
|
|
|
async function fillTablePartiallyWithText(page) {
|
|
await page.keyboard.type('a');
|
|
await page.keyboard.press('ArrowRight');
|
|
await page.keyboard.press('b');
|
|
await page.keyboard.press('Tab');
|
|
await page.keyboard.press('c');
|
|
await page.keyboard.down('Shift');
|
|
await page.keyboard.press('Tab');
|
|
await page.keyboard.up('Shift');
|
|
await page.keyboard.press('b');
|
|
await page.keyboard.press('ArrowDown');
|
|
await page.keyboard.press('ArrowLeft');
|
|
await page.keyboard.press('d');
|
|
await page.keyboard.press('ArrowRight');
|
|
await page.keyboard.press('e');
|
|
await page.keyboard.press('ArrowRight');
|
|
await page.keyboard.press('f');
|
|
await page.keyboard.press('ArrowUp');
|
|
await page.keyboard.press('c');
|
|
}
|
|
|
|
test.describe.parallel('Tables', () => {
|
|
test(`Can a table be inserted from the toolbar`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 2, 2);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
undefined,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test(`Can type inside of table cell`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await page.keyboard.type('abc');
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">abc</span></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
undefined,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test.describe
|
|
.parallel(`Can exit tables with the horizontal arrow keys`, () => {
|
|
test(`Can exit the first cell of a non-nested table`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 0, 0],
|
|
});
|
|
|
|
await moveLeft(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [0],
|
|
focusOffset: 0,
|
|
focusPath: [0],
|
|
});
|
|
|
|
await moveRight(page, 1);
|
|
await page.keyboard.type('ab');
|
|
await assertSelection(page, {
|
|
anchorOffset: 2,
|
|
anchorPath: [1, 0, 0, 0, 0, 0],
|
|
focusOffset: 2,
|
|
focusPath: [1, 0, 0, 0, 0, 0],
|
|
});
|
|
|
|
await moveRight(page, 3);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 1, 1, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 1, 1, 0],
|
|
});
|
|
});
|
|
|
|
test(`Can exit the last cell of a non-nested table`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await moveRight(page, 3);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 1, 1, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 1, 1, 0],
|
|
});
|
|
|
|
await moveRight(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [2],
|
|
focusOffset: 0,
|
|
focusPath: [2],
|
|
});
|
|
|
|
await moveLeft(page, 1);
|
|
await page.keyboard.type('ab');
|
|
await assertSelection(page, {
|
|
anchorOffset: 2,
|
|
anchorPath: [1, 1, 1, 0, 0, 0],
|
|
focusOffset: 2,
|
|
focusPath: [1, 1, 1, 0, 0, 0],
|
|
});
|
|
|
|
await moveRight(page, 3);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [2],
|
|
focusOffset: 0,
|
|
focusPath: [2],
|
|
});
|
|
});
|
|
|
|
test(`Can exit the first cell of a nested table into the parent table cell`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 0, 1, 0, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 0, 1, 0, 0, 0],
|
|
});
|
|
|
|
await moveLeft(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 0, 0],
|
|
});
|
|
});
|
|
|
|
test(`Can exit the last cell of a nested table into the parent table cell`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await moveRight(page, 3);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 0, 1, 1, 1, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 0, 1, 1, 1, 0],
|
|
});
|
|
|
|
await moveRight(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 0, 2],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 0, 2],
|
|
});
|
|
});
|
|
});
|
|
|
|
test(`Can insert a paragraph after a table, that is the last node, with the "Enter" key`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
browserName,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
// Table edge cursor doesn't show up in Firefox.
|
|
test.fixme(browserName === 'firefox');
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await moveDown(page, 2);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [2],
|
|
focusOffset: 0,
|
|
focusPath: [2],
|
|
});
|
|
|
|
await deleteBackward(page);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 1, 1, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 1, 1, 0],
|
|
});
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
`,
|
|
undefined,
|
|
{ignoreClasses: true},
|
|
);
|
|
|
|
await moveRight(page, 1);
|
|
// The native window selection should be on the root, whereas
|
|
// the editor selection should be on the last cell of the table.
|
|
await assertSelection(page, {
|
|
anchorOffset: 2,
|
|
anchorPath: [],
|
|
focusOffset: 2,
|
|
focusPath: [],
|
|
});
|
|
|
|
await page.keyboard.press('Enter');
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [2],
|
|
focusOffset: 0,
|
|
focusPath: [2],
|
|
});
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
undefined,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test(`Can type text after a table that is the last node`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
browserName,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
// Table edge cursor doesn't show up in Firefox.
|
|
test.fixme(browserName === 'firefox');
|
|
// After typing, the dom selection gets set back to the internal previous selection during the update.
|
|
test.fixme(LEGACY_EVENTS);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await moveDown(page, 2);
|
|
await deleteBackward(page);
|
|
|
|
await moveRight(page, 1);
|
|
await page.keyboard.type('a');
|
|
await assertSelection(page, {
|
|
anchorOffset: 1,
|
|
anchorPath: [2, 0, 0],
|
|
focusOffset: 1,
|
|
focusPath: [2, 0, 0],
|
|
});
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p dir="ltr"><span data-lexical-text="true">a</span></p>
|
|
`,
|
|
undefined,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test(`Can enter a table from a paragraph underneath via the left arrow key`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await moveDown(page, 2);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [2],
|
|
focusOffset: 0,
|
|
focusPath: [2],
|
|
});
|
|
|
|
await moveLeft(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 1, 1, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 1, 1, 0],
|
|
});
|
|
});
|
|
|
|
test.describe.parallel(`Can navigate table with keyboard`, () => {
|
|
test(`Can navigate cells horizontally`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
undefined,
|
|
{ignoreClasses: true},
|
|
);
|
|
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 0, 0],
|
|
});
|
|
|
|
await moveRight(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 1, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 1, 0],
|
|
});
|
|
|
|
await moveRight(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 1, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 1, 0, 0],
|
|
});
|
|
|
|
await moveRight(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 1, 1, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 1, 1, 0],
|
|
});
|
|
|
|
await moveLeft(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 1, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 1, 0, 0],
|
|
});
|
|
|
|
await moveLeft(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 1, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 1, 0],
|
|
});
|
|
|
|
await moveLeft(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 0, 0],
|
|
});
|
|
});
|
|
|
|
test(`Can navigate cells vertically`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 0, 0],
|
|
});
|
|
|
|
await moveDown(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 1, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 1, 0, 0],
|
|
});
|
|
|
|
await moveUp(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 0,
|
|
anchorPath: [1, 0, 0, 0],
|
|
focusOffset: 0,
|
|
focusPath: [1, 0, 0, 0],
|
|
});
|
|
});
|
|
|
|
test('Should not navigate cells when typeahead menu is open and focused', async ({
|
|
page,
|
|
isCollab,
|
|
isPlainText,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 2);
|
|
|
|
await page.keyboard.type('@A');
|
|
await assertSelection(page, {
|
|
anchorOffset: 2,
|
|
anchorPath: [1, 0, 0, 0, 0, 0],
|
|
focusOffset: 2,
|
|
focusPath: [1, 0, 0, 0, 0, 0],
|
|
});
|
|
|
|
await waitForSelector(page, `#typeahead-menu ul li:first-child.selected`);
|
|
|
|
await moveDown(page, 1);
|
|
await assertSelection(page, {
|
|
anchorOffset: 2,
|
|
anchorPath: [1, 0, 0, 0, 0, 0],
|
|
focusOffset: 2,
|
|
focusPath: [1, 0, 0, 0, 0, 0],
|
|
});
|
|
|
|
await waitForSelector(
|
|
page,
|
|
'#typeahead-menu ul li:nth-child(2).selected',
|
|
);
|
|
});
|
|
});
|
|
|
|
test(`Can select cells using Table selection`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 3);
|
|
|
|
await fillTablePartiallyWithText(page);
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 1},
|
|
true,
|
|
false,
|
|
);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><span data-lexical-text="true">a</span></p>
|
|
</th>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><span data-lexical-text="true">bb</span></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><span data-lexical-text="true">d</span></p>
|
|
</th>
|
|
<td
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><span data-lexical-text="true">e</span></p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">a</span></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">bb</span></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">d</span></p>
|
|
</th>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">e</span></p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test(`Can select cells using Table selection via keyboard`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
browserName,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 3, 3);
|
|
|
|
await fillTablePartiallyWithText(page);
|
|
|
|
let p = page;
|
|
|
|
if (IS_COLLAB) {
|
|
await focusEditor(page);
|
|
p = await page.frame('left');
|
|
}
|
|
|
|
const firstRowFirstColumnCellBoundingBox = await p.locator(
|
|
'table:first-of-type > tr:nth-child(1) > th:nth-child(1)',
|
|
);
|
|
|
|
// Focus on inside the iFrame or the boundingBox() below returns null.
|
|
await firstRowFirstColumnCellBoundingBox.click();
|
|
|
|
await page.keyboard.down('Shift');
|
|
await page.keyboard.press('ArrowRight');
|
|
// Firefox range selection spans across cells after two arrow key press
|
|
if (browserName === 'firefox') {
|
|
await page.keyboard.press('ArrowRight');
|
|
}
|
|
await page.keyboard.press('ArrowDown');
|
|
await page.keyboard.up('Shift');
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><span data-lexical-text="true">a</span></p>
|
|
</th>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><span data-lexical-text="true">bb</span></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><span data-lexical-text="true">d</span></p>
|
|
</th>
|
|
<td
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><span data-lexical-text="true">e</span></p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">a</span></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">bb</span></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">d</span></p>
|
|
</th>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">e</span></p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
{ignoreClasses: true, ignoreInlineStyles: true},
|
|
);
|
|
});
|
|
|
|
test(`Can style text using Table selection`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 3);
|
|
|
|
await fillTablePartiallyWithText(page);
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 1},
|
|
true,
|
|
false,
|
|
);
|
|
|
|
await clickSelectors(page, ['.bold', '.italic', '.underline']);
|
|
|
|
await selectFromAdditionalStylesDropdown(page, '.strikethrough');
|
|
|
|
// Check that the character styles are applied.
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><strong data-lexical-text="true">a</strong></p>
|
|
</th>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><strong data-lexical-text="true">bb</strong></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><strong data-lexical-text="true">d</strong></p>
|
|
</th>
|
|
<td
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p dir="ltr"><strong data-lexical-text="true">e</strong></p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><strong data-lexical-text="true">a</strong></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><strong data-lexical-text="true">bb</strong></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><strong data-lexical-text="true">d</strong></p>
|
|
</th>
|
|
<td>
|
|
<p dir="ltr"><strong data-lexical-text="true">e</strong></p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test(`Can copy + paste (internal) using Table selection`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 3);
|
|
|
|
await fillTablePartiallyWithText(page);
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 1},
|
|
true,
|
|
false,
|
|
);
|
|
|
|
const clipboard = await copyToClipboard(page);
|
|
|
|
// For some reason you need to click the paragraph twice for this to pass
|
|
// on Collab Firefox.
|
|
await click(page, 'div.ContentEditable__root > p:first-of-type');
|
|
await click(page, 'div.ContentEditable__root > p:first-of-type');
|
|
|
|
await pasteFromClipboard(page, clipboard);
|
|
|
|
// Check that the character styles are applied.
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">a</span></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">bb</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">d</span></p>
|
|
</th>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">e</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">a</span></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">bb</span></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">d</span></p>
|
|
</th>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">e</span></p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
undefined,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test(`Can clear text using Table selection`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 3);
|
|
|
|
await fillTablePartiallyWithText(page);
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 1},
|
|
true,
|
|
false,
|
|
);
|
|
|
|
await page.keyboard.press('Backspace');
|
|
|
|
// Check that the text was cleared.
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
undefined,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test(`Range Selection is corrected when it contains a partial Table.`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 1, 2);
|
|
await moveToEditorBeginning(page);
|
|
|
|
await page.keyboard.down('Shift');
|
|
await page.keyboard.press('ArrowRight');
|
|
await page.keyboard.up('Shift');
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p><br /></p>
|
|
</th>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test(`Select All when document contains tables adds custom table styles.`, async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await page.keyboard.type('Hello World');
|
|
|
|
await insertTable(page, 2, 3);
|
|
|
|
await selectAll(page);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p dir="ltr"><span data-lexical-text="true">Hello World</span></p>
|
|
<table>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p><br /></p>
|
|
</th>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p><br /></p>
|
|
</th>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p><br /></p>
|
|
</th>
|
|
<td
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p><br /></p>
|
|
</td>
|
|
<td
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
html`
|
|
<p dir="ltr"><span data-lexical-text="true">Hello World</span></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
<td>
|
|
<p><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test(`Horizontal rule inside cell`, async ({page, isPlainText, isCollab}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 1, 2);
|
|
await page.keyboard.type('123');
|
|
await insertHorizontalRule(page);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th>
|
|
<p><span data-lexical-text="true">123</span></p>
|
|
<hr contenteditable="false" data-lexical-decorator="true" />
|
|
<p><br /></p>
|
|
</th>
|
|
<th>
|
|
<p><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
undefined,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
|
|
test('Grid selection: can select multiple cells and insert an image', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
browserName,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 2, 2);
|
|
|
|
await click(page, '.PlaygroundEditorTheme__tableCell');
|
|
await page.keyboard.type('Hello');
|
|
|
|
await page.keyboard.down('Shift');
|
|
await page.keyboard.press('ArrowRight');
|
|
// Firefox range selection spans across cells after two arrow key press
|
|
if (browserName === 'firefox') {
|
|
await page.keyboard.press('ArrowRight');
|
|
}
|
|
await page.keyboard.press('ArrowDown');
|
|
await page.keyboard.up('Shift');
|
|
|
|
await insertSampleImage(page);
|
|
await page.keyboard.type(' <- it works!');
|
|
|
|
// Wait for Decorator to mount.
|
|
await page.waitForTimeout(3000);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">Hello</span>
|
|
</p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span
|
|
class="editor-image"
|
|
contenteditable="false"
|
|
data-lexical-decorator="true">
|
|
<div draggable="false">
|
|
<img
|
|
alt="Yellow flower in tilt shift lens"
|
|
draggable="false"
|
|
src="${SAMPLE_IMAGE_URL}"
|
|
style="height: inherit; max-width: 500px; width: inherit" />
|
|
</div>
|
|
</span>
|
|
<span data-lexical-text="true"><- it works!</span>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Grid selection: can backspace lines, backspacing empty cell does not destroy it #3278', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 1, 2);
|
|
|
|
await click(page, '.PlaygroundEditorTheme__tableCell');
|
|
await page.keyboard.type('cell one');
|
|
await moveRight(page, 1);
|
|
await page.keyboard.type('first line');
|
|
await page.keyboard.press('Enter');
|
|
await page.keyboard.type('second line');
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">cell one</span>
|
|
</p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">first line</span>
|
|
</p>
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">second line</span>
|
|
</p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
|
|
await pressBackspace(page, 50);
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">cell one</span>
|
|
</p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Can remove new lines in a collapsible section inside of a table', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
browserName,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 1, 2);
|
|
await insertCollapsible(page);
|
|
|
|
await page.keyboard.type('123');
|
|
await page.keyboard.press('ArrowDown');
|
|
await page.keyboard.type('123');
|
|
await page.keyboard.press('Enter');
|
|
await page.keyboard.press('Enter');
|
|
await page.keyboard.press('Enter');
|
|
|
|
const collapsibleOpeningTag =
|
|
browserName === 'chromium'
|
|
? '<div class="Collapsible__container" open="">'
|
|
: '<details class="Collapsible__container" open="">';
|
|
const collapsibleClosingTag =
|
|
browserName === 'chromium' ? '</div>' : '</details>';
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
${collapsibleOpeningTag}
|
|
<summary class="Collapsible__title">
|
|
<p class="PlaygroundEditorTheme__paragraph">
|
|
<span data-lexical-text="true">123</span>
|
|
</p>
|
|
</summary>
|
|
<div class="Collapsible__content">
|
|
<p class="PlaygroundEditorTheme__paragraph">
|
|
<span data-lexical-text="true">123</span>
|
|
</p>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</div>
|
|
${collapsibleClosingTag}
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
|
|
await pressBackspace(page, 10);
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
${collapsibleOpeningTag}
|
|
<summary class="Collapsible__title">
|
|
<p class="PlaygroundEditorTheme__paragraph">
|
|
<span data-lexical-text="true">123</span>
|
|
</p>
|
|
</summary>
|
|
<div class="Collapsible__content">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</div>
|
|
${collapsibleClosingTag}
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Merge/unmerge cells (1)', async ({page, isPlainText, isCollab}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 1, 3);
|
|
|
|
await click(page, '.PlaygroundEditorTheme__tableCell');
|
|
await moveRight(page, 1);
|
|
await page.keyboard.type('first');
|
|
await page.keyboard.press('Tab');
|
|
await page.keyboard.type('second');
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 1, y: 0},
|
|
{x: 2, y: 0},
|
|
true,
|
|
true,
|
|
);
|
|
await mergeTableCells(page);
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
|
|
colspan="2">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">first</span>
|
|
</p>
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">second</span>
|
|
</p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
|
|
await unmergeTableCell(page);
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">first</span>
|
|
</p>
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">second</span>
|
|
</p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell"><br /></td>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Merge/unmerge cells (2)', async ({page, isPlainText, isCollab}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 3, 3);
|
|
|
|
await click(page, '.PlaygroundEditorTheme__tableCell');
|
|
await moveRight(page, 1);
|
|
await page.keyboard.type('first');
|
|
await page.keyboard.press('Tab');
|
|
await page.keyboard.type('second');
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 1, y: 1},
|
|
{x: 2, y: 2},
|
|
false,
|
|
false,
|
|
);
|
|
await mergeTableCells(page);
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">first</span>
|
|
</p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">second</span>
|
|
</p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td
|
|
class="PlaygroundEditorTheme__tableCell"
|
|
colspan="2"
|
|
rowspan="2">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
|
|
await unmergeTableCell(page);
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">first</span>
|
|
</p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">second</span>
|
|
</p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell"><br /></td>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell"><br /></td>
|
|
<td class="PlaygroundEditorTheme__tableCell"><br /></td>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Merge with content', async ({page, isPlainText, isCollab}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 3, 3);
|
|
await moveDown(page, 1);
|
|
await moveRight(page, 1);
|
|
await page.keyboard.type('A');
|
|
await moveRight(page, 1);
|
|
await page.keyboard.type('B');
|
|
await moveRight(page, 2);
|
|
await page.keyboard.type('C');
|
|
await moveRight(page, 1);
|
|
await page.keyboard.type('D');
|
|
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 1, y: 1},
|
|
{x: 2, y: 2},
|
|
false,
|
|
false,
|
|
);
|
|
await mergeTableCells(page);
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td
|
|
class="PlaygroundEditorTheme__tableCell"
|
|
colspan="2"
|
|
rowspan="2">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">A</span>
|
|
</p>
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">B</span>
|
|
</p>
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">C</span>
|
|
</p>
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">D</span>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Select multiple merged cells (selection expands to a rectangle)', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 3, 3);
|
|
|
|
await click(page, '.PlaygroundEditorTheme__tableCell');
|
|
await moveDown(page, 1);
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 0, y: 1},
|
|
true,
|
|
true,
|
|
);
|
|
await mergeTableCells(page);
|
|
|
|
await moveRight(page, 1);
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 1, y: 0},
|
|
{x: 2, y: 0},
|
|
true,
|
|
true,
|
|
);
|
|
await mergeTableCells(page);
|
|
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 0},
|
|
true,
|
|
true,
|
|
);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table
|
|
class="PlaygroundEditorTheme__table PlaygroundEditorTheme__tableSelection">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
|
|
rowspan="2"
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
|
|
colspan="2"
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td
|
|
class="PlaygroundEditorTheme__tableCell"
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<td
|
|
class="PlaygroundEditorTheme__tableCell"
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
|
|
rowspan="2">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
|
|
colspan="2">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Insert row above (with conflicting merged cell)', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 2, 2);
|
|
|
|
await click(page, '.PlaygroundEditorTheme__tableCell');
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 1, y: 0},
|
|
{x: 1, y: 1},
|
|
true,
|
|
false,
|
|
);
|
|
await mergeTableCells(page);
|
|
|
|
await moveLeft(page, 1);
|
|
await insertTableRowBelow(page);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
|
|
rowspan="3">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Insert column before (with conflicting merged cell)', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 2, 2);
|
|
|
|
await click(page, '.PlaygroundEditorTheme__tableCell');
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 0},
|
|
true,
|
|
true,
|
|
);
|
|
await mergeTableCells(page);
|
|
|
|
await moveDown(page, 1);
|
|
await moveRight(page, 1);
|
|
await insertTableColumnBefore(page);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
|
|
colspan="3">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Insert column before (with selected cell with rowspan > 1)', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 2, 1);
|
|
|
|
await click(page, '.PlaygroundEditorTheme__tableCell');
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 0, y: 1},
|
|
true,
|
|
true,
|
|
);
|
|
await mergeTableCells(page);
|
|
await insertTableColumnBefore(page);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
|
|
rowspan="2">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Insert column before (with 1+ selected cells in a row)', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 2, 2);
|
|
|
|
await click(page, '.PlaygroundEditorTheme__tableCell');
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 0},
|
|
true,
|
|
true,
|
|
);
|
|
await insertTableColumnBefore(page);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Delete rows (with conflicting merged cell)', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 4, 2);
|
|
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 1, y: 1},
|
|
{x: 1, y: 3},
|
|
false,
|
|
false,
|
|
);
|
|
await mergeTableCells(page);
|
|
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 0, y: 1},
|
|
true,
|
|
true,
|
|
);
|
|
|
|
await deleteTableRows(page);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell" rowspan="2">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Delete columns (with conflicting merged cell)', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 2, 4);
|
|
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 1, y: 1},
|
|
{x: 3, y: 1},
|
|
false,
|
|
false,
|
|
);
|
|
await mergeTableCells(page);
|
|
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 0},
|
|
true,
|
|
true,
|
|
);
|
|
|
|
await deleteTableColumns(page);
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<td class="PlaygroundEditorTheme__tableCell" colspan="2">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Deselect when click outside #3785 #4138', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await page.keyboard.type('123');
|
|
await insertTable(page, 1, 1);
|
|
await selectAll(page);
|
|
|
|
await click(page, 'div[contenteditable="true"] p:first-of-type');
|
|
|
|
await assertSelection(page, {
|
|
anchorOffset: 3,
|
|
anchorPath: [0, 0, 0],
|
|
focusOffset: 3,
|
|
focusPath: [0, 0, 0],
|
|
});
|
|
});
|
|
|
|
test('Background color to cell', async ({page, isPlainText, isCollab}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 1, 1);
|
|
await setBackgroundColor(page);
|
|
await click(page, '.color-picker-basic-color button');
|
|
await click(page, '.Modal__closeButton');
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
|
|
style="background-color: rgb(208, 2, 27)">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Cell merge feature disabled', async ({page, isPlainText, isCollab}) => {
|
|
await initialize({isCollab, page, tableCellMerge: false});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await pasteFromClipboard(page, {
|
|
'text/html': `<div dir="ltr">
|
|
<table>
|
|
<tbody>
|
|
<tr>
|
|
<td colspan="2" rowspan="2">
|
|
<p dir="ltr">Hello world</p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr">a</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p dir="ltr">b</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p dir="ltr">c</p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr">d</p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr">e</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>`,
|
|
});
|
|
|
|
await page.pause();
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">Hello world</span>
|
|
</p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell"><br /></td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">a</span>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="PlaygroundEditorTheme__tableCell"><br /></td>
|
|
<td class="PlaygroundEditorTheme__tableCell"><br /></td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">b</span>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">c</span>
|
|
</p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">d</span>
|
|
</p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">e</span>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Cell background color feature disabled', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page, tableCellBackgroundColor: false});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await pasteFromClipboard(page, {
|
|
'text/html': `<div dir="ltr">
|
|
<table>
|
|
<tbody>
|
|
<tr>
|
|
<td style="background-color: red">
|
|
<p dir="ltr">Hello world</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>`,
|
|
});
|
|
|
|
await page.pause();
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p
|
|
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
|
|
dir="ltr">
|
|
<span data-lexical-text="true">Hello world</span>
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Add column header after merging cells #4378', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
if (IS_COLLAB) {
|
|
// The contextual menu positioning needs fixing (it's hardcoded to show on the right side)
|
|
page.setViewportSize({height: 1000, width: 3000});
|
|
}
|
|
|
|
await focusEditor(page);
|
|
|
|
await insertTable(page, 4, 4);
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 1, y: 2},
|
|
{x: 3, y: 3},
|
|
false,
|
|
false,
|
|
);
|
|
await mergeTableCells(page);
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 3, y: 1},
|
|
{x: 3, y: 1},
|
|
false,
|
|
false,
|
|
);
|
|
await toggleColumnHeader(page);
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
<table class="PlaygroundEditorTheme__table">
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<td class="PlaygroundEditorTheme__tableCell">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
<td
|
|
class="PlaygroundEditorTheme__tableCell"
|
|
colspan="3"
|
|
rowspan="2">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
</th>
|
|
</tr>
|
|
</table>
|
|
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
|
|
`,
|
|
);
|
|
});
|
|
|
|
test('Can align text using Table selection', async ({
|
|
page,
|
|
isPlainText,
|
|
isCollab,
|
|
}) => {
|
|
await initialize({isCollab, page});
|
|
test.skip(isPlainText);
|
|
|
|
await focusEditor(page);
|
|
await insertTable(page, 2, 3);
|
|
|
|
await fillTablePartiallyWithText(page);
|
|
await selectCellsFromTableCords(
|
|
page,
|
|
{x: 0, y: 0},
|
|
{x: 1, y: 1},
|
|
true,
|
|
false,
|
|
);
|
|
|
|
await selectFromAlignDropdown(page, '.center-align');
|
|
|
|
await assertHTML(
|
|
page,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent; text-align: center">
|
|
<p dir="ltr" style="text-align: center">
|
|
<span data-lexical-text="true">a</span>
|
|
</p>
|
|
</th>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent; text-align: center">
|
|
<p dir="ltr" style="text-align: center">
|
|
<span data-lexical-text="true">bb</span>
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent; text-align: center">
|
|
<p dir="ltr" style="text-align: center">
|
|
<span data-lexical-text="true">d</span>
|
|
</p>
|
|
</th>
|
|
<td
|
|
style="background-color: rgb(172, 206, 247); caret-color: transparent; text-align: center">
|
|
<p dir="ltr" style="text-align: center">
|
|
<span data-lexical-text="true">e</span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
html`
|
|
<p><br /></p>
|
|
<table>
|
|
<tr>
|
|
<th style="text-align: center">
|
|
<p dir="ltr" style="text-align: center">
|
|
<span data-lexical-text="true">a</span>
|
|
</p>
|
|
</th>
|
|
<th style="text-align: center">
|
|
<p dir="ltr" style="text-align: center">
|
|
<span data-lexical-text="true">bb</span>
|
|
</p>
|
|
</th>
|
|
<th>
|
|
<p dir="ltr"><span data-lexical-text="true">cc</span></p>
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th style="text-align: center">
|
|
<p dir="ltr" style="text-align: center">
|
|
<span data-lexical-text="true">d</span>
|
|
</p>
|
|
</th>
|
|
<td style="text-align: center">
|
|
<p dir="ltr" style="text-align: center">
|
|
<span data-lexical-text="true">e</span>
|
|
</p>
|
|
</td>
|
|
<td>
|
|
<p dir="ltr"><span data-lexical-text="true">f</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p><br /></p>
|
|
`,
|
|
{ignoreClasses: true},
|
|
);
|
|
});
|
|
});
|