From 2396f3a095d2dcf6248d60eae262a0564d13e2d9 Mon Sep 17 00:00:00 2001 From: Alex Stine Date: Wed, 9 Mar 2022 17:16:55 -0500 Subject: [PATCH] Add some tests for TreeGrid. Update README to reflect latest functionality. (#39302) * Start working on updating/implementing new tests. * Update README docs. * Add tests for Home/End. Fix missing onFocus consumer for Home/End. * Add item to changelog. * A few more changelog details. * Fix changelog formatting. --- packages/components/CHANGELOG.md | 1 + packages/components/src/tree-grid/README.md | 2 +- packages/components/src/tree-grid/index.js | 4 + .../components/src/tree-grid/test/index.js | 78 +++++++++++++++---- 4 files changed, 67 insertions(+), 18 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 69a2735bd44ed5..74b338633c1b15 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -6,6 +6,7 @@ - `ConfirmDialog`: Add support for custom label text on the confirmation and cancelation buttons ([#38994](https://github.com/WordPress/gutenberg/pull/38994)) - `InputControl`: Allow `onBlur` for empty values to commit the change when `isPressEnterToChange` is true, and move reset behavior to the ESCAPE key. ([#39109](https://github.com/WordPress/gutenberg/pull/39109)). +- `TreeGrid`: Add tests for Home/End keyboard navigation. Add `onFocusRow` callback for Home/End keyboard navigation, this was missed in the implementation PR. Modify test for expanding/collapsing a row as row 1 implements this now. Update README with latest changes. ([#39302](https://github.com/WordPress/gutenberg/pull/39302)) ### Bug Fix diff --git a/packages/components/src/tree-grid/README.md b/packages/components/src/tree-grid/README.md index 66264a0104b7fd..45e140306b58ad 100644 --- a/packages/components/src/tree-grid/README.md +++ b/packages/components/src/tree-grid/README.md @@ -114,7 +114,7 @@ Aside from the documented callback functions, any props specified will be passed ###### onFocusRow( event: Event, startRow: HTMLElement, destinationRow: HTMLElement ) -Callback that fires when focus is shifted from one row to another via the UP and DOWN keys. +Callback that fires when focus is shifted from one row to another via the Up and Down keys. Callback is also fired on Home and End keys which move focus from the beginning row to the end row. The callback is passed the event, the start row element that the focus was on originally, and the destination row element after the focus has moved. diff --git a/packages/components/src/tree-grid/index.js b/packages/components/src/tree-grid/index.js index cf84160d060d09..2e5731cb068af2 100644 --- a/packages/components/src/tree-grid/index.js +++ b/packages/components/src/tree-grid/index.js @@ -275,6 +275,10 @@ function TreeGrid( ); focusablesInNextRow[ nextIndex ].focus(); + // Let consumers know the row that was originally focused, + // and the row that is now in focus. + onFocusRow( event, activeRow, rows[ nextRowIndex ] ); + // Prevent key use for anything else. This ensures Voiceover // doesn't try to handle key navigation. event.preventDefault(); diff --git a/packages/components/src/tree-grid/test/index.js b/packages/components/src/tree-grid/test/index.js index b565ebdb4a57eb..7f2193bba79108 100644 --- a/packages/components/src/tree-grid/test/index.js +++ b/packages/components/src/tree-grid/test/index.js @@ -6,7 +6,7 @@ import { fireEvent, render, screen } from '@testing-library/react'; /** * WordPress dependencies */ -import { LEFT, RIGHT, UP, DOWN } from '@wordpress/keycodes'; +import { LEFT, RIGHT, UP, DOWN, HOME, END } from '@wordpress/keycodes'; import { forwardRef } from '@wordpress/element'; /** @@ -68,10 +68,10 @@ describe( 'TreeGrid', () => { level={ 1 } positionInSet={ 1 } setSize={ 3 } - isExpanded={ true } + isExpanded={ false } > - Row 1 + { level={ 1 } positionInSet={ 3 } setSize={ 3 } - isExpanded={ true } + isExpanded={ false } > Row 3 @@ -97,16 +97,16 @@ describe( 'TreeGrid', () => { ); - screen.getByText( 'Row 2' ).focus(); - const row2Element = screen.getByText( 'Row 2' ).closest( 'tr' ); + screen.getByText( 'Row 1' ).focus(); + const row1Element = screen.getByText( 'Row 1' ).closest( 'tr' ); - fireEvent.keyDown( screen.getByText( 'Row 2' ), { + fireEvent.keyDown( screen.getByText( 'Row 1' ), { key: 'ArrowRight', keyCode: RIGHT, - currentTarget: row2Element, + currentTarget: row1Element, } ); - expect( onExpandRow ).toHaveBeenCalledWith( row2Element ); + expect( onExpandRow ).toHaveBeenCalledWith( row1Element ); } ); } ); @@ -120,17 +120,17 @@ describe( 'TreeGrid', () => { level={ 1 } positionInSet={ 1 } setSize={ 3 } - isExpanded={ false } + isExpanded={ true } > - Row 1 + Row 1 Row 2 @@ -149,16 +149,16 @@ describe( 'TreeGrid', () => { ); - screen.getByText( 'Row 2' ).focus(); - const row2Element = screen.getByText( 'Row 2' ).closest( 'tr' ); + screen.getByText( 'Row 1' ).focus(); + const row1Element = screen.getByText( 'Row 1' ).closest( 'tr' ); - fireEvent.keyDown( screen.getByText( 'Row 2' ), { + fireEvent.keyDown( screen.getByText( 'Row 1' ), { key: 'ArrowLeft', keyCode: LEFT, - currentTarget: row2Element, + currentTarget: row1Element, } ); - expect( onCollapseRow ).toHaveBeenCalledWith( row2Element ); + expect( onCollapseRow ).toHaveBeenCalledWith( row1Element ); } ); } ); @@ -205,6 +205,28 @@ describe( 'TreeGrid', () => { ); } ); + it( 'should call onFocusRow with event, start and end nodes when pressing End', () => { + const onFocusRow = jest.fn(); + render( ); + + screen.getByText( 'Row 1' ).focus(); + + const row1Element = screen.getByText( 'Row 1' ).closest( 'tr' ); + const row3Element = screen.getByText( 'Row 3' ).closest( 'tr' ); + + fireEvent.keyDown( screen.getByText( 'Row 1' ), { + key: 'End', + keyCode: END, + currentTarget: row1Element, + } ); + + expect( onFocusRow ).toHaveBeenCalledWith( + expect.objectContaining( { key: 'End', keyCode: END } ), + row1Element, + row3Element + ); + } ); + it( 'should call onFocusRow with event, start and end nodes when pressing Up Arrow', () => { const onFocusRow = jest.fn(); render( ); @@ -227,6 +249,28 @@ describe( 'TreeGrid', () => { ); } ); + it( 'should call onFocusRow with event, start and end nodes when pressing Home', () => { + const onFocusRow = jest.fn(); + render( ); + + screen.getByText( 'Row 3' ).focus(); + + const row3Element = screen.getByText( 'Row 3' ).closest( 'tr' ); + const row1Element = screen.getByText( 'Row 1' ).closest( 'tr' ); + + fireEvent.keyDown( screen.getByText( 'Row 3' ), { + key: 'Home', + keyCode: HOME, + currentTarget: row3Element, + } ); + + expect( onFocusRow ).toHaveBeenCalledWith( + expect.objectContaining( { key: 'Home', keyCode: HOME } ), + row3Element, + row1Element + ); + } ); + it( 'should call onFocusRow when shift key is held', () => { const onFocusRow = jest.fn(); render( );