From 41d460574a8d7ef9b34ce6f1f0da63850064a8c8 Mon Sep 17 00:00:00 2001 From: Ryan Cogswell <287804+ryancogswell@users.noreply.github.com> Date: Tue, 2 Jul 2019 06:13:51 -0500 Subject: [PATCH 1/4] [Menu] Fix autoFocus to work correctly with keepMounted --- packages/material-ui/src/Menu/Menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/material-ui/src/Menu/Menu.js b/packages/material-ui/src/Menu/Menu.js index 4fc18e1ddb71e7..1f85ef394bfc28 100644 --- a/packages/material-ui/src/Menu/Menu.js +++ b/packages/material-ui/src/Menu/Menu.js @@ -53,7 +53,7 @@ const Menu = React.forwardRef(function Menu(props, ref) { ...other } = props; - const autoFocus = autoFocusProp !== undefined ? autoFocusProp : !disableAutoFocusItem; + const autoFocus = (autoFocusProp !== undefined ? autoFocusProp : !disableAutoFocusItem) && open; const menuListActionsRef = React.useRef(null); const firstValidItemRef = React.useRef(null); From 8feb68642c3b8d4411872e7082201f8a548279da Mon Sep 17 00:00:00 2001 From: Ryan Cogswell <287804+ryancogswell@users.noreply.github.com> Date: Tue, 2 Jul 2019 09:00:22 -0500 Subject: [PATCH 2/4] [test] Verify Menu focus navigation with keepMounted --- .../material-ui/test/integration/Menu.test.js | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/material-ui/test/integration/Menu.test.js b/packages/material-ui/test/integration/Menu.test.js index 3b6a08c60e32da..be79d8b25ae38a 100644 --- a/packages/material-ui/test/integration/Menu.test.js +++ b/packages/material-ui/test/integration/Menu.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { assert } from 'chai'; +import { assert, expect } from 'chai'; import TestUtils from 'react-dom/test-utils'; import { createMount } from '@material-ui/core/test-utils'; import Popover from '@material-ui/core/Popover'; @@ -10,6 +10,7 @@ import { setRef } from '../../src/utils/reactHelpers'; import { stub } from 'sinon'; import PropTypes from 'prop-types'; import { createMuiTheme } from '@material-ui/core/styles'; +import { cleanup, render, fireEvent } from 'test/utils/createClientRender'; describe(' integration', () => { let mount; @@ -17,10 +18,12 @@ describe(' integration', () => { before(() => { // StrictModeViolation: test uses simulate mount = createMount({ strict: false }); + // StrictModeViolation: Uses MenuItem }); after(() => { mount.cleanUp(); + cleanup(); }); describe('mounted open', () => { @@ -147,6 +150,28 @@ describe(' integration', () => { }); }); + describe('render with keepMounted', () => { + let wrapper; + + before(() => { + // Using render instead of createClientRender because createClientRender specifies an explicit + // base element that is the starting point for queries, but the menu would be rendered outside + // of that base element. + wrapper = render(); + }); + + it('should focus the list on open', () => { + const button = wrapper.getByLabelText('When device is locked'); + const menu = wrapper.getByRole('menu'); + expect(menu).to.not.be.focused; + button.focus(); + fireEvent.click(button); + expect(menu).to.be.focused; + fireEvent.keyDown(document.activeElement, { key: 'ArrowDown' }); + expect(wrapper.getAllByRole('menuitem')[0]).to.be.focused; + }); + }); + describe('Menu variant differences', () => { const contentAnchorTracker = [false, false, false]; const focusTracker = [false, false, false]; From 0bef09c5a1f4b69eb6bbf0ddaf21aad3858d6539 Mon Sep 17 00:00:00 2001 From: Ryan Cogswell <287804+ryancogswell@users.noreply.github.com> Date: Tue, 2 Jul 2019 09:16:19 -0500 Subject: [PATCH 3/4] [test] Separate RTL test from mount tests so that cleanup is more reliable --- .../material-ui/test/integration/Menu.test.js | 656 +++++++++--------- 1 file changed, 330 insertions(+), 326 deletions(-) diff --git a/packages/material-ui/test/integration/Menu.test.js b/packages/material-ui/test/integration/Menu.test.js index be79d8b25ae38a..d89c81cf8c2a27 100644 --- a/packages/material-ui/test/integration/Menu.test.js +++ b/packages/material-ui/test/integration/Menu.test.js @@ -13,390 +13,394 @@ import { createMuiTheme } from '@material-ui/core/styles'; import { cleanup, render, fireEvent } from 'test/utils/createClientRender'; describe(' integration', () => { - let mount; - - before(() => { - // StrictModeViolation: test uses simulate - mount = createMount({ strict: false }); - // StrictModeViolation: Uses MenuItem - }); - - after(() => { - mount.cleanUp(); - cleanup(); - }); - - describe('mounted open', () => { - let wrapper; - let portalLayer; + describe('Using mount', () => { + let mount; before(() => { - wrapper = mount(); + // StrictModeViolation: test uses simulate + mount = createMount({ strict: false }); }); - it('should not be open', () => { - const popover = wrapper.find(Popover); - assert.strictEqual(popover.props().open, false, 'should have passed open=false to Popover'); - const menuEl = document.getElementById('simple-menu'); - assert.strictEqual(menuEl, null); + after(() => { + mount.cleanUp(); }); - it('should focus the list as nothing has been selected', () => { - wrapper.find('button').simulate('click'); - portalLayer = document.querySelector('[data-mui-test="Modal"]'); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('ul')[0]); - }); + describe('mounted open', () => { + let wrapper; + let portalLayer; - it('should change focus to the first item when down arrow is pressed', () => { - TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { - key: 'ArrowDown', + before(() => { + wrapper = mount(); }); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[0]); - }); - it('should change focus to the 2nd item when down arrow is pressed', () => { - TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { - key: 'ArrowDown', + it('should not be open', () => { + const popover = wrapper.find(Popover); + assert.strictEqual(popover.props().open, false, 'should have passed open=false to Popover'); + const menuEl = document.getElementById('simple-menu'); + assert.strictEqual(menuEl, null); }); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[1]); - }); - it('should change focus to the 3rd item when down arrow is pressed', () => { - TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { - key: 'ArrowDown', + it('should focus the list as nothing has been selected', () => { + wrapper.find('button').simulate('click'); + portalLayer = document.querySelector('[data-mui-test="Modal"]'); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('ul')[0]); }); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); - }); - it('should switch focus from the 3rd item to the 1st item when down arrow is pressed', () => { - TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { - key: 'ArrowDown', + it('should change focus to the first item when down arrow is pressed', () => { + TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { + key: 'ArrowDown', + }); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[0]); }); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[0]); - }); - it('should switch focus from the 1st item to the 3rd item when up arrow is pressed', () => { - TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { - key: 'ArrowUp', + it('should change focus to the 2nd item when down arrow is pressed', () => { + TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { + key: 'ArrowDown', + }); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[1]); }); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); - }); - it('should switch focus from the 3rd item to the 1st item when home key is pressed', () => { - TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { - key: 'Home', + it('should change focus to the 3rd item when down arrow is pressed', () => { + TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { + key: 'ArrowDown', + }); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); }); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[0]); - }); - it('should switch focus from the 1st item to the 3rd item when end key is pressed', () => { - TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { - key: 'End', + it('should switch focus from the 3rd item to the 1st item when down arrow is pressed', () => { + TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { + key: 'ArrowDown', + }); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[0]); }); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); - }); - it('should keep focus on the last item when a key with no associated action is pressed', () => { - TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { - key: 'ArrowRight', + it('should switch focus from the 1st item to the 3rd item when up arrow is pressed', () => { + TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { + key: 'ArrowUp', + }); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); }); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); - }); - it('should change focus to the 2nd item when up arrow is pressed', () => { - TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { - key: 'ArrowUp', + it('should switch focus from the 3rd item to the 1st item when home key is pressed', () => { + TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { + key: 'Home', + }); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[0]); }); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[1]); - }); - it('should select the 2nd item and close the menu', () => { - portalLayer.querySelectorAll('li')[1].click(); - assert.strictEqual(wrapper.text(), 'selectedIndex: 1, open: false'); - }); - }); + it('should switch focus from the 1st item to the 3rd item when end key is pressed', () => { + TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { + key: 'End', + }); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); + }); - describe('opening with a selected item', () => { - let wrapper; + it('should keep focus on the last item when a key with no associated action is pressed', () => { + TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { + key: 'ArrowRight', + }); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); + }); - before(() => { - wrapper = mount(); - }); + it('should change focus to the 2nd item when up arrow is pressed', () => { + TestUtils.Simulate.keyDown(portalLayer.querySelector('ul'), { + key: 'ArrowUp', + }); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[1]); + }); - it('should not be open', () => { - const popover = wrapper.find(Popover); - assert.strictEqual(popover.props().open, false); - const menuEl = document.getElementById('simple-menu'); - assert.strictEqual(menuEl, null); + it('should select the 2nd item and close the menu', () => { + portalLayer.querySelectorAll('li')[1].click(); + assert.strictEqual(wrapper.text(), 'selectedIndex: 1, open: false'); + }); }); - it('should focus the 3rd selected item', () => { - wrapper.find('button').simulate('click'); - const portalLayer = document.querySelector('[data-mui-test="Modal"]'); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); - }); + describe('opening with a selected item', () => { + let wrapper; - it('should select the 2nd item and close the menu', () => { - const portalLayer = document.querySelector('[data-mui-test="Modal"]'); - const item = portalLayer.querySelector('ul').children[1]; - item.click(); - assert.strictEqual(wrapper.text(), 'selectedIndex: 1, open: false'); - }); + before(() => { + wrapper = mount(); + }); - it('should focus the 2nd selected item', () => { - wrapper.find('button').simulate('click'); - const portalLayer = document.querySelector('[data-mui-test="Modal"]'); - assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[1]); - }); - }); + it('should not be open', () => { + const popover = wrapper.find(Popover); + assert.strictEqual(popover.props().open, false); + const menuEl = document.getElementById('simple-menu'); + assert.strictEqual(menuEl, null); + }); - describe('render with keepMounted', () => { - let wrapper; + it('should focus the 3rd selected item', () => { + wrapper.find('button').simulate('click'); + const portalLayer = document.querySelector('[data-mui-test="Modal"]'); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[2]); + }); - before(() => { - // Using render instead of createClientRender because createClientRender specifies an explicit - // base element that is the starting point for queries, but the menu would be rendered outside - // of that base element. - wrapper = render(); - }); + it('should select the 2nd item and close the menu', () => { + const portalLayer = document.querySelector('[data-mui-test="Modal"]'); + const item = portalLayer.querySelector('ul').children[1]; + item.click(); + assert.strictEqual(wrapper.text(), 'selectedIndex: 1, open: false'); + }); - it('should focus the list on open', () => { - const button = wrapper.getByLabelText('When device is locked'); - const menu = wrapper.getByRole('menu'); - expect(menu).to.not.be.focused; - button.focus(); - fireEvent.click(button); - expect(menu).to.be.focused; - fireEvent.keyDown(document.activeElement, { key: 'ArrowDown' }); - expect(wrapper.getAllByRole('menuitem')[0]).to.be.focused; + it('should focus the 2nd selected item', () => { + wrapper.find('button').simulate('click'); + const portalLayer = document.querySelector('[data-mui-test="Modal"]'); + assert.strictEqual(document.activeElement, portalLayer.querySelectorAll('li')[1]); + }); }); - }); - describe('Menu variant differences', () => { - const contentAnchorTracker = [false, false, false]; - const focusTracker = [false, false, false]; - let menuListFocusTracker = false; - const tabIndexTracker = [false, false, false]; - const TrackingMenuItem = React.forwardRef(({ itemIndex, ...other }, ref) => { - return ( - { - focusTracker[itemIndex] = true; - }} - ref={instance => { - setRef(ref, instance); - if (instance && !instance.stubbed) { - if (instance.tabIndex === 0) { - tabIndexTracker[itemIndex] = true; - } else if (instance.tabIndex > 0) { - tabIndexTracker[itemIndex] = instance.tabIndex; + describe('Menu variant differences', () => { + const contentAnchorTracker = [false, false, false]; + const focusTracker = [false, false, false]; + let menuListFocusTracker = false; + const tabIndexTracker = [false, false, false]; + const TrackingMenuItem = React.forwardRef(({ itemIndex, ...other }, ref) => { + return ( + { + focusTracker[itemIndex] = true; + }} + ref={instance => { + setRef(ref, instance); + if (instance && !instance.stubbed) { + if (instance.tabIndex === 0) { + tabIndexTracker[itemIndex] = true; + } else if (instance.tabIndex > 0) { + tabIndexTracker[itemIndex] = instance.tabIndex; + } + const offsetTop = instance.offsetTop; + stub(instance, 'offsetTop').get(() => { + contentAnchorTracker[itemIndex] = true; + return offsetTop; + }); + instance.stubbed = true; } - const offsetTop = instance.offsetTop; - stub(instance, 'offsetTop').get(() => { - contentAnchorTracker[itemIndex] = true; - return offsetTop; - }); - instance.stubbed = true; - } - }} - {...other} - /> - ); - }); - TrackingMenuItem.propTypes = { - /** - * @ignore - */ - itemIndex: PropTypes.number, - }; - // Array.fill not supported by Chrome 41 - const fill = (array, value) => { - for (let i = 0; i < array.length; i += 1) { - array[i] = value; - } - }; - const mountTrackingMenu = ( - variant, - { - selectedIndex, - selectedTabIndex, - invalidIndex, - autoFocusIndex, - disabledIndex, - autoFocus, - themeDirection, - } = {}, - ) => { - const theme = - themeDirection !== undefined - ? createMuiTheme({ - direction: themeDirection, - }) - : undefined; - - fill(contentAnchorTracker, false); - fill(focusTracker, false); - menuListFocusTracker = false; - fill(tabIndexTracker, false); - mount( - { - menuListFocusTracker = true; - }, - }} - > - {[0, 1, 2].map(itemIndex => { - if (itemIndex === invalidIndex) { - return null; - } - return ( - - Menu Item {itemIndex} - - ); - })} - , - ); - }; - - it('[variant=menu] adds coverage for rtl and Tab with no onClose', () => { - // This isn't adding very meaningful coverage apart from verifying it doesn't error, but - // it was so close to 100% that this has value in avoiding needing to drill into coverage - // details to see what isn't being tested. - mountTrackingMenu('menu', { themeDirection: 'rtl' }); - assert.deepEqual(contentAnchorTracker, [true, false, false]); - assert.deepEqual(focusTracker, [false, false, false]); - assert.strictEqual(menuListFocusTracker, true); - assert.deepEqual(tabIndexTracker, [false, false, false]); - - // Adds coverage for Tab with no onClose - TestUtils.Simulate.keyDown(document.activeElement, { - key: 'Tab', + }} + {...other} + /> + ); + }); + TrackingMenuItem.propTypes = { + /** + * @ignore + */ + itemIndex: PropTypes.number, + }; + // Array.fill not supported by Chrome 41 + const fill = (array, value) => { + for (let i = 0; i < array.length; i += 1) { + array[i] = value; + } + }; + const mountTrackingMenu = ( + variant, + { + selectedIndex, + selectedTabIndex, + invalidIndex, + autoFocusIndex, + disabledIndex, + autoFocus, + themeDirection, + } = {}, + ) => { + const theme = + themeDirection !== undefined + ? createMuiTheme({ + direction: themeDirection, + }) + : undefined; + + fill(contentAnchorTracker, false); + fill(focusTracker, false); + menuListFocusTracker = false; + fill(tabIndexTracker, false); + mount( + { + menuListFocusTracker = true; + }, + }} + > + {[0, 1, 2].map(itemIndex => { + if (itemIndex === invalidIndex) { + return null; + } + return ( + + Menu Item {itemIndex} + + ); + })} + , + ); + }; + + it('[variant=menu] adds coverage for rtl and Tab with no onClose', () => { + // This isn't adding very meaningful coverage apart from verifying it doesn't error, but + // it was so close to 100% that this has value in avoiding needing to drill into coverage + // details to see what isn't being tested. + mountTrackingMenu('menu', { themeDirection: 'rtl' }); + assert.deepEqual(contentAnchorTracker, [true, false, false]); + assert.deepEqual(focusTracker, [false, false, false]); + assert.strictEqual(menuListFocusTracker, true); + assert.deepEqual(tabIndexTracker, [false, false, false]); + + // Adds coverage for Tab with no onClose + TestUtils.Simulate.keyDown(document.activeElement, { + key: 'Tab', + }); }); - }); - it('[variant=menu] nothing selected', () => { - assert.deepEqual(contentAnchorTracker, [true, false, false]); - assert.deepEqual(focusTracker, [false, false, false]); - assert.strictEqual(menuListFocusTracker, true); - assert.deepEqual(tabIndexTracker, [false, false, false]); - }); + it('[variant=menu] nothing selected', () => { + assert.deepEqual(contentAnchorTracker, [true, false, false]); + assert.deepEqual(focusTracker, [false, false, false]); + assert.strictEqual(menuListFocusTracker, true); + assert.deepEqual(tabIndexTracker, [false, false, false]); + }); - it('[variant=menu] nothing selected, autoFocus on third', () => { - mountTrackingMenu('menu', { autoFocusIndex: 2 }); - assert.deepEqual(contentAnchorTracker, [true, false, false]); - assert.deepEqual(focusTracker, [false, false, true]); - assert.strictEqual(menuListFocusTracker, true); - assert.deepEqual(tabIndexTracker, [false, false, false]); - }); + it('[variant=menu] nothing selected, autoFocus on third', () => { + mountTrackingMenu('menu', { autoFocusIndex: 2 }); + assert.deepEqual(contentAnchorTracker, [true, false, false]); + assert.deepEqual(focusTracker, [false, false, true]); + assert.strictEqual(menuListFocusTracker, true); + assert.deepEqual(tabIndexTracker, [false, false, false]); + }); - it('[variant=selectedMenu] nothing selected', () => { - mountTrackingMenu('selectedMenu'); - assert.deepEqual(contentAnchorTracker, [true, false, false]); - assert.deepEqual(focusTracker, [false, false, false]); - assert.strictEqual(menuListFocusTracker, true); - assert.deepEqual(tabIndexTracker, [false, false, false]); - }); + it('[variant=selectedMenu] nothing selected', () => { + mountTrackingMenu('selectedMenu'); + assert.deepEqual(contentAnchorTracker, [true, false, false]); + assert.deepEqual(focusTracker, [false, false, false]); + assert.strictEqual(menuListFocusTracker, true); + assert.deepEqual(tabIndexTracker, [false, false, false]); + }); - it('[variant=selectedMenu] nothing selected, first index invalid', () => { - mountTrackingMenu('selectedMenu', { invalidIndex: 0 }); - assert.deepEqual(contentAnchorTracker, [false, true, false]); - assert.deepEqual(focusTracker, [false, false, false]); - assert.strictEqual(menuListFocusTracker, true); - assert.deepEqual(tabIndexTracker, [false, false, false]); - }); + it('[variant=selectedMenu] nothing selected, first index invalid', () => { + mountTrackingMenu('selectedMenu', { invalidIndex: 0 }); + assert.deepEqual(contentAnchorTracker, [false, true, false]); + assert.deepEqual(focusTracker, [false, false, false]); + assert.strictEqual(menuListFocusTracker, true); + assert.deepEqual(tabIndexTracker, [false, false, false]); + }); - it('[variant=menu] second item selected', () => { - mountTrackingMenu('menu', { selectedIndex: 1 }); - assert.deepEqual(contentAnchorTracker, [true, false, false]); - assert.deepEqual(focusTracker, [false, false, false]); - assert.strictEqual(menuListFocusTracker, true); - assert.deepEqual(tabIndexTracker, [false, false, false]); - }); + it('[variant=menu] second item selected', () => { + mountTrackingMenu('menu', { selectedIndex: 1 }); + assert.deepEqual(contentAnchorTracker, [true, false, false]); + assert.deepEqual(focusTracker, [false, false, false]); + assert.strictEqual(menuListFocusTracker, true); + assert.deepEqual(tabIndexTracker, [false, false, false]); + }); - it('[variant=selectedMenu] second item selected, explicit tabIndex', () => { - mountTrackingMenu('selectedMenu', { selectedIndex: 1, selectedTabIndex: 2 }); - assert.deepEqual(contentAnchorTracker, [false, true, false]); - assert.deepEqual(focusTracker, [false, true, false]); - assert.strictEqual(menuListFocusTracker, true); - assert.deepEqual(tabIndexTracker, [false, 2, false]); - }); + it('[variant=selectedMenu] second item selected, explicit tabIndex', () => { + mountTrackingMenu('selectedMenu', { selectedIndex: 1, selectedTabIndex: 2 }); + assert.deepEqual(contentAnchorTracker, [false, true, false]); + assert.deepEqual(focusTracker, [false, true, false]); + assert.strictEqual(menuListFocusTracker, true); + assert.deepEqual(tabIndexTracker, [false, 2, false]); + }); - it('[variant=selectedMenu] second item selected', () => { - mountTrackingMenu('selectedMenu', { selectedIndex: 1 }); - assert.deepEqual(contentAnchorTracker, [false, true, false]); - assert.deepEqual(focusTracker, [false, true, false]); - assert.strictEqual(menuListFocusTracker, true); - assert.deepEqual(tabIndexTracker, [false, true, false]); - }); + it('[variant=selectedMenu] second item selected', () => { + mountTrackingMenu('selectedMenu', { selectedIndex: 1 }); + assert.deepEqual(contentAnchorTracker, [false, true, false]); + assert.deepEqual(focusTracker, [false, true, false]); + assert.strictEqual(menuListFocusTracker, true); + assert.deepEqual(tabIndexTracker, [false, true, false]); + }); + + it('[variant=selectedMenu] second item selected and disabled', () => { + mountTrackingMenu('selectedMenu', { selectedIndex: 1, disabledIndex: 1 }); + assert.deepEqual(contentAnchorTracker, [true, false, false]); + assert.deepEqual(focusTracker, [false, false, false]); + assert.strictEqual(menuListFocusTracker, true); + assert.deepEqual(tabIndexTracker, [false, false, false]); + }); - it('[variant=selectedMenu] second item selected and disabled', () => { - mountTrackingMenu('selectedMenu', { selectedIndex: 1, disabledIndex: 1 }); - assert.deepEqual(contentAnchorTracker, [true, false, false]); - assert.deepEqual(focusTracker, [false, false, false]); - assert.strictEqual(menuListFocusTracker, true); - assert.deepEqual(tabIndexTracker, [false, false, false]); + it('[variant=selectedMenu] second item selected, no autoFocus', () => { + mountTrackingMenu('selectedMenu', { selectedIndex: 1, autoFocus: false }); + assert.deepEqual(contentAnchorTracker, [false, true, false]); + assert.deepEqual(focusTracker, [false, false, false]); + assert.strictEqual(menuListFocusTracker, false); + assert.deepEqual(tabIndexTracker, [false, true, false]); + }); }); - it('[variant=selectedMenu] second item selected, no autoFocus', () => { - mountTrackingMenu('selectedMenu', { selectedIndex: 1, autoFocus: false }); - assert.deepEqual(contentAnchorTracker, [false, true, false]); - assert.deepEqual(focusTracker, [false, false, false]); - assert.strictEqual(menuListFocusTracker, false); - assert.deepEqual(tabIndexTracker, [false, true, false]); + describe('closing', () => { + let wrapper; + let portalLayer; + + beforeEach(() => { + wrapper = mount(); + wrapper.find('button').simulate('click'); + portalLayer = document.querySelector('[data-mui-test="Modal"]'); + }); + + it('should close the menu with tab', done => { + wrapper.setProps({ + onExited() { + assert.strictEqual(document.getElementById('[data-mui-test="Menu"]'), null); + done(); + }, + }); + assert.strictEqual(wrapper.text(), 'selectedIndex: null, open: true'); + const list = portalLayer.querySelector('ul'); + TestUtils.Simulate.keyDown(list, { + key: 'Tab', + }); + assert.strictEqual(wrapper.text(), 'selectedIndex: null, open: false'); + }); + + it('should close the menu using the backdrop', done => { + wrapper.setProps({ + onExited() { + assert.strictEqual(document.getElementById('[data-mui-test="Menu"]'), null); + done(); + }, + }); + assert.strictEqual(wrapper.text(), 'selectedIndex: null, open: true'); + const backdrop = portalLayer.querySelector('[data-mui-test="Backdrop"]'); + assert.strictEqual(backdrop != null, true); + backdrop.click(); + assert.strictEqual(wrapper.text(), 'selectedIndex: null, open: false'); + }); }); }); - describe('closing', () => { + describe('Using RTL render with keepMounted', () => { let wrapper; - let portalLayer; - beforeEach(() => { - wrapper = mount(); - wrapper.find('button').simulate('click'); - portalLayer = document.querySelector('[data-mui-test="Modal"]'); + before(() => { + // Using render instead of createClientRender because createClientRender specifies an explicit + // base element that is the starting point for queries, but the menu would be rendered outside + // of that base element. + wrapper = render(); }); - it('should close the menu with tab', done => { - wrapper.setProps({ - onExited() { - assert.strictEqual(document.getElementById('[data-mui-test="Menu"]'), null); - done(); - }, - }); - assert.strictEqual(wrapper.text(), 'selectedIndex: null, open: true'); - const list = portalLayer.querySelector('ul'); - TestUtils.Simulate.keyDown(list, { - key: 'Tab', - }); - assert.strictEqual(wrapper.text(), 'selectedIndex: null, open: false'); + after(() => { + cleanup(); }); - it('should close the menu using the backdrop', done => { - wrapper.setProps({ - onExited() { - assert.strictEqual(document.getElementById('[data-mui-test="Menu"]'), null); - done(); - }, - }); - assert.strictEqual(wrapper.text(), 'selectedIndex: null, open: true'); - const backdrop = portalLayer.querySelector('[data-mui-test="Backdrop"]'); - assert.strictEqual(backdrop != null, true); - backdrop.click(); - assert.strictEqual(wrapper.text(), 'selectedIndex: null, open: false'); + it('should focus the list on open', () => { + const button = wrapper.getByLabelText('When device is locked'); + const menu = wrapper.getByRole('menu'); + expect(menu).to.not.be.focused; + button.focus(); + fireEvent.click(button); + expect(menu).to.be.focused; + fireEvent.keyDown(document.activeElement, { key: 'ArrowDown' }); + expect(wrapper.getAllByRole('menuitem')[0]).to.be.focused; }); }); }); From 21a725d63526796ef979fe8ae6e008696ac207b3 Mon Sep 17 00:00:00 2001 From: Ryan Cogswell Date: Tue, 2 Jul 2019 11:10:47 -0500 Subject: [PATCH 4/4] poke azure