diff --git a/frontend/package.json b/frontend/package.json index ebd3487cea..33fe869394 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,7 +10,7 @@ "@fortawesome/free-solid-svg-icons": "^5.15.1", "@fortawesome/react-fontawesome": "^0.1.11", "@hookform/error-message": "^0.0.5", - "@trussworks/react-uswds": "1.11.0", + "@trussworks/react-uswds": "2.4.1", "@use-it/interval": "^1.0.0", "draft-js": "^0.11.7", "draftjs-to-html": "^0.9.1", diff --git a/frontend/src/components/Accordion.js b/frontend/src/components/Accordion.js new file mode 100644 index 0000000000..e60b2d4640 --- /dev/null +++ b/frontend/src/components/Accordion.js @@ -0,0 +1,122 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; + +export const AccordionItem = ({ + title, + id, + content, + expanded, + className, + handleToggle, + headingSize, +}) => { + const headingClasses = `usa-accordion__heading ${className}`; + const contentClasses = `usa-accordion__content usa-prose ${className}`; + const HeadingSizeTag = `h${headingSize}`; + return ( + <> + + + + + + ); +}; + +AccordionItem.propTypes = { + title: PropTypes.string.isRequired, + content: PropTypes.string.isRequired, + expanded: PropTypes.bool.isRequired, + id: PropTypes.string.isRequired, + className: PropTypes.string, + handleToggle: PropTypes.func, + headingSize: PropTypes.number.isRequired, +}; + +AccordionItem.defaultProps = { + className: '', + handleToggle: () => { }, +}; + +export const Accordion = ({ + bordered, + items, + multiselectable, + headingSize, +}) => { + const [openItems, setOpenState] = useState( + items.filter((i) => !!i.expanded).map((i) => i.id), + ); + + const classes = bordered ? 'usa-accordion usa-accordion--bordered' : 'usa-accordion'; + + const toggleItem = (itemId) => { + const newOpenItems = [...openItems]; + const itemIndex = openItems.indexOf(itemId); + const isMultiselectable = multiselectable; + + if (itemIndex > -1) { + newOpenItems.splice(itemIndex, 1); + } else if (isMultiselectable) { + newOpenItems.push(itemId); + } else { + newOpenItems.splice(0, newOpenItems.length); + newOpenItems.push(itemId); + } + setOpenState(newOpenItems); + }; + + return ( +
+ {items.map((item) => ( + -1} + handleToggle={() => { + toggleItem(item.id); + }} + headingSize={headingSize} + /> + ))} +
+ ); +}; + +Accordion.propTypes = { + bordered: PropTypes.bool, + multiselectable: PropTypes.bool, + items: PropTypes.arrayOf(PropTypes.shape(AccordionItem)).isRequired, + headingSize: PropTypes.number, +}; + +Accordion.defaultProps = { + bordered: false, + multiselectable: false, + headingSize: 2, +}; + +export default Accordion; diff --git a/frontend/src/components/DeleteReportModal.css b/frontend/src/components/DeleteReportModal.css deleted file mode 100644 index 75e4094818..0000000000 --- a/frontend/src/components/DeleteReportModal.css +++ /dev/null @@ -1,26 +0,0 @@ -#deleteDialog div { - border-style: none; - padding: 3px 0px 17px 15px; - margin: 7px 0px 0px 3px; - text-align: left; - line-height: 20px; - font-size: 14px; -} - -#deleteDialog h2 { - font-size: 22px; - margin-top: 20px; - margin-bottom: -10px; -} - -#deleteDialog button { - margin-left: 0px; - margin-right: 14px; - padding: 9px 38px 9px 38px; - font-size: medium; - font-weight: 600; -} - -#deleteDialog .usa-button--secondary { - background-color: #D42240; -} diff --git a/frontend/src/components/DeleteReportModal.js b/frontend/src/components/DeleteReportModal.js deleted file mode 100644 index 25682a3851..0000000000 --- a/frontend/src/components/DeleteReportModal.js +++ /dev/null @@ -1,67 +0,0 @@ -import React, { useCallback, useEffect, useRef } from 'react'; -import PropTypes from 'prop-types'; -import { Button, Modal } from '@trussworks/react-uswds'; - -import { ESCAPE_KEY_CODES } from '../Constants'; -import './DeleteReportModal.css'; - -const DeleteModal = ({ - onDelete, onClose, closeModal, -}) => { - const modalRef = useRef(null); - - const onEscape = useCallback((event) => { - if (ESCAPE_KEY_CODES.includes(event.key)) { - closeModal(); - } - }, [closeModal]); - - useEffect(() => { - document.addEventListener('keydown', onEscape, false); - return () => { - document.removeEventListener('keydown', onEscape, false); - }; - }, [onEscape]); - - useEffect(() => { - const button = modalRef.current.querySelector('button'); - if (button) { - button.focus(); - } - }); - - return ( - - ); -}; - -DeleteModal.propTypes = { - onDelete: PropTypes.func.isRequired, - onClose: PropTypes.func.isRequired, - closeModal: PropTypes.func.isRequired, -}; - -export default DeleteModal; diff --git a/frontend/src/components/ExternalResourceModal.js b/frontend/src/components/ExternalResourceModal.js index 79d68f3f80..c4491aa9e5 100644 --- a/frontend/src/components/ExternalResourceModal.js +++ b/frontend/src/components/ExternalResourceModal.js @@ -1,75 +1,18 @@ -import React, { useCallback, useEffect, useRef } from 'react'; +import React, { useRef } from 'react'; import PropTypes from 'prop-types'; -import { - Button, Modal, Alert, useModal, connectModal, -} from '@trussworks/react-uswds'; - +import { Alert } from '@trussworks/react-uswds'; +import Modal from './Modal'; import { isValidURL, isInternalGovernmentLink } from '../utils'; -const ESCAPE_KEY_CODE = 27; - -const ExternalResourceModal = ({ onOpen, onClose }) => ( - External Resources Disclaimer} - actions={( - <> - - - - - )} - > - - Note: - {' '} - This link is hosted outside of an OHS-led system. - OHS does not have responsibility for external content or - the privacy policies of non-government websites. - - -); - -ExternalResourceModal.propTypes = { - onOpen: PropTypes.func.isRequired, - onClose: PropTypes.func.isRequired, -}; - const ExternalLink = ({ to, children }) => { const modalRef = useRef(null); - const { isOpen, openModal, closeModal } = useModal(); - - const onEscape = useCallback((event) => { - if (event.keyCode === ESCAPE_KEY_CODE) { - closeModal(); - } - }, [closeModal]); - - useEffect(() => { - document.addEventListener('keydown', onEscape, false); - return () => { - document.removeEventListener('keydown', onEscape, false); - }; - }, [onEscape]); - - useEffect(() => { - if (!modalRef.current) return; - - const button = modalRef.current.querySelector('button'); - if (button) { - button.focus(); - } - }); if (!isValidURL(to)) { return to; } - const onClick = () => { - closeModal(); + const openResource = () => { + modalRef.current.toggleModal(false); window.open(to, '_blank'); }; @@ -78,19 +21,28 @@ const ExternalLink = ({ to, children }) => { if (isInternalGovernmentLink(to)) { window.open(to, '_blank'); } else { - openModal(); + modalRef.current.toggleModal(true); } }; - const ConnectModal = connectModal(() => ( - - )); - return ( <> -
- -
+ + + Note: + {' '} + This link is hosted outside of an OHS-led system. + OHS does not have responsibility for external content or + the privacy policies of non-government websites. + + {children} {' '} @@ -103,8 +55,4 @@ ExternalLink.propTypes = { to: PropTypes.string.isRequired, children: PropTypes.node.isRequired, }; - -export { - ExternalResourceModal, - ExternalLink, -}; +export default ExternalLink; diff --git a/frontend/src/components/FileUploader.js b/frontend/src/components/FileUploader.js index 871e7edf16..be4bc32c4c 100644 --- a/frontend/src/components/FileUploader.js +++ b/frontend/src/components/FileUploader.js @@ -5,15 +5,14 @@ // react-dropzone examples all use prop spreading. Disabling the eslint no prop spreading // rules https://github.com/react-dropzone/react-dropzone /* eslint-disable react/jsx-props-no-spreading */ -import React, { useState, useRef, useEffect } from 'react'; +import React, { useState, useRef } from 'react'; import PropTypes from 'prop-types'; import { useDropzone } from 'react-dropzone'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTrash } from '@fortawesome/free-solid-svg-icons'; -import { - Button, Alert, Modal, connectModal, -} from '@trussworks/react-uswds'; +import { Button, Alert } from '@trussworks/react-uswds'; import { uploadFile, deleteFile } from '../fetchers/File'; +import Modal from './Modal'; import './FileUploader.css'; @@ -111,17 +110,17 @@ function Dropzone(props) { Upload Resources {errorMessage - && ( - - This is an error - - )} + && ( + + This is an error + + )} {fileRejections.length > 0 - && ( - - - - )} + && ( + + + + )} ); } @@ -157,71 +156,65 @@ export const getStatus = (status) => { }; const DeleteFileModal = ({ - onFileRemoved, files, index, closeModal, + modalRef, onFileRemoved, files, index, }) => { - const deleteModal = useRef(null); - const onClose = () => { + const onDeleteFile = () => { onFileRemoved(index) - .then(closeModal()); + .then(modalRef.current.toggleModal(false)); }; - useEffect(() => { - deleteModal.current.querySelector('button').focus(); - }); + return ( -
+ <> Delete File} - actions={( - <> - - - - )} + modalRef={modalRef} + onOk={onDeleteFile} + modalId="DeleteFileModal" + title="Delete File" + okButtonText="Delete" + okButtonAriaLabel="This button will permanently delete the file." >

