From 945f665d80a6913d47a8095354575242f5643785 Mon Sep 17 00:00:00 2001 From: John Coburn Date: Wed, 18 Jan 2023 10:41:31 -0600 Subject: [PATCH] Update eslint to 8.31.0, handle lint (#1941) * update eslint, handle lint * remove effect in useAdvancedSearch hook * remove only * don't use require.context in the jsdom browser * resolve sticky columns story conflict --- .eslintrc | 9 ++- hooks/tests/useClickOutside-test.js | 2 +- lib/Accordion/ExpandAllButton.js | 14 ++-- .../useAdvancedSearch/useAdvancedSearch.js | 18 ++--- .../tests/AdvancedSearch-test.js | 59 +++++++++++++- lib/FocusLink/FocusLink.js | 76 +++++++++---------- lib/Icon/icons.js | 14 +++- lib/List/tests/interactor.js | 8 +- lib/MultiColumnList/stories/CheckboxSelect.js | 2 +- lib/MultiColumnList/tests/interactor.js | 2 - lib/MultiSelection/MultiSelection.js | 7 +- lib/Paneset/PaneResizeContainer.js | 15 ++++ lib/Paneset/tests/PaneResize-test.js | 2 +- lib/Popper/tests/interactor.js | 2 +- lib/TextField/tests/interactor.js | 4 +- package.json | 2 +- util/RootCloseWrapper.js | 6 +- 17 files changed, 165 insertions(+), 77 deletions(-) diff --git a/.eslintrc b/.eslintrc index 3e8e9a6a5..91149fa83 100644 --- a/.eslintrc +++ b/.eslintrc @@ -17,7 +17,14 @@ "max-classes-per-file": "off", "max-len": "off", "no-unused-expressions": "off", - "react/prop-types": "off" + "react/prop-types": "off", + "semi": "off" + } + }, + { + "files": ["lib/**/**"], + "rules": { + "semi": "off" } } ], diff --git a/hooks/tests/useClickOutside-test.js b/hooks/tests/useClickOutside-test.js index 0d3d9c5c5..1aeff6aaa 100644 --- a/hooks/tests/useClickOutside-test.js +++ b/hooks/tests/useClickOutside-test.js @@ -16,7 +16,7 @@ import { mountWithContext } from '../../tests/helpers'; import useClickOutside from '../useClickOutside'; const UseClickOutsideInteractor = interactor(class UseClickOutsideInteractor { - static defaultScope ='#test-component'; + static defaultScope = '#test-component'; clickOutsideElement = clickable('#click-outside-element'); clickInsideElement = clickable('#click-inside-element'); }); diff --git a/lib/Accordion/ExpandAllButton.js b/lib/Accordion/ExpandAllButton.js index 3761fb52b..523b4574c 100644 --- a/lib/Accordion/ExpandAllButton.js +++ b/lib/Accordion/ExpandAllButton.js @@ -25,6 +25,12 @@ const propTypes = { setStatus: PropTypes.func, }; +function handleClick({ accordionStatus, func, setStatus, onToggle }) { + const newState = expandAll(accordionStatus, func); + if (setStatus) setStatus(newState); + if (onToggle) onToggle(newState); +} + const ExpandAllButton = ({ accordionStatus, collapseLabel: collapseLabelProp, @@ -40,17 +46,11 @@ const ExpandAllButton = ({ const func = majorityCollapsed(accordionStatus); - function handleClick() { - const newState = expandAll(accordionStatus, func); - if (setStatus) setStatus(newState); - if (onToggle) onToggle(newState); - } - return ( + + {({ resetRows }) => ( + <> + + + )} + + + ) +} describe('AdvancedSearch', () => { const advancedSearch = new Interactor(); @@ -235,4 +260,36 @@ describe('AdvancedSearch', () => { expect(onCancelSpy.calledOnce).to.be.true; }); }); + + describe('updating initialRowSearch', () => { + beforeEach(async () => { + await mountWithContext( + + ); + }); + + it('renders applicable values', async () => { + await advancedSearch.find(RowInteractor({ index: 0 })).perform(el => { + expect(el.querySelector('[data-test-advanced-search-query]').value).to.equal('try'); + }); + }); + + describe('resetting from the outside', () => { + beforeEach(async () => { + await ButtonInteractor('Reset').click(); + }); + + it('renders updated query values', async () => { + await advancedSearch.find(RowInteractor({ index: 0 })).perform(el => { + expect(el.querySelector('[data-test-advanced-search-query]').value).to.equal('test'); + }); + }); + }) + }) }); diff --git a/lib/FocusLink/FocusLink.js b/lib/FocusLink/FocusLink.js index b05d2bffc..db5860b69 100644 --- a/lib/FocusLink/FocusLink.js +++ b/lib/FocusLink/FocusLink.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback, useRef } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import css from './FocusLink.css'; @@ -18,58 +18,58 @@ const propTypes = { targetNextAfter: PropTypes.element, }; -const FocusLink = (props) => { - // eslint-disable-next-line react/forbid-foreign-prop-types - const [{ target, component, tabIndex, targetNextAfter }, rest] = separateComponentProps(props, FocusLink.propTypes); - - let link = null; - - function focusTarget() { - if (typeof target === 'string') { - let id = target; +function focusTarget(target) { + if (typeof target === 'string') { + let id = target; - if (target.charAt(0) === '#') { - id = target.replace('#', ''); - } + if (target.charAt(0) === '#') { + id = target.replace('#', ''); + } - const tgt = document.getElementById(id); - if (tgt) { - tgt.focus(); - } - } else if (typeof target === 'object') { - props.target.focus(); + const tgt = document.getElementById(id); + if (tgt) { + tgt.focus(); } + } else if (typeof target === 'object') { + target.focus(); } +} - function focusNext() { - let nextFocusable; - if (props.targetNextAfter) { - nextFocusable = getNextFocusable(targetNextAfter, false); - } else { - nextFocusable = getNextFocusable(link, false); - } - nextFocusable.focus(); +function focusNext(targetNextAfter = false, link) { + let nextFocusable; + if (targetNextAfter) { + nextFocusable = getNextFocusable(targetNextAfter, false); + } else { + nextFocusable = getNextFocusable(link.current, false); } + nextFocusable.focus(); +} + +const FocusLink = (props) => { + // eslint-disable-next-line react/forbid-foreign-prop-types + const [{ target, component, tabIndex, targetNextAfter }, rest] = separateComponentProps(props, FocusLink.propTypes); + + let link = useRef(null); - function handleClick(e) { + const handleClick = useCallback((e) => { e.preventDefault(); if (props.target) { - focusTarget(); + focusTarget(target); } else { - focusNext(); + focusNext(targetNextAfter, link); } - } + }, [props.target, targetNextAfter, link, target]) - function handleKeyPress(e) { + const handleKeyDown = useCallback((e) => { e.preventDefault(); if (e.key === 'Enter') { if (props.target) { - focusTarget(); + focusTarget(target); } else { - focusNext(); + focusNext(targetNextAfter, link); } } - } + }, [props.target, targetNextAfter, link, target]) function getClass() { return classNames( @@ -84,11 +84,11 @@ const FocusLink = (props) => { return ( { link = ref; }} + ref={link} role="button" tabIndex={tabIndex || 0} onClick={handleClick} - onKeyPress={handleKeyPress} + onKeyDown={handleKeyDown} className={getClass()} {...rest} > @@ -103,7 +103,7 @@ const FocusLink = (props) => { role="button" tabIndex={tabIndex || 0} onClick={handleClick} - onKeyPress={handleKeyPress} + onKeyDown={handleKeyDown} className={getClass()} {...rest} > diff --git a/lib/Icon/icons.js b/lib/Icon/icons.js index c9b423661..097d463e6 100644 --- a/lib/Icon/icons.js +++ b/lib/Icon/icons.js @@ -9,10 +9,16 @@ import omitProps from '../../util/omitProps'; /** * Import SVG icons */ -const req = require.context('!!react-svg-loader!./icons/', true, /\.svg$/); -const icons = req.keys().reduce((images, path) => Object.assign(images, { - [path.slice(2, path.length - 4)]: req(path).default, -}), {}); +let icons = { default: import('./icons/default.svg') }; +// check to see if we're in the node test browser - this environment doesn't +// use webpack to build, so it will failwhen require.context is executed for whatever reason. +if (!navigator.userAgent.includes('jsdom')) { + const req = require.context('!!react-svg-loader!./icons/', true, /\.svg$/); + icons = req.keys().reduce((images, path) => Object.assign(images, { + [path.slice(2, path.length - 4)]: req(path).default, + }), {}); +} + const SpinnerEllipsis = ({ className, ...rest }) => (
diff --git a/lib/List/tests/interactor.js b/lib/List/tests/interactor.js index 2d596f94a..46e653da3 100644 --- a/lib/List/tests/interactor.js +++ b/lib/List/tests/interactor.js @@ -13,11 +13,11 @@ export default interactor(class ListInteractor { return count(selector); } - hasUL= isPresent('ul'); + hasUL = isPresent('ul'); hasEmptyMessage = isPresent('[class*=isEmptyMessage---]'); emptyMessageText = text('[class*=isEmptyMessage---]'); - hasMarginBottom0Class= hasClass('ul', `${css.marginBottom0}`); - hasBulletedClass= hasClass('ul', `${css.listStyleBullets}`); - hasDefaultClass= hasClass('ul', `${css.listStyleDefault}`); + hasMarginBottom0Class = hasClass('ul', `${css.marginBottom0}`); + hasBulletedClass = hasClass('ul', `${css.listStyleBullets}`); + hasDefaultClass = hasClass('ul', `${css.listStyleDefault}`); itemCount = this.countItems(); }); diff --git a/lib/MultiColumnList/stories/CheckboxSelect.js b/lib/MultiColumnList/stories/CheckboxSelect.js index 375fdeae2..4c0b4f061 100644 --- a/lib/MultiColumnList/stories/CheckboxSelect.js +++ b/lib/MultiColumnList/stories/CheckboxSelect.js @@ -70,7 +70,7 @@ export default class CheckboxSelect extends React.Component { } } - isSelected =({ item }) => ( + isSelected = ({ item }) => ( this.state.allSelected || (this.state.selected.findIndex(s => s.index === item.index) !== -1) ); diff --git a/lib/MultiColumnList/tests/interactor.js b/lib/MultiColumnList/tests/interactor.js index 760223793..625b03373 100644 --- a/lib/MultiColumnList/tests/interactor.js +++ b/lib/MultiColumnList/tests/interactor.js @@ -72,8 +72,6 @@ export default interactor(class MultiColumnListInteractor { listScrollTop = property('[class*=mclScrollable---]', 'scrollTop'); - listScrollTop = property('[class*=mclScrollable---]', 'scrollTop'); - columnsMeasured() { return this.when(() => (this.cell.style && this.cell.style.width !== '')); } diff --git a/lib/MultiSelection/MultiSelection.js b/lib/MultiSelection/MultiSelection.js index 7f775b076..be86cf5f6 100644 --- a/lib/MultiSelection/MultiSelection.js +++ b/lib/MultiSelection/MultiSelection.js @@ -44,7 +44,12 @@ class MultiSelection extends React.Component { asyncFiltering: PropTypes.bool, autoFocus: PropTypes.bool, backspaceDeletes: PropTypes.bool, - dataOptions: PropTypes.arrayOf(PropTypes.any), + dataOptions: PropTypes.arrayOf( + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.object + ]) + ), dirty: PropTypes.bool, disabled: PropTypes.bool, emptyMessage: PropTypes.string, diff --git a/lib/Paneset/PaneResizeContainer.js b/lib/Paneset/PaneResizeContainer.js index 10188cbc7..fd1ef8e8d 100644 --- a/lib/Paneset/PaneResizeContainer.js +++ b/lib/Paneset/PaneResizeContainer.js @@ -1,4 +1,5 @@ import React, { useState, useRef, useEffect, useCallback } from 'react'; +import PropTypes from 'prop-types'; import cloneDeep from 'lodash/cloneDeep'; import isEqual from 'lodash/isEqual'; import insertByClientRect from './insertByClientRect'; @@ -248,4 +249,18 @@ const PaneResizeContainer = ({ isRoot, children, onElementResize, parentElement, return children; }; +PaneResizeContainer.propTypes = { + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]), + isRoot: PropTypes.bool, + onElementResize: PropTypes.func, + parentElement: PropTypes.element, + resizeContainerRef: PropTypes.oneOfType([ + PropTypes.object, + PropTypes.func + ]) +} + export default PaneResizeContainer; diff --git a/lib/Paneset/tests/PaneResize-test.js b/lib/Paneset/tests/PaneResize-test.js index 257b430b7..c7de8d1b3 100644 --- a/lib/Paneset/tests/PaneResize-test.js +++ b/lib/Paneset/tests/PaneResize-test.js @@ -59,7 +59,7 @@ describe('Pane Resizing', () => { const resizeCursor = ResizeCursorInteractor(); beforeEach(async () => { - function resizeCallback() { handleResize = true; } + const resizeCallback = () => { handleResize = true; } await mountWithContext( Content diff --git a/lib/Popper/tests/interactor.js b/lib/Popper/tests/interactor.js index a8168f0bc..b54a7983d 100644 --- a/lib/Popper/tests/interactor.js +++ b/lib/Popper/tests/interactor.js @@ -5,7 +5,7 @@ import { } from '@bigtest/interactor'; export default interactor(class PopperInteractor { - isDisplayAnchor= isPresent('[data-test-popper-anchor]'); + isDisplayAnchor = isPresent('[data-test-popper-anchor]'); isDisplayOverlay = isPresent('[data-test-popper-overlay]'); overlayIsRenderedInPortal = isPresent('#root [data-test-popper-overlay]'); overlayIsVisible = isVisible('[data-test-popper-overlay]'); diff --git a/lib/TextField/tests/interactor.js b/lib/TextField/tests/interactor.js index 1c42eba9e..7e6435b89 100644 --- a/lib/TextField/tests/interactor.js +++ b/lib/TextField/tests/interactor.js @@ -39,9 +39,9 @@ export default interactor(class TextFieldInteractor { label = text('label'); labelRendered = isPresent('label'); endControl = isPresent('[class*=endControls---] span') - endControlsWidth= find('[class*=endControls---]').offsetWidth; + endControlsWidth = find('[class*=endControls---]').offsetWidth; startControl = isPresent('[class*=startControls---] span'); - startControlsWidth= find('[class*=startControls---]').offsetWidth; + startControlsWidth = find('[class*=startControls---]').offsetWidth; inputComputed = computedStyle('input'); inputReadOnly = attribute('input', 'readonly'); inputError = isPresent(errorClass); diff --git a/package.json b/package.json index baca4edc0..d55a65ed7 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "babel-plugin-remove-jsx-attributes": "^0.0.2", "chai": "^4.1.2", "core-js": "^3.6.1", - "eslint": "^7.32.0", + "eslint": "^8.31.0", "faker": "^4.1.0", "file-loader": "^2.0.0", "karma-viewport": "^1.0.4", diff --git a/util/RootCloseWrapper.js b/util/RootCloseWrapper.js index f1eb3da68..91c6a1e0d 100644 --- a/util/RootCloseWrapper.js +++ b/util/RootCloseWrapper.js @@ -18,9 +18,9 @@ const RootCloseWrapper = forwardRef(({ children, onRootClose, disabled }, ref) = }); RootCloseWrapper.propTypes = { - children: PropTypes.node, - disabled: PropTypes.bool, - onRootClose: PropTypes.func, + children: PropTypes.node, // eslint-disable-line react/no-unused-prop-types + disabled: PropTypes.bool, // eslint-disable-line react/no-unused-prop-types + onRootClose: PropTypes.func, // eslint-disable-line react/no-unused-prop-types }; RootCloseWrapper.defaultProps = {