diff --git a/editor/modes/visual-editor/index.js b/editor/modes/visual-editor/index.js index d1edd5a1becb08..3b0d36840431b7 100644 --- a/editor/modes/visual-editor/index.js +++ b/editor/modes/visual-editor/index.js @@ -92,6 +92,7 @@ class VisualEditor extends Component { 'mod+shift+z': this.undoOrRedo, backspace: this.deleteSelectedBlocks, del: this.deleteSelectedBlocks, + escape: this.props.clearSelectedBlock, } } /> diff --git a/test/e2e/integration/003-multi-block-selection.js b/test/e2e/integration/003-multi-block-selection.js new file mode 100644 index 00000000000000..dc721b5f63895b --- /dev/null +++ b/test/e2e/integration/003-multi-block-selection.js @@ -0,0 +1,58 @@ +describe( 'Multi-block selection', () => { + before( () => { + cy.newPost(); + } ); + + it( 'Should select/unselect multiple blocks', () => { + const lastBlockSelector = '.editor-visual-editor__block-edit:last [contenteditable="true"]:first'; + const firstBlockContainerSelector = '.editor-visual-editor__block:first'; + const lastBlockContainerSelector = '.editor-visual-editor__block:last'; + const multiSelectedCssClass = 'is-multi-selected'; + + // Creating test blocks + // Using the placeholder + cy.get( '[value="Write your story"]' ).click(); + cy.get( lastBlockSelector ).type( 'First Paragraph' ); + + // Using the quick inserter + cy.get( '.editor-visual-editor__inserter [aria-label="Insert Paragraph"]' ).click(); + cy.get( lastBlockSelector ).type( 'Second Paragraph' ); + + // Default: No selection + cy.get( firstBlockContainerSelector ).should( 'not.have.class', multiSelectedCssClass ); + cy.get( lastBlockContainerSelector ).should( 'not.have.class', multiSelectedCssClass ); + + // Multiselect via Shift + click + cy.get( firstBlockContainerSelector ).click(); + cy.get( 'body' ).type( '{shift}', { release: false } ); + cy.get( lastBlockContainerSelector ).click(); + + // Verify selection + cy.get( firstBlockContainerSelector ).should( 'have.class', multiSelectedCssClass ); + cy.get( lastBlockContainerSelector ).should( 'have.class', multiSelectedCssClass ); + + // Unselect + cy.get( 'body' ).type( '{shift}' ); // releasing shift + cy.get( lastBlockContainerSelector ).click(); + + // No selection + cy.get( firstBlockContainerSelector ).should( 'not.have.class', multiSelectedCssClass ); + cy.get( lastBlockContainerSelector ).should( 'not.have.class', multiSelectedCssClass ); + + // Multiselect via keyboard + // Mac uses meta modifier so we press both here + cy.get( 'body' ).type( '{ctrl}a' ); + cy.get( 'body' ).type( '{meta}a' ); + + // Verify selection + cy.get( firstBlockContainerSelector ).should( 'have.class', multiSelectedCssClass ); + cy.get( lastBlockContainerSelector ).should( 'have.class', multiSelectedCssClass ); + + // Unselect + cy.get( 'body' ).type( '{esc}' ); + + // No selection + cy.get( firstBlockContainerSelector ).should( 'not.have.class', multiSelectedCssClass ); + cy.get( lastBlockContainerSelector ).should( 'not.have.class', multiSelectedCssClass ); + } ); +} );