Are you sure you want to delete {' '} - {files[index].originalFileName} + { files[index] ? files[index].originalFileName : null } {' '} ?

This action cannot be undone.

-
+ ); }; DeleteFileModal.propTypes = { + modalRef: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.shape(), + ]).isRequired, onFileRemoved: PropTypes.func.isRequired, - closeModal: PropTypes.func.isRequired, - index: PropTypes.number.isRequired, + index: PropTypes.number, files: PropTypes.arrayOf(PropTypes.object).isRequired, }; -const ConnectedDeleteFileModal = connectModal(DeleteFileModal); +DeleteFileModal.defaultProps = { + index: null, +}; const FileTable = ({ onFileRemoved, files }) => { const [index, setIndex] = useState(null); - const [isOpen, setIsOpen] = useState(false); - const closeModal = () => setIsOpen(false); - + const modalRef = useRef(); const handleDelete = (newIndex) => { setIndex(newIndex); - setIsOpen(true); + modalRef.current.toggleModal(true); }; return (
- @@ -273,7 +266,7 @@ const FileTable = ({ onFileRemoved, files }) => {
{files.length === 0 && ( -

No files uploaded

+

No files uploaded

)}
); diff --git a/frontend/src/components/IdleModal.js b/frontend/src/components/IdleModal.js index 5c25e0deb6..c49e12c448 100644 --- a/frontend/src/components/IdleModal.js +++ b/frontend/src/components/IdleModal.js @@ -4,12 +4,11 @@ milliseconds the logout prop is called. */ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import { useIdleTimer } from 'react-idle-timer'; -import { - Button, Modal, connectModal, useModal, Alert, -} from '@trussworks/react-uswds'; +import { Alert } from '@trussworks/react-uswds'; +import Modal from './Modal'; // list of events to determine activity // https://github.com/SupremeTechnopriest/react-idle-timer#default-events @@ -28,7 +27,7 @@ const EVENTS = [ function IdleModal({ modalTimeout, logoutTimeout, logoutUser }) { const [inactiveTimeout, updateInactiveTimeout] = useState(); - const { isOpen, openModal, closeModal } = useModal(); + const modalRef = useRef(); const modalVisibleTime = logoutTimeout - modalTimeout; const timeoutMinutes = Math.floor(modalVisibleTime / 1000 / 60); @@ -41,28 +40,6 @@ function IdleModal({ modalTimeout, logoutTimeout, logoutUser }) { timeToLogoutMsg = `${timeoutMinutes} minutes`; } - const Connected = connectModal(() => ( - Are you still there?} - actions={( - - )} - > - - You will be automatically logged out due to inactivity in - {' '} - { timeToLogoutMsg } - {' '} - unless you become active again. - - Press any key to continue your session - - - - )); - // Make sure we clean up any timeout functions when this component // is unmounted useEffect(() => function cleanup() { @@ -73,15 +50,15 @@ function IdleModal({ modalTimeout, logoutTimeout, logoutUser }) { const onIdle = () => { const timer = setTimeout(() => { - closeModal(); + modalRef.current.toggleModal(false); logoutUser(true); }, modalVisibleTime); - openModal(); + modalRef.current.toggleModal(true); updateInactiveTimeout(timer); }; const onActive = () => { - closeModal(); + modalRef.current.toggleModal(false); clearTimeout(inactiveTimeout); }; @@ -94,7 +71,22 @@ function IdleModal({ modalTimeout, logoutTimeout, logoutUser }) { }); return ( - + {}} + modalId="IdleReportModal" + title="Are you still there?" + showOkButton={false} + cancelButtonText="Stay logged in" + > + + You will be automatically logged out due to inactivity in + {' '} + {timeToLogoutMsg} + {' '} + unless you become active again. + + ); } diff --git a/frontend/src/components/Modal.css b/frontend/src/components/Modal.css index 5d33eb0e3e..e7d67cb115 100644 --- a/frontend/src/components/Modal.css +++ b/frontend/src/components/Modal.css @@ -1,19 +1,16 @@ -#popup-modal div { - border-style: none; - padding: 3px 0px 17px 15px; - margin: 7px 0px 0px 3px; - text-align: left; - line-height: 1.2; - font-size: 14px; +.popup-modal h2 { + font-family: 'Source Sans Pro Web', 'Helvetica Neue', Helvetica, 'Roboto, Arial', sans-serif; } -#popup-modal h2 { - font-size: 22px; - margin-top: 20px; - margin-bottom: -10px; +.popup-modal .usa-button--secondary { + margin-left: 8px; } -#popup-modal button { +.popup-modal .usa-modal__main { + margin: 0px; +} + +.popup-modal button { margin-left: 0px; margin-right: 14px; padding: 9px 38px 9px 38px; @@ -21,6 +18,6 @@ font-weight: 600; } -#popup-modal .usa-button--secondary { - background-color: #D42240; -} +.popup-modal:not(.show-close-x) .usa-modal__close { + display: none; +} \ No newline at end of file diff --git a/frontend/src/components/Modal.js b/frontend/src/components/Modal.js index cf4114246f..f9238fc0c2 100644 --- a/frontend/src/components/Modal.js +++ b/frontend/src/components/Modal.js @@ -1,68 +1,81 @@ -import React, { useCallback, useEffect, useRef } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import { Button, Modal as TrussWorksModal } from '@trussworks/react-uswds'; -import { ESCAPE_KEY_CODES } from '../Constants'; +import { + Button, Modal as TrussWorksModal, ModalHeading, ModalFooter, ButtonGroup, ModalToggleButton, +} from '@trussworks/react-uswds'; import './Modal.css'; const Modal = ({ - onOk, onClose, closeModal, title, okButtonText, okButtonAriaLabel, children, -}) => { - const modalRef = useRef(null); - - const onEscape = useCallback((event) => { - if (ESCAPE_KEY_CODES.includes(event.key)) { - closeModal(); - } - }, [closeModal]); - - useEffect(() => { - document.addEventListener('keydown', onEscape, false); - return () => { - document.removeEventListener('keydown', onEscape, false); - }; - }, [onEscape]); - - useEffect(() => { - const button = modalRef.current.querySelector('button'); - if (button) { - button.focus(); - } - }); - - return ( - +); Modal.propTypes = { - onOk: PropTypes.func.isRequired, - onClose: PropTypes.func.isRequired, - closeModal: PropTypes.func.isRequired, + modalRef: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.shape(), + ]).isRequired, + modalId: PropTypes.string.isRequired, + onOk: PropTypes.func, title: PropTypes.string.isRequired, - okButtonText: PropTypes.string.isRequired, + okButtonText: PropTypes.string, okButtonAriaLabel: PropTypes.string, + showOkButton: PropTypes.bool, + cancelButtonText: PropTypes.string, + showCloseX: PropTypes.bool, + isLarge: PropTypes.bool, children: PropTypes.node.isRequired, }; Modal.defaultProps = { + onOk: () => { }, okButtonAriaLabel: null, + okButtonText: '', + showCloseX: false, + showOkButton: true, + isLarge: false, + cancelButtonText: 'Cancel', + }; export default Modal; diff --git a/frontend/src/components/__tests__/Accordion.js b/frontend/src/components/__tests__/Accordion.js new file mode 100644 index 0000000000..4728e86de1 --- /dev/null +++ b/frontend/src/components/__tests__/Accordion.js @@ -0,0 +1,375 @@ +import React from 'react'; +import { render, fireEvent } from '@testing-library/react'; +import { Accordion } from '../Accordion'; + +const testItems = [ + { + title: 'First Amendment', + content: ( +

+ Congress shall make no law respecting an establishment of religion, or + prohibiting the free exercise thereof; or abridging the freedom of + speech, or of the press; or the right of the people peaceably to + assemble, and to petition the Government for a redress of grievances. +

+ ), + expanded: false, + id: '123', + }, + { + title: 'Second Amendment', + content: ( + <> +

+ A well regulated Militia, being necessary to the security of a free + State, the right of the people to keep and bear Arms, shall not be + infringed. +

+ {' '} +
    +
  • This is a list item
  • +
  • Another list item
  • +
+ + ), + expanded: false, + id: 'abc', + }, + { + title: 'Third Amendment', + content: ( +

+ No Soldier shall, in time of peace be quartered in any house, without + the consent of the Owner, nor in time of war, but in a manner to be + prescribed by law. +

+ ), + expanded: false, + id: 'def', + }, + { + title: 'Fourth Amendment', + content: ( +

+ The right of the people to be secure in their persons, houses, papers, + and effects, against unreasonable searches and seizures, shall not be + violated, and no Warrants shall issue, but upon probable cause, + supported by Oath or affirmation, and particularly describing the place + to be searched, and the persons or things to be seized. +

+ ), + expanded: false, + id: '456', + }, + { + title: 'Fifth Amendment', + content: ( +

+ No person shall be held to answer for a capital, or otherwise infamous + crime, unless on a presentment or indictment of a Grand Jury, except in + cases arising in the land or naval forces, or in the Militia, when in + actual service in time of War or public danger; nor shall any person be + subject for the same offence to be twice put in jeopardy of life or + limb; nor shall be compelled in any criminal case to be a witness + against himself, nor be deprived of life, liberty, or property, without + due process of law; nor shall private property be taken for public use, + without just compensation. +

+ ), + expanded: false, + id: '789', + }, +]; + +describe('Accordion component', () => { + it('renders without errors', () => { + const { queryByTestId } = render(); + expect(queryByTestId('accordion')).toBeInTheDocument(); + }); + + it('renders a header and content for each item', () => { + const { getByTestId } = render(); + const accordionEl = getByTestId('accordion'); + expect(accordionEl.childElementCount).toBe(testItems.length * 2); + }); + + it('no items are open by default', () => { + const { getByTestId } = render(); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + }); + + describe('when you toggle a closed item', () => { + it('opens', () => { + const { getByTestId, getByText } = render(); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + + fireEvent.click(getByText(testItems[1].title)); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + }); + }); + + describe('when you toggle an open item', () => { + it('closes', () => { + const { getByText, getByTestId } = render(); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + + fireEvent.click(getByText(testItems[0].title)); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + + fireEvent.click(getByText(testItems[0].title)); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + }); + }); + + describe('when multiselectable is false (default behavior)', () => { + it('when an item is opened, clicking a different item closes the previously opened item', () => { + const { getByText, getByTestId } = render(); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + + fireEvent.click(getByText(testItems[3].title)); + fireEvent.click(getByText(testItems[1].title)); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + + fireEvent.click(getByText(testItems[4].title)); + fireEvent.click(getByText(testItems[2].title)); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + }); + }); + + describe('when multiselectable is true', () => { + it('when an item is opened, previously open items remain open', () => { + const { getByText, getByTestId } = render( + , + ); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + + fireEvent.click(getByText(testItems[0].title)); + fireEvent.click(getByText(testItems[1].title)); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + + fireEvent.click(getByText(testItems[0].title)); + fireEvent.click(getByText(testItems[3].title)); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).not.toBeVisible(); + + fireEvent.click(getByText(testItems[2].title)); + fireEvent.click(getByText(testItems[4].title)); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).toBeVisible(); + }); + }); + + describe('with expanded items on mount', () => { + const testExpandedItems = [ + { + title: 'First Amendment', + content: ( +

+ Congress shall make no law respecting an establishment of religion, + or prohibiting the free exercise thereof; or abridging the freedom + of speech, or of the press; or the right of the people peaceably to + assemble, and to petition the Government for a redress of + grievances. +

+ ), + expanded: false, + id: '123', + }, + { + title: 'Second Amendment', + content: ( + <> +

+ A well regulated Militia, being necessary to the security of a + free State, the right of the people to keep and bear Arms, shall + not be infringed. +

+ {' '} +
    +
  • This is a list item
  • +
  • Another list item
  • +
+ + ), + expanded: true, + id: 'abc', + }, + { + title: 'Third Amendment', + content: ( +

+ No Soldier shall, in time of peace be quartered in any house, + without the consent of the Owner, nor in time of war, but in a + manner to be prescribed by law. +

+ ), + expanded: false, + id: 'def', + }, + { + title: 'Fourth Amendment', + content: ( +

+ The right of the people to be secure in their persons, houses, + papers, and effects, against unreasonable searches and seizures, + shall not be violated, and no Warrants shall issue, but upon + probable cause, supported by Oath or affirmation, and particularly + describing the place to be searched, and the persons or things to be + seized. +

+ ), + expanded: true, + id: '456', + }, + { + title: 'Fifth Amendment', + content: ( +

+ No person shall be held to answer for a capital, or otherwise + infamous crime, unless on a presentment or indictment of a Grand + Jury, except in cases arising in the land or naval forces, or in the + Militia, when in actual service in time of War or public danger; nor + shall any person be subject for the same offence to be twice put in + jeopardy of life or limb; nor shall be compelled in any criminal + case to be a witness against himself, nor be deprived of life, + liberty, or property, without due process of law; nor shall private + property be taken for public use, without just compensation. +

+ ), + expanded: true, + id: '789', + }, + ]; + + it('shows the expanded items by default', () => { + const { getByTestId } = render(); + + expect(getByTestId(`accordionItem_${testItems[0].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[1].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[2].id}`)).not.toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[3].id}`)).toBeVisible(); + expect(getByTestId(`accordionItem_${testItems[4].id}`)).toBeVisible(); + }); + }); + + describe('with custom classNames for Accordion Items', () => { + const customTestItems = [ + { + title: 'First Amendment', + content: ( +

+ Congress shall make no law respecting an establishment of religion, + or prohibiting the free exercise thereof; or abridging the freedom + of speech, or of the press; or the right of the people peaceably to + assemble, and to petition the Government for a redress of + grievances. +

+ ), + expanded: false, + id: '123', + className: 'myCustomAccordionItem', + }, + { + title: 'Second Amendment', + content: ( + <> +

+ A well regulated Militia, being necessary to the security of a + free State, the right of the people to keep and bear Arms, shall + not be infringed. +

+ {' '} +
    +
  • This is a list item
  • +
  • Another list item
  • +
+ + ), + expanded: false, + id: 'abc', + }, + { + title: 'Third Amendment', + content: ( +

+ No Soldier shall, in time of peace be quartered in any house, + without the consent of the Owner, nor in time of war, but in a + manner to be prescribed by law. +

+ ), + expanded: false, + id: 'def', + }, + ]; + + it('passes the class onto the given AccordionItem element', () => { + const { getByTestId } = render(); + expect(getByTestId(`accordionItem_${testItems[0].id}`)).toHaveClass( + 'myCustomAccordionItem', + ); + }); + }); +}); diff --git a/frontend/src/components/__tests__/DeleteReportModal.js b/frontend/src/components/__tests__/DeleteReportModal.js deleted file mode 100644 index bfedf09546..0000000000 --- a/frontend/src/components/__tests__/DeleteReportModal.js +++ /dev/null @@ -1,75 +0,0 @@ -import '@testing-library/jest-dom'; -import React from 'react'; -import { - render, screen, -} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { useModal, connectModal, Button } from '@trussworks/react-uswds'; - -import DeleteReportModal from '../DeleteReportModal'; - -const SomeComponent = () => { - const { isOpen, openModal, closeModal } = useModal(); - const ConnectModal = connectModal(DeleteReportModal); - - return ( -
- {}} - onClose={() => {}} - closeModal={closeModal} - isOpen={isOpen} - /> - -
- ); -}; - -describe('DeleteReportModal', () => { - it('shows two buttons', async () => { - // Given a page with a modal - render( {}} - onClose={() => {}} - closeModal={() => {}} - isOpen - />); - // When the modal is triggered - const buttons = await screen.findAllByRole('button'); - - // Then we see our options - expect(buttons.length).toBe(2); - }); - - it('exits when escape key is pressed', async () => { - // Given a page with a modal - render(); - - // When the modal is triggered - const button = await screen.findByText('Open'); - userEvent.click(button); - - const modal = await screen.findByTestId('modal'); - expect(modal).toBeVisible(); - - // And the modal can closeclose the modal via the escape key - userEvent.type(modal, '{esc}', { skipClick: true }); - expect(screen.queryByTestId('modal')).not.toBeTruthy(); - }); - - it('does not escape when any other key is pressed', async () => { - // Given a page with a modal - render(); - - // When the modal is triggered - const button = await screen.findByText('Open'); - userEvent.click(button); - - const modal = await screen.findByTestId('modal'); - expect(modal).toBeVisible(); - - // And the modal can closeclose the modal via the escape key - userEvent.type(modal, '{enter}', { skipClick: true }); - expect(screen.queryByTestId('modal')).toBeTruthy(); - }); -}); diff --git a/frontend/src/components/__tests__/ExternalResourceModal.js b/frontend/src/components/__tests__/ExternalResourceModal.js index 83e8df99aa..59fae7e477 100644 --- a/frontend/src/components/__tests__/ExternalResourceModal.js +++ b/frontend/src/components/__tests__/ExternalResourceModal.js @@ -6,7 +6,7 @@ import { import userEvent from '@testing-library/user-event'; import join from 'url-join'; -import { ExternalLink } from '../ExternalResourceModal'; +import ExternalLink from '../ExternalResourceModal'; import { isExternalURL, isValidURL } from '../../utils'; import { GOVERNMENT_HOSTNAME_EXTENSION } from '../../Constants'; @@ -29,7 +29,8 @@ describe('External Resources', () => { userEvent.click(link); // Then we see the modal - expect(await screen.findByTestId('modal')).toBeVisible(); + const modal = document.querySelector('#ExternalResourceModal'); + expect(modal.firstChild).toHaveClass('is-visible'); }); it('closes modal when cancel button is pressed', async () => { @@ -39,12 +40,15 @@ describe('External Resources', () => { // When the users clicks it userEvent.click(link); - expect(await screen.findByTestId('modal')).toBeVisible(); + let modal = document.querySelector('#ExternalResourceModal'); + expect(modal.firstChild).toHaveClass('is-visible'); // Then the user can make the modal disappear via the cancel button const cancelButton = await screen.findByText('Cancel'); userEvent.click(cancelButton); - expect(screen.queryByTestId('modal')).not.toBeTruthy(); + + modal = document.querySelector('#ExternalResourceModal'); + expect(modal.firstChild).toHaveClass('is-hidden'); }); it('closes modal when escape key is pressed', async () => { @@ -54,16 +58,20 @@ describe('External Resources', () => { // When the users clicks it userEvent.click(link); - const modal = await screen.findByTestId('modal'); - expect(modal).toBeVisible(); + let modal = document.querySelector('#ExternalResourceModal'); + expect(modal.firstChild).toHaveClass('is-visible'); // Then they try to close with delete key - userEvent.type(modal, '{del}', { skipClick: true }); - expect(screen.queryByTestId('modal')).toBeTruthy(); + const modalWindow = await screen.findByRole('heading', { name: /external resources disclaimer/i, hidden: true }); + userEvent.type(modalWindow, '{del}', { skipClick: true }); + + modal = document.querySelector('#ExternalResourceModal'); + expect(modal.firstChild).toHaveClass('is-visible'); // And they can close the modal via the escape key userEvent.type(modal, '{esc}', { skipClick: true }); - expect(screen.queryByTestId('modal')).not.toBeTruthy(); + modal = document.querySelector('#ExternalResourceModal'); + expect(modal.firstChild).toHaveClass('is-hidden'); }); it('shows external link when ok is pressed', async () => { @@ -79,7 +87,8 @@ describe('External Resources', () => { userEvent.click(acceptButton); // Then we hide the modal - expect(screen.queryByTestId('modal')).not.toBeTruthy(); + const modal = document.querySelector('#ExternalResourceModal'); + expect(modal.firstChild).toHaveClass('is-hidden'); // And a new tab has been opened expect(windowSpy).toHaveBeenCalledWith('https://www.google.com', '_blank'); diff --git a/frontend/src/components/__tests__/IdleModal.js b/frontend/src/components/__tests__/IdleModal.js index 73a63c8afb..63309cd738 100644 --- a/frontend/src/components/__tests__/IdleModal.js +++ b/frontend/src/components/__tests__/IdleModal.js @@ -33,7 +33,8 @@ describe('IdleModal', () => { act(() => { jest.advanceTimersByTime(11); }); - expect(screen.getByTestId('modal')).toBeVisible(); + const modal = document.querySelector('#IdleReportModal'); + expect(modal.firstChild).toHaveClass('is-visible'); }); it('logout is called after logoutTimeout milliseconds of inactivity', () => { @@ -63,7 +64,9 @@ describe('IdleModal', () => { renderIdleModal(20, 10, logout); act(() => { jest.advanceTimersByTime(12); - expect(screen.getByTestId('modal')).toBeVisible(); + const modal = document.querySelector('#IdleReportModal'); + expect(modal.firstChild).toHaveClass('is-visible'); + const testDiv = screen.getByTestId('test'); userEvent.type(testDiv, 'test'); }); @@ -76,7 +79,7 @@ describe('IdleModal', () => { renderIdleModal(20, 10); act(() => { jest.advanceTimersByTime(11); - expect(screen.getByRole('alert').textContent).toContain('in less than a minute'); + expect(screen.getByTestId(/alert/i).textContent).toContain('in less than a minute'); }); }); @@ -84,7 +87,7 @@ describe('IdleModal', () => { renderIdleModal(1000 * 60 + 10, 10); act(() => { jest.advanceTimersByTime(11); - expect(screen.getByRole('alert').textContent).toContain('in a minute'); + expect(screen.getByTestId(/alert/i).textContent).toContain('in a minute'); }); }); @@ -92,7 +95,7 @@ describe('IdleModal', () => { renderIdleModal((1000 * 60 * 5) + 10, 10); act(() => { jest.advanceTimersByTime(11); - expect(screen.getByRole('alert').textContent).toContain('in 5 minutes'); + expect(screen.getByTestId(/alert/i).textContent).toContain('in 5 minutes'); }); }); }); diff --git a/frontend/src/components/__tests__/Modal.js b/frontend/src/components/__tests__/Modal.js index 357469f780..08b9bbc878 100644 --- a/frontend/src/components/__tests__/Modal.js +++ b/frontend/src/components/__tests__/Modal.js @@ -1,74 +1,117 @@ +/* eslint-disable react/prop-types */ import '@testing-library/jest-dom'; -import React from 'react'; +import React, { useRef } from 'react'; import { render, screen, } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { useModal, connectModal, Button } from '@trussworks/react-uswds'; +import { ModalToggleButton } from '@trussworks/react-uswds'; import Modal from '../Modal'; -const SomeComponent = () => { - const { isOpen, openModal, closeModal } = useModal(); - const ConnectModal = connectModal(Modal); +const ModalComponent = ( + { + onOk = () => { }, + modalIdValue = 'popup-modal', + title = 'Test Report Modal', + okButtonText = 'Ok', + okButtonAriaLabel = 'This button will ok the modal action.', + showOkButton = true, + cancelButtonText = 'Cancel', + showCloseX = false, + isLarge = false, + }, +) => { + const modalRef = useRef(); return (
- {}} - onClose={() => {}} - closeModal={closeModal} - isOpen={isOpen} - /> - + Open + Close + +
+ Are you sure you want to perform this action? +
+
); }; describe('Modal', () => { - it('shows two buttons', async () => { - // Given a page with a modal - render( {}} - onClose={() => {}} - closeModal={() => {}} - isOpen - />); - // When the modal is triggered - const buttons = await screen.findAllByRole('button'); - - // Then we see our options - expect(buttons.length).toBe(2); + it('renders correctly', async () => { + render(); + expect(await screen.findByRole('heading', { name: /test report modal/i, hidden: true })).toBeVisible(); + expect(await screen.findByText(/are you sure you want to perform this action\?/i)).toBeVisible(); + expect(await screen.findByRole('button', { name: /cancel/i })).toBeVisible(); + expect(await screen.findByRole('button', { name: /this button will ok the modal action\./i })).toBeVisible(); + }); + + it('correctly hides and shows', async () => { + render(); + + // Defaults modal to hidden. + let modalElement = document.querySelector('#popup-modal'); + expect(modalElement.firstChild).toHaveClass('is-hidden'); + + // Open modal. + const button = await screen.findByText('Open'); + userEvent.click(button); + + // Check modal is visible. + modalElement = document.querySelector('#popup-modal'); + expect(modalElement.firstChild).toHaveClass('is-visible'); }); it('exits when escape key is pressed', async () => { - // Given a page with a modal - render(); + render(); - // When the modal is triggered + // Open modal. const button = await screen.findByText('Open'); userEvent.click(button); - const modal = await screen.findByTestId('modal'); - expect(modal).toBeVisible(); + // Modal is visible. + let modalElement = document.querySelector('#popup-modal'); + expect(modalElement.firstChild).toHaveClass('is-visible'); + + // Press ESC. + userEvent.type(modalElement, '{esc}', { skipClick: true }); - // And the modal can closeclose the modal via the escape key - userEvent.type(modal, '{esc}', { skipClick: true }); - expect(screen.queryByTestId('modal')).not.toBeTruthy(); + // Check Modal is hidden. + modalElement = document.querySelector('#popup-modal'); + expect(modalElement.firstChild).toHaveClass('is-hidden'); }); it('does not escape when any other key is pressed', async () => { - // Given a page with a modal - render(); + render(); - // When the modal is triggered + // Open modal. const button = await screen.findByText('Open'); userEvent.click(button); - const modal = await screen.findByTestId('modal'); - expect(modal).toBeVisible(); + // Modal is open. + let modalElement = document.querySelector('#popup-modal'); + expect(modalElement.firstChild).toHaveClass('is-visible'); + + // Press ENTER. + userEvent.type(modalElement, '{enter}', { skipClick: true }); + + // Modal is still open. + modalElement = document.querySelector('#popup-modal'); + expect(modalElement.firstChild).toHaveClass('is-visible'); + }); - // And the modal can close the modal via the escape key - userEvent.type(modal, '{enter}', { skipClick: true }); - expect(screen.queryByTestId('modal')).toBeTruthy(); + it('hides ok button', async () => { + render(); + expect(screen.queryByRole('button', { name: /this button will ok the modal action\./i })).not.toBeInTheDocument(); }); }); diff --git a/frontend/src/pages/ActivityReport/Pages/Review/ReviewItem.js b/frontend/src/pages/ActivityReport/Pages/Review/ReviewItem.js index 22d432b279..7828d2a023 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/ReviewItem.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/ReviewItem.js @@ -4,7 +4,7 @@ import _ from 'lodash'; import { Link } from 'react-router-dom'; import { useFormContext } from 'react-hook-form/dist/index.ie11'; -import { ExternalLink } from '../../../../components/ExternalResourceModal'; +import ExternalLink from '../../../../components/ExternalResourceModal'; import { isValidURL, isExternalURL, isInternalGovernmentLink } from '../../../../utils'; const ReviewItem = ({ diff --git a/frontend/src/pages/ActivityReport/Pages/Review/index.js b/frontend/src/pages/ActivityReport/Pages/Review/index.js index 57ccdee2d9..4fe8be404c 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/index.js @@ -1,15 +1,12 @@ import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; -import { - Accordion, -} from '@trussworks/react-uswds'; import { Helmet } from 'react-helmet'; - import Submitter from './Submitter'; import Approver from './Approver'; import PrintSummary from '../PrintSummary'; import { REPORT_STATUSES } from '../../../../Constants'; import './index.css'; +import { Accordion } from '../../../../components/Accordion'; const ReviewSubmit = ({ onSubmit, @@ -76,6 +73,7 @@ const ReviewSubmit = ({ Review and submit + {!isApprover && ( - + <> + + + )} {isApprover @@ -100,7 +101,9 @@ const ReviewSubmit = ({ formData={formData} isPendingApprover={isPendingApprover} > - + <> + + )} diff --git a/frontend/src/pages/ApprovedActivityReport/index.js b/frontend/src/pages/ApprovedActivityReport/index.js index 6c2215e275..f7a1c03f4c 100644 --- a/frontend/src/pages/ApprovedActivityReport/index.js +++ b/frontend/src/pages/ApprovedActivityReport/index.js @@ -1,7 +1,7 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useRef } from 'react'; import PropTypes from 'prop-types'; import ReactRouterPropTypes from 'react-router-prop-types'; -import { Grid, useModal, connectModal } from '@trussworks/react-uswds'; +import { Grid, ModalToggleButton } from '@trussworks/react-uswds'; import { Redirect } from 'react-router-dom'; import moment from 'moment-timezone'; import { Helmet } from 'react-helmet'; @@ -147,11 +147,10 @@ export default function ApprovedActivityReport({ match, user }) { const [granteeNextSteps, setGranteeNextSteps] = useState([]); const [specialistNextSteps, setSpecialistNextSteps] = useState([]); - const { isOpen, openModal, closeModal } = useModal(); - const ConnectModal = connectModal(Modal); - const [justUnlocked, updatedJustUnlocked] = useState(false); + const modalRef = useRef(); + useEffect(() => { const allowedRegions = allRegionsUserHasPermissionTo(user); @@ -274,7 +273,7 @@ export default function ApprovedActivityReport({ match, user }) { const onUnlock = async () => { await unlockReport(reportId); - closeModal(); + modalRef.current.toggleModal(false); updatedJustUnlocked(true); }; @@ -326,19 +325,16 @@ export default function ApprovedActivityReport({ match, user }) { : null} {navigator && navigator.clipboard - ? + ? : null} - + {user && user.permissions && canUnlockReports(user) - ? + ? Unlock Report : null} - onUnlock()} - onClose={closeModal} - isOpen={isOpen} - openModal={openModal} - closeModal={closeModal} modalId="UnlockReportModal" title="Unlock Activity Report" okButtonText="Unlock" @@ -357,7 +353,7 @@ export default function ApprovedActivityReport({ match, user }) {
must be re-submitted for approval. -
+

TTA activity report diff --git a/frontend/src/pages/Landing/MyAlerts.js b/frontend/src/pages/Landing/MyAlerts.js index 7fb04655de..bb4f14a4e1 100644 --- a/frontend/src/pages/Landing/MyAlerts.js +++ b/frontend/src/pages/Landing/MyAlerts.js @@ -1,12 +1,10 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ -import React, { useState } from 'react'; +import React, { useState, useRef } from 'react'; import PropTypes from 'prop-types'; -import { - Tag, Table, useModal, connectModal, -} from '@trussworks/react-uswds'; +import { Tag, Table } from '@trussworks/react-uswds'; import { Link, useHistory } from 'react-router-dom'; import moment from 'moment'; -import DeleteReportModal from '../../components/DeleteReportModal'; +import Modal from '../../components/Modal'; import Container from '../../components/Container'; import ContextMenu from '../../components/ContextMenu'; import NewReport from './NewReport'; @@ -22,15 +20,15 @@ import Tooltip from '../../components/Tooltip'; function ReportsRow({ reports, removeAlert, message }) { const history = useHistory(); - const { isOpen, openModal, closeModal } = useModal(); - const ConnectModal = connectModal(DeleteReportModal); - const [idToDelete, updateIdToDelete] = useState(0); + const modalRef = useRef(); const onDelete = async (reportId) => { + if (modalRef && modalRef.current) { + modalRef.current.toggleModal(false); + } await deleteReport(reportId); removeAlert(reportId); - closeModal(); }; const tableRows = reports.map((report, index, { length }) => { @@ -75,7 +73,7 @@ function ReportsRow({ reports, removeAlert, message }) { }, { label: 'Delete', - onClick: () => { updateIdToDelete(id); openModal(); }, + onClick: () => { updateIdToDelete(id); modalRef.current.toggleModal(true); }, }, ]; @@ -118,7 +116,7 @@ function ReportsRow({ reports, removeAlert, message }) { buttonLabel={`pending approvals: ${approversToolTipText}. Click button to visually reveal this information.`} /> ) - : '' } + : ''} - onDelete(idToDelete)} - onClose={closeModal} - isOpen={isOpen} - openModal={openModal} - closeModal={closeModal} - /> + onDelete(idToDelete)} + modalId="DeleteReportModal" + title="Delete Activity Report" + okButtonText="Delete" + okButtonAriaLabel="This button will permanently delete the report." + > +
+ Are you sure you want to delete this activity report? +
+ This action + {' '} + cannot + {' '} + be undone. +
+
{tableRows} ); @@ -291,24 +300,6 @@ function MyAlerts(props) { )} - - - {renderTotal( - alertsOffset, - alertsPerPage, - alertsActivePage, - alertReportsCount, - )} - -
diff --git a/frontend/src/pages/Landing/__tests__/MyAlerts.js b/frontend/src/pages/Landing/__tests__/MyAlerts.js index 58666c68e3..c2f66ba9c9 100644 --- a/frontend/src/pages/Landing/__tests__/MyAlerts.js +++ b/frontend/src/pages/Landing/__tests__/MyAlerts.js @@ -232,14 +232,10 @@ describe('My Alerts', () => { const contextMenu = await screen.findAllByTestId('ellipsis-button'); expect(contextMenu).toBeTruthy(); + const button = await screen.findByRole('button', { name: /this button will permanently delete the report\./i, hidden: true }); + await userEvent.click(button); - const button = await screen.findByRole('button', { - name: 'Delete', - }); - - userEvent.click(button); - - const modal = screen.queryByRole('modal'); - expect(modal).not.toBeTruthy(); + const modal = document.querySelector('#DeleteReportModal'); + expect(modal.firstChild).toHaveClass('is-hidden'); }); }); diff --git a/frontend/yarn-audit-known-issues b/frontend/yarn-audit-known-issues index 78ad308d54..81c45a45d5 100644 --- a/frontend/yarn-audit-known-issues +++ b/frontend/yarn-audit-known-issues @@ -6,20 +6,6 @@ {"type":"auditAdvisory","data":{"resolution":{"id":1002401,"path":"react-scripts>webpack-dev-server>yargs>cliui>wrap-ansi>strip-ansi>ansi-regex","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.1.0","paths":["jest-junit>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-scripts>webpack-dev-server>yargs>string-width>strip-ansi>ansi-regex","react-scripts>webpack-dev-server>yargs>cliui>string-width>strip-ansi>ansi-regex","react-scripts>webpack-dev-server>yargs>cliui>wrap-ansi>string-width>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-scripts>webpack-dev-server>yargs>cliui>strip-ansi>ansi-regex"]},{"version":"4.1.0","paths":["react-scripts>webpack-dev-server>yargs>cliui>wrap-ansi>strip-ansi>ansi-regex"]}],"metadata":null,"vulnerable_versions":">2.1.1 <5.0.1","module_name":"ansi-regex","severity":"moderate","github_advisory_id":"GHSA-93q8-gq69-wqmw","cves":["CVE-2021-3807"],"access":"public","patched_versions":">=5.0.1","updated":"2021-09-23T15:45:50.000Z","recommendation":"Upgrade to version 5.0.1 or later","cwe":"CWE-918","found_by":null,"deleted":null,"id":1002401,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3807\n- https://github.com/advisories/GHSA-93q8-gq69-wqmw","created":"2021-10-07T07:31:50.502Z","reported_by":null,"title":" Inefficient Regular Expression Complexity in chalk/ansi-regex","npm_advisory_id":null,"overview":"ansi-regex is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-93q8-gq69-wqmw"}}} {"type":"auditAdvisory","data":{"resolution":{"id":1002423,"path":"react-scripts>@svgr/webpack>@svgr/plugin-svgo>svgo>css-select>nth-check","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"1.0.2","paths":["react-scripts>@svgr/webpack>@svgr/plugin-svgo>svgo>css-select>nth-check","react-scripts>optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-svgo>svgo>css-select>nth-check"]}],"metadata":null,"vulnerable_versions":"<2.0.1","module_name":"nth-check","severity":"moderate","github_advisory_id":"GHSA-rp65-9cf3-cjxr","cves":["CVE-2021-3803"],"access":"public","patched_versions":">=2.0.1","updated":"2021-09-20T20:15:09.000Z","recommendation":"Upgrade to version 2.0.1 or later","cwe":"CWE-1333","found_by":null,"deleted":null,"id":1002423,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3803\n- https://github.com/advisories/GHSA-rp65-9cf3-cjxr","created":"2021-10-07T07:31:50.506Z","reported_by":null,"title":"Inefficient Regular Expression Complexity in nth-check","npm_advisory_id":null,"overview":"nth-check is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-rp65-9cf3-cjxr"}}} {"type":"auditAdvisory","data":{"resolution":{"id":1002423,"path":"react-scripts>optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-svgo>svgo>css-select>nth-check","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"1.0.2","paths":["react-scripts>@svgr/webpack>@svgr/plugin-svgo>svgo>css-select>nth-check","react-scripts>optimize-css-assets-webpack-plugin>cssnano>cssnano-preset-default>postcss-svgo>svgo>css-select>nth-check"]}],"metadata":null,"vulnerable_versions":"<2.0.1","module_name":"nth-check","severity":"moderate","github_advisory_id":"GHSA-rp65-9cf3-cjxr","cves":["CVE-2021-3803"],"access":"public","patched_versions":">=2.0.1","updated":"2021-09-20T20:15:09.000Z","recommendation":"Upgrade to version 2.0.1 or later","cwe":"CWE-1333","found_by":null,"deleted":null,"id":1002423,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3803\n- https://github.com/advisories/GHSA-rp65-9cf3-cjxr","created":"2021-10-07T07:31:50.506Z","reported_by":null,"title":"Inefficient Regular Expression Complexity in nth-check","npm_advisory_id":null,"overview":"nth-check is vulnerable to Inefficient Regular Expression Complexity","url":"https://github.com/advisories/GHSA-rp65-9cf3-cjxr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} -{"type":"auditAdvisory","data":{"resolution":{"id":1002475,"path":"react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.0.1","paths":["react-scripts>webpack>micromatch>snapdragon>base>cache-base>set-value","react-scripts>webpack>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>react-dev-utils>fork-ts-checker-webpack-plugin>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>webpack-dev-server>chokidar>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>@jest/reporters>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>braces>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>set-value","react-scripts>jest>jest-cli>@jest/core>jest-runner>jest-runtime>jest-config>babel-jest>@jest/transform>jest-haste-map>sane>anymatch>micromatch>extglob>expand-brackets>snapdragon>base>cache-base>union-value>set-value"]}],"metadata":null,"vulnerable_versions":"<4.0.1","module_name":"set-value","severity":"high","github_advisory_id":"GHSA-4jqc-8m5r-9rpr","cves":["CVE-2021-23440"],"access":"public","patched_versions":">=4.0.1","updated":"2021-09-13T19:33:19.000Z","recommendation":"Upgrade to version 4.0.1 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002475,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23440\n- https://github.com/advisories/GHSA-4jqc-8m5r-9rpr","created":"2021-10-07T07:31:50.512Z","reported_by":null,"title":"Prototype Pollution in set-value","npm_advisory_id":null,"overview":"This affects the package set-value before 4.0.1. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path parameter are arrays.","url":"https://github.com/advisories/GHSA-4jqc-8m5r-9rpr"}}} {"type":"auditAdvisory","data":{"resolution":{"id":1002487,"path":"react-scripts>react-dev-utils>immer","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"8.0.1","paths":["react-scripts>react-dev-utils>immer"]}],"metadata":null,"vulnerable_versions":"<9.0.6","module_name":"immer","severity":"high","github_advisory_id":"GHSA-c36v-fmgq-m8hx","cves":["CVE-2021-3757"],"access":"public","patched_versions":">=9.0.6","updated":"2021-09-03T20:17:22.000Z","recommendation":"Upgrade to version 9.0.6 or later","cwe":"CWE-915","found_by":null,"deleted":null,"id":1002487,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-3757\n- https://github.com/advisories/GHSA-c36v-fmgq-m8hx","created":"2021-10-07T07:31:50.514Z","reported_by":null,"title":"Prototype Pollution in immer","npm_advisory_id":null,"overview":"immer is vulnerable to Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')","url":"https://github.com/advisories/GHSA-c36v-fmgq-m8hx"}}} {"type":"auditAdvisory","data":{"resolution":{"id":1002492,"path":"react-scripts>react-dev-utils>immer","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"8.0.1","paths":["react-scripts>react-dev-utils>immer"]}],"metadata":null,"vulnerable_versions":"<9.0.6","module_name":"immer","severity":"critical","github_advisory_id":"GHSA-33f9-j839-rf8h","cves":["CVE-2021-23436"],"access":"public","patched_versions":">=9.0.6","updated":"2021-09-02T16:57:32.000Z","recommendation":"Upgrade to version 9.0.6 or later","cwe":"CWE-843","found_by":null,"deleted":null,"id":1002492,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2021-23436\n- https://github.com/advisories/GHSA-33f9-j839-rf8h","created":"2021-10-07T07:31:50.514Z","reported_by":null,"title":"Prototype Pollution in immer","npm_advisory_id":null,"overview":"This affects the package immer before 9.0.6. A type confusion vulnerability can lead to a bypass of CVE-2020-28477 when the user-provided keys used in the path parameter are arrays. In particular, this bypass is possible because the condition (p === \"__proto__\" || p === \"constructor\") in applyPatches_ returns false if p is ['__proto__'] (or ['constructor']). The === operator (strict equality operator) returns false if the operands have different type.","url":"https://github.com/advisories/GHSA-33f9-j839-rf8h"}}} {"type":"auditAdvisory","data":{"resolution":{"id":1002503,"path":"react-js-pagination>tar","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.2.2","paths":["react-js-pagination>tar"]}],"metadata":null,"vulnerable_versions":"<4.4.18","module_name":"tar","severity":"high","github_advisory_id":"GHSA-5955-9wpr-37jh","cves":["CVE-2021-37713"],"access":"public","patched_versions":">=4.4.18","updated":"2021-08-31T16:02:33.000Z","recommendation":"Upgrade to version 4.4.18 or later","cwe":"CWE-22","found_by":null,"deleted":null,"id":1002503,"references":"- https://github.com/npm/node-tar/security/advisories/GHSA-5955-9wpr-37jh\n- https://nvd.nist.gov/vuln/detail/CVE-2021-37713\n- https://github.com/advisories/GHSA-5955-9wpr-37jh","created":"2021-10-07T07:31:50.519Z","reported_by":null,"title":"Arbitrary File Creation/Overwrite on Windows via insufficient relative path sanitization","npm_advisory_id":null,"overview":"### Impact\n\nArbitrary File Creation, Arbitrary File Overwrite, Arbitrary Code Execution\n\nnode-tar aims to guarantee that any file whose location would be outside of the extraction target directory is not extracted. This is, in part, accomplished by sanitizing absolute paths of entries within the archive, skipping archive entries that contain `..` path portions, and resolving the sanitized paths against the extraction target directory.\n\nThis logic was insufficient on Windows systems when extracting tar files that contained a path that was not an absolute path, but specified a drive letter different from the extraction target, such as `C:some\\path`. If the drive letter does not match the extraction target, for example `D:\\extraction\\dir`, then the result of `path.resolve(extractionDirectory, entryPath)` would resolve against the current working directory on the `C:` drive, rather than the extraction target directory.\n\nAdditionally, a `..` portion of the path could occur immediately after the drive letter, such as `C:../foo`, and was not properly sanitized by the logic that checked for `..` within the normalized and split portions of the path.\n\nThis only affects users of `node-tar` on Windows systems.\n\n### Patches\n\n4.4.18 || 5.0.10 || 6.1.9\n\n### Workarounds\n\nThere is no reasonable way to work around this issue without performing the same path normalization procedures that node-tar now does.\n\nUsers are encouraged to upgrade to the latest patched versions of node-tar, rather than attempt to sanitize paths themselves.\n\n### Fix\n\nThe fixed versions strip path roots from all paths prior to being resolved against the extraction target folder, even if such paths are not \"absolute\".\n\nAdditionally, a path starting with a drive letter and then two dots, like `c:../`, would bypass the check for `..` path portions. This is checked properly in the patched versions.\n\nFinally, a defense in depth check is added, such that if the `entry.absolute` is outside of the extraction taret, and we are not in preservePaths:true mode, a warning is raised on that entry, and it is skipped. Currently, it is believed that this check is redundant, but it did catch some oversights in development.\n","url":"https://github.com/advisories/GHSA-5955-9wpr-37jh"}}} diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 7b968a2ff1..efeefd429c 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2082,10 +2082,10 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== -"@trussworks/react-uswds@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@trussworks/react-uswds/-/react-uswds-1.11.0.tgz#f5f01247038792e8fec40c828e32bc78bcc04c95" - integrity sha512-wIFzLM/1aJ0enyt42YFcJRSlEALfRU2qPaVK5955mHmP083l9o2CrnmJDK7La8ebrNxtyhhgrx76K3PwFgRCjQ== +"@trussworks/react-uswds@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@trussworks/react-uswds/-/react-uswds-2.4.1.tgz#62604c86940492564465286c8214ae22a4bb5e2b" + integrity sha512-jjzBV3nVH3ee0UhWJmQr8+5k/bOTQREUWMi0U75dhF6z+kalw20c9yWBA4DlsE6ePu5d55y3ye2Rz7F+4dO+dA== "@turf/area@^6.4.0": version "6.5.0" @@ -3535,7 +3535,7 @@ box-intersect@^1.0.1: bit-twiddle "^1.0.2" typedarray-pool "^1.1.0" -"box-intersect@github:plotly/box-intersect#v1.1.0": +box-intersect@plotly/box-intersect#v1.1.0: version "1.1.0" resolved "https://codeload.github.com/plotly/box-intersect/tar.gz/1c21ef897c37eb69e5c1efeca7087726dd8d6a23" dependencies: @@ -7879,7 +7879,7 @@ incremental-convex-hull@^1.0.1: robust-orientation "^1.1.2" simplicial-complex "^1.0.0" -"incremental-convex-hull@github:plotly/incremental-convex-hull#v1.1.0": +incremental-convex-hull@plotly/incremental-convex-hull#v1.1.0: version "1.1.0" resolved "https://codeload.github.com/plotly/incremental-convex-hull/tar.gz/352d9e73861913695fd4e1a4c6ad79898c0c8268" dependencies: @@ -9983,7 +9983,7 @@ ndarray-extract-contour@^1.0.0: dependencies: typedarray-pool "^1.0.0" -"ndarray-extract-contour@github:plotly/ndarray-extract-contour#v1.1.0": +ndarray-extract-contour@plotly/ndarray-extract-contour#v1.1.0: version "1.1.0" resolved "https://codeload.github.com/plotly/ndarray-extract-contour/tar.gz/0d8ed3a2fee873f08868c35894d608794e8e9d83" dependencies: @@ -9997,7 +9997,7 @@ ndarray-gradient@^1.0.0: cwise-compiler "^1.0.0" dup "^1.0.0" -"ndarray-gradient@github:plotly/ndarray-gradient#v1.1.0": +ndarray-gradient@plotly/ndarray-gradient#v1.1.0: version "1.1.0" resolved "https://codeload.github.com/plotly/ndarray-gradient/tar.gz/c43b0856d77084cfac7c9d96c6ddc73aeddc0bd8" dependencies: @@ -10015,7 +10015,7 @@ ndarray-ops@^1.1.0, ndarray-ops@^1.2.1, ndarray-ops@^1.2.2: dependencies: cwise-compiler "^1.0.0" -"ndarray-ops@github:plotly/ndarray-ops#v1.3.0": +ndarray-ops@plotly/ndarray-ops#v1.3.0: version "1.3.0" resolved "https://codeload.github.com/plotly/ndarray-ops/tar.gz/afac881492696196c9966f77507558737f60c716" @@ -10027,7 +10027,7 @@ ndarray-pack@^1.2.1: cwise-compiler "^1.1.2" ndarray "^1.0.13" -"ndarray-pack@github:plotly/ndarray-pack#v1.3.0": +ndarray-pack@plotly/ndarray-pack#v1.3.0: version "1.3.0" resolved "https://codeload.github.com/plotly/ndarray-pack/tar.gz/b0cd1f835c2b623f860a3dbb0c5709c98b30aea0" dependencies: @@ -10049,7 +10049,7 @@ ndarray-sort@^1.0.0: dependencies: typedarray-pool "^1.0.0" -"ndarray-sort@github:plotly/ndarray-sort#v1.1.0": +ndarray-sort@plotly/ndarray-sort#v1.1.0: version "1.1.0" resolved "https://codeload.github.com/plotly/ndarray-sort/tar.gz/8b3c03c0c58906640a0551505601544c9775a87a" dependencies: @@ -10063,7 +10063,7 @@ ndarray@^1.0.11, ndarray@^1.0.13, ndarray@^1.0.14, ndarray@^1.0.15, ndarray@^1.0 iota-array "^1.0.0" is-buffer "^1.0.2" -"ndarray@github:plotly/ndarray#v1.1.0": +ndarray@plotly/ndarray#v1.1.0: version "1.1.0" resolved "https://codeload.github.com/plotly/ndarray/tar.gz/70ec67233be65de444307a6916aba2655e28bd84" dependencies: @@ -13102,7 +13102,7 @@ robust-determinant@^1.1.0: robust-sum "^1.0.0" two-product "^1.0.0" -"robust-determinant@github:plotly/robust-determinant#v1.2.1": +robust-determinant@plotly/robust-determinant#v1.2.1: version "1.2.1" resolved "https://codeload.github.com/plotly/robust-determinant/tar.gz/7cb499bb02411de80ae1a90e54893e46af82ca5e" dependencies: @@ -13136,7 +13136,7 @@ robust-linear-solve@^1.0.0: dependencies: robust-determinant "^1.1.0" -"robust-linear-solve@github:plotly/robust-linear-solve#v1.1.1": +robust-linear-solve@plotly/robust-linear-solve#v1.1.1: version "1.1.1" resolved "https://codeload.github.com/plotly/robust-linear-solve/tar.gz/90ad6de2ce011a1e0b53d9e9f6bf8d117053c492" dependencies: @@ -13580,7 +13580,7 @@ simplicial-complex-contour@^1.0.2: ndarray-sort "^1.0.0" typedarray-pool "^1.1.0" -"simplicial-complex-contour@github:plotly/simplicial-complex-contour#v1.1.0": +simplicial-complex-contour@plotly/simplicial-complex-contour#v1.1.0: version "1.1.0" resolved "https://codeload.github.com/plotly/simplicial-complex-contour/tar.gz/3c09d0c163385b874fedc0a366b29b6e713bfd99" dependencies: @@ -14203,7 +14203,7 @@ surface-nets@^1.0.0, surface-nets@^1.0.2: triangulate-hypercube "^1.0.0" zero-crossings "^1.0.0" -"surface-nets@github:plotly/surface-nets#v1.1.1": +surface-nets@plotly/surface-nets#v1.1.1: version "1.1.1" resolved "https://codeload.github.com/plotly/surface-nets/tar.gz/d80900ed4c39a1b07f9d8577180960945236d996" dependencies: @@ -15804,6 +15804,6 @@ zero-crossings@^1.0.0: dependencies: cwise-compiler "^1.0.0" -"zero-crossings@github:plotly/zero-crossings#v1.1.0": +zero-crossings@plotly/zero-crossings#v1.1.0: version "1.1.0" resolved "https://codeload.github.com/plotly/zero-crossings/tar.gz/4746771f490344e21c84d1f631cb661d8c5ff508"