From 73c9bdf40b0c52540a384b9ddf8bfd4e51316198 Mon Sep 17 00:00:00 2001 From: Peter Savchenko Date: Mon, 28 Nov 2022 20:23:30 +0400 Subject: [PATCH] fix(block-events): split block with removing of selected text fragment (#2186) * fix(block-events): split block with removing of selected text fragment * Update BlockEvents.spec.ts --- src/components/flipper.ts | 8 ++-- .../modules/toolbar/blockSettings.ts | 4 +- test/cypress/support/commands.ts | 30 +++++++++++++ test/cypress/support/index.d.ts | 13 ++++++ .../cypress/tests/modules/BlockEvents.spec.ts | 43 +++++++++++++++++++ 5 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 test/cypress/tests/modules/BlockEvents.spec.ts diff --git a/src/components/flipper.ts b/src/components/flipper.ts index 52118b0b..28998460 100644 --- a/src/components/flipper.ts +++ b/src/components/flipper.ts @@ -279,15 +279,17 @@ export default class Flipper { } if (this.iterator.currentItem) { + /** + * Stop Enter propagation only if flipper is ready to select focused item + */ + event.stopPropagation(); + event.preventDefault(); this.iterator.currentItem.click(); } if (_.isFunction(this.activateCallback)) { this.activateCallback(this.iterator.currentItem); } - - event.preventDefault(); - event.stopPropagation(); } /** diff --git a/src/components/modules/toolbar/blockSettings.ts b/src/components/modules/toolbar/blockSettings.ts index 0cc5b498..9629a1f5 100644 --- a/src/components/modules/toolbar/blockSettings.ts +++ b/src/components/modules/toolbar/blockSettings.ts @@ -52,7 +52,7 @@ export default class BlockSettings extends Module { * @todo remove once BlockSettings becomes standalone non-module class */ public get flipper(): Flipper { - return this.popover.flipper; + return this.popover?.flipper; } /** @@ -63,7 +63,7 @@ export default class BlockSettings extends Module { /** * Popover instance. There is a util for vertical lists. */ - private popover: Popover; + private popover: Popover | undefined; /** * Panel with block settings with 2 sections: diff --git a/test/cypress/support/commands.ts b/test/cypress/support/commands.ts index b2a24276..21929c5d 100644 --- a/test/cypress/support/commands.ts +++ b/test/cypress/support/commands.ts @@ -126,3 +126,33 @@ Cypress.Commands.add('render', { prevSubject: true }, async (subject: EditorJS, return subject; }); + + +/** + * Select passed text in element + * Note. Previous subject should have 'textNode' as firstChild + * + * Usage + * cy.get('[data-cy=editorjs]') + * .find('.ce-paragraph') + * .selectText('block te') + * + * @param text - text to select + */ +Cypress.Commands.add('selectText', { + prevSubject: true, +}, (subject, text: string) => { + const el = subject[0]; + const document = el.ownerDocument; + const range = document.createRange(); + const textNode = el.firstChild; + const selectionPositionStart = textNode.textContent.indexOf(text); + const selectionPositionEnd = selectionPositionStart + text.length; + + range.setStart(textNode, selectionPositionStart); + range.setEnd(textNode, selectionPositionEnd); + document.getSelection().removeAllRanges(); + document.getSelection().addRange(range); + + return subject; +}); diff --git a/test/cypress/support/index.d.ts b/test/cypress/support/index.d.ts index 477e3e7d..4fce3b37 100644 --- a/test/cypress/support/index.d.ts +++ b/test/cypress/support/index.d.ts @@ -47,6 +47,19 @@ declare global { * @param data — data to render */ render(data: OutputData): Chainable; + + /** + * Select passed text in element + * Note. Previous subject should have 'textNode' as firstChild + * + * Usage + * cy.get('[data-cy=editorjs]') + * .find('.ce-paragraph') + * .selectText('block te') + * + * @param text - text to select + */ + selectText(text: string): Chainable; } interface ApplicationWindow { diff --git a/test/cypress/tests/modules/BlockEvents.spec.ts b/test/cypress/tests/modules/BlockEvents.spec.ts new file mode 100644 index 00000000..b7737cb7 --- /dev/null +++ b/test/cypress/tests/modules/BlockEvents.spec.ts @@ -0,0 +1,43 @@ +describe('Keydown', function () { + describe('enter', function () { + it('should split block and remove selected fragment if some text fragment selected', function () { + cy.createEditor({ + data: { + blocks: [ + { + type: 'paragraph', + data: { + text: 'The block with some text', + }, + }, + ], + }, + }); + + + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.get('[data-cy=editorjs]') + .find('.ce-paragraph') + .click() + .selectText('with so') + .wait(0) + .type('{enter}'); + + + cy.get('[data-cy=editorjs]') + .find('div.ce-block') + .then((blocks) => { + /** + * Check that there is two blocks after split + */ + expect(blocks.length).to.equal(2); + + /** + * Check that selected text fragment has been removed + */ + expect(blocks[0].textContent).to.equal('The block '); + expect(blocks[1].textContent).to.equal('me text'); + }); + }); + }); +});