From 48c5de8df254af52099b3763c96a0def39b09853 Mon Sep 17 00:00:00 2001 From: joshwooding <12938082+joshwooding@users.noreply.github.com> Date: Fri, 26 Jun 2020 01:19:35 +0100 Subject: [PATCH] Use #20147 and modify slightly --- .../material-ui-lab/src/TreeItem/TreeItem.js | 3 +- .../src/TreeItem/TreeItem.test.js | 35 ++++++++++--------- .../material-ui-lab/src/TreeView/TreeView.js | 8 +++-- .../src/TreeView/descendants.js | 4 +++ 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/packages/material-ui-lab/src/TreeItem/TreeItem.js b/packages/material-ui-lab/src/TreeItem/TreeItem.js index ea966ae11996b1..b857b6551d7e63 100644 --- a/packages/material-ui-lab/src/TreeItem/TreeItem.js +++ b/packages/material-ui-lab/src/TreeItem/TreeItem.js @@ -347,6 +347,7 @@ const TreeItem = React.forwardRef(function TreeItem(props, ref) { id: nodeId, index, parentId, + expandable, }); return () => { @@ -355,7 +356,7 @@ const TreeItem = React.forwardRef(function TreeItem(props, ref) { } return undefined; - }, [registerNode, unregisterNode, parentId, index, nodeId]); + }, [registerNode, unregisterNode, parentId, index, nodeId, expandable]); React.useEffect(() => { if (mapFirstChar && label) { diff --git a/packages/material-ui-lab/src/TreeItem/TreeItem.test.js b/packages/material-ui-lab/src/TreeItem/TreeItem.test.js index 04b2a712c666cd..347c24231fb0f2 100644 --- a/packages/material-ui-lab/src/TreeItem/TreeItem.test.js +++ b/packages/material-ui-lab/src/TreeItem/TreeItem.test.js @@ -837,8 +837,9 @@ describe('', () => { describe('asterisk key interaction', () => { it('expands all siblings that are at the same level as the current node', () => { + const toggleSpy = spy(); const { getByTestId } = render( - + @@ -862,6 +863,8 @@ describe('', () => { fireEvent.keyDown(getByTestId('one'), { key: '*' }); + expect(toggleSpy.args[0][1]).to.have.length(3); + expect(getByTestId('one')).to.have.attribute('aria-expanded', 'true'); expect(getByTestId('three')).to.have.attribute('aria-expanded', 'true'); expect(getByTestId('five')).to.have.attribute('aria-expanded', 'true'); @@ -989,27 +992,27 @@ describe('', () => { fireEvent.keyDown(getByTestId('three'), { key: 'ArrowDown', shiftKey: true }); expect(getByTestId('four')).toHaveFocus(); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(2); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(2); fireEvent.keyDown(getByTestId('four'), { key: 'ArrowDown', shiftKey: true }); expect(getByTestId('three')).to.have.attribute('aria-selected', 'true'); expect(getByTestId('four')).to.have.attribute('aria-selected', 'true'); expect(getByTestId('five')).to.have.attribute('aria-selected', 'true'); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(3); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(3); fireEvent.keyDown(getByTestId('five'), { key: 'ArrowUp', shiftKey: true }); expect(getByTestId('four')).toHaveFocus(); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(2); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(2); fireEvent.keyDown(getByTestId('four'), { key: 'ArrowUp', shiftKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(1); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(1); fireEvent.keyDown(getByTestId('three'), { key: 'ArrowUp', shiftKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(2); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(2); fireEvent.keyDown(getByTestId('two'), { key: 'ArrowUp', shiftKey: true }); @@ -1018,7 +1021,7 @@ describe('', () => { expect(getByTestId('three')).to.have.attribute('aria-selected', 'true'); expect(getByTestId('four')).to.have.attribute('aria-selected', 'false'); expect(getByTestId('five')).to.have.attribute('aria-selected', 'false'); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(3); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(3); }); specify('keyboard arrow does not select when selectionDisabled', () => { @@ -1036,11 +1039,11 @@ describe('', () => { fireEvent.keyDown(getByTestId('three'), { key: 'ArrowDown', shiftKey: true }); expect(getByTestId('four')).toHaveFocus(); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0); fireEvent.keyDown(getByTestId('four'), { key: 'ArrowUp', shiftKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0); }); specify('keyboard arrow merge', () => { @@ -1066,12 +1069,12 @@ describe('', () => { fireEvent.keyDown(getByTestId('four'), { key: 'ArrowUp', shiftKey: true }); fireEvent.keyDown(getByTestId('three'), { key: 'ArrowUp', shiftKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(5); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(5); fireEvent.keyDown(getByTestId('two'), { key: 'ArrowDown', shiftKey: true }); fireEvent.keyDown(getByTestId('three'), { key: 'ArrowDown', shiftKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(3); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(3); }); specify('keyboard space', () => { @@ -1178,11 +1181,11 @@ describe('', () => { getByTestId('five').focus(); fireEvent.keyDown(getByTestId('five'), { key: 'End', shiftKey: true, ctrlKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0); fireEvent.keyDown(getByTestId('nine'), { key: 'Home', shiftKey: true, ctrlKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0); }); specify('mouse', () => { @@ -1236,7 +1239,7 @@ describe('', () => { fireEvent.click(getByText('five')); fireEvent.click(getByText('nine'), { shiftKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0); }); }); @@ -1317,7 +1320,7 @@ describe('', () => { getByTestId('one').focus(); fireEvent.keyDown(getByTestId('one'), { key: 'a', ctrlKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(5); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(5); }); specify('ctrl + a does not select all when disableSelection', () => { @@ -1334,7 +1337,7 @@ describe('', () => { getByTestId('one').focus(); fireEvent.keyDown(getByTestId('one'), { key: 'a', ctrlKey: true }); - expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0); + expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0); }); }); }); diff --git a/packages/material-ui-lab/src/TreeView/TreeView.js b/packages/material-ui-lab/src/TreeView/TreeView.js index 99773af868b86d..f0a72c2e7d3ff7 100644 --- a/packages/material-ui-lab/src/TreeView/TreeView.js +++ b/packages/material-ui-lab/src/TreeView/TreeView.js @@ -94,6 +94,8 @@ const TreeView = React.forwardRef(function TreeView(props, ref) { [expanded], ); + const isExpandable = React.useCallback((id) => nodeMap.current[id]?.expandable, []); + const isSelected = React.useCallback( (id) => (Array.isArray(selected) ? selected.indexOf(id) !== -1 : selected === id), [selected], @@ -315,7 +317,7 @@ const TreeView = React.forwardRef(function TreeView(props, ref) { const map = nodeMap.current[id]; const siblings = getChildren(map.parentId); - const diff = siblings.filter((child) => !isExpanded(child)); + const diff = siblings.filter((child) => isExpandable(child) && !isExpanded(child)); const newExpanded = expanded.concat(diff); @@ -495,9 +497,9 @@ const TreeView = React.forwardRef(function TreeView(props, ref) { * Mapping Helpers */ const registerNode = React.useCallback((node) => { - const { id, index, parentId } = node; + const { id, index, parentId, expandable } = node; - nodeMap.current[id] = { id, index, parentId }; + nodeMap.current[id] = { id, index, parentId, expandable }; }, []); const getNodesToRemove = React.useCallback((id) => { diff --git a/packages/material-ui-lab/src/TreeView/descendants.js b/packages/material-ui-lab/src/TreeView/descendants.js index 1b106335abeeb7..872cfb123c170a 100644 --- a/packages/material-ui-lab/src/TreeView/descendants.js +++ b/packages/material-ui-lab/src/TreeView/descendants.js @@ -1,6 +1,10 @@ import * as React from 'react'; import PropTypes from 'prop-types'; +/** Credit: https://github.com/reach/reach-ui/blob/86a046f54d53b6420e392b3fa56dd991d9d4e458/packages/descendants/README.md + * Modified slightly to suit our purposes. + */ + // To replace with .findIndex() once we stop IE 11 support. function findIndex(array, comp) { for (let i = 0; i < array.length; i += 1) {