From 09ce42d0c6bc76f5e93cb9ea19882e96e373e160 Mon Sep 17 00:00:00 2001 From: chad1008 <13856531+chad1008@users.noreply.github.com> Date: Mon, 4 Dec 2023 13:18:45 -0500 Subject: [PATCH] add `selectOnMove` unit tests --- packages/components/src/tabs/test/index.tsx | 214 +++++++++++++++++++- 1 file changed, 213 insertions(+), 1 deletion(-) diff --git a/packages/components/src/tabs/test/index.tsx b/packages/components/src/tabs/test/index.tsx index fac8127c4cc0d8..4ab48e30483e9a 100644 --- a/packages/components/src/tabs/test/index.tsx +++ b/packages/components/src/tabs/test/index.tsx @@ -7,7 +7,7 @@ import userEvent from '@testing-library/user-event'; /** * WordPress dependencies */ -import { useState } from '@wordpress/element'; +import { useEffect, useState } from '@wordpress/element'; /** * Internal dependencies @@ -102,6 +102,10 @@ const ControlledTabs = ( { string | undefined | null >( props.selectedTabId ); + useEffect( () => { + setSelectedTabId( props.selectedTabId ); + }, [ props.selectedTabId ] ); + return ( { } ); } ); + describe( 'When `selectOnMove` is `true`', () => { + it( 'should automatically select a newly focused tab', async () => { + const user = userEvent.setup(); + + render( ); + + // Tab should focus the currently selected tab, which is Alpha. + await user.keyboard( '[Tab]' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( await getSelectedTab() ).toHaveFocus(); + + // Arrow keys should select and move focus to the next tab. + await user.keyboard( '[ArrowRight]' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + expect( await getSelectedTab() ).toHaveFocus(); + } ); + } ); + + describe( 'When `selectOnMove` is `false`', () => { + it( 'should apply focus without automatically changing the selected tab', async () => { + const user = userEvent.setup(); + + render( + + ); + + // Tab should focus the currently selected tab, which is Alpha. + await user.keyboard( '[Tab]' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + expect( await getSelectedTab() ).toHaveFocus(); + + // Arrow key should move focus but not automatically change the selected tab. + await user.keyboard( '[ArrowRight]' ); + expect( + screen.getByRole( 'tab', { name: 'Beta' } ) + ).toHaveFocus(); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + + // Pressing the spacebar should select the focused tab. + await user.keyboard( '[Space]' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + + // Arrow key should move focus but not automatically change the selected tab. + await user.keyboard( '[ArrowRight]' ); + expect( + screen.getByRole( 'tab', { name: 'Gamma' } ) + ).toHaveFocus(); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + + // Pressing the enter/return should select the focused tab. + await user.keyboard( '[Enter]' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + } ); + } ); + describe( 'Disabled tab', () => { it( 'should disable the tab when `disabled` is `true`', async () => { const user = userEvent.setup(); @@ -1203,5 +1262,158 @@ describe( 'Tabs', () => { ).not.toBeInTheDocument(); } ); } ); + + describe( 'When `selectOnMove` is `true`', () => { + it( 'should automatically select a newly focused tab', async () => { + const user = userEvent.setup(); + + render( ); + + // This assertion ensures the component has had time to fully + // render, preventing flakiness. + // see https://github.com/WordPress/gutenberg/pull/55950 + await waitFor( async () => + expect( + await screen.findByRole( 'tab', { name: 'Beta' } ) + ).toHaveAttribute( 'aria-selected', 'true' ) + ); + + await user.keyboard( '[Tab]' ); + + // Tab key should focus the currently selected tab, which is Beta. + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + expect( await getSelectedTab() ).toHaveFocus(); + + // Arrow keys should select and move focus to the next tab. + await user.keyboard( '[ArrowRight]' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( await getSelectedTab() ).toHaveFocus(); + } ); + it( 'should automatically update focus when the selected tab is changed by the controlling component', async () => { + const user = userEvent.setup(); + + const { rerender } = render( + + ); + + // This assertion ensures the component has had time to fully + // render, preventing flakiness. + // see https://github.com/WordPress/gutenberg/pull/55950 + await waitFor( async () => + expect( + await screen.findByRole( 'tab', { name: 'Beta' } ) + ).toHaveAttribute( 'aria-selected', 'true' ) + ); + + // Tab key should focus the currently selected tab, which is Beta. + await user.keyboard( '[Tab]' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + expect( await getSelectedTab() ).toHaveFocus(); + + rerender( + + ); + + // When the selected tab is changed, it should automatically receive focus. + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + expect( await getSelectedTab() ).toHaveFocus(); + } ); + } ); + describe( 'When `selectOnMove` is `false`', () => { + it( 'should apply focus without automatically changing the selected tab', async () => { + const user = userEvent.setup(); + + render( + + ); + + // This assertion ensures the component has had time to fully + // render, preventing flakiness. + // see https://github.com/WordPress/gutenberg/pull/55950 + await waitFor( async () => + expect( + await screen.findByRole( 'tab', { name: 'Beta' } ) + ).toHaveAttribute( 'aria-selected', 'true' ) + ); + + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + + // Tab key should focus the currently selected tab, which is Beta. + await user.keyboard( '[Tab]' ); + expect( + await screen.findByRole( 'tab', { name: 'Beta' } ) + ).toHaveFocus(); + + // Arrow key should move focus but not automatically change the selected tab. + await user.keyboard( '[ArrowRight]' ); + expect( + screen.getByRole( 'tab', { name: 'Gamma' } ) + ).toHaveFocus(); + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + + // Pressing the spacebar should select the focused tab. + await user.keyboard( '[Space]' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + + // Arrow key should move focus but not automatically change the selected tab. + await user.keyboard( '[ArrowRight]' ); + expect( + screen.getByRole( 'tab', { name: 'Alpha' } ) + ).toHaveFocus(); + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + + // Pressing the enter/return should select the focused tab. + await user.keyboard( '[Enter]' ); + expect( await getSelectedTab() ).toHaveTextContent( 'Alpha' ); + } ); + it( 'should not automatically update focus when the selected tab is changed by the controlling component', async () => { + const user = userEvent.setup(); + + const { rerender } = render( + + ); + + // This assertion ensures the component has had time to fully + // render, preventing flakiness. + // see https://github.com/WordPress/gutenberg/pull/55950 + await waitFor( async () => + expect( + await screen.findByRole( 'tab', { name: 'Beta' } ) + ).toHaveAttribute( 'aria-selected', 'true' ) + ); + + expect( await getSelectedTab() ).toHaveTextContent( 'Beta' ); + + // Tab key should focus the currently selected tab, which is Beta. + await user.keyboard( '[Tab]' ); + expect( await getSelectedTab() ).toHaveFocus(); + + rerender( + + ); + + // When the selected tab is changed, it should not automatically receive focus. + expect( await getSelectedTab() ).toHaveTextContent( 'Gamma' ); + // `waitFor` is needed here to prevent testing library from + // throwing a 'not wrapped in `act()`' error. + await waitFor( () => + expect( + screen.getByRole( 'tab', { name: 'Beta' } ) + ).toHaveFocus() + ); + } ); + } ); } ); } );