From 0d65a699a9a39cff0d2a4c12b4d0c1733d996aeb Mon Sep 17 00:00:00 2001 From: Zak Burke Date: Mon, 11 Nov 2024 09:24:31 -0500 Subject: [PATCH] STCOR-882 return to previous location on logout-timeout (#1558) PR #1551 introduced a regression to the functionality added in STCOR-849/PR #1523. The correct behavior is for the logout button on the timeout page to point to the previous location, but after #1551 the button always pointed to `/`. Refs STCOR-882, STCOR-849 --- src/components/Logout/Logout.js | 14 ++++- src/components/Logout/Logout.test.js | 64 ++++++++++++++++---- test/jest/__mock__/stripesComponents.mock.js | 25 +++++--- 3 files changed, 82 insertions(+), 21 deletions(-) diff --git a/src/components/Logout/Logout.js b/src/components/Logout/Logout.js index e99e0cae9..1f3650ca8 100644 --- a/src/components/Logout/Logout.js +++ b/src/components/Logout/Logout.js @@ -13,7 +13,11 @@ import { import OrganizationLogo from '../OrganizationLogo'; import { useStripes } from '../../StripesContext'; -import { logout } from '../../loginServices'; +import { + getUnauthorizedPathFromSession, + logout, + removeUnauthorizedPathFromSession, +} from '../../loginServices'; import styles from './Logout.css'; @@ -51,6 +55,12 @@ const Logout = () => { [] ); + const handleClick = (_e) => { + removeUnauthorizedPathFromSession(); + }; + + const redirectTo = getUnauthorizedPathFromSession() || '/'; + if (!didLogout) { return ; } @@ -71,7 +81,7 @@ const Logout = () => { - + diff --git a/src/components/Logout/Logout.test.js b/src/components/Logout/Logout.test.js index aa950b0da..f887ee111 100644 --- a/src/components/Logout/Logout.test.js +++ b/src/components/Logout/Logout.test.js @@ -1,15 +1,17 @@ import { render, screen } from '@folio/jest-config-stripes/testing-library/react'; +import { userEvent } from '@folio/jest-config-stripes/testing-library/user-event'; import { useLocation } from 'react-router'; import Logout from './Logout'; import { useStripes } from '../../StripesContext'; -import { logout } from '../../loginServices'; +import { getUnauthorizedPathFromSession, logout, setUnauthorizedPathToSession } from '../../loginServices'; jest.mock('../OrganizationLogo'); jest.mock('../../StripesContext'); jest.mock('react-router'); jest.mock('../../loginServices', () => ({ + ...jest.requireActual('../../loginServices'), logout: jest.fn(() => Promise.resolve()), })); @@ -36,6 +38,15 @@ describe('Logout', () => { expect(logout).toHaveBeenCalled(); screen.getByText('stripes-core.logoutComplete'); }); + + it('"log in again" href points to "/"', async () => { + const mockUseStripes = useStripes; + mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: false } }); + + render(); + const button = screen.getByRole('button'); + expect(button).toHaveAttribute('href', '/'); + }); }); describe('Timeout logout', () => { @@ -44,21 +55,50 @@ describe('Logout', () => { mockUseLocation.mockReturnValue({ pathName: '/logout-timeout' }); }); - it('if not authenticated, renders a timeout message', async () => { - const mockUseStripes = useStripes; - mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: false } }); + describe('if authenticated', () => { + it('calls logout then renders a timeout message', async () => { + const mockUseStripes = useStripes; + mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: true } }); - render(); - screen.getByText('stripes-core.rtr.idleSession.sessionExpiredSoSad'); + render(); + expect(logout).toHaveBeenCalled(); + screen.getByText('stripes-core.rtr.idleSession.sessionExpiredSoSad'); + }); + + it('"login in again" href points to pre-timeout location', () => { + const previousPath = '/monkey?bagel'; + setUnauthorizedPathToSession(previousPath); + + const mockUseStripes = useStripes; + mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: false } }); + + render(); + + expect(screen.getByRole('button')).toHaveAttribute('href', previousPath); + }); + + it('clicking "log in again" clears pre-timeout location from storage', async () => { + setUnauthorizedPathToSession('/monkey?bagel'); + + const user = userEvent.setup(); + const mockUseStripes = useStripes; + mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: false } }); + + render(); + + await user.click(screen.getByRole('button')); + expect(getUnauthorizedPathFromSession()).toBeFalsy(); + }); }); - it('if authenticated, calls logout then renders a timeout message', async () => { - const mockUseStripes = useStripes; - mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: true } }); + describe('if not authenticated', () => { + it('renders a timeout message', async () => { + const mockUseStripes = useStripes; + mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: false } }); - render(); - expect(logout).toHaveBeenCalled(); - screen.getByText('stripes-core.rtr.idleSession.sessionExpiredSoSad'); + render(); + screen.getByText('stripes-core.rtr.idleSession.sessionExpiredSoSad'); + }); }); }); }); diff --git a/test/jest/__mock__/stripesComponents.mock.js b/test/jest/__mock__/stripesComponents.mock.js index 49bac0f60..b5ab8fe37 100644 --- a/test/jest/__mock__/stripesComponents.mock.js +++ b/test/jest/__mock__/stripesComponents.mock.js @@ -14,13 +14,24 @@ jest.mock('@folio/stripes-components', () => ({ {props.children} )), - Button: jest.fn(({ children, onClick = jest.fn() }) => ( - - )), + Button: jest.fn(({ children, to, onClick = jest.fn() }) => { + if (to) { + return ( + + + {children} + + + ); + } + return ( + + ); + }), Callout: jest.fn(({ children, ...rest }) => ( {children} )),