diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f89ebeaab..ecb848b7dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,48 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.12.0](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.1...v2.12.0) (2025-02-18) + +**Note:** Version bump only for package pn-frontend + + + + + +# [2.12.0-RC.1](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.0...v2.12.0-RC.1) (2025-02-05) + +**Note:** Version bump only for package pn-frontend + + + + + +# [2.12.0-RC.0](https://github.com/pagopa/pn-frontend/compare/v2.11.1...v2.12.0-RC.0) (2025-02-04) + + +### Bug Fixes + +* **pn-13210:** manage accessibility when closing modal ([#1451](https://github.com/pagopa/pn-frontend/issues/1451)) ([2b4981b](https://github.com/pagopa/pn-frontend/commit/2b4981bddc8f6651ac47bb2cf371f63e33962959)) +* **pn-13211:** Removed redirect when login fails ([#1445](https://github.com/pagopa/pn-frontend/issues/1445)) ([6ff0d2a](https://github.com/pagopa/pn-frontend/commit/6ff0d2aec98f161d5f23e7af49e41c31c7a7dcb7)) +* **pn-13213:** aria label for payments and statistics checkboxes ([#1450](https://github.com/pagopa/pn-frontend/issues/1450)) ([0d4d250](https://github.com/pagopa/pn-frontend/commit/0d4d25007aa3c2012c6bd3cba235cc32e8d65be1)) +* **pn-13214:** inactivity handler accessibility ([#1454](https://github.com/pagopa/pn-frontend/issues/1454)) ([7af07bd](https://github.com/pagopa/pn-frontend/commit/7af07bdc5861815ae484e0856d17f80ec3ac6096)) +* **pn-13216:** Added descriptions to radio buttons ([#1444](https://github.com/pagopa/pn-frontend/issues/1444)) ([9fb7b79](https://github.com/pagopa/pn-frontend/commit/9fb7b79a755c6850d9ec2ffbb62aff60ec88e7a1)) +* **pn-13255:** fixed aria attributes on the modal for revoking the delegation ([#1453](https://github.com/pagopa/pn-frontend/issues/1453)) ([cf2bfd9](https://github.com/pagopa/pn-frontend/commit/cf2bfd9844c412aa7f881a833c2fcaae01650355)) +* **pn-13591:** Handle Calendar for a11y ([#1448](https://github.com/pagopa/pn-frontend/issues/1448)) ([7be12df](https://github.com/pagopa/pn-frontend/commit/7be12dfb572f2eb50e3f857d78174410b1a181ac)) +* **pn-13593:** screen reader doesn't read api key value ([#1449](https://github.com/pagopa/pn-frontend/issues/1449)) ([7b11fb7](https://github.com/pagopa/pn-frontend/commit/7b11fb7ceb22d46bfd4dcea6bcbb6e1a2c3f85ae)) +* **pn-13596:** screen reader doesn't read notification status tooltip on mobile ([#1439](https://github.com/pagopa/pn-frontend/issues/1439)) ([b28f472](https://github.com/pagopa/pn-frontend/commit/b28f47258e5bd3cf4d9a2a3c95b86bfb42114ce8)) +* **pn-13598:** accessibility for the delegation tag group ([#1452](https://github.com/pagopa/pn-frontend/issues/1452)) ([a8626a2](https://github.com/pagopa/pn-frontend/commit/a8626a27ca23f9de030bc0b51d825d685bcee737)) + + +### Features + +* **pn-13215:** Screen reader doesn't read all the attachments in timeline ([#1442](https://github.com/pagopa/pn-frontend/issues/1442)) ([877bf49](https://github.com/pagopa/pn-frontend/commit/877bf49c486485f9e0ce6b04b6423a78824180e8)) +* **pn-13595:** removed automatic redirect before logout ([#1456](https://github.com/pagopa/pn-frontend/issues/1456)) ([c7d823f](https://github.com/pagopa/pn-frontend/commit/c7d823f72e9e64eeeccfcafebb0b05f4b188959c)) + + + + + ## [2.11.1](https://github.com/pagopa/pn-frontend/compare/v2.11.0...v2.11.1) (2025-01-31) **Note:** Version bump only for package pn-frontend diff --git a/lerna.json b/lerna.json index af92cdeea7..d3336a0e5d 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "2.11.1", + "version": "2.12.0", "npmClient": "yarn", "useWorkspaces": true, "command": { diff --git a/packages/pn-commons/CHANGELOG.md b/packages/pn-commons/CHANGELOG.md index cc79cfc7b8..d2a0273333 100644 --- a/packages/pn-commons/CHANGELOG.md +++ b/packages/pn-commons/CHANGELOG.md @@ -3,6 +3,43 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.12.0](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.1...v2.12.0) (2025-02-18) + +**Note:** Version bump only for package @pagopa-pn/pn-commons + + + + + +# [2.12.0-RC.1](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.0...v2.12.0-RC.1) (2025-02-05) + +**Note:** Version bump only for package @pagopa-pn/pn-commons + + + + + +# [2.12.0-RC.0](https://github.com/pagopa/pn-frontend/compare/v2.11.1...v2.12.0-RC.0) (2025-02-04) + + +### Bug Fixes + +* **pn-13210:** manage accessibility when closing modal ([#1451](https://github.com/pagopa/pn-frontend/issues/1451)) ([2b4981b](https://github.com/pagopa/pn-frontend/commit/2b4981bddc8f6651ac47bb2cf371f63e33962959)) +* **pn-13213:** aria label for payments and statistics checkboxes ([#1450](https://github.com/pagopa/pn-frontend/issues/1450)) ([0d4d250](https://github.com/pagopa/pn-frontend/commit/0d4d25007aa3c2012c6bd3cba235cc32e8d65be1)) +* **pn-13214:** inactivity handler accessibility ([#1454](https://github.com/pagopa/pn-frontend/issues/1454)) ([7af07bd](https://github.com/pagopa/pn-frontend/commit/7af07bdc5861815ae484e0856d17f80ec3ac6096)) +* **pn-13591:** Handle Calendar for a11y ([#1448](https://github.com/pagopa/pn-frontend/issues/1448)) ([7be12df](https://github.com/pagopa/pn-frontend/commit/7be12dfb572f2eb50e3f857d78174410b1a181ac)) +* **pn-13596:** screen reader doesn't read notification status tooltip on mobile ([#1439](https://github.com/pagopa/pn-frontend/issues/1439)) ([b28f472](https://github.com/pagopa/pn-frontend/commit/b28f47258e5bd3cf4d9a2a3c95b86bfb42114ce8)) +* **pn-13598:** accessibility for the delegation tag group ([#1452](https://github.com/pagopa/pn-frontend/issues/1452)) ([a8626a2](https://github.com/pagopa/pn-frontend/commit/a8626a27ca23f9de030bc0b51d825d685bcee737)) + + +### Features + +* **pn-13215:** Screen reader doesn't read all the attachments in timeline ([#1442](https://github.com/pagopa/pn-frontend/issues/1442)) ([877bf49](https://github.com/pagopa/pn-frontend/commit/877bf49c486485f9e0ce6b04b6423a78824180e8)) + + + + + ## [2.11.1](https://github.com/pagopa/pn-frontend/compare/v2.11.0...v2.11.1) (2025-01-31) **Note:** Version bump only for package @pagopa-pn/pn-commons diff --git a/packages/pn-commons/package.json b/packages/pn-commons/package.json index 66a0476ba6..c028d32e09 100644 --- a/packages/pn-commons/package.json +++ b/packages/pn-commons/package.json @@ -1,6 +1,6 @@ { "name": "@pagopa-pn/pn-commons", - "version": "2.11.1", + "version": "2.12.0", "private": true, "main": "./src/index.ts", "dependencies": { @@ -65,7 +65,7 @@ "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", "@vitejs/plugin-react": "^4.2.1", - "@vitest/coverage-v8": "^1.3.1", + "@vitest/coverage-v8": "^1.6.1", "css-mediaquery": "^0.1.2", "eslint": "7.11.0", "eslint-config-prettier": "^8.10.0", @@ -78,7 +78,7 @@ "prettier": "^2.8.8", "sonarqube-scanner": "^3.3.0", "vite": "^5.1.4", - "vitest": "1.3.1", + "vitest": "^1.6.1", "vitest-sonar-reporter": "^2.0.0" } } diff --git a/packages/pn-commons/src/components/CustomDatePicker.tsx b/packages/pn-commons/src/components/CustomDatePicker.tsx index 56cf8c4acc..2023f06326 100644 --- a/packages/pn-commons/src/components/CustomDatePicker.tsx +++ b/packages/pn-commons/src/components/CustomDatePicker.tsx @@ -26,11 +26,12 @@ const CustomDatePicker = ( slotProps={{ ...props.slotProps, toolbar: { hidden: true }, - actionBar: { actions: [] }, + actionBar: { actions: ['cancel'] }, layout: { className: 'PnDatePicker' }, // don't remove it! it is used for tests }} closeOnSelect localeText={{ + cancelButtonLabel: getLocalizedOrDefaultLabel('common', 'button.close'), openPreviousView: getLocalizedOrDefaultLabel('common', 'date-picker.left-arrow'), openNextView: getLocalizedOrDefaultLabel('common', 'date-picker.right-arrow'), calendarViewSwitchingButtonAriaLabel: (view) => @@ -47,7 +48,6 @@ const CustomDatePicker = ( return getLocalizedOrDefaultLabel('common', 'date-picker.select-date'); }, }} - data-testid="ciao" /> ); diff --git a/packages/pn-commons/src/components/CustomMobileDialog/CustomMobileDialogContent.tsx b/packages/pn-commons/src/components/CustomMobileDialog/CustomMobileDialogContent.tsx index 64f5092992..81880b03d1 100644 --- a/packages/pn-commons/src/components/CustomMobileDialog/CustomMobileDialogContent.tsx +++ b/packages/pn-commons/src/components/CustomMobileDialog/CustomMobileDialogContent.tsx @@ -1,10 +1,11 @@ import { ReactElement, ReactNode, Ref, forwardRef, useImperativeHandle } from 'react'; import CloseIcon from '@mui/icons-material/Close'; -import { Dialog, DialogTitle, Grid, Slide, Typography } from '@mui/material'; +import { Dialog, DialogTitle, Grid, IconButton, Slide, Typography } from '@mui/material'; import { styled } from '@mui/material/styles'; import { TransitionProps } from '@mui/material/transitions'; +import { getLocalizedOrDefaultLabel } from '../../utility/localization.utility'; import { useCustomMobileDialogContext } from './CustomMobileDialog.context'; type Props = { @@ -82,17 +83,19 @@ const CustomMobileDialogContent = forwardRef<{ toggleOpen: () => void }, Props>( - + aria-label={getLocalizedOrDefaultLabel('common', 'button.close')} + > + + diff --git a/packages/pn-commons/src/components/CustomTagGroup/CustomTagGroup.tsx b/packages/pn-commons/src/components/CustomTagGroup/CustomTagGroup.tsx index 2768e5c66f..89e45c02bf 100644 --- a/packages/pn-commons/src/components/CustomTagGroup/CustomTagGroup.tsx +++ b/packages/pn-commons/src/components/CustomTagGroup/CustomTagGroup.tsx @@ -21,9 +21,15 @@ const TagIndicator: React.FC<{ arrayChildren: Array; visibleItems: number; dataTestId: string; -}> = ({ boxProps, arrayChildren, visibleItems, dataTestId }) => ( - - + ariaLabel?: string; +}> = ({ boxProps, arrayChildren, visibleItems, dataTestId, ariaLabel }) => ( + + ); @@ -50,14 +56,18 @@ const CustomTagGroup: React.FC = ({ onOpen={onOpen} tooltipContent={<>{arrayChildren.slice(visibleItems).map((c) => c)}>} > - + c.props?.children?.props?.value) // + .filter(Boolean) + .join(',')} /> - + )} {disableTooltip && ( diff --git a/packages/pn-commons/src/components/CustomTagGroup/__test__/CustomTagGroup.test.tsx b/packages/pn-commons/src/components/CustomTagGroup/__test__/CustomTagGroup.test.tsx index 182a14ef9e..e878eecc58 100644 --- a/packages/pn-commons/src/components/CustomTagGroup/__test__/CustomTagGroup.test.tsx +++ b/packages/pn-commons/src/components/CustomTagGroup/__test__/CustomTagGroup.test.tsx @@ -1,13 +1,18 @@ import { vi } from 'vitest'; import { Box } from '@mui/material'; +import { Tag } from '@pagopa/mui-italia'; import { fireEvent, render, screen, waitFor } from '../../../test-utils'; import CustomTagGroup from '../CustomTagGroup'; describe('CustomTagGroup component', () => { const tagsArray = ['mock-tag-1', 'mock-tag-2', 'mock-tag-3', 'mock-tag-4']; - const tags = tagsArray.map((v, i) => {v}); + const tags = tagsArray.map((v, i) => ( + + + + )); const mockCallbackFn = vi.fn(); beforeEach(() => { @@ -57,4 +62,15 @@ describe('CustomTagGroup component', () => { expect(tooltip).not.toBeInTheDocument(); expect(mockCallbackFn).toBeCalledTimes(0); }); + + it('renders component with limited 1 tags with aria-label', () => { + const { getByTestId } = render( + + {tags} + + ); + const tooltipIndicator = getByTestId('custom-tooltip-indicator'); + expect(tooltipIndicator).toBeInTheDocument(); + expect(tooltipIndicator).toHaveAttribute('aria-label', 'mock-tag-3,mock-tag-4'); + }); }); diff --git a/packages/pn-commons/src/components/CustomTooltip.tsx b/packages/pn-commons/src/components/CustomTooltip.tsx index 656149e1da..c5d2ab5844 100644 --- a/packages/pn-commons/src/components/CustomTooltip.tsx +++ b/packages/pn-commons/src/components/CustomTooltip.tsx @@ -1,14 +1,10 @@ import { cloneElement, useState } from 'react'; -import { Box, SxProps } from '@mui/material'; -import ClickAwayListener from '@mui/material/ClickAwayListener'; -// ReactNode, cloneElement import Tooltip, { TooltipProps } from '@mui/material/Tooltip'; type Props = { tooltipContent: any; openOnClick: boolean; - sx?: SxProps; onOpen?: () => void; children: JSX.Element; tooltipProps?: Partial; @@ -18,7 +14,6 @@ const CustomTooltip: React.FC = ({ openOnClick, tooltipContent, children, - sx, onOpen, tooltipProps, }) => { @@ -37,27 +32,23 @@ const CustomTooltip: React.FC = ({ }; return ( - - - - {openOnClick ? cloneElement(children, { + + {openOnClick + ? cloneElement(children, { onClick: handleTooltipOpen, - }) : children} - - - + }) + : children} + ); }; diff --git a/packages/pn-commons/src/components/Data/PnTable/PnTableHeaderCell.tsx b/packages/pn-commons/src/components/Data/PnTable/PnTableHeaderCell.tsx index c9d54df47e..6405ae6215 100644 --- a/packages/pn-commons/src/components/Data/PnTable/PnTableHeaderCell.tsx +++ b/packages/pn-commons/src/components/Data/PnTable/PnTableHeaderCell.tsx @@ -49,6 +49,13 @@ const PnTableHeaderCell = ({ direction={sort.orderBy === columnId ? sort.order : 'asc'} onClick={sortHandler(columnId)} data-testid={testId ? `${testId}.sort.${columnId.toString()}` : null} + sx={{ + '&:focus-visible': { + borderRadius: '2px', + outlineOffset: '4px', + outline: '2px solid currentColor' + } + }} > {children} {sort.orderBy === columnId && ( diff --git a/packages/pn-commons/src/components/InactivityHandler.tsx b/packages/pn-commons/src/components/InactivityHandler.tsx index 61c63dc4f6..f6b8c023a8 100644 --- a/packages/pn-commons/src/components/InactivityHandler.tsx +++ b/packages/pn-commons/src/components/InactivityHandler.tsx @@ -1,4 +1,11 @@ -import { Fragment, useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; + +import { Button, DialogContentText, DialogTitle } from '@mui/material'; + +import { getLocalizedOrDefaultLabel } from '../utility/localization.utility'; +import PnDialog from './PnDialog/PnDialog'; +import PnDialogActions from './PnDialog/PnDialogActions'; +import PnDialogContent from './PnDialog/PnDialogContent'; type Props = { /** Inactivity timer (in milliseconds), if 0 the inactivity timer is disabled */ @@ -8,43 +15,66 @@ type Props = { children?: React.ReactNode; }; -const InactivityHandler: React.FC = ({ inactivityTimer, children, onTimerExpired }) => { +const InactivityHandler: React.FC = ({ inactivityTimer, onTimerExpired, children }) => { const [initTimeout, setInitTimeout] = useState(true); - + const [openModal, setOpenModal] = useState(false); const resetTimer = () => setInitTimeout(!initTimeout); - const initListeners = () => { - window.addEventListener('mousemove', resetTimer); - window.addEventListener('scroll', resetTimer); - window.addEventListener('keydown', resetTimer); - }; - - const cleanUpListeners = () => { - window.removeEventListener('mousemove', resetTimer); - window.removeEventListener('scroll', resetTimer); - window.removeEventListener('keydown', resetTimer); - }; - // init timer useEffect(() => { if (inactivityTimer) { - // init listeners - initListeners(); + // this is the timer after wich the inactivity modal is shown + const inactivityWarningTimer = inactivityTimer - 30 * 1000; // init timer const timer = setTimeout(() => { - cleanUpListeners(); onTimerExpired(); }, inactivityTimer); + + const warningTimer = setTimeout(() => { + setOpenModal(true); + }, inactivityWarningTimer); + // cleanup function return () => { + setOpenModal(false); clearTimeout(timer); - cleanUpListeners(); + clearTimeout(warningTimer); }; } return () => {}; }, [initTimeout]); - return {children}; + return ( + <> + + + {getLocalizedOrDefaultLabel('common', 'inactivity.title')} + + + + {getLocalizedOrDefaultLabel('common', 'inactivity.body')} + + + + + {getLocalizedOrDefaultLabel('common', 'inactivity.action')} + + + + {children} + > + ); }; export default InactivityHandler; diff --git a/packages/pn-commons/src/components/NotificationDetail/NotificationDetailTimelineStep.tsx b/packages/pn-commons/src/components/NotificationDetail/NotificationDetailTimelineStep.tsx index 810ed683b4..2aa0ddf51c 100644 --- a/packages/pn-commons/src/components/NotificationDetail/NotificationDetailTimelineStep.tsx +++ b/packages/pn-commons/src/components/NotificationDetail/NotificationDetailTimelineStep.tsx @@ -281,24 +281,22 @@ const NotificationDetailTimelineStep = ({ - {timelineStatusInfos.description} - {s.legalFactsIds && - s.legalFactsIds.length > 0 && - s.legalFactsIds.map((lf) => ( - clickHandler(lf)} - key={lf.key} - data-testid="download-legalfact-micro" - > - {getLegalFactLabel(s, lf.category, lf.key || '')} - - ))} + {timelineStatusInfos.description} + {s.legalFactsIds && + s.legalFactsIds.length > 0 && + s.legalFactsIds.map((lf) => ( + clickHandler(lf)} + disabled={disableDownloads} + key={lf.key} + data-testid="download-legalfact-micro" + > + {getLegalFactLabel(s, lf.category, lf.key || '')} + + ))} } diff --git a/packages/pn-commons/src/components/NotificationDetail/NotificationPaymentPagoPAItem.tsx b/packages/pn-commons/src/components/NotificationDetail/NotificationPaymentPagoPAItem.tsx index e66900025f..7baf350b35 100644 --- a/packages/pn-commons/src/components/NotificationDetail/NotificationPaymentPagoPAItem.tsx +++ b/packages/pn-commons/src/components/NotificationDetail/NotificationPaymentPagoPAItem.tsx @@ -157,6 +157,7 @@ const NotificationPaymentPagoPAStatusElem: React.FC<{ !isSinglePayment && ( { expect(microLegalFacts[counter]).toHaveTextContent( getLegalFactLabel(step, lf.category, lf.key || '') ); - expect(microLegalFacts[counter]).toHaveStyle({ - color: theme.palette.primary.main, - cursor: 'pointer', - }); } + expect(microLegalFacts[counter]).toBeEnabled() counter++; } }); @@ -140,7 +137,7 @@ describe('NotificationDetailTimelineStep', () => { moreLessButton = getByTestId('more-less-timeline-step'); expect(moreLessButton).toHaveTextContent('Show Less'); fireEvent.click(moreLessButton); - expect(eventTrackingCallbackShowMore).toBeCalledTimes(2); + expect(eventTrackingCallbackShowMore).toHaveBeenCalledTimes(2); // After clicking "Show Less", additional steps should be hidden dateItemsMicro = queryAllByTestId('dateItemMicro'); expect(dateItemsMicro).toHaveLength(0); @@ -165,7 +162,7 @@ describe('NotificationDetailTimelineStep', () => { fireEvent.click(btn); // Verify that the clickHandler function is called with the expected arguments expect(mockClickHandler).toHaveBeenCalledTimes(index + 1); - expect(mockClickHandler).toBeCalledWith(legalFacts[index].file); + expect(mockClickHandler).toHaveBeenCalledWith(legalFacts[index].file); }); // expand step const moreLessButton = getByTestId('more-less-timeline-step'); @@ -179,14 +176,14 @@ describe('NotificationDetailTimelineStep', () => { fireEvent.click(microLegalFacts[counter]); // Verify that the clickHandler function is called with the expected arguments expect(mockClickHandler).toHaveBeenCalledTimes(legalFacts.length + counter + 1); - expect(mockClickHandler).toBeCalledWith(lf); + expect(mockClickHandler).toHaveBeenCalledWith(lf); } counter++; } }); }); - it('renders component with disabled donwloads', () => { + it('renders component with disabled downloads', () => { const { getAllByTestId, getByTestId } = render( { fireEvent.click(moreLessButton); const microLegalFacts = getAllByTestId('download-legalfact-micro'); microLegalFacts.forEach((btn) => { - expect(btn).toHaveStyle({ - color: theme.palette.text.disabled, - cursor: 'default', - }); + expect(btn).toBeDisabled(); }); }); diff --git a/packages/pn-commons/src/components/Notifications/StatusTooltip.tsx b/packages/pn-commons/src/components/Notifications/StatusTooltip.tsx index b4804f4308..00193b53b3 100644 --- a/packages/pn-commons/src/components/Notifications/StatusTooltip.tsx +++ b/packages/pn-commons/src/components/Notifications/StatusTooltip.tsx @@ -3,6 +3,7 @@ import { Fragment, ReactNode } from 'react'; import { SxProps, TooltipProps } from '@mui/material'; import Chip from '@mui/material/Chip'; +import { useIsMobile } from '../../hooks'; import CustomTooltip from '../CustomTooltip'; const StatusTooltip = ({ @@ -19,15 +20,20 @@ const StatusTooltip = ({ chipProps?: SxProps; }) => { const tooltipContent = {tooltip}; + const isMobile = useIsMobile(); return ( {label} : label} color={color} - sx={{ ...chipProps, cursor: 'default' }} + sx={{ + ...chipProps, + cursor: 'default', + }} data-testid={`statusChip-${label}`} + aria-label={isMobile ? `${label}: ${tooltip}` : undefined} /> ); diff --git a/packages/pn-commons/src/components/SessionModal.tsx b/packages/pn-commons/src/components/SessionModal.tsx index 2e44d3ffbf..7d7a1b8717 100644 --- a/packages/pn-commons/src/components/SessionModal.tsx +++ b/packages/pn-commons/src/components/SessionModal.tsx @@ -75,7 +75,7 @@ const SessionModal: React.FC = ({ {onConfirm && ( - + {onConfirmLabel} diff --git a/packages/pn-commons/src/components/__test__/InactivityHandler.test.tsx b/packages/pn-commons/src/components/__test__/InactivityHandler.test.tsx index 5db76205b4..bdec93615d 100644 --- a/packages/pn-commons/src/components/__test__/InactivityHandler.test.tsx +++ b/packages/pn-commons/src/components/__test__/InactivityHandler.test.tsx @@ -1,10 +1,10 @@ import { vi } from 'vitest'; -import { fireEvent, render, waitFor } from '../../test-utils'; +import { act, fireEvent, render, within } from '../../test-utils'; import InactivityHandler from '../InactivityHandler'; const timerExpiredHandler = vi.fn(); -const inactivityTimer = 2000; +const inactivityTimer = 60 * 1000; const Component = () => ( @@ -13,31 +13,35 @@ const Component = () => ( ); describe('InactivityHandler Component', () => { + beforeAll(() => { + vi.useFakeTimers(); + }); + beforeEach(() => { vi.resetAllMocks(); vi.clearAllMocks(); }); + afterAll(() => { + vi.useRealTimers(); + }); + it('test inactivity', async () => { // render component - render(); - await waitFor( - () => { - expect(timerExpiredHandler).toBeCalledTimes(1); - }, - { timeout: inactivityTimer + 1000 } - ); + const { container } = render(); + expect(container).toHaveTextContent('Mocked children'); + await act(() => vi.advanceTimersByTime(inactivityTimer)); + expect(timerExpiredHandler).toHaveBeenCalledTimes(1); }); it('test user interaction', async () => { // render component - const result = render(); - fireEvent.mouseMove(result.container); - await waitFor( - () => { - expect(timerExpiredHandler).toBeCalledTimes(0); - }, - { timeout: inactivityTimer + 1000 } - ); + const { getByTestId } = render(); + await act(() => vi.advanceTimersByTime(inactivityTimer - 30 * 1000)); + const inactivityDialog = getByTestId('inactivity-modal'); + expect(inactivityDialog).toBeInTheDocument(); + const inactivityButton = within(inactivityDialog).getByTestId('inactivity-button'); + fireEvent.click(inactivityButton); + expect(timerExpiredHandler).toHaveBeenCalledTimes(0); }); }); diff --git a/packages/pn-data-viz/CHANGELOG.md b/packages/pn-data-viz/CHANGELOG.md index 8a38b5a085..405740a1d2 100644 --- a/packages/pn-data-viz/CHANGELOG.md +++ b/packages/pn-data-viz/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.12.0](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.1...v2.12.0) (2025-02-18) + +**Note:** Version bump only for package @pagopa-pn/pn-data-viz + + + + + +# [2.12.0-RC.1](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.0...v2.12.0-RC.1) (2025-02-05) + +**Note:** Version bump only for package @pagopa-pn/pn-data-viz + + + + + +# [2.12.0-RC.0](https://github.com/pagopa/pn-frontend/compare/v2.11.1...v2.12.0-RC.0) (2025-02-04) + + +### Bug Fixes + +* **pn-13213:** aria label for payments and statistics checkboxes ([#1450](https://github.com/pagopa/pn-frontend/issues/1450)) ([0d4d250](https://github.com/pagopa/pn-frontend/commit/0d4d25007aa3c2012c6bd3cba235cc32e8d65be1)) + + + + + ## [2.11.1](https://github.com/pagopa/pn-frontend/compare/v2.11.0...v2.11.1) (2025-01-31) **Note:** Version bump only for package @pagopa-pn/pn-data-viz diff --git a/packages/pn-data-viz/package.json b/packages/pn-data-viz/package.json index c4ce13cc40..4847c4a06e 100644 --- a/packages/pn-data-viz/package.json +++ b/packages/pn-data-viz/package.json @@ -1,6 +1,6 @@ { "name": "@pagopa-pn/pn-data-viz", - "version": "2.11.1", + "version": "2.12.0", "private": true, "description": "SEND component library for data visualization", "keywords": [ @@ -33,7 +33,7 @@ "eslint-plugin-react-hooks": "^4.3.0", "eslint-plugin-sonarjs": "^0.10.0", "vite": "^5.1.4", - "vitest": "1.3.1", + "vitest": "^1.6.1", "vitest-canvas-mock": "^0.3.3", "vitest-sonar-reporter": "^2.0.0" } diff --git a/packages/pn-data-viz/src/PnEcharts.tsx b/packages/pn-data-viz/src/PnEcharts.tsx index d919cfea49..e6f63e09b1 100644 --- a/packages/pn-data-viz/src/PnEcharts.tsx +++ b/packages/pn-data-viz/src/PnEcharts.tsx @@ -4,15 +4,8 @@ import type { EChartOption, SetOptionOpts } from 'echarts'; import { useEffect, useMemo, useRef } from 'react'; import type { CSSProperties } from 'react'; -import { - Avatar, - Box, - Checkbox, - ListItem, - ListItemAvatar, - ListItemText, - Stack, -} from '@mui/material'; +import CircleIcon from '@mui/icons-material/Circle'; +import { Box, Checkbox, FormControl, FormControlLabel, Stack, Typography } from '@mui/material'; import senderDashboard from './theme/senderDashboard'; @@ -106,28 +99,41 @@ export function PnECharts({ () => legend?.map((item, index) => { const color = option.color?.[index] ?? ''; - const avatarSx = { - bgcolor: color, + const circleSx = { + color, width: 10, height: 10, + mr: 1, }; return ( - - toggleSerie(item)} - defaultChecked - sx={{ - color, - '&.Mui-checked': { - color, - }, - }} + + toggleSerie(item)} + defaultChecked + sx={{ + color, + '&.Mui-checked': { + color, + }, + }} + /> + } + label={ + <> + + + {item} + + > + } /> - - - - - + ); }), [theme] diff --git a/packages/pn-pa-webapp/CHANGELOG.md b/packages/pn-pa-webapp/CHANGELOG.md index 91466f126a..bcc0e4aaa9 100644 --- a/packages/pn-pa-webapp/CHANGELOG.md +++ b/packages/pn-pa-webapp/CHANGELOG.md @@ -3,6 +3,41 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.12.0](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.1...v2.12.0) (2025-02-18) + +**Note:** Version bump only for package @pagopa-pn/pn-pa-webapp + + + + + +# [2.12.0-RC.1](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.0...v2.12.0-RC.1) (2025-02-05) + +**Note:** Version bump only for package @pagopa-pn/pn-pa-webapp + + + + + +# [2.12.0-RC.0](https://github.com/pagopa/pn-frontend/compare/v2.11.1...v2.12.0-RC.0) (2025-02-04) + + +### Bug Fixes + +* **pn-13210:** manage accessibility when closing modal ([#1451](https://github.com/pagopa/pn-frontend/issues/1451)) ([2b4981b](https://github.com/pagopa/pn-frontend/commit/2b4981bddc8f6651ac47bb2cf371f63e33962959)) +* **pn-13214:** inactivity handler accessibility ([#1454](https://github.com/pagopa/pn-frontend/issues/1454)) ([7af07bd](https://github.com/pagopa/pn-frontend/commit/7af07bdc5861815ae484e0856d17f80ec3ac6096)) +* **pn-13593:** screen reader doesn't read api key value ([#1449](https://github.com/pagopa/pn-frontend/issues/1449)) ([7b11fb7](https://github.com/pagopa/pn-frontend/commit/7b11fb7ceb22d46bfd4dcea6bcbb6e1a2c3f85ae)) +* **pn-13596:** screen reader doesn't read notification status tooltip on mobile ([#1439](https://github.com/pagopa/pn-frontend/issues/1439)) ([b28f472](https://github.com/pagopa/pn-frontend/commit/b28f47258e5bd3cf4d9a2a3c95b86bfb42114ce8)) + + +### Features + +* **pn-13595:** removed automatic redirect before logout ([#1456](https://github.com/pagopa/pn-frontend/issues/1456)) ([c7d823f](https://github.com/pagopa/pn-frontend/commit/c7d823f72e9e64eeeccfcafebb0b05f4b188959c)) + + + + + ## [2.11.1](https://github.com/pagopa/pn-frontend/compare/v2.11.0...v2.11.1) (2025-01-31) **Note:** Version bump only for package @pagopa-pn/pn-pa-webapp diff --git a/packages/pn-pa-webapp/openapitools.json b/packages/pn-pa-webapp/openapitools.json index 7090bbdd30..b1bc3635d2 100644 --- a/packages/pn-pa-webapp/openapitools.json +++ b/packages/pn-pa-webapp/openapitools.json @@ -6,7 +6,7 @@ "generators": { "bff-notifications": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-pa-notifications.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-pa-notifications.yaml", "output": "./src/generated-client/notifications", "additionalProperties": { "supportsES6": true, @@ -17,7 +17,7 @@ }, "bff-api-keys": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-pa-apikeys.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-pa-apikeys.yaml", "output": "./src/generated-client/api-keys", "additionalProperties": { "supportsES6": true, @@ -28,7 +28,7 @@ }, "bff-tos-privacy": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-tos-privacy.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-tos-privacy.yaml", "output": "./src/generated-client/tos-privacy", "additionalProperties": { "supportsES6": true, @@ -39,7 +39,7 @@ }, "bff-pa-info": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-pa-info.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-pa-info.yaml", "output": "./src/generated-client/info-pa", "additionalProperties": { "supportsES6": true, @@ -50,7 +50,7 @@ }, "bff-downtime-logs": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-downtime-logs.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-downtime-logs.yaml", "output": "./src/generated-client/downtime-logs", "additionalProperties": { "supportsES6": true, diff --git a/packages/pn-pa-webapp/package.json b/packages/pn-pa-webapp/package.json index a88300b386..06d6d2c76d 100644 --- a/packages/pn-pa-webapp/package.json +++ b/packages/pn-pa-webapp/package.json @@ -1,7 +1,7 @@ { "name": "@pagopa-pn/pn-pa-webapp", "description": "Backoffice di SEND per la Pubblica Amministrazione", - "version": "2.11.1", + "version": "2.12.0", "private": true, "dependencies": { "@emotion/react": "^11.11.1", @@ -77,7 +77,7 @@ "@typescript-eslint/parser": "^6.7.3", "@vitejs/plugin-basic-ssl": "^1.1.0", "@vitejs/plugin-react": "^4.2.1", - "@vitest/coverage-v8": "^1.3.1", + "@vitest/coverage-v8": "^1.6.1", "axios-mock-adapter": "^1.22.0", "eslint": "7.11.0", "eslint-config-prettier": "^8.10.0", @@ -90,7 +90,7 @@ "prettier": "^2.8.8", "sonarqube-scanner": "^3.3.0", "vite": "^5.1.4", - "vitest": "^1.3.1", + "vitest": "^1.6.1", "vitest-canvas-mock": "^0.3.3", "vitest-sonar-reporter": "^2.0.0" } diff --git a/packages/pn-pa-webapp/public/locales/it/apikeys.json b/packages/pn-pa-webapp/public/locales/it/apikeys.json index 5713ef3604..575f73a0e5 100644 --- a/packages/pn-pa-webapp/public/locales/it/apikeys.json +++ b/packages/pn-pa-webapp/public/locales/it/apikeys.json @@ -41,7 +41,7 @@ "status": "Stato" }, "context-menu": { - "title": "Opzioni su API Key", + "title": "Menu azioni su API Key", "enable": "Attiva", "block": "Blocca", "rotate": "Ruota", @@ -86,5 +86,6 @@ "continue-button": "Continua", "required-fields": "Campi obbligatori", "no-groups": "Nessun gruppo disponibile" - } + }, + "api-key-succesfully-deleted": "Chiave pubblica eliminata con successo." } diff --git a/packages/pn-pa-webapp/public/locales/it/common.json b/packages/pn-pa-webapp/public/locales/it/common.json index bbb3fd06bb..8e4271c9f3 100644 --- a/packages/pn-pa-webapp/public/locales/it/common.json +++ b/packages/pn-pa-webapp/public/locales/it/common.json @@ -24,7 +24,8 @@ "logout": "Esci", "pago-pa-link": "Sito di PagoPA S.p.A.", "reserved-area": "Area Riservata", - "notification-platform": "SEND - Servizio Notifiche Digitali" + "notification-platform": "SEND - Servizio Notifiche Digitali", + "logout-message": "Confermi di voler uscire da SEND?" }, "tos": { "title": "SEND - Servizio Notifiche Digitali", @@ -167,5 +168,10 @@ "downtime_language_banner": { "message": "Il testo originario di questi documenti è in lingua italiana. In caso di contrasto tra la versione italiana e le traduzioni in altre lingue, prevarranno il significato e le condizioni della lingua italiana.", "link": "Consulta le traduzioni" + }, + "inactivity": { + "title": "Vuoi davvero uscire da SEND?", + "body": "La disconnessione è in corso. Se hai cambiato idea premi “Mantieni l’accesso” entro pochi secondi.", + "action": "Mantieni l’accesso" } } diff --git a/packages/pn-pa-webapp/src/App.tsx b/packages/pn-pa-webapp/src/App.tsx index 52650e5706..e59f96a376 100644 --- a/packages/pn-pa-webapp/src/App.tsx +++ b/packages/pn-pa-webapp/src/App.tsx @@ -8,13 +8,15 @@ import ErrorIcon from '@mui/icons-material/Error'; import HelpIcon from '@mui/icons-material/Help'; import StatisticsIcon from '@mui/icons-material/ShowChart'; import VpnKey from '@mui/icons-material/VpnKey'; -import { Box } from '@mui/material'; +import { Box, Button, DialogTitle } from '@mui/material'; import { APP_VERSION, AppMessage, AppResponseMessage, Layout, LoadingOverlay, + PnDialog, + PnDialogActions, ResponseEventDispatcher, SideMenu, SideMenuItem, @@ -33,7 +35,6 @@ import { getAdditionalLanguages, getInstitutions, getProductsOfInstitution, - logout, } from './redux/auth/actions'; import { useAppDispatch, useAppSelector } from './redux/hooks'; import { RootState } from './redux/store'; @@ -41,6 +42,7 @@ import { getConfiguration } from './services/configuration.service'; import { PAAppErrorFactory } from './utility/AppError/PAAppErrorFactory'; import './utility/onetrust'; import { getMenuItems } from './utility/role.utility'; +import { goToSelfcareLogin } from './navigation/navigation.utility'; // Cfr. PN-6096 // -------------------- @@ -70,6 +72,7 @@ const ActualApp = () => { // TODO check if it can exist more than one role on user const role = loggedUserOrganizationParty?.roles[0]; const idOrganization = loggedUserOrganizationParty?.id; + const [openModal, setOpenModal] = useState(false); const { tosConsent, privacyConsent } = useAppSelector((state: RootState) => state.userState); const currentStatus = useAppSelector((state: RootState) => state.appStatus.currentStatus); const { SELFCARE_BASE_URL, SELFCARE_SEND_PROD_ID, IS_STATISTICS_ENABLED } = getConfiguration(); @@ -88,21 +91,21 @@ const ActualApp = () => { const productsList = products.length > 0 ? [ - reservedArea, - ...products.map((product) => ({ - ...product, - productUrl: `${product.productUrl}&lang=${i18n.language}`, - })), - ] + reservedArea, + ...products.map((product) => ({ + ...product, + productUrl: `${product.productUrl}&lang=${i18n.language}`, + })), + ] : [ - reservedArea, - { - id: '0', - title: t('header.notification-platform'), - productUrl: '', - linkType: 'internal' as LinkType, - }, - ]; + reservedArea, + { + id: '0', + title: t('header.notification-platform'), + productUrl: '', + linkType: 'internal' as LinkType, + }, + ]; const productId = products.length > 0 ? SELFCARE_SEND_PROD_ID : '0'; const institutionsList = institutions.map((institution) => ({ @@ -200,7 +203,7 @@ const ActualApp = () => { const isPrivacyPage = path[1] === 'privacy-tos'; const handleLogout = () => { - void dispatch(logout()); + setOpenModal(true); }; const handleAssistanceClick = () => { @@ -255,6 +258,31 @@ const ActualApp = () => { onAssistanceClick={handleAssistanceClick} isLogged={!!sessionToken} > + + {t("header.logout-message")} + + setOpenModal(false)} + > + {t("button.annulla")} + + { + sessionStorage.clear(); + goToSelfcareLogin(); + setOpenModal(false); + }} + > + {t("header.logout")} + + + + diff --git a/packages/pn-pa-webapp/src/components/ApiKeys/ApiKeyDataSwitch.tsx b/packages/pn-pa-webapp/src/components/ApiKeys/ApiKeyDataSwitch.tsx index 9b61db645e..a9201f7ebf 100644 --- a/packages/pn-pa-webapp/src/components/ApiKeys/ApiKeyDataSwitch.tsx +++ b/packages/pn-pa-webapp/src/components/ApiKeys/ApiKeyDataSwitch.tsx @@ -2,7 +2,7 @@ import { MouseEvent, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { MoreVert } from '@mui/icons-material'; -import { Box, IconButton, Menu, MenuItem, Typography } from '@mui/material'; +import { Box, IconButton, Menu, MenuItem, Stack, Typography } from '@mui/material'; import { CustomTagGroup, CustomTooltip, @@ -45,6 +45,11 @@ const ApiKeyContextMenu = ({ setAnchorEl(null); }; + const handleModalClickAndClose = (view: ModalApiKeyView) => { + handleClose(); // a11y: force close menu for keyboard navigation + handleModalClick(view, apiKeyId); + }; + return ( @@ -66,12 +71,14 @@ const ApiKeyContextMenu = ({ open={open} onClose={handleClose} onClick={handleClose} - PaperProps={{ - elevation: 0, - sx: { - overflow: 'visible', - filter: 'drop-shadow(0px 2px 8px rgba(0,0,0,0.32))', - mt: 1.5, + slotProps={{ + paper: { + elevation: 0, + sx: { + overflow: 'visible', + filter: 'drop-shadow(0px 2px 8px rgba(0,0,0,0.32))', + mt: 1.5, + }, }, }} transformOrigin={{ horizontal: 'right', vertical: 'top' }} @@ -81,7 +88,7 @@ const ApiKeyContextMenu = ({ handleModalClick(ModalApiKeyView.VIEW, apiKeyId)} + onClick={() => handleModalClickAndClose(ModalApiKeyView.VIEW)} > {t('context-menu.view')} @@ -90,7 +97,7 @@ const ApiKeyContextMenu = ({ handleModalClick(ModalApiKeyView.ROTATE, apiKeyId)} + onClick={() => handleModalClickAndClose(ModalApiKeyView.ROTATE)} > {t('context-menu.rotate')} @@ -99,7 +106,7 @@ const ApiKeyContextMenu = ({ handleModalClick(ModalApiKeyView.BLOCK, apiKeyId)} + onClick={() => handleModalClickAndClose(ModalApiKeyView.BLOCK)} > {t('context-menu.block')} @@ -108,7 +115,7 @@ const ApiKeyContextMenu = ({ handleModalClick(ModalApiKeyView.DELETE, apiKeyId)} + onClick={() => handleModalClickAndClose(ModalApiKeyView.DELETE)} > {t('context-menu.delete')} @@ -117,7 +124,7 @@ const ApiKeyContextMenu = ({ handleModalClick(ModalApiKeyView.ENABLE, apiKeyId)} + onClick={() => handleModalClickAndClose(ModalApiKeyView.ENABLE)} > {t('context-menu.enable')} @@ -126,7 +133,7 @@ const ApiKeyContextMenu = ({ handleModalClick(ModalApiKeyView.VIEW_GROUPS_ID, apiKeyId)} + onClick={() => handleModalClickAndClose(ModalApiKeyView.VIEW_GROUPS_ID)} > {t('context-menu.view-groups-id')} @@ -156,22 +163,31 @@ const ApiKeyDataSwitch: React.FC<{ } if (type === 'value') { return ( - - {`${data.value.substring(0, 10)}...`} + + {data.value} + data.value || ''} /> - + ); } if (type === 'lastUpdate') { diff --git a/packages/pn-pa-webapp/src/components/ApiKeys/DesktopApiKeys.tsx b/packages/pn-pa-webapp/src/components/ApiKeys/DesktopApiKeys.tsx index ede10be398..0bae9f9535 100644 --- a/packages/pn-pa-webapp/src/components/ApiKeys/DesktopApiKeys.tsx +++ b/packages/pn-pa-webapp/src/components/ApiKeys/DesktopApiKeys.tsx @@ -52,13 +52,13 @@ const DesktopApiKeys = ({ apiKeys, handleModalClick }: Props) => { { id: 'name', label: t('table.name'), - cellProps: { width: '30%' }, + cellProps: { width: '20%' }, sortable: false, }, { id: 'value', label: t('table.api-key'), - cellProps: { width: '25%' }, + cellProps: { width: '30%' }, sortable: false, }, { @@ -74,13 +74,13 @@ const DesktopApiKeys = ({ apiKeys, handleModalClick }: Props) => { { id: 'status', label: t('table.status'), - cellProps: { width: '10%', align: 'left' }, + cellProps: { width: '15%' }, sortable: false, // TODO: will be re-enabled in PN-1124 }, { id: 'contextMenu', label: '', - cellProps: { width: '5%', align: 'left' }, + cellProps: { width: '5%' }, sortable: false, }, ]; @@ -88,10 +88,10 @@ const DesktopApiKeys = ({ apiKeys, handleModalClick }: Props) => { return ( <> {apiKeys && apiKeys.length > 0 ? ( - + {columns.map((column) => ( - + {column.label} ))} diff --git a/packages/pn-pa-webapp/src/components/ApiKeys/__test__/ApiKeyDataSwitch.test.tsx b/packages/pn-pa-webapp/src/components/ApiKeys/__test__/ApiKeyDataSwitch.test.tsx index 113da96edd..6da7ef1ed0 100644 --- a/packages/pn-pa-webapp/src/components/ApiKeys/__test__/ApiKeyDataSwitch.test.tsx +++ b/packages/pn-pa-webapp/src/components/ApiKeys/__test__/ApiKeyDataSwitch.test.tsx @@ -31,7 +31,7 @@ describe('ApiKeyDataSwitch Component', () => { const { container, getByTestId } = render( ); - const regexp = new RegExp(`^${data.value.substring(0, 10)}...$`, 'ig'); + const regexp = new RegExp(`^${data.value}`, 'ig'); expect(container).toHaveTextContent(regexp); const clipboard = getByTestId('copyToClipboard'); expect(clipboard).toBeInTheDocument(); @@ -52,11 +52,11 @@ describe('ApiKeyDataSwitch Component', () => { const groupsString = data.groups.length > 3 ? data.groups - .map((group) => group.name) - .splice(0, 3) - .join('') + - '\\+' + - (data.groups.length - 3).toString() + .map((group) => group.name) + .splice(0, 3) + .join('') + + '\\+' + + (data.groups.length - 3).toString() : data.groups.map((group) => group.name).join(''); const regexp = new RegExp(`^${groupsString}$`, 'ig'); expect(container).toHaveTextContent(regexp); diff --git a/packages/pn-pa-webapp/src/navigation/SessionGuard.tsx b/packages/pn-pa-webapp/src/navigation/SessionGuard.tsx index 7a814fe9c7..0d3835afe8 100644 --- a/packages/pn-pa-webapp/src/navigation/SessionGuard.tsx +++ b/packages/pn-pa-webapp/src/navigation/SessionGuard.tsx @@ -54,7 +54,6 @@ const SessionGuardRender = () => { const { isUnauthorizedUser, messageUnauthorizedUser, isClosedSession } = useAppSelector( (state: RootState) => state.userState ); - const dispatch = useAppDispatch(); const { t } = useTranslation(['common']); const { hasApiErrors } = useErrors(); @@ -89,7 +88,10 @@ const SessionGuardRender = () => { ) : ( dispatch(logout())} + onTimerExpired={() => { + sessionStorage.clear(); + goToSelfcareLogin(); + }} > diff --git a/packages/pn-pa-webapp/src/pages/ApiKeys.page.tsx b/packages/pn-pa-webapp/src/pages/ApiKeys.page.tsx index 7175aee367..a263efb7b5 100644 --- a/packages/pn-pa-webapp/src/pages/ApiKeys.page.tsx +++ b/packages/pn-pa-webapp/src/pages/ApiKeys.page.tsx @@ -9,6 +9,7 @@ import { CustomPagination, PaginationData, TitleBox, + appStateActions, calculatePages, useIsMobile, } from '@pagopa-pn/pn-commons'; @@ -146,7 +147,16 @@ const ApiKeys = () => { const apiKeyDeleted = (apiKeyId: string) => { handleCloseModal(); - void dispatch(deleteApiKey(apiKeyId)).then(fetchApiKeys); + void dispatch(deleteApiKey(apiKeyId)) + .then(() => + dispatch( + appStateActions.addSuccess({ + title: '', + message: t('api-key-succesfully-deleted'), + }) + ) + ) + .then(fetchApiKeys); }; // Pagination handlers diff --git a/packages/pn-pa-webapp/src/pages/Statistics.page.tsx b/packages/pn-pa-webapp/src/pages/Statistics.page.tsx index 6599162384..142753f7a5 100644 --- a/packages/pn-pa-webapp/src/pages/Statistics.page.tsx +++ b/packages/pn-pa-webapp/src/pages/Statistics.page.tsx @@ -138,8 +138,11 @@ const Statistics = () => { diff --git a/packages/pn-pa-webapp/src/pages/__test__/ApiKeys.page.test.tsx b/packages/pn-pa-webapp/src/pages/__test__/ApiKeys.page.test.tsx index 72de5048dc..ca8f071d25 100644 --- a/packages/pn-pa-webapp/src/pages/__test__/ApiKeys.page.test.tsx +++ b/packages/pn-pa-webapp/src/pages/__test__/ApiKeys.page.test.tsx @@ -129,8 +129,7 @@ describe('ApiKeys Page', async () => { .reply(200, { ...mockApiKeysDTO, items: mockApiKeysDTO.items.slice(0, 2) }); mock .onGet( - `/bff/v1/api-keys?limit=10&lastKey=${ - mockApiKeysDTO.lastKey + `/bff/v1/api-keys?limit=10&lastKey=${mockApiKeysDTO.lastKey }&lastUpdate=${encodeURIComponent(mockApiKeysDTO.lastUpdate!)}&showVirtualKey=true` ) .reply(200, { ...mockApiKeysDTO, items: mockApiKeysDTO.items.slice(2) }); @@ -143,7 +142,7 @@ describe('ApiKeys Page', async () => { let rows = result.getAllByTestId('tableApiKeys.body.row'); expect(rows).toHaveLength(2); rows.forEach((row, index) => { - expect(row).toHaveTextContent(`${mockApiKeysDTO.items[index].value.substring(0, 10)}...`); + expect(row).toHaveTextContent(`${mockApiKeysDTO.items[index].value}`); }); expect(mock.history.get).toHaveLength(1); // change page @@ -157,7 +156,7 @@ describe('ApiKeys Page', async () => { await waitFor(() => { rows = result.getAllByTestId('tableApiKeys.body.row'); expect(rows).toHaveLength(1); - expect(rows[0]).toHaveTextContent(`${mockApiKeysDTO.items[2].value.substring(0, 10)}...`); + expect(rows[0]).toHaveTextContent(`${mockApiKeysDTO.items[2].value}`); }); // change size const itemsPerPageSelector = result.getByTestId('itemsPerPageSelector'); @@ -172,7 +171,7 @@ describe('ApiKeys Page', async () => { rows = result.getAllByTestId('tableApiKeys.body.row'); expect(rows).toHaveLength(3); rows.forEach((row, index) => { - expect(row).toHaveTextContent(`${mockApiKeysDTO.items[index].value.substring(0, 10)}...`); + expect(row).toHaveTextContent(`${mockApiKeysDTO.items[index].value.substring(0, 10)}`); }); }); }); diff --git a/packages/pn-personafisica-login/CHANGELOG.md b/packages/pn-personafisica-login/CHANGELOG.md index e3191288fc..118fbe071c 100644 --- a/packages/pn-personafisica-login/CHANGELOG.md +++ b/packages/pn-personafisica-login/CHANGELOG.md @@ -3,6 +3,34 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.12.0](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.1...v2.12.0) (2025-02-18) + +**Note:** Version bump only for package @pagopa-pn/pn-personafisica-login + + + + + +# [2.12.0-RC.1](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.0...v2.12.0-RC.1) (2025-02-05) + +**Note:** Version bump only for package @pagopa-pn/pn-personafisica-login + + + + + +# [2.12.0-RC.0](https://github.com/pagopa/pn-frontend/compare/v2.11.1...v2.12.0-RC.0) (2025-02-04) + + +### Bug Fixes + +* **pn-13210:** manage accessibility when closing modal ([#1451](https://github.com/pagopa/pn-frontend/issues/1451)) ([2b4981b](https://github.com/pagopa/pn-frontend/commit/2b4981bddc8f6651ac47bb2cf371f63e33962959)) +* **pn-13211:** Removed redirect when login fails ([#1445](https://github.com/pagopa/pn-frontend/issues/1445)) ([6ff0d2a](https://github.com/pagopa/pn-frontend/commit/6ff0d2aec98f161d5f23e7af49e41c31c7a7dcb7)) + + + + + ## [2.11.1](https://github.com/pagopa/pn-frontend/compare/v2.11.0...v2.11.1) (2025-01-31) **Note:** Version bump only for package @pagopa-pn/pn-personafisica-login diff --git a/packages/pn-personafisica-login/package.json b/packages/pn-personafisica-login/package.json index 1bf7f3b27d..b360778ccc 100644 --- a/packages/pn-personafisica-login/package.json +++ b/packages/pn-personafisica-login/package.json @@ -1,7 +1,7 @@ { "name": "@pagopa-pn/pn-personafisica-login", "description": "Pagina di login di SEND per il cittadino", - "version": "2.11.1", + "version": "2.12.0", "private": true, "homepage": "auth", "dependencies": { @@ -67,7 +67,7 @@ "@typescript-eslint/parser": "^6.7.3", "@vitejs/plugin-basic-ssl": "^1.1.0", "@vitejs/plugin-react": "^4.2.1", - "@vitest/coverage-v8": "^1.3.1", + "@vitest/coverage-v8": "^1.6.1", "eslint": "7.11.0", "eslint-config-prettier": "^8.10.0", "eslint-plugin-functional": "^3.7.2", @@ -79,7 +79,7 @@ "prettier": "^2.8.8", "sonarqube-scanner": "^3.3.0", "vite": "^5.1.4", - "vitest": "^1.3.1", + "vitest": "^1.6.1", "vitest-sonar-reporter": "^2.0.0" } } diff --git a/packages/pn-personafisica-login/src/pages/login/Login.tsx b/packages/pn-personafisica-login/src/pages/login/Login.tsx index acbb2bd839..cf44eed5e0 100644 --- a/packages/pn-personafisica-login/src/pages/login/Login.tsx +++ b/packages/pn-personafisica-login/src/pages/login/Login.tsx @@ -59,10 +59,6 @@ const Login = () => { }); }; - if (showIDPS) { - return setShowIDPS(false)} />; - } - const changeLanguageHandler = async (langCode: string) => { await i18n.changeLanguage(langCode); }; @@ -72,6 +68,10 @@ const Login = () => { window.location.href = `mailto:${PAGOPA_HELP_EMAIL}`; }; + const closeIDPS = () => { + setShowIDPS(false); + }; + return ( { + ); }; diff --git a/packages/pn-personafisica-login/src/pages/login/SpidSelect.tsx b/packages/pn-personafisica-login/src/pages/login/SpidSelect.tsx index 3e71bc7195..44e63dc30f 100644 --- a/packages/pn-personafisica-login/src/pages/login/SpidSelect.tsx +++ b/packages/pn-personafisica-login/src/pages/login/SpidSelect.tsx @@ -1,7 +1,7 @@ import { Trans, useTranslation } from 'react-i18next'; import ClearOutlinedIcon from '@mui/icons-material/ClearOutlined'; -import { IconButton } from '@mui/material'; +import { Dialog, DialogContent, IconButton } from '@mui/material'; import Button from '@mui/material/Button'; import Grid from '@mui/material/Grid'; import Icon from '@mui/material/Icon'; @@ -15,7 +15,7 @@ import { IdentityProvider, getIDPS } from '../../utility/IDPS'; import PFLoginEventStrategyFactory from '../../utility/MixpanelUtils/PFLoginEventStrategyFactory'; import { shuffleList } from '../../utility/utils'; -const SpidSelect = ({ onBack }: { onBack: () => void }) => { +const SpidSelect = ({ show, onClose }: { show: boolean; onClose: () => void }) => { const { URL_API_LOGIN, SPID_TEST_ENV_ENABLED, SPID_VALIDATOR_ENV_ENABLED } = getConfiguration(); const { t } = useTranslation(['login']); const IDPS = getIDPS(SPID_TEST_ENV_ENABLED, SPID_VALIDATOR_ENV_ENABLED); @@ -35,102 +35,108 @@ const SpidSelect = ({ onBack }: { onBack: () => void }) => { }; return ( - - - - - - - - - - - - - - - {t('spidSelect.title')} - - - - - {shuffledIDPS.map((IDP, i) => ( - + + + + + + + - getSPID(IDP)} - sx={{ width: '100px', padding: '0' }} - aria-label={IDP.name} + + + + + + + {t('spidSelect.title')} + + + + + {shuffledIDPS.map((IDP, i) => ( + - - - - - - ))} + getSPID(IDP)} + sx={{ width: '100px', padding: '0' }} + aria-label={IDP.name} + > + + + + + + ))} + + + + + + + {'spidSelect.hintText'} + + + + + {t('spidSelect.cancelButton')} + - - - - - {'spidSelect.hintText'} - - - - - {t('spidSelect.cancelButton')} - - - - + + ); }; diff --git a/packages/pn-personafisica-login/src/pages/login/__test__/Login.test.tsx b/packages/pn-personafisica-login/src/pages/login/__test__/Login.test.tsx index e1d5f820ad..8e44c0c0c9 100644 --- a/packages/pn-personafisica-login/src/pages/login/__test__/Login.test.tsx +++ b/packages/pn-personafisica-login/src/pages/login/__test__/Login.test.tsx @@ -2,7 +2,7 @@ import { BrowserRouter } from 'react-router-dom'; import { vi } from 'vitest'; import { AppRouteParams } from '@pagopa-pn/pn-commons'; -import { getById, queryById } from '@pagopa-pn/pn-commons/src/test-utils'; +import { getById, queryById, waitFor } from '@pagopa-pn/pn-commons/src/test-utils'; import { fireEvent, render } from '../../../__test__/test-utils'; import { getConfiguration } from '../../../services/configuration.service'; @@ -72,7 +72,7 @@ describe('test login page', () => { expect(storageAarOps.read()).toBe('fake-aar-token'); }); - it('select spid login', () => { + it('select spid login', async () => { const { container } = render( @@ -80,7 +80,7 @@ describe('test login page', () => { ); const spidButton = getById(container, 'spidButton'); fireEvent.click(spidButton!); - const spidSelect = getById(container, 'spidSelect'); + const spidSelect = await waitFor(() => document.querySelector('#spidSelect')); expect(spidSelect).toBeInTheDocument(); }); diff --git a/packages/pn-personafisica-login/src/pages/login/__test__/SpidSelect.test.tsx b/packages/pn-personafisica-login/src/pages/login/__test__/SpidSelect.test.tsx index b52dbaf784..7e2ad0ce50 100644 --- a/packages/pn-personafisica-login/src/pages/login/__test__/SpidSelect.test.tsx +++ b/packages/pn-personafisica-login/src/pages/login/__test__/SpidSelect.test.tsx @@ -39,7 +39,8 @@ describe('test spid select page', () => { it('renders page', () => { const { URL_API_LOGIN } = getConfiguration(); - const { container } = render(); + render(); + const container = document.body; expect(container).toHaveTextContent('spidSelect.title'); const backIcon = getById(container, 'backIcon'); expect(backIcon).toBeInTheDocument(); @@ -58,8 +59,9 @@ describe('test spid select page', () => { }); it('clicks on back buttons', () => { - const { container } = render(); - const backIcon = getById(container, 'backIcon'); + render(); + const container = document.body; + const backIcon = getById(document.body, 'backIcon'); fireEvent.click(backIcon); expect(backHandler).toBeCalledTimes(1); const backButton = getById(container, 'backButton'); @@ -68,7 +70,8 @@ describe('test spid select page', () => { }); it('request spid', () => { - const { container } = render(); + render(); + const container = document.body; const requestForSpid = getById(container, 'requestForSpid'); expect(requestForSpid).toHaveAttribute('href', idps.richiediSpid); }); diff --git a/packages/pn-personafisica-login/src/pages/loginError/LoginError.tsx b/packages/pn-personafisica-login/src/pages/loginError/LoginError.tsx index 9f8b83728a..582074a52e 100644 --- a/packages/pn-personafisica-login/src/pages/loginError/LoginError.tsx +++ b/packages/pn-personafisica-login/src/pages/loginError/LoginError.tsx @@ -26,7 +26,6 @@ const LoginError = () => { const navigate = useNavigate(); const [urlSearchParams] = useSearchParams(); const errorCode = urlSearchParams.has('errorCode') ? urlSearchParams.get('errorCode') : null; - const navigationTimeout = process.env.NODE_ENV !== 'test' ? 15000 : 2000; // PN-1989 - per alcune causali di errore, si evita il passaggio transitorio per la pagina di errore // e si fa il redirect verso la pagina di login immediatamente @@ -64,23 +63,12 @@ const LoginError = () => { }; const goToLogin = () => navigate(ROUTE_LOGIN); + // log error useEffect(() => { handleError(window.location.search, errorCode!); }, []); - useEffect(() => { - const timeout = setTimeout(() => { - navigate(ROUTE_LOGIN); - }, navigationTimeout); - - return () => { - if (timeout) { - clearTimeout(timeout); - } - }; - }, []); - return ( diff --git a/packages/pn-personafisica-login/src/pages/loginError/__test__/LoginError.test.tsx b/packages/pn-personafisica-login/src/pages/loginError/__test__/LoginError.test.tsx index 203d03ab97..3ddebaba1f 100644 --- a/packages/pn-personafisica-login/src/pages/loginError/__test__/LoginError.test.tsx +++ b/packages/pn-personafisica-login/src/pages/loginError/__test__/LoginError.test.tsx @@ -1,7 +1,7 @@ import { BrowserRouter } from 'react-router-dom'; import { vi } from 'vitest'; -import { act, getById } from '@pagopa-pn/pn-commons/src/test-utils'; +import { fireEvent, getById, waitFor } from '@pagopa-pn/pn-commons/src/test-utils'; import { render } from '../../../__test__/test-utils'; import { ROUTE_LOGIN } from '../../../navigation/routes.const'; @@ -32,13 +32,14 @@ function mockCreateMockedSearchParams() { return mockedSearchParams; } + describe('LoginError component', () => { afterEach(() => { vi.clearAllMocks(); }); it('login technical error - code generic', async () => { - vi.useFakeTimers(); + spidErrorCode = '2'; render( @@ -49,17 +50,15 @@ describe('LoginError component', () => { expect(errorDialog).toHaveTextContent('loginError.title'); const message = getById(errorDialog, 'message'); expect(message).toHaveTextContent('loginError.message'); - // Wait login redirect - act(() => { - vi.advanceTimersByTime(2000); - }); - expect(mockNavigateFn).toBeCalledTimes(1); - expect(mockNavigateFn).toBeCalledWith(ROUTE_LOGIN); - vi.useRealTimers(); + const buttonRedirect = getById(document.body, 'login-button'); + fireEvent.click(buttonRedirect) + await waitFor(()=>{ + expect(mockNavigateFn).toHaveBeenCalledTimes(1); + expect(mockNavigateFn).toHaveBeenCalledWith(ROUTE_LOGIN); + }) }); it('login too many retry error - code 19', async () => { - vi.useFakeTimers(); spidErrorCode = '19'; render( @@ -71,17 +70,9 @@ describe('LoginError component', () => { expect(errorDialog).toHaveTextContent('loginError.title'); const message = getById(errorDialog, 'message'); expect(message).toHaveTextContent('loginError.code.error_19'); - // Wait login redirect - act(() => { - vi.advanceTimersByTime(2000); - }); - expect(mockNavigateFn).toBeCalledTimes(1); - expect(mockNavigateFn).toBeCalledWith(ROUTE_LOGIN); - vi.useRealTimers(); }); it('login two authentication factor error - code 20', async () => { - vi.useFakeTimers(); spidErrorCode = '20'; render( @@ -93,17 +84,9 @@ describe('LoginError component', () => { expect(errorDialog).toHaveTextContent('loginError.title'); const message = getById(errorDialog, 'message'); expect(message).toHaveTextContent('loginError.code.error_20'); - // Wait login redirect - act(() => { - vi.advanceTimersByTime(2000); - }); - expect(mockNavigateFn).toBeCalledTimes(1); - expect(mockNavigateFn).toBeCalledWith(ROUTE_LOGIN); - vi.useRealTimers(); }); it('login waiting for too long error - code 21', async () => { - vi.useFakeTimers(); spidErrorCode = '21'; render( @@ -115,17 +98,9 @@ describe('LoginError component', () => { expect(errorDialog).toHaveTextContent('loginError.title'); const message = getById(errorDialog, 'message'); expect(message).toHaveTextContent('loginError.code.error_21'); - // Wait login redirect - act(() => { - vi.advanceTimersByTime(2000); - }); - expect(mockNavigateFn).toBeCalledTimes(1); - expect(mockNavigateFn).toBeCalledWith(ROUTE_LOGIN); - vi.useRealTimers(); }); it('login consent necessary error - code 22', async () => { - vi.useFakeTimers(); spidErrorCode = '22'; render( @@ -137,17 +112,10 @@ describe('LoginError component', () => { expect(errorDialog).toHaveTextContent('loginError.title'); const message = getById(errorDialog, 'message'); expect(message).toHaveTextContent('loginError.code.error_22'); - // Wait login redirect - act(() => { - vi.advanceTimersByTime(2000); - }); - expect(mockNavigateFn).toBeCalledTimes(1); - expect(mockNavigateFn).toBeCalledWith(ROUTE_LOGIN); - vi.useRealTimers(); + }); it('login spid identity rewoked or suspended error - code 23', async () => { - vi.useFakeTimers(); spidErrorCode = '23'; render( @@ -159,17 +127,10 @@ describe('LoginError component', () => { expect(errorDialog).toHaveTextContent('loginError.title'); const message = getById(errorDialog, 'message'); expect(message).toHaveTextContent('loginError.code.error_23'); - // Wait login redirect - act(() => { - vi.advanceTimersByTime(2000); - }); - expect(mockNavigateFn).toBeCalledTimes(1); - expect(mockNavigateFn).toBeCalledWith(ROUTE_LOGIN); - vi.useRealTimers(); + }); it('user cancelled the login - code 25', async () => { - vi.useFakeTimers(); spidErrorCode = '25'; render( @@ -181,17 +142,10 @@ describe('LoginError component', () => { expect(errorDialog).toHaveTextContent('loginError.title'); const message = getById(errorDialog, 'message'); expect(message).toHaveTextContent('loginError.code.error_25'); - // Wait login redirect - act(() => { - vi.advanceTimersByTime(2000); - }); - expect(mockNavigateFn).toBeCalledTimes(1); - expect(mockNavigateFn).toBeCalledWith(ROUTE_LOGIN); - vi.useRealTimers(); + }); it('user used a different spid type - code 30', async () => { - vi.useFakeTimers(); spidErrorCode = '30'; render( @@ -203,17 +157,10 @@ describe('LoginError component', () => { expect(errorDialog).toHaveTextContent('loginError.title'); const message = getById(errorDialog, 'message'); expect(message).toHaveTextContent('loginError.code.error_30'); - // Wait login redirect - act(() => { - vi.advanceTimersByTime(2000); - }); - expect(mockNavigateFn).toBeCalledTimes(1); - expect(mockNavigateFn).toBeCalledWith(ROUTE_LOGIN); - vi.useRealTimers(); + }); it("user doesn't have the minimum required age - code 1001", async () => { - vi.useFakeTimers(); spidErrorCode = '1001'; render( @@ -225,12 +172,6 @@ describe('LoginError component', () => { expect(errorDialog).toHaveTextContent('loginError.title'); const message = getById(errorDialog, 'message'); expect(message).toHaveTextContent('loginError.code.error_1001'); - // Wait login redirect - act(() => { - vi.advanceTimersByTime(2000); - }); - expect(mockNavigateFn).toBeCalledTimes(1); - expect(mockNavigateFn).toBeCalledWith(ROUTE_LOGIN); - vi.useRealTimers(); + }); }); diff --git a/packages/pn-personafisica-webapp/CHANGELOG.md b/packages/pn-personafisica-webapp/CHANGELOG.md index 696ffb393a..b7a23b39db 100644 --- a/packages/pn-personafisica-webapp/CHANGELOG.md +++ b/packages/pn-personafisica-webapp/CHANGELOG.md @@ -3,6 +3,42 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.12.0](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.1...v2.12.0) (2025-02-18) + +**Note:** Version bump only for package @pagopa-pn/pn-personafisica-webapp + + + + + +# [2.12.0-RC.1](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.0...v2.12.0-RC.1) (2025-02-05) + +**Note:** Version bump only for package @pagopa-pn/pn-personafisica-webapp + + + + + +# [2.12.0-RC.0](https://github.com/pagopa/pn-frontend/compare/v2.11.1...v2.12.0-RC.0) (2025-02-04) + + +### Bug Fixes + +* **pn-13210:** manage accessibility when closing modal ([#1451](https://github.com/pagopa/pn-frontend/issues/1451)) ([2b4981b](https://github.com/pagopa/pn-frontend/commit/2b4981bddc8f6651ac47bb2cf371f63e33962959)) +* **pn-13214:** inactivity handler accessibility ([#1454](https://github.com/pagopa/pn-frontend/issues/1454)) ([7af07bd](https://github.com/pagopa/pn-frontend/commit/7af07bdc5861815ae484e0856d17f80ec3ac6096)) +* **pn-13216:** Added descriptions to radio buttons ([#1444](https://github.com/pagopa/pn-frontend/issues/1444)) ([9fb7b79](https://github.com/pagopa/pn-frontend/commit/9fb7b79a755c6850d9ec2ffbb62aff60ec88e7a1)) +* **pn-13255:** fixed aria attributes on the modal for revoking the delegation ([#1453](https://github.com/pagopa/pn-frontend/issues/1453)) ([cf2bfd9](https://github.com/pagopa/pn-frontend/commit/cf2bfd9844c412aa7f881a833c2fcaae01650355)) +* **pn-13598:** accessibility for the delegation tag group ([#1452](https://github.com/pagopa/pn-frontend/issues/1452)) ([a8626a2](https://github.com/pagopa/pn-frontend/commit/a8626a27ca23f9de030bc0b51d825d685bcee737)) + + +### Features + +* **pn-13595:** removed automatic redirect before logout ([#1456](https://github.com/pagopa/pn-frontend/issues/1456)) ([c7d823f](https://github.com/pagopa/pn-frontend/commit/c7d823f72e9e64eeeccfcafebb0b05f4b188959c)) + + + + + ## [2.11.1](https://github.com/pagopa/pn-frontend/compare/v2.11.0...v2.11.1) (2025-01-31) **Note:** Version bump only for package @pagopa-pn/pn-personafisica-webapp diff --git a/packages/pn-personafisica-webapp/openapitools.json b/packages/pn-personafisica-webapp/openapitools.json index 530927ec6d..f975ab3ed8 100644 --- a/packages/pn-personafisica-webapp/openapitools.json +++ b/packages/pn-personafisica-webapp/openapitools.json @@ -6,7 +6,7 @@ "generators": { "bff-notifications": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-recipient-notifications.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-recipient-notifications.yaml", "output": "./src/generated-client/notifications", "additionalProperties": { "supportsES6": true, @@ -17,7 +17,7 @@ }, "bff-tos-privacy": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-tos-privacy.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-tos-privacy.yaml", "output": "./src/generated-client/tos-privacy", "additionalProperties": { "supportsES6": true, @@ -28,7 +28,7 @@ }, "bff-downtime-logs": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-downtime-logs.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-downtime-logs.yaml", "output": "./src/generated-client/downtime-logs", "additionalProperties": { "supportsES6": true, @@ -39,7 +39,7 @@ }, "bff-payments": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-payments.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-payments.yaml", "output": "./src/generated-client/payments", "additionalProperties": { "supportsES6": true, @@ -50,7 +50,7 @@ }, "bff-digital-addresses": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-recipient-digital-addresses.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-recipient-digital-addresses.yaml", "output": "./src/generated-client/digital-addresses", "additionalProperties": { "supportsES6": true, @@ -61,7 +61,7 @@ }, "bff-mandate": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-recipient-mandate.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-recipient-mandate.yaml", "output": "./src/generated-client/mandate", "additionalProperties": { "supportsES6": true, @@ -72,7 +72,7 @@ }, "bff-recipient-info": { "generatorName": "typescript-axios", - "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/0c7599ecae180c1c27b62073c236eed02157c7bc/docs/openapi/api-external-pn-bff-recipient-info.yaml", + "inputSpec": "https://raw.githubusercontent.com/pagopa/pn-bff/5355801397984dd3c3187e417d49e90c6c4076ae/docs/openapi/api-external-pn-bff-recipient-info.yaml", "output": "./src/generated-client/recipient-info", "additionalProperties": { "supportsES6": true, diff --git a/packages/pn-personafisica-webapp/package.json b/packages/pn-personafisica-webapp/package.json index c3ab329ce9..af6c93a531 100644 --- a/packages/pn-personafisica-webapp/package.json +++ b/packages/pn-personafisica-webapp/package.json @@ -1,7 +1,7 @@ { "name": "@pagopa-pn/pn-personafisica-webapp", "description": "SEND - Servizio Notifiche Digitali per il cittadino", - "version": "2.11.1", + "version": "2.12.0", "private": true, "dependencies": { "@emotion/react": "^11.11.1", @@ -82,7 +82,7 @@ "@typescript-eslint/parser": "^6.7.3", "@vitejs/plugin-basic-ssl": "^1.1.0", "@vitejs/plugin-react": "^4.2.1", - "@vitest/coverage-v8": "^1.3.1", + "@vitest/coverage-v8": "^1.6.1", "axios-mock-adapter": "^1.22.0", "eslint": "7.11.0", "eslint-config-prettier": "^8.10.0", @@ -95,7 +95,7 @@ "prettier": "^2.8.8", "sonarqube-scanner": "^3.3.0", "vite": "^5.1.4", - "vitest": "^1.3.1", + "vitest": "^1.6.1", "vitest-sonar-reporter": "^2.0.0" } } diff --git a/packages/pn-personafisica-webapp/public/locales/de/deleghe.json b/packages/pn-personafisica-webapp/public/locales/de/deleghe.json index 18b30d8067..a114e129ee 100644 --- a/packages/pn-personafisica-webapp/public/locales/de/deleghe.json +++ b/packages/pn-personafisica-webapp/public/locales/de/deleghe.json @@ -42,7 +42,8 @@ "notificationsFrom": "Zustellungen von:", "allNotifications": "Alle Zustellungen", "active": "Aktivieren", - "pending": "Wartet auf Bestätigung" + "pending": "Wartet auf Bestätigung", + "menu-aria-label": "Aktionsmenü" } }, "nuovaDelega": { diff --git a/packages/pn-personafisica-webapp/public/locales/en/deleghe.json b/packages/pn-personafisica-webapp/public/locales/en/deleghe.json index 2291612e6c..dbe3a27063 100644 --- a/packages/pn-personafisica-webapp/public/locales/en/deleghe.json +++ b/packages/pn-personafisica-webapp/public/locales/en/deleghe.json @@ -42,7 +42,8 @@ "notificationsFrom": "Notifications from:", "allNotifications": "All notifications", "active": "Active", - "pending": "Awaiting confirmation" + "pending": "Awaiting confirmation", + "menu-aria-label": "Actions menu" } }, "nuovaDelega": { diff --git a/packages/pn-personafisica-webapp/public/locales/fr/deleghe.json b/packages/pn-personafisica-webapp/public/locales/fr/deleghe.json index 6853ce8ece..f782ee7735 100644 --- a/packages/pn-personafisica-webapp/public/locales/fr/deleghe.json +++ b/packages/pn-personafisica-webapp/public/locales/fr/deleghe.json @@ -42,7 +42,8 @@ "notificationsFrom": "Notifications de :", "allNotifications": "Toutes les notifications", "active": "Activer", - "pending": "En attente de confirmation" + "pending": "En attente de confirmation", + "menu-aria-label": "Menu actions" } }, "nuovaDelega": { diff --git a/packages/pn-personafisica-webapp/public/locales/it/common.json b/packages/pn-personafisica-webapp/public/locales/it/common.json index 017e3520af..7f38bd5bd3 100644 --- a/packages/pn-personafisica-webapp/public/locales/it/common.json +++ b/packages/pn-personafisica-webapp/public/locales/it/common.json @@ -31,7 +31,8 @@ }, "header": { "logout": "Esci", - "pago-pa-link": "Sito di PagoPA S.p.A." + "pago-pa-link": "Sito di PagoPA S.p.A.", + "logout-message": "Confermi di voler uscire da SEND?" }, "tos": { "title": "SEND - Servizio Notifiche Digitali", @@ -192,5 +193,10 @@ "message": "Il testo originario di questi documenti è in lingua italiana. In caso di contrasto tra la versione italiana e le traduzioni in altre lingue, prevarranno il significato e le condizioni della lingua italiana.", "link": "Consulta le traduzioni" }, - "no-spaces-at-edges": "Elimina gli spazi all'inizio o alla fine" + "no-spaces-at-edges": "Elimina gli spazi all'inizio o alla fine", + "inactivity": { + "title": "Vuoi davvero uscire da SEND?", + "body": "La disconnessione è in corso. Se hai cambiato idea premi “Mantieni l’accesso” entro pochi secondi.", + "action": "Mantieni l’accesso" + } } diff --git a/packages/pn-personafisica-webapp/public/locales/it/deleghe.json b/packages/pn-personafisica-webapp/public/locales/it/deleghe.json index b36be3c251..fe71397ff4 100644 --- a/packages/pn-personafisica-webapp/public/locales/it/deleghe.json +++ b/packages/pn-personafisica-webapp/public/locales/it/deleghe.json @@ -42,7 +42,8 @@ "notificationsFrom": "Notifiche da:", "allNotifications": "Tutte le notifiche", "active": "Attiva", - "pending": "In attesa di conferma" + "pending": "In attesa di conferma", + "menu-aria-label": "Menù azioni" } }, "nuovaDelega": { @@ -54,13 +55,15 @@ "subtitle": "Inserisci i dati della persona fisica o giuridica a cui vuoi delegare la lettura delle tue notifiche.", "form": { "personType": "Soggetto giuridico*:", + "personType-content-subtitle": "Seleziona la tipologia di soggetto giuridico", "naturalPerson": "Persona fisica", "legalPerson": "Persona giuridica", "firstName": "Nome*", "lastName": "Cognome*", "fiscalCode": "Codice Fiscale*", "businessName": "Ragione Sociale*", - "viewFrom": "Potrà visualizzare le notifiche da parte di*:", + "viewFrom": "Potrà consultare le notifiche da parte di*:", + "viewFrom-content-subtitle": "Seleziona un’opzione", "allEntities": "Tutti gli enti", "onlySelected": "Solo enti selezionati", "selectEntities": "Seleziona enti*", @@ -87,7 +90,9 @@ "businessName": { "required": "La ragione sociale è obbligatoria" }, - "entiSelected": { "required": "Seleziona almeno un ente" }, + "entiSelected": { + "required": "Seleziona almeno un ente" + }, "expirationDate": { "required": "La data di termine delega è obbligatoria", "wrong": "Data errata" @@ -128,4 +133,4 @@ "message": "Uno o più dei dati inseriti non sono validi" } } -} +} \ No newline at end of file diff --git a/packages/pn-personafisica-webapp/public/locales/sl/deleghe.json b/packages/pn-personafisica-webapp/public/locales/sl/deleghe.json index 72c766c143..b1eced0a81 100644 --- a/packages/pn-personafisica-webapp/public/locales/sl/deleghe.json +++ b/packages/pn-personafisica-webapp/public/locales/sl/deleghe.json @@ -42,7 +42,8 @@ "notificationsFrom": "Obvestila od:", "allNotifications": "Vsa obvestila", "active": "Aktiviraj", - "pending": "Čakanje na potrditev" + "pending": "Čakanje na potrditev", + "menu-aria-label": "Meni dejanj" } }, "nuovaDelega": { diff --git a/packages/pn-personafisica-webapp/src/App.tsx b/packages/pn-personafisica-webapp/src/App.tsx index e35ceee655..8f00069cdb 100644 --- a/packages/pn-personafisica-webapp/src/App.tsx +++ b/packages/pn-personafisica-webapp/src/App.tsx @@ -10,7 +10,7 @@ import LogoutRoundedIcon from '@mui/icons-material/LogoutRounded'; import MailOutlineIcon from '@mui/icons-material/MailOutline'; import MarkunreadMailboxIcon from '@mui/icons-material/MarkunreadMailbox'; import SettingsIcon from '@mui/icons-material/Settings'; -import { Box } from '@mui/material'; +import { Box, Button, DialogTitle } from '@mui/material'; import { APP_VERSION, AppMessage, @@ -18,6 +18,8 @@ import { AppResponseError, AppResponseMessage, Layout, + PnDialog, + PnDialogActions, ResponseEventDispatcher, SideMenu, SideMenuItem, @@ -30,11 +32,10 @@ import { import { ProductEntity } from '@pagopa/mui-italia'; import { PFEventsType } from './models/PFEventsType'; -import { getCurrentEventTypePage } from './navigation/navigation.utility'; +import { getCurrentEventTypePage, goToLoginPortal } from './navigation/navigation.utility'; import Router from './navigation/routes'; import * as routes from './navigation/routes.const'; import { getCurrentAppStatus } from './redux/appStatus/actions'; -import { logout } from './redux/auth/actions'; import { useAppDispatch, useAppSelector } from './redux/hooks'; import { getDomicileInfo, getSidemenuInformation } from './redux/sidemenu/actions'; import { RootState } from './redux/store'; @@ -69,6 +70,7 @@ const App = () => { const dispatch = useAppDispatch(); const { t, i18n } = useTranslation(['common', 'notifiche']); const [isInitialized, setIsInitialized] = useState(false); + const [openModal, setOpenModal] = useState(false); const loggedUser = useAppSelector((state: RootState) => state.userState.user); const { tosConsent, fetchedTos, privacyConsent, fetchedPrivacy } = useAppSelector( (state: RootState) => state.userState @@ -226,7 +228,7 @@ const App = () => { }); const handleUserLogout = () => { - void dispatch(logout()); + setOpenModal(true); }; const handleEventTrackingCallbackAppCrash = (e: Error, eInfo: ErrorInfo) => { @@ -302,6 +304,25 @@ const App = () => { eventTrackingCallbackRefreshPage={handleEventTrackingCallbackRefreshPage} enableAssistanceButton={showAssistanceButton} > + + {t('header.logout-message')} + + setOpenModal(false)}> + {t('button.annulla')} + + { + sessionStorage.clear(); + goToLoginPortal(); + setOpenModal(false); + }} + > + {t('header.logout')} + + + {/* await dispatch(logout())} /> */} ({ @@ -71,7 +62,6 @@ const reduxInitialState = { describe('App', async () => { let mock: MockAdapter; let result: RenderResult; - const original = window.location; const mockOpenFn = vi.fn(); const originalOpen = window.open; @@ -152,18 +142,19 @@ describe('App', async () => { await waitFor(() => { expect(result.container).toHaveTextContent('Profile Page'); }); - Object.defineProperty(window, 'location', { - writable: true, - value: { href: '', replace: vi.fn() }, - }); + fireEvent.click(userButton!); menu = await waitFor(() => screen.getByRole('presentation')); menuItems = within(menu).getAllByRole('menuitem'); fireEvent.click(menuItems[1]); - await waitFor(() => { - expect(testStore.getState().userState.user.sessionToken).toBe(''); - }); - Object.defineProperty(window, 'location', { writable: true, value: original }); + + const logoutDialog = await waitFor(() => screen.getByTestId('dialog')); + expect(logoutDialog).toBeInTheDocument(); + const confirmLogoutButton = within(logoutDialog).getByTestId('confirm-button'); + fireEvent.click(confirmLogoutButton); + expect(sessionStorage.getItem('user')).toBeNull(); + expect(mockOpenFn).toHaveBeenCalledTimes(1); + expect(mockOpenFn).toHaveBeenCalledWith(`${LOGOUT}`, '_self'); }); it('sidemenu not included if error in API call to fetch TOS and Privacy', async () => { diff --git a/packages/pn-personafisica-webapp/src/components/Contacts/DefaultDigitalContact.tsx b/packages/pn-personafisica-webapp/src/components/Contacts/DefaultDigitalContact.tsx index f1e5c0949f..8e5ecb4a82 100644 --- a/packages/pn-personafisica-webapp/src/components/Contacts/DefaultDigitalContact.tsx +++ b/packages/pn-personafisica-webapp/src/components/Contacts/DefaultDigitalContact.tsx @@ -134,7 +134,6 @@ const DefaultDigitalContact = forwardRef<{ toggleEdit: () => void }, Props>( void }, Props>( { name: 'courtesy-contacts.sms-add', }) ); - expect(phoneButton).toBeDisabled(); + expect(phoneButton).toBeEnabled(); expect(emailInput).toHaveValue(''); const emaileButton = await waitFor(() => within(emailContact).getByRole('button', { name: 'courtesy-contacts.email-add', }) ); - expect(emaileButton).toBeDisabled(); + expect(emaileButton).toBeEnabled(); }); it('renders components - contacts', () => { diff --git a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/DefaultDigitalContact.test.tsx b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/DefaultDigitalContact.test.tsx index 8482787eb4..ef19bc84f0 100644 --- a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/DefaultDigitalContact.test.tsx +++ b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/DefaultDigitalContact.test.tsx @@ -49,7 +49,7 @@ describe('DefaultDigitalContact Component', () => { expect(input).toHaveValue(''); const button = await waitFor(() => getById(container, 'default_pec-button')); expect(button).toHaveTextContent('Button'); - expect(button).toBeDisabled(); + expect(button).toBeEnabled(); }); it('insert value', async () => { @@ -102,7 +102,7 @@ describe('DefaultDigitalContact Component', () => { expect(input).toHaveValue('not valid'); }); const button = await waitFor(() => getById(container, 'default_pec-button')); - expect(button).toBeDisabled(); + expect(button).toBeEnabled(); const errorMessage = container.querySelector(`#default_pec-helper-text`); expect(errorMessage).toBeInTheDocument(); }); @@ -221,7 +221,7 @@ describe('DefaultDigitalContact Component', () => { expect(input).toHaveValue('invalid value'); }); const newButtons = container.querySelectorAll('button'); - expect(newButtons[0]).toBeDisabled(); + expect(newButtons[0]).toBeEnabled(); }); it('remove contact', () => { diff --git a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/EmailContactItem.test.tsx b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/EmailContactItem.test.tsx index 21eb25902e..ee58404184 100644 --- a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/EmailContactItem.test.tsx +++ b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/EmailContactItem.test.tsx @@ -52,7 +52,7 @@ describe('testing EmailContactItem', () => { expect(errorMessage).toBeInTheDocument(); expect(errorMessage).toHaveTextContent('courtesy-contacts.valid-email'); const buttons = form!.querySelectorAll('button'); - expect(buttons[0]).toBeDisabled(); + expect(buttons[0]).toBeEnabled(); fireEvent.change(input!, { target: { value: '' } }); await waitFor(() => expect(input!).toHaveValue('')); expect(errorMessage).toBeInTheDocument(); @@ -76,7 +76,7 @@ describe('testing EmailContactItem', () => { await waitFor(() => { expect(input).toHaveValue(INVALID_EMAIL); }); - expect(saveButton).toBeDisabled(); + expect(saveButton).toBeEnabled(); const inputError = container.querySelector(`#default_email-helper-text`); expect(inputError).toHaveTextContent('courtesy-contacts.valid-email'); }); diff --git a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/LegalContacts.test.tsx b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/LegalContacts.test.tsx index 69fb92480f..4f4aecd74c 100644 --- a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/LegalContacts.test.tsx +++ b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/LegalContacts.test.tsx @@ -78,7 +78,7 @@ describe('LegalContacts Component', async () => { expect(pecInput).toHaveValue(''); const button = within(pecContact).getByRole('button', { name: 'button.attiva' }); await waitFor(() => { - expect(button).toBeDisabled(); + expect(button).toBeEnabled(); }); const sercqSendContact = getByTestId(`default_sercqSendContact`); expect(sercqSendContact).toBeInTheDocument(); diff --git a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/PecContactItem.test.tsx b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/PecContactItem.test.tsx index fdf05c09c3..d4fa771149 100644 --- a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/PecContactItem.test.tsx +++ b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/PecContactItem.test.tsx @@ -64,7 +64,7 @@ describe('PecContactItem component', () => { expect(errorMessage).toBeInTheDocument(); expect(errorMessage).toHaveTextContent('legal-contacts.valid-pec'); const buttons = form!.querySelectorAll('button'); - expect(buttons[0]).toBeDisabled(); + expect(buttons[0]).toBeEnabled(); fireEvent.change(input!, { target: { value: '' } }); await waitFor(() => expect(input!).toHaveValue('')); expect(errorMessage).toBeInTheDocument(); @@ -238,7 +238,7 @@ describe('PecContactItem component', () => { await waitFor(() => { expect(input).toHaveValue('invalid-pec'); }); - expect(saveButton).toBeDisabled(); + expect(saveButton).toBeEnabled(); const inputError = container.querySelector('#default_pec-helper-text'); expect(inputError).toHaveTextContent('legal-contacts.valid-pec'); }); diff --git a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/SmsContactItem.test.tsx b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/SmsContactItem.test.tsx index 824b34da98..dd0c9b9e1b 100644 --- a/packages/pn-personafisica-webapp/src/components/Contacts/__test__/SmsContactItem.test.tsx +++ b/packages/pn-personafisica-webapp/src/components/Contacts/__test__/SmsContactItem.test.tsx @@ -55,7 +55,7 @@ describe('test SmsContactItem', () => { expect(errorMessage).toBeInTheDocument(); expect(errorMessage).toHaveTextContent('courtesy-contacts.valid-sms'); const buttons = form!.querySelectorAll('button'); - expect(buttons[0]).toBeDisabled(); + expect(buttons[0]).toBeEnabled(); fireEvent.change(input!, { target: { value: '' } }); await waitFor(() => { expect(input!).toHaveValue(''); @@ -81,7 +81,7 @@ describe('test SmsContactItem', () => { await waitFor(() => { expect(input).toHaveValue(INPUT_INVALID_PHONE); }); - expect(saveButton).toBeDisabled(); + expect(saveButton).toBeEnabled(); const inputError = container.querySelector(`#default_sms-helper-text`); expect(inputError).toHaveTextContent('courtesy-contacts.valid-sms'); }); diff --git a/packages/pn-personafisica-webapp/src/components/Deleghe/ConfirmationModal.tsx b/packages/pn-personafisica-webapp/src/components/Deleghe/ConfirmationModal.tsx index 2ce2d6ea1e..814b692d43 100644 --- a/packages/pn-personafisica-webapp/src/components/Deleghe/ConfirmationModal.tsx +++ b/packages/pn-personafisica-webapp/src/components/Deleghe/ConfirmationModal.tsx @@ -25,7 +25,7 @@ export default function ConfirmationModal({ id="confirmation-dialog" open={open} onClose={handleClose} - aria-labelledby="responsive-dialog-title" + aria-labelledby="confirmation-dialog-delegations" maxWidth="lg" > {title} diff --git a/packages/pn-personafisica-webapp/src/components/Deleghe/Delegates.tsx b/packages/pn-personafisica-webapp/src/components/Deleghe/Delegates.tsx index d836b1a5b0..94b6f4aa74 100644 --- a/packages/pn-personafisica-webapp/src/components/Deleghe/Delegates.tsx +++ b/packages/pn-personafisica-webapp/src/components/Deleghe/Delegates.tsx @@ -81,12 +81,12 @@ const Delegates = () => { { id: 'visibilityIds', label: t('deleghe.table.permissions'), - cellProps: { width: '14%' }, + cellProps: { width: '20%' }, }, { id: 'status', label: t('deleghe.table.status'), - cellProps: { width: '18%' }, + cellProps: { width: '15%' }, }, { id: 'menu', @@ -140,7 +140,10 @@ const Delegates = () => { reloadAction={() => dispatch(getMandatesByDelegator())} > {rows.length > 0 ? ( - + {delegatesColumns.map((column) => ( { sortable={column.sortable} handleClick={handleChangeSorting} testId="delegatesTable.header.cell" + cellProps={column.cellProps} > {column.label} diff --git a/packages/pn-personafisica-webapp/src/components/Deleghe/DelegationsElements.tsx b/packages/pn-personafisica-webapp/src/components/Deleghe/DelegationsElements.tsx index 083d91ac13..6659494431 100644 --- a/packages/pn-personafisica-webapp/src/components/Deleghe/DelegationsElements.tsx +++ b/packages/pn-personafisica-webapp/src/components/Deleghe/DelegationsElements.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'; import MoreVertIcon from '@mui/icons-material/MoreVert'; import { Box, Button, IconButton, Menu as MUIMenu, MenuItem, Typography } from '@mui/material'; import { Variant } from '@mui/material/styles/createTypography'; -import { CustomTagGroup, useIsMobile } from '@pagopa-pn/pn-commons'; +import { CustomTagGroup } from '@pagopa-pn/pn-commons'; import { Tag } from '@pagopa/mui-italia'; import { PFEventsType } from '../../models/PFEventsType'; @@ -76,7 +76,7 @@ export const Menu = (props: any) => { id={`delegation-menu-icon-${props.id}`} onClick={handleClick} data-testid="delegationMenuIcon" - aria-label="Delegation Menu Icon" + aria-label={t('deleghe.table.menu-aria-label')} > @@ -99,7 +99,6 @@ export const OrganizationsList = (props: { visibleItems?: number; }) => { const { t } = useTranslation(['deleghe']); - const isMobile = useIsMobile(); return ( <> {props.organizations.length === 0 ? ( @@ -107,7 +106,7 @@ export const OrganizationsList = (props: { {t('deleghe.table.allNotifications')} ) : ( - + {t('deleghe.table.notificationsFrom')} diff --git a/packages/pn-personafisica-webapp/src/navigation/SessionGuard.tsx b/packages/pn-personafisica-webapp/src/navigation/SessionGuard.tsx index 733f70d2ef..51e31903be 100644 --- a/packages/pn-personafisica-webapp/src/navigation/SessionGuard.tsx +++ b/packages/pn-personafisica-webapp/src/navigation/SessionGuard.tsx @@ -62,7 +62,6 @@ const SessionGuardRender = () => { const { isUnauthorizedUser, messageUnauthorizedUser, isClosedSession } = useAppSelector( (state: RootState) => state.userState ); - const dispatch = useAppDispatch(); const { t } = useTranslation(['common']); const { hasApiErrors } = useErrors(); @@ -102,7 +101,10 @@ const SessionGuardRender = () => { return ( dispatch(logout())} + onTimerExpired={() => { + sessionStorage.clear(); + goToLoginPortal(); + }} > diff --git a/packages/pn-personafisica-webapp/src/pages/NuovaDelega.page.tsx b/packages/pn-personafisica-webapp/src/pages/NuovaDelega.page.tsx index bd12558317..1952e506ad 100644 --- a/packages/pn-personafisica-webapp/src/pages/NuovaDelega.page.tsx +++ b/packages/pn-personafisica-webapp/src/pages/NuovaDelega.page.tsx @@ -252,9 +252,12 @@ const NuovaDelega = () => { {!isMobile && breadcrumbs} - + {t('nuovaDelega.form.personType')} + + {t('nuovaDelega.form.personType-content-subtitle')} + { event.currentTarget.value ); }} + aria-labelledby='personType' > { helperText={getError(touched.codiceFiscale, errors.codiceFiscale)} fullWidth /> - + {t('nuovaDelega.form.viewFrom')} + + {t('nuovaDelega.form.viewFrom-content-subtitle')} + { handleGetAllEntities(); } }} + aria-labelledby='selectEntities' > { getConfiguration(); const dispatch = useAppDispatch(); const { t, i18n } = useTranslation(['common', 'notifiche']); + const [openModal, setOpenModal] = useState(false); const loggedUser = useAppSelector((state: RootState) => state.userState.user); const { tosConsent, fetchedTos, privacyConsent, fetchedPrivacy } = useAppSelector( (state: RootState) => state.userState @@ -258,7 +261,7 @@ const ActualApp = () => { }); const handleUserLogout = () => { - void dispatch(logout()); + setOpenModal(true); }; return ( @@ -292,6 +295,29 @@ const ActualApp = () => { isLogged={!!sessionToken} hasTermsOfService={true} > + + {t("header.logout-message")} + + setOpenModal(false)} + > + {t("button.annulla")} + + { + sessionStorage.clear(); + goToLoginPortal(); + setOpenModal(false); + }} + > + {t("header.logout")} + + + {/* await dispatch(logout())} /> */} diff --git a/packages/pn-personagiuridica-webapp/src/components/Contacts/DefaultDigitalContact.tsx b/packages/pn-personagiuridica-webapp/src/components/Contacts/DefaultDigitalContact.tsx index 90c6fcb579..3b9637e23a 100644 --- a/packages/pn-personagiuridica-webapp/src/components/Contacts/DefaultDigitalContact.tsx +++ b/packages/pn-personagiuridica-webapp/src/components/Contacts/DefaultDigitalContact.tsx @@ -134,7 +134,6 @@ const DefaultDigitalContact = forwardRef<{ toggleEdit: () => void }, Props>( void }, Props>( { name: 'courtesy-contacts.sms-add', }) ); - expect(phoneButton).toBeDisabled(); + expect(phoneButton).toBeEnabled(); expect(emailInput).toHaveValue(''); const emaileButton = await waitFor(() => within(emailContact).getByRole('button', { name: 'courtesy-contacts.email-add', }) ); - expect(emaileButton).toBeDisabled(); + expect(emaileButton).toBeEnabled(); }); it('renders components - contacts', async () => { diff --git a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/DefaultDigitalContact.test.tsx b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/DefaultDigitalContact.test.tsx index 8482787eb4..ef19bc84f0 100644 --- a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/DefaultDigitalContact.test.tsx +++ b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/DefaultDigitalContact.test.tsx @@ -49,7 +49,7 @@ describe('DefaultDigitalContact Component', () => { expect(input).toHaveValue(''); const button = await waitFor(() => getById(container, 'default_pec-button')); expect(button).toHaveTextContent('Button'); - expect(button).toBeDisabled(); + expect(button).toBeEnabled(); }); it('insert value', async () => { @@ -102,7 +102,7 @@ describe('DefaultDigitalContact Component', () => { expect(input).toHaveValue('not valid'); }); const button = await waitFor(() => getById(container, 'default_pec-button')); - expect(button).toBeDisabled(); + expect(button).toBeEnabled(); const errorMessage = container.querySelector(`#default_pec-helper-text`); expect(errorMessage).toBeInTheDocument(); }); @@ -221,7 +221,7 @@ describe('DefaultDigitalContact Component', () => { expect(input).toHaveValue('invalid value'); }); const newButtons = container.querySelectorAll('button'); - expect(newButtons[0]).toBeDisabled(); + expect(newButtons[0]).toBeEnabled(); }); it('remove contact', () => { diff --git a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/EmailContactItem.test.tsx b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/EmailContactItem.test.tsx index baeca3a138..081ef2c34e 100644 --- a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/EmailContactItem.test.tsx +++ b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/EmailContactItem.test.tsx @@ -52,7 +52,7 @@ describe('testing EmailContactItem', () => { expect(errorMessage).toBeInTheDocument(); expect(errorMessage).toHaveTextContent('courtesy-contacts.valid-email'); const buttons = form!.querySelectorAll('button'); - expect(buttons[0]).toBeDisabled(); + expect(buttons[0]).toBeEnabled(); fireEvent.change(input!, { target: { value: '' } }); await waitFor(() => expect(input!).toHaveValue('')); expect(errorMessage).toBeInTheDocument(); @@ -80,7 +80,7 @@ describe('testing EmailContactItem', () => { await waitFor(() => { expect(input).toHaveValue(INVALID_EMAIL); }); - expect(saveButton).toBeDisabled(); + expect(saveButton).toBeEnabled(); const inputError = container.querySelector(`#default_email-helper-text`); expect(inputError).toHaveTextContent('courtesy-contacts.valid-email'); }); diff --git a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/LegalContacts.test.tsx b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/LegalContacts.test.tsx index 3abdcc6be5..e3a2e46b57 100644 --- a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/LegalContacts.test.tsx +++ b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/LegalContacts.test.tsx @@ -77,7 +77,7 @@ describe('LegalContacts Component', async () => { expect(pecInput).toHaveValue(''); const button = within(pecContact).getByRole('button', { name: 'button.attiva' }); await waitFor(() => { - expect(button).toBeDisabled(); + expect(button).toBeEnabled(); }); const sercqSendContact = getByTestId(`default_sercqSendContact`); expect(sercqSendContact).toBeInTheDocument(); diff --git a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/PecContactItem.test.tsx b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/PecContactItem.test.tsx index 20addd5986..8197b53463 100644 --- a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/PecContactItem.test.tsx +++ b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/PecContactItem.test.tsx @@ -64,7 +64,7 @@ describe('PecContactItem component', () => { expect(errorMessage).toBeInTheDocument(); expect(errorMessage).toHaveTextContent('legal-contacts.valid-pec'); const buttons = form!.querySelectorAll('button'); - expect(buttons[0]).toBeDisabled(); + expect(buttons[0]).toBeEnabled(); fireEvent.change(input!, { target: { value: '' } }); await waitFor(() => expect(input!).toHaveValue('')); expect(errorMessage).toBeInTheDocument(); @@ -238,7 +238,7 @@ describe('PecContactItem component', () => { await waitFor(() => { expect(input).toHaveValue('invalid-pec'); }); - expect(saveButton).toBeDisabled(); + expect(saveButton).toBeEnabled(); const inputError = container.querySelector('#default_pec-helper-text'); expect(inputError).toHaveTextContent('legal-contacts.valid-pec'); }); diff --git a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/SmsContactItem.test.tsx b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/SmsContactItem.test.tsx index cead8ed58e..ec8992600e 100644 --- a/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/SmsContactItem.test.tsx +++ b/packages/pn-personagiuridica-webapp/src/components/Contacts/__test__/SmsContactItem.test.tsx @@ -55,7 +55,7 @@ describe('test SmsContactItem', () => { expect(errorMessage).toBeInTheDocument(); expect(errorMessage).toHaveTextContent('courtesy-contacts.valid-sms'); const buttons = form!.querySelectorAll('button'); - expect(buttons[0]).toBeDisabled(); + expect(buttons[0]).toBeEnabled(); fireEvent.change(input!, { target: { value: '' } }); await waitFor(() => { expect(input!).toHaveValue(''); @@ -85,7 +85,7 @@ describe('test SmsContactItem', () => { await waitFor(() => { expect(input).toHaveValue(INPUT_INVALID_PHONE); }); - expect(saveButton).toBeDisabled(); + expect(saveButton).toBeEnabled(); const inputError = container.querySelector(`#default_sms-helper-text`); expect(inputError).toHaveTextContent('courtesy-contacts.valid-sms'); }); diff --git a/packages/pn-personagiuridica-webapp/src/components/Deleghe/ConfirmationModal.tsx b/packages/pn-personagiuridica-webapp/src/components/Deleghe/ConfirmationModal.tsx index 3a0141c226..0294e58d71 100644 --- a/packages/pn-personagiuridica-webapp/src/components/Deleghe/ConfirmationModal.tsx +++ b/packages/pn-personagiuridica-webapp/src/components/Deleghe/ConfirmationModal.tsx @@ -28,7 +28,7 @@ export default function ConfirmationModal({ id="confirmation-dialog" open={open} onClose={onClose} - aria-labelledby="responsive-dialog-title" + aria-labelledby="dialog-title" data-testid="confirmationDialog" > {title} diff --git a/packages/pn-personagiuridica-webapp/src/components/Deleghe/DelegatesByCompany.tsx b/packages/pn-personagiuridica-webapp/src/components/Deleghe/DelegatesByCompany.tsx index 3c1b48e366..dce49f1402 100644 --- a/packages/pn-personagiuridica-webapp/src/components/Deleghe/DelegatesByCompany.tsx +++ b/packages/pn-personagiuridica-webapp/src/components/Deleghe/DelegatesByCompany.tsx @@ -98,7 +98,7 @@ const DelegatesByCompany = () => { id: 'visibilityIds', label: t('deleghe.table.permissions'), tableConfiguration: { - cellProps: { width: '11%' }, + cellProps: { width: '20%' }, }, cardConfiguration: { wrapValueInTypography: false, @@ -108,7 +108,7 @@ const DelegatesByCompany = () => { id: 'status', label: t('deleghe.table.status'), tableConfiguration: { - cellProps: { width: '18%' }, + cellProps: { width: '15%' }, }, cardConfiguration: { position: 'left', @@ -178,6 +178,7 @@ const DelegatesByCompany = () => { currentSort={sort} onChangeSorting={setSort} testId="delegatesTable" + slotProps={{ table: { sx: { tableLayout: 'fixed' } } }} > {delegatesColumn.map((column) => ( @@ -185,6 +186,7 @@ const DelegatesByCompany = () => { key={column.id.toString()} columnId={column.id} sortable={column.tableConfiguration.sortable} + cellProps={column.tableConfiguration.cellProps} > {column.label} diff --git a/packages/pn-personagiuridica-webapp/src/components/Deleghe/DelegationsElements.tsx b/packages/pn-personagiuridica-webapp/src/components/Deleghe/DelegationsElements.tsx index 5ffb78d3ef..37f165d122 100644 --- a/packages/pn-personagiuridica-webapp/src/components/Deleghe/DelegationsElements.tsx +++ b/packages/pn-personagiuridica-webapp/src/components/Deleghe/DelegationsElements.tsx @@ -11,7 +11,6 @@ import { CustomTagGroup, Row, appStateActions, - useIsMobile, } from '@pagopa-pn/pn-commons'; import { Tag } from '@pagopa/mui-italia'; import { AnyAction } from '@reduxjs/toolkit'; @@ -294,7 +293,6 @@ export const OrganizationsList: React.FC = ({ visibleItems, }) => { const { t } = useTranslation(['deleghe']); - const isMobile = useIsMobile(); return ( <> @@ -303,7 +301,7 @@ export const OrganizationsList: React.FC = ({ {t('deleghe.table.allNotifications')} ) : ( - + {t('deleghe.table.notificationsFrom')} diff --git a/packages/pn-personagiuridica-webapp/src/navigation/SessionGuard.tsx b/packages/pn-personagiuridica-webapp/src/navigation/SessionGuard.tsx index 23ce442658..e1b210b9ce 100644 --- a/packages/pn-personagiuridica-webapp/src/navigation/SessionGuard.tsx +++ b/packages/pn-personagiuridica-webapp/src/navigation/SessionGuard.tsx @@ -44,6 +44,7 @@ const manageUnforbiddenError = (e: any) => { return true; }; + // Perché ci sono due componenti. // Il codice in SessionGuard implementa i steps necessari per determinare se c'è sessione, se è utente abilitato, se è sessione anonima, ecc.. // D'altra parte, SessionGuardRender implementa la logica di cosa si deve renderizzare, @@ -56,14 +57,14 @@ const manageUnforbiddenError = (e: any) => { */ const SessionGuardRender = () => { const [params] = useSearchParams(); - const { IS_INACTIVITY_HANDLER_ENABLED } = getConfiguration(); + const isInitialized = useAppSelector((state: RootState) => state.appState.isInitialized); const { sessionToken } = useAppSelector((state: RootState) => state.userState.user); const { isUnauthorizedUser, messageUnauthorizedUser, isClosedSession } = useAppSelector( (state: RootState) => state.userState ); - const dispatch = useAppDispatch(); + const { t } = useTranslation(['common']); const { hasApiErrors } = useErrors(); @@ -110,7 +111,10 @@ const SessionGuardRender = () => { return ( dispatch(logout())} + onTimerExpired={() => { + sessionStorage.clear(); + goToLoginPortal(); + }} > diff --git a/packages/pn-personagiuridica-webapp/src/pages/NuovaDelega.page.tsx b/packages/pn-personagiuridica-webapp/src/pages/NuovaDelega.page.tsx index 2d51a4910c..f1cdc0250a 100644 --- a/packages/pn-personagiuridica-webapp/src/pages/NuovaDelega.page.tsx +++ b/packages/pn-personagiuridica-webapp/src/pages/NuovaDelega.page.tsx @@ -219,9 +219,12 @@ const NuovaDelega = () => { {!isMobile && breadcrumbs} - + {t('nuovaDelega.form.personType')} + + {t('nuovaDelega.form.personType-content-subtitle')} + { event.currentTarget.value ); }} + aria-labelledby='personType' > { helperText={getError(touched.codiceFiscale, errors.codiceFiscale)} fullWidth /> - + {t('nuovaDelega.form.viewFrom')} + + {t('nuovaDelega.form.viewFrom-content-subtitle')} + { handleGetAllEntities(); } }} + aria-labelledby='selectEntities' > { ); }; -export default NuovaDelega; +export default NuovaDelega; \ No newline at end of file diff --git a/packages/pn-validator/CHANGELOG.md b/packages/pn-validator/CHANGELOG.md index c79d77de62..20c7b7143e 100644 --- a/packages/pn-validator/CHANGELOG.md +++ b/packages/pn-validator/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.12.0](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.1...v2.12.0) (2025-02-18) + +**Note:** Version bump only for package @pagopa-pn/pn-validator + + + + + +# [2.12.0-RC.1](https://github.com/pagopa/pn-frontend/compare/v2.12.0-RC.0...v2.12.0-RC.1) (2025-02-05) + +**Note:** Version bump only for package @pagopa-pn/pn-validator + + + + + +# [2.12.0-RC.0](https://github.com/pagopa/pn-frontend/compare/v2.11.1...v2.12.0-RC.0) (2025-02-04) + +**Note:** Version bump only for package @pagopa-pn/pn-validator + + + + + ## [2.11.1](https://github.com/pagopa/pn-frontend/compare/v2.11.0...v2.11.1) (2025-01-31) **Note:** Version bump only for package @pagopa-pn/pn-validator diff --git a/packages/pn-validator/package.json b/packages/pn-validator/package.json index 61f7a2beec..c89a845295 100644 --- a/packages/pn-validator/package.json +++ b/packages/pn-validator/package.json @@ -1,6 +1,6 @@ { "name": "@pagopa-pn/pn-validator", - "version": "2.11.1", + "version": "2.12.0", "private": true, "main": "./src/index.ts", "dependencies": { @@ -21,14 +21,14 @@ "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", - "@vitest/coverage-v8": "^1.3.1", + "@vitest/coverage-v8": "^1.6.1", "eslint": "7.11.0", "eslint-config-prettier": "^8.10.0", "eslint-plugin-functional": "^3.7.2", "eslint-plugin-import": "^2.25.3", "eslint-plugin-sonarjs": "^0.10.0", "sonarqube-scanner": "^3.3.0", - "vitest": "^1.3.1", + "vitest": "^1.6.1", "vitest-sonar-reporter": "^2.0.0" } } diff --git a/yarn.lock b/yarn.lock index 411d0a1d42..d24408909b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.3.tgz#90749bde8b89cd41764224f5aac29cd4138f75ff" integrity sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ== -"@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.2.1": +"@ampproject/remapping@^2.2.0": version "2.2.1" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== @@ -15,6 +15,14 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@ampproject/remapping@^2.2.1": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": version "7.16.7" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" @@ -437,6 +445,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + "@babel/helper-validator-identifier@^7.16.7": version "7.16.7" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" @@ -457,6 +470,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + "@babel/helper-validator-option@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" @@ -579,11 +597,18 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== -"@babel/parser@^7.23.6", "@babel/parser@^7.24.0": +"@babel/parser@^7.24.0": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== +"@babel/parser@^7.25.4": + version "7.26.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.7.tgz#e114cd099e5f7d17b05368678da0fb9f69b3385c" + integrity sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w== + dependencies: + "@babel/types" "^7.26.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz#02dc8a03f613ed5fdc29fb2f728397c78146c962" @@ -1484,9 +1509,17 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" +"@babel/types@^7.25.4", "@babel/types@^7.26.7": + version "7.26.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.7.tgz#5e2b89c0768e874d4d061961f3a5a153d71dc17a" + integrity sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" - resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== "@date-io/core@^2.15.0": @@ -1844,7 +1877,7 @@ "@istanbuljs/schema@^0.1.2": version "0.1.3" - resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== "@jest/expect-utils@^29.7.0": @@ -1882,6 +1915,15 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.8" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" @@ -1897,6 +1939,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + "@jridgewell/sourcemap-codec@1.4.14": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" @@ -1912,14 +1959,6 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.12": - version "0.3.20" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" - integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - "@jridgewell/trace-mapping@^0.3.17": version "0.3.19" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" @@ -1928,6 +1967,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" @@ -2955,11 +3002,6 @@ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== -"@types/istanbul-lib-coverage@^2.0.1": - version "2.0.4" - resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== - "@types/istanbul-lib-report@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" @@ -3279,63 +3321,63 @@ "@types/babel__core" "^7.20.5" react-refresh "^0.14.0" -"@vitest/coverage-v8@^1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-1.3.1.tgz#cf5ed8eb5bff6658cea126d0f8fcd2872de0b59f" - integrity sha512-UuBnkSJUNE9rdHjDCPyJ4fYuMkoMtnghes1XohYa4At0MS3OQSAo97FrbwSLRshYsXThMZy1+ybD/byK5llyIg== +"@vitest/coverage-v8@^1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-1.6.1.tgz#47230491ec73aa288a92e36b75c1671b3f741d4e" + integrity sha512-6YeRZwuO4oTGKxD3bijok756oktHSIm3eczVVzNe3scqzuhLwltIF3S9ZL/vwOVIpURmU6SnZhziXXAfw8/Qlw== dependencies: "@ampproject/remapping" "^2.2.1" "@bcoe/v8-coverage" "^0.2.3" debug "^4.3.4" istanbul-lib-coverage "^3.2.2" istanbul-lib-report "^3.0.1" - istanbul-lib-source-maps "^4.0.1" + istanbul-lib-source-maps "^5.0.4" istanbul-reports "^3.1.6" magic-string "^0.30.5" magicast "^0.3.3" picocolors "^1.0.0" std-env "^3.5.0" + strip-literal "^2.0.0" test-exclude "^6.0.0" - v8-to-istanbul "^9.2.0" -"@vitest/expect@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.3.1.tgz#d4c14b89c43a25fd400a6b941f51ba27fe0cb918" - integrity sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw== +"@vitest/expect@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.6.1.tgz#b90c213f587514a99ac0bf84f88cff9042b0f14d" + integrity sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog== dependencies: - "@vitest/spy" "1.3.1" - "@vitest/utils" "1.3.1" + "@vitest/spy" "1.6.1" + "@vitest/utils" "1.6.1" chai "^4.3.10" -"@vitest/runner@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.3.1.tgz#e7f96cdf74842934782bfd310eef4b8695bbfa30" - integrity sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg== +"@vitest/runner@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.6.1.tgz#10f5857c3e376218d58c2bfacfea1161e27e117f" + integrity sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA== dependencies: - "@vitest/utils" "1.3.1" + "@vitest/utils" "1.6.1" p-limit "^5.0.0" pathe "^1.1.1" -"@vitest/snapshot@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.3.1.tgz#193a5d7febf6ec5d22b3f8c5a093f9e4322e7a88" - integrity sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ== +"@vitest/snapshot@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.6.1.tgz#90414451a634bb36cd539ccb29ae0d048a8c0479" + integrity sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ== dependencies: magic-string "^0.30.5" pathe "^1.1.1" pretty-format "^29.7.0" -"@vitest/spy@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.3.1.tgz#814245d46d011b99edd1c7528f5725c64e85a88b" - integrity sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig== +"@vitest/spy@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.6.1.tgz#33376be38a5ed1ecd829eb986edaecc3e798c95d" + integrity sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw== dependencies: tinyspy "^2.2.0" -"@vitest/utils@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.3.1.tgz#7b05838654557544f694a372de767fcc9594d61a" - integrity sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ== +"@vitest/utils@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.6.1.tgz#6d2f36cb6d866f2bbf59da854a324d6bf8040f17" + integrity sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g== dependencies: diff-sequences "^29.6.3" estree-walker "^3.0.3" @@ -5834,7 +5876,7 @@ html-encoding-sniffer@^4.0.0: html-escaper@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== html-parse-stringify@^3.0.1: @@ -6409,26 +6451,12 @@ isobject@^3.0.1: resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= -istanbul-lib-coverage@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - -istanbul-lib-coverage@^3.2.2: +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-report@^3.0.1: +istanbul-lib-report@^3.0.0, istanbul-lib-report@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== @@ -6437,14 +6465,14 @@ istanbul-lib-report@^3.0.1: make-dir "^4.0.0" supports-color "^7.1.0" -istanbul-lib-source-maps@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== +istanbul-lib-source-maps@^5.0.4: + version "5.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" + integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== dependencies: + "@jridgewell/trace-mapping" "^0.3.23" debug "^4.1.1" istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" istanbul-reports@^3.1.6: version "3.1.7" @@ -6947,15 +6975,15 @@ magic-string@^0.30.5: "@jridgewell/sourcemap-codec" "^1.4.15" magicast@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.3.tgz#a15760f982deec9dabc5f314e318d7c6bddcb27b" - integrity sha512-ZbrP1Qxnpoes8sz47AM0z08U+jW6TyRgZzcWy3Ma3vDhJttwMwAFDMMQFobwdBxByBD46JYmxRzeF7w2+wJEuw== + version "0.3.5" + resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.5.tgz#8301c3c7d66704a0771eb1bad74274f0ec036739" + integrity sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ== dependencies: - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" - source-map-js "^1.0.2" + "@babel/parser" "^7.25.4" + "@babel/types" "^7.25.4" + source-map-js "^1.2.0" -make-dir@3.1.0, make-dir@^3.0.0: +make-dir@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -8872,7 +8900,7 @@ semver@7.3.8: dependencies: lru-cache "^6.0.0" -semver@7.5.4, semver@^7.0.0, semver@^7.1.1, semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: +semver@7.5.4, semver@^7.0.0, semver@^7.1.1, semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -8884,6 +8912,11 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +semver@^7.5.3: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -9020,12 +9053,7 @@ sort-keys@^2.0.0: dependencies: is-plain-obj "^1.0.0" -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map-js@^1.2.1: +source-map-js@^1.2.0, source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== @@ -9376,7 +9404,7 @@ tempy@1.0.0: test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== dependencies: "@istanbuljs/schema" "^0.1.2" @@ -9423,10 +9451,10 @@ tinybench@^2.5.1: resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.6.0.tgz#1423284ee22de07c91b3752c048d2764714b341b" integrity sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA== -tinypool@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.2.tgz#84013b03dc69dacb322563a475d4c0a9be00f82a" - integrity sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ== +tinypool@^0.8.3: + version "0.8.4" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.4.tgz#e217fe1270d941b39e98c625dcecebb1408c9aa8" + integrity sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ== tinyspy@^2.2.0: version "2.2.1" @@ -9784,15 +9812,6 @@ v8-compile-cache@2.3.0, v8-compile-cache@^2.0.3: resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -v8-to-istanbul@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^2.0.0" - validate-npm-package-license@3.0.4, validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" @@ -9822,10 +9841,10 @@ validate-npm-package-name@^5.0.0: dependencies: builtins "^5.0.0" -vite-node@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.3.1.tgz#a93f7372212f5d5df38e945046b945ac3f4855d2" - integrity sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng== +vite-node@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.6.1.tgz#fff3ef309296ea03ceaa6ca4bb660922f5416c57" + integrity sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA== dependencies: cac "^6.7.14" debug "^4.3.4" @@ -9834,9 +9853,9 @@ vite-node@1.3.1: vite "^5.0.0" vite@^5.0.0, vite@^5.1.4: - version "5.4.9" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.9.tgz#215c80cbebfd09ccbb9ceb8c0621391c9abdc19c" - integrity sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg== + version "5.4.14" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.14.tgz#ff8255edb02134df180dcfca1916c37a6abe8408" + integrity sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA== dependencies: esbuild "^0.21.3" postcss "^8.4.43" @@ -9856,16 +9875,16 @@ vitest-sonar-reporter@^2.0.0: resolved "https://registry.yarnpkg.com/vitest-sonar-reporter/-/vitest-sonar-reporter-2.0.0.tgz#6372e5faba2b2834eac0b2cd1283263d38d0e718" integrity sha512-LorC3NnmrBrryx4+l3BEsNQjD0Y7wfmrD1y/+tHDuZUuVj7w8nOxRXCBSppDfmgfpToOhwchh0JcL4IGMKUKDA== -vitest@1.3.1, vitest@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.3.1.tgz#2d7e9861f030d88a4669392a4aecb40569d90937" - integrity sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ== - dependencies: - "@vitest/expect" "1.3.1" - "@vitest/runner" "1.3.1" - "@vitest/snapshot" "1.3.1" - "@vitest/spy" "1.3.1" - "@vitest/utils" "1.3.1" +vitest@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.6.1.tgz#b4a3097adf8f79ac18bc2e2e0024c534a7a78d2f" + integrity sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag== + dependencies: + "@vitest/expect" "1.6.1" + "@vitest/runner" "1.6.1" + "@vitest/snapshot" "1.6.1" + "@vitest/spy" "1.6.1" + "@vitest/utils" "1.6.1" acorn-walk "^8.3.2" chai "^4.3.10" debug "^4.3.4" @@ -9877,9 +9896,9 @@ vitest@1.3.1, vitest@^1.3.1: std-env "^3.5.0" strip-literal "^2.0.0" tinybench "^2.5.1" - tinypool "^0.8.2" + tinypool "^0.8.3" vite "^5.0.0" - vite-node "1.3.1" + vite-node "1.6.1" why-is-node-running "^2.2.2" void-elements@3.1.0: