Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into bug/6008-Selection-…
Browse files Browse the repository at this point in the history
…is-removed-when-changing-style-of-2-different-nodes
  • Loading branch information
Sahejkm committed Jun 3, 2024
2 parents 8045573 + 723285e commit 85e873f
Show file tree
Hide file tree
Showing 19 changed files with 194 additions and 118 deletions.
26 changes: 0 additions & 26 deletions .github/workflows/after-approval.yml

This file was deleted.

6 changes: 4 additions & 2 deletions .github/workflows/tests-extended.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ on:
- 'packages/lexical-website/**'
- 'packages/*/README.md'
- '.size-limit.js'
pull_request_review:
types: [submitted]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
e2e-tests:
if: github.repository_owner == 'facebook' && contains(github.event.pull_request.labels.*.name, 'extended-tests')
if: (github.repository_owner == 'facebook' && contains(github.event.pull_request.labels.*.name, 'extended-tests') && github.event.review.state != 'approved') || (github.event.review.state == 'approved' && !contains(github.event.pull_request.labels.*.name, 'extended-tests'))
uses: ./.github/workflows/call-e2e-all-tests.yml

integration-tests:
if: github.repository_owner == 'facebook' && contains(github.event.pull_request.labels.*.name, 'extended-tests')
if: (github.repository_owner == 'facebook' && contains(github.event.pull_request.labels.*.name, 'extended-tests') && github.event.review.state != 'approved') || (github.event.review.state == 'approved' && !contains(github.event.pull_request.labels.*.name, 'extended-tests'))
uses: ./.github/workflows/call-integration-tests.yml
1 change: 1 addition & 0 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ function sizeLimitConfig(pkg) {
return ['require', 'import'].map((type) => {
const aliasType = getAliasType(type);
return {
import: '*',
path:
aliasType[pkg] != null
? aliasType[pkg]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* 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 {
assertHTML,
click,
doubleClick,
focusEditor,
html,
initialize,
pasteFromClipboard,
test,
} from '../../../utils/index.mjs';

test.describe('ContextMenuCopyAndPaste', () => {
test.use({shouldUseLexicalContextMenu: true});
test.beforeEach(({isCollab, page, shouldUseLexicalContextMenu}) =>
initialize({isCollab, page, shouldUseLexicalContextMenu}),
);

test('Basic copy-paste #6231', async ({page, isPlainText}) => {
test.skip(isPlainText);
await focusEditor(page);

await page.keyboard.type('hello');
await click(page, '.lock');

await page.pause();
await doubleClick(page, 'div[contenteditable="false"] span');
await page.pause();
await click(page, 'div[contenteditable="false"] span', {button: 'right'});
await click(page, '#typeahead-menu [role="option"] :text("Copy")');

await click(page, '.unlock');
await focusEditor(page);

await pasteFromClipboard(page);

await assertHTML(
page,
html`
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span data-lexical-text="true">hellohello</span>
</p>
`,
);
});
});
2 changes: 1 addition & 1 deletion packages/lexical-playground/__tests__/e2e/Links.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ test.beforeEach(({isPlainText}) => {
test.skip(isPlainText);
});

test.describe('Links', () => {
test.describe.parallel('Links', () => {
test.beforeEach(({isCollab, page}) => initialize({isCollab, page}));
test(`Can convert a text node into a link`, async ({page}) => {
await focusEditor(page);
Expand Down
2 changes: 1 addition & 1 deletion packages/lexical-playground/__tests__/e2e/List.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ test.beforeEach(({isPlainText}) => {
test.skip(isPlainText);
});

test.describe('Nested List', () => {
test.describe.parallel('Nested List', () => {
test.beforeEach(({isCollab, page}) => initialize({isCollab, page}));

test(`Can create a list and partially copy some content out of it`, async ({
Expand Down
4 changes: 2 additions & 2 deletions packages/lexical-playground/__tests__/e2e/Markdown.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async function checkHTMLExpectationsIncludingUndoRedo(
await assertHTML(page, forwardHTML);
}

test.describe('Markdown', () => {
test.describe.parallel('Markdown', () => {
test.beforeEach(({isCollab, page}) => initialize({isCollab, page}));
const triggersAndExpectations = [
{
Expand Down Expand Up @@ -374,7 +374,7 @@ async function assertMarkdownImportExport(
await assertHTML(page, expectedHTML);
}

test.describe('Markdown', () => {
test.describe.parallel('Markdown', () => {
test.beforeEach(({isCollab, isPlainText, page}) => {
test.skip(isPlainText);
return initialize({isCollab, page});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import {
YOUTUBE_SAMPLE_URL,
} from '../utils/index.mjs';

test.describe('Selection', () => {
test.describe.parallel('Selection', () => {
test.beforeEach(({isCollab, page}) => initialize({isCollab, page}));
test('does not focus the editor on load', async ({page}) => {
const editorHasFocus = async () =>
Expand Down
7 changes: 4 additions & 3 deletions packages/lexical-playground/__tests__/e2e/Tables.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async function fillTablePartiallyWithText(page) {
await page.keyboard.press('c');
}

test.describe('Tables', () => {
test.describe.parallel('Tables', () => {
test(`Can a table be inserted from the toolbar`, async ({
page,
isPlainText,
Expand Down Expand Up @@ -152,7 +152,8 @@ test.describe('Tables', () => {
);
});

test.describe(`Can exit tables with the horizontal arrow keys`, () => {
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,
Expand Down Expand Up @@ -488,7 +489,7 @@ test.describe('Tables', () => {
});
});

test.describe(`Can navigate table with keyboard`, () => {
test.describe.parallel(`Can navigate table with keyboard`, () => {
test(`Can navigate cells horizontally`, async ({
page,
isPlainText,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
waitForSelector,
} from '../utils/index.mjs';

test.describe('TextFormatting', () => {
test.describe.parallel('TextFormatting', () => {
test.beforeEach(({isCollab, page}) => initialize({isCollab, page}));
test(`Can create bold text using the shortcut`, async ({
page,
Expand Down
19 changes: 19 additions & 0 deletions packages/lexical-playground/__tests__/e2e/Toolbar.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,25 @@ test.describe('Toolbar', () => {
ignoreClasses: true,
ignoreInlineStyles: true,
},
(actualHtml) =>
// flaky fix: remove the extra <p><br /></p> that appears occasionally in CI runs
actualHtml.replace(
html`
<p dir="ltr">
<span data-lexical-text="true">
Yellow flower in tilt shift lens
</span>
</p>
<p><br /></p>
`,
html`
<p dir="ltr">
<span data-lexical-text="true">
Yellow flower in tilt shift lens
</span>
</p>
`,
),
);

// Delete image
Expand Down
34 changes: 31 additions & 3 deletions packages/lexical-playground/__tests__/utils/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export async function initialize({
showNestedEditorTreeView,
tableCellMerge,
tableCellBackgroundColor,
shouldUseLexicalContextMenu,
}) {
// Tests with legacy events often fail to register keypress, so
// slowing it down to reduce flakiness
Expand Down Expand Up @@ -90,6 +91,7 @@ export async function initialize({
if (tableCellBackgroundColor !== undefined) {
appSettings.tableCellBackgroundColor = tableCellBackgroundColor;
}
appSettings.shouldUseLexicalContextMenu = !!shouldUseLexicalContextMenu;

const urlParams = appSettingsToURLParams(appSettings);
const url = `http://localhost:${E2E_PORT}/${
Expand Down Expand Up @@ -145,6 +147,7 @@ export const test = base.extend({
isPlainText: IS_PLAIN_TEXT,
isRichText: IS_RICH_TEXT,
legacyEvents: LEGACY_EVENTS,
shouldUseLexicalContextMenu: false,
});

export {expect} from '@playwright/test';
Expand Down Expand Up @@ -177,6 +180,7 @@ async function assertHTMLOnPageOrFrame(
ignoreClasses,
ignoreInlineStyles,
frameName,
actualHtmlModificationsCallback = (actualHtml) => actualHtml,
) {
const expected = prettifyHTML(expectedHtml.replace(/\n/gm, ''), {
ignoreClasses,
Expand All @@ -187,10 +191,13 @@ async function assertHTMLOnPageOrFrame(
.locator('div[contenteditable="true"]')
.first()
.innerHTML();
const actual = prettifyHTML(actualHtml.replace(/\n/gm, ''), {
let actual = prettifyHTML(actualHtml.replace(/\n/gm, ''), {
ignoreClasses,
ignoreInlineStyles,
});

actual = actualHtmlModificationsCallback(actual);

expect(
actual,
`innerHTML of contenteditable in ${frameName} did not match`,
Expand All @@ -206,6 +213,7 @@ export async function assertHTML(
expectedHtml,
expectedHtmlFrameRight = expectedHtml,
{ignoreClasses = false, ignoreInlineStyles = false} = {},
actualHtmlModificationsCallback,
) {
if (IS_COLLAB) {
await Promise.all([
Expand All @@ -215,13 +223,15 @@ export async function assertHTML(
ignoreClasses,
ignoreInlineStyles,
'left frame',
actualHtmlModificationsCallback,
),
assertHTMLOnPageOrFrame(
page.frame('right'),
expectedHtmlFrameRight,
ignoreClasses,
ignoreInlineStyles,
'right frame',
actualHtmlModificationsCallback,
),
]);
} else {
Expand Down Expand Up @@ -407,7 +417,10 @@ export async function copyToClipboard(page) {
return await copyToClipboardPageOrFrame(getPageOrFrame(page));
}

async function pasteFromClipboardPageOrFrame(pageOrFrame, clipboardData) {
async function pasteWithClipboardDataFromPageOrFrame(
pageOrFrame,
clipboardData,
) {
const canUseBeforeInput = await supportsBeforeInput(pageOrFrame);
await pageOrFrame.evaluate(
async ({
Expand Down Expand Up @@ -478,7 +491,16 @@ async function pasteFromClipboardPageOrFrame(pageOrFrame, clipboardData) {
* @param {import('@playwright/test').Page} page
*/
export async function pasteFromClipboard(page, clipboardData) {
await pasteFromClipboardPageOrFrame(getPageOrFrame(page), clipboardData);
if (clipboardData === undefined) {
await keyDownCtrlOrMeta(page);
await page.keyboard.press('v');
await keyUpCtrlOrMeta(page);
return;
}
await pasteWithClipboardDataFromPageOrFrame(
getPageOrFrame(page),
clipboardData,
);
}

export async function sleep(delay) {
Expand Down Expand Up @@ -525,6 +547,12 @@ export async function click(page, selector, options) {
await frame.click(selector, options);
}

export async function doubleClick(page, selector, options) {
const frame = getPageOrFrame(page);
await frame.waitForSelector(selector, options);
await frame.dblclick(selector, options);
}

export async function focus(page, selector, options) {
await locate(page, selector).focus(options);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ import {
import * as React from 'react';
import {Suspense, useCallback, useEffect, useRef, useState} from 'react';

import useModal from '../hooks/useModal';
import LinkPlugin from '../plugins/LinkPlugin';
import Button from '../ui/Button';
import ContentEditable from '../ui/ContentEditable';
import {DialogActions} from '../ui/Dialog';
import Placeholder from '../ui/Placeholder';
import Select from '../ui/Select';
import TextInput from '../ui/TextInput';
import useModal from '../../hooks/useModal';
import LinkPlugin from '../../plugins/LinkPlugin';
import Button from '../../ui/Button';
import ContentEditable from '../../ui/ContentEditable';
import {DialogActions} from '../../ui/Dialog';
import Placeholder from '../../ui/Placeholder';
import Select from '../../ui/Select';
import TextInput from '../../ui/TextInput';
import {$isInlineImageNode, InlineImageNode} from './InlineImageNode';

const imageCache = new Set();
Expand Down Expand Up @@ -352,7 +352,7 @@ export default function InlineImageComponent({
return (
<Suspense fallback={null}>
<>
<div draggable={draggable}>
<span draggable={draggable}>
<button
className="image-edit-button"
ref={buttonRef}
Expand Down Expand Up @@ -380,9 +380,9 @@ export default function InlineImageComponent({
height={height}
position={position}
/>
</div>
</span>
{showCaption && (
<div className="image-caption-container">
<span className="image-caption-container">
<LexicalNestedComposer initialEditor={caption}>
<AutoFocusPlugin />
<LinkPlugin />
Expand All @@ -398,7 +398,7 @@ export default function InlineImageComponent({
ErrorBoundary={LexicalErrorBoundary}
/>
</LexicalNestedComposer>
</div>
</span>
)}
</>
{modal}
Expand Down
2 changes: 1 addition & 1 deletion packages/lexical-playground/src/nodes/PlaygroundNodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {EquationNode} from './EquationNode';
import {ExcalidrawNode} from './ExcalidrawNode';
import {FigmaNode} from './FigmaNode';
import {ImageNode} from './ImageNode';
import {InlineImageNode} from './InlineImageNode';
import {InlineImageNode} from './InlineImageNode/InlineImageNode';
import {KeywordNode} from './KeywordNode';
import {LayoutContainerNode} from './LayoutContainerNode';
import {LayoutItemNode} from './LayoutItemNode';
Expand Down
Loading

0 comments on commit 85e873f

Please sign in to comment.