Skip to content

Commit

Permalink
Rewrite tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Oct 4, 2019
1 parent c22a36b commit 41cb592
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 89 deletions.
15 changes: 15 additions & 0 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,21 @@ function BlockListBlock( {
* @param {boolean} ignoreInnerBlocks Should not focus inner blocks.
*/
const focusTabbable = ( ignoreInnerBlocks ) => {
const selection = window.getSelection();

if ( selection.rangeCount && ! selection.isCollapsed ) {
const { startContainer, endContainer } = selection.getRangeAt( 0 );

if (
! blockNodeRef.current.contains( startContainer ) ||
! blockNodeRef.current.contains( endContainer )
) {
selection.removeAllRanges();
wrapper.current.focus();
return;
}
}

// Focus is captured by the wrapper node, so while focus transition
// should only consider tabbables within editable display, since it
// may be the wrapper itself or a side control which triggered the
Expand Down
243 changes: 154 additions & 89 deletions packages/e2e-tests/specs/multi-block-selection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,127 +10,120 @@ import {
getEditedPostContent,
} from '@wordpress/e2e-test-utils';

describe( 'Multi-block selection', () => {
beforeEach( async () => {
await createNewPost();
} );

it( 'Should select/unselect multiple blocks', async () => {
const firstBlockSelector = '[data-type="core/paragraph"]';
const secondBlockSelector = '[data-type="core/image"]';
const thirdBlockSelector = '[data-type="core/quote"]';
const multiSelectedCssClass = 'is-multi-selected';
async function getSelectedFlatIndices() {
return await page.evaluate( () => {
const indices = [];
let single;

Array.from(
document.querySelectorAll( '.wp-block' )
).forEach( ( node, index ) => {
if ( node.classList.contains( 'is-selected' ) ) {
single = index;
}

// Creating test blocks
await clickBlockAppender();
await page.keyboard.type( 'First Paragraph' );
await insertBlock( 'Image' );
await insertBlock( 'Quote' );
await page.keyboard.type( 'Quote Block' );

const blocks = [ firstBlockSelector, secondBlockSelector, thirdBlockSelector ];
const expectMultiSelected = async ( selectors, areMultiSelected ) => {
for ( const selector of selectors ) {
const className = await page.$eval( selector, ( element ) => element.className );
if ( areMultiSelected ) {
expect( className ).toEqual( expect.stringContaining( multiSelectedCssClass ) );
} else {
expect( className ).not.toEqual( expect.stringContaining( multiSelectedCssClass ) );
}
if ( node.classList.contains( 'is-multi-selected' ) ) {
indices.push( index );
}
};
} );

// Default: No selection
await expectMultiSelected( blocks, false );
return single !== undefined ? single : indices;
} );
}

// Multiselect via Shift + click
await page.mouse.move( 200, 300 );
await page.click( firstBlockSelector );
await page.keyboard.down( 'Shift' );
await page.click( thirdBlockSelector );
await page.keyboard.up( 'Shift' );
/**
* Tests if the native selection matches the block selection.
*/
async function testNativeSelection() {
await page.evaluate( () => {
const selection = window.getSelection();
const elements = Array.from(
document.querySelectorAll( '.is-multi-selected' )
);

if ( ! elements.length ) {
const element = document.querySelector( '.is-selected' );

if ( ! element || ! selection.rangeCount ) {
return;
}

// Verify selection
await expectMultiSelected( blocks, true );
const { startContainer, endContainer } = selection.getRangeAt( 0 );

// Unselect
await page.click( secondBlockSelector );
if ( ! element.contains( startContainer ) ) {
throw 'expected selection to start in the selected block';
}

// No selection
await expectMultiSelected( blocks, false );
if ( ! element.contains( endContainer ) ) {
throw 'expected selection to start in the selected block';
}

// Multiselect via keyboard
await page.click( 'body' );
await pressKeyWithModifier( 'primary', 'a' );
return;
}

// Verify selection
await expectMultiSelected( blocks, true );
if ( ! selection.rangeCount === 1 ) {
throw 'expected one range';
}

// Unselect
await page.keyboard.press( 'Escape' );
if ( selection.isCollapsed ) {
throw 'expected an uncollapsed selection';
}

// No selection
await expectMultiSelected( blocks, false );
const firstElement = elements[ 0 ];
const lastElement = elements[ elements.length - 1 ];
const { startContainer, endContainer } = selection.getRangeAt( 0 );

// Select all via double shortcut.
await page.click( firstBlockSelector );
await pressKeyWithModifier( 'primary', 'a' );
await pressKeyWithModifier( 'primary', 'a' );
await expectMultiSelected( blocks, true );
} );
if ( ! firstElement.contains( startContainer ) ) {
throw 'expected selection to start in the first selected block';
}

it( 'Should select/unselect multiple blocks using Shift + Arrows', async () => {
const firstBlockSelector = '[data-type="core/paragraph"]';
const secondBlockSelector = '[data-type="core/image"]';
const thirdBlockSelector = '[data-type="core/quote"]';
const multiSelectedCssClass = 'is-multi-selected';
if ( ! lastElement.contains( endContainer ) ) {
throw 'expected selection to end in the last selected block';
}
} );
}

// Creating test blocks
await clickBlockAppender();
await page.keyboard.type( 'First Paragraph' );
await insertBlock( 'Image' );
await insertBlock( 'Quote' );
await page.keyboard.type( 'Quote Block' );

const blocks = [ firstBlockSelector, secondBlockSelector, thirdBlockSelector ];
const expectMultiSelected = async ( selectors, areMultiSelected ) => {
for ( const selector of selectors ) {
const className = await page.$eval( selector, ( element ) => element.className );
if ( areMultiSelected ) {
expect( className ).toEqual( expect.stringContaining( multiSelectedCssClass ) );
} else {
expect( className ).not.toEqual( expect.stringContaining( multiSelectedCssClass ) );
}
}
};
describe( 'Multi-block selection', () => {
beforeEach( async () => {
await createNewPost();
} );

// Default: No selection
await expectMultiSelected( blocks, false );
it.skip( 'Should select/unselect multiple blocks', async () => {

// Multiselect via Shift + click
await page.mouse.move( 200, 300 );
await page.click( firstBlockSelector );
await page.keyboard.down( 'Shift' );
await page.keyboard.press( 'ArrowDown' ); // Two blocks selected
await page.keyboard.press( 'ArrowDown' ); // Three blocks selected
await page.click( thirdBlockSelector );
await page.keyboard.up( 'Shift' );

// Verify selection
await expectMultiSelected( blocks, true );
await testNativeSelection();

// Unselect
await page.click( secondBlockSelector );

// No selection
await expectMultiSelected( blocks, false );
await testNativeSelection();
} );

it( 'should speak() number of blocks selected with multi-block selection', async () => {
it( 'should select with double ctrl+a and speak', async () => {
await clickBlockAppender();
await page.keyboard.type( 'First Paragraph' );
await insertBlock( 'Paragraph' );
await page.keyboard.type( 'Second Paragraph' );
await insertBlock( 'Paragraph' );
await page.keyboard.type( 'Third Paragraph' );
await page.keyboard.type( '1' );
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '2' );
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '3' );

// Multiselect via keyboard.
await pressKeyWithModifier( 'primary', 'a' );
await pressKeyWithModifier( 'primary', 'a' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toEqual( [ 1, 2, 3 ] );

// TODO: It would be great to do this test by spying on `wp.a11y.speak`,
// but it's very difficult to do that because `wp.a11y` has
// DOM-dependant side-effect setup code and doesn't seem straightforward
Expand Down Expand Up @@ -188,6 +181,7 @@ describe( 'Multi-block selection', () => {
await page.keyboard.press( 'ArrowLeft' );
await pressKeyWithModifier( 'shift', 'ArrowRight' );
await pressKeyWithModifier( 'shift', 'ArrowUp' );
await testNativeSelection();
// This delete all blocks.
await page.keyboard.press( 'Backspace' );

Expand All @@ -203,4 +197,75 @@ describe( 'Multi-block selection', () => {

expect( await getEditedPostContent() ).toMatchSnapshot();
} );

it( 'should select and deselect with shift and arrow keys', async () => {
await clickBlockAppender();
await page.keyboard.type( '1' );
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '2' );
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '3' );
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '4' );
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '5' );
await page.keyboard.press( 'ArrowUp' );
await page.keyboard.press( 'ArrowUp' );
await pressKeyWithModifier( 'shift', 'ArrowDown' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toEqual( [ 3, 4 ] );

await pressKeyWithModifier( 'shift', 'ArrowDown' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toEqual( [ 3, 4, 5 ] );

await pressKeyWithModifier( 'shift', 'ArrowUp' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toEqual( [ 3, 4 ] );

await pressKeyWithModifier( 'shift', 'ArrowUp' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toBe( 3 );

await pressKeyWithModifier( 'shift', 'ArrowUp' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toEqual( [ 2, 3 ] );

await pressKeyWithModifier( 'shift', 'ArrowUp' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toEqual( [ 1, 2, 3 ] );

await pressKeyWithModifier( 'shift', 'ArrowDown' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toEqual( [ 2, 3 ] );

await pressKeyWithModifier( 'shift', 'ArrowDown' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toBe( 3 );
} );

it( 'should deselect with Escape', async () => {
await clickBlockAppender();
await page.keyboard.type( '1' );
await page.keyboard.press( 'Enter' );
await page.keyboard.type( '2' );

await pressKeyWithModifier( 'primary', 'a' );
await pressKeyWithModifier( 'primary', 'a' );

await testNativeSelection();
expect( await getSelectedFlatIndices() ).toEqual( [ 1, 2 ] );

await page.keyboard.press( 'Escape' );

expect( await getSelectedFlatIndices() ).toEqual( [] );
} );
} );

0 comments on commit 41cb592

Please sign in to comment.