diff --git a/src/components/Logout/Logout.js b/src/components/Logout/Logout.js
index c8361a16..3d582c73 100644
--- a/src/components/Logout/Logout.js
+++ b/src/components/Logout/Logout.js
@@ -1,5 +1,4 @@
import { useEffect, useState } from 'react';
-import PropTypes from 'prop-types';
import { Redirect } from 'react-router';
import { FormattedMessage } from 'react-intl';
@@ -13,16 +12,15 @@ import { getLocale, logout } from '../../loginServices';
* This corresponds to the '/logout' route, allowing that route to be directly
* accessible rather than only accessible through the menu action.
*
- * @param {object} history
*/
-const Logout = ({ history }) => {
+const Logout = () => {
const stripes = useStripes();
const [didLogout, setDidLogout] = useState(false);
useEffect(
() => {
getLocale(stripes.okapi.url, stripes.store, stripes.okapi.tenant)
- .then(logout(stripes.okapi.url, stripes.store, history))
+ .then(logout(stripes.okapi.url, stripes.store))
.then(setDidLogout(true));
},
// no dependencies because we only want to start the logout process once.
@@ -35,8 +33,4 @@ const Logout = ({ history }) => {
return didLogout ? : ;
};
-Logout.propTypes = {
- history: PropTypes.object,
-};
-
export default Logout;
diff --git a/src/components/LogoutTimeout/LogoutTimeout.js b/src/components/LogoutTimeout/LogoutTimeout.js
index 1945ec28..557a32c0 100644
--- a/src/components/LogoutTimeout/LogoutTimeout.js
+++ b/src/components/LogoutTimeout/LogoutTimeout.js
@@ -12,14 +12,14 @@ import {
import OrganizationLogo from '../OrganizationLogo';
import { useStripes } from '../../StripesContext';
-import { logout } from '../../loginServices';
-
-import styles from './LogoutTimeout.css';
import {
getUnauthorizedPathFromSession,
+ logout,
removeUnauthorizedPathFromSession,
} from '../../loginServices';
+import styles from './LogoutTimeout.css';
+
/**
* LogoutTimeout
* Show a "sorry, your session timed out message"; if the session is still
@@ -52,16 +52,15 @@ const LogoutTimeout = () => {
[]
);
- if (!didLogout) {
- return ;
- }
-
const handleClick = (_e) => {
removeUnauthorizedPathFromSession();
};
- const previousPath = getUnauthorizedPathFromSession();
- const redirectTo = previousPath ?? '/';
+ const redirectTo = getUnauthorizedPathFromSession() || '/';
+
+ if (!didLogout) {
+ return ;
+ }
return (
diff --git a/src/components/LogoutTimeout/LogoutTimeout.test.js b/src/components/LogoutTimeout/LogoutTimeout.test.js
index 532c5c4e..cb8606ea 100644
--- a/src/components/LogoutTimeout/LogoutTimeout.test.js
+++ b/src/components/LogoutTimeout/LogoutTimeout.test.js
@@ -3,7 +3,7 @@ import { userEvent } from '@folio/jest-config-stripes/testing-library/user-event
import LogoutTimeout from './LogoutTimeout';
import { useStripes } from '../../StripesContext';
-import { getUnauthorizedPathFromSession, setUnauthorizedPathToSession } from '../../loginServices';
+import { getUnauthorizedPathFromSession, logout, setUnauthorizedPathToSession } from '../../loginServices';
jest.mock('../OrganizationLogo');
jest.mock('../../StripesContext');
@@ -11,6 +11,13 @@ jest.mock('react-router', () => ({
Redirect: () => Redirect
,
}));
+jest.mock('../../loginServices', () => ({
+ logout: jest.fn(() => Promise.resolve()),
+ getUnauthorizedPathFromSession: jest.fn(),
+ removeUnauthorizedPathFromSession: jest.fn(),
+ setUnauthorizedPathToSession: jest.fn(),
+}));
+
describe('LogoutTimeout', () => {
describe('if not authenticated', () => {
it('renders a timeout message', async () => {
@@ -21,7 +28,7 @@ describe('LogoutTimeout', () => {
screen.getByText('stripes-core.rtr.idleSession.sessionExpiredSoSad');
});
- it('clears previous path from storage after clicking', async () => {
+ it('clears previous path from storage after clicking "log in again"', async () => {
const previousPath = '/monkey?bagel';
setUnauthorizedPathToSession(previousPath);
const user = userEvent.setup();
@@ -31,16 +38,34 @@ describe('LogoutTimeout', () => {
render();
await user.click(screen.getByRole('button'));
-
- expect(getUnauthorizedPathFromSession()).toBe(null);
+ expect(getUnauthorizedPathFromSession()).toBeFalsy();
});
});
- it('if authenticated, renders a redirect', async () => {
- const mockUseStripes = useStripes;
- mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: true } });
+ describe('if not authenticated', () => {
+ it('calls logout then renders a timeout message', async () => {
+ const mockUseStripes = useStripes;
+ mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: true } });
+
+ render();
+ expect(logout).toHaveBeenCalled();
+ screen.getByText('stripes-core.rtr.idleSession.sessionExpiredSoSad');
+ });
+
+ it('clears previous path from storage after clicking "log in again"', async () => {
+ const previousPath = '/monkey?bagel';
+ setUnauthorizedPathToSession(previousPath);
+ const user = userEvent.setup();
+ const mockUseStripes = useStripes;
+ mockUseStripes.mockReturnValue({ okapi: { isAuthenticated: true } });
+
+ render();
+
+ expect(logout).toHaveBeenCalled();
+ screen.getByText('stripes-core.rtr.idleSession.sessionExpiredSoSad');
- render();
- screen.getByText('Redirect');
+ await user.click(screen.getByRole('button'));
+ expect(getUnauthorizedPathFromSession()).toBeFalsy();
+ });
});
});
diff --git a/src/components/SessionEventContainer/SessionEventContainer.js b/src/components/SessionEventContainer/SessionEventContainer.js
index d5e200fe..af19c588 100644
--- a/src/components/SessionEventContainer/SessionEventContainer.js
+++ b/src/components/SessionEventContainer/SessionEventContainer.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import createInactivityTimer from 'inactivity-timer';
import ms from 'ms';
-import { logout, SESSION_NAME, setUnauthorizedPathToSession } from '../../loginServices';
+import { SESSION_NAME, setUnauthorizedPathToSession } from '../../loginServices';
import KeepWorkingModal from './KeepWorkingModal';
import { useStripes } from '../../StripesContext';
import {
@@ -22,26 +22,20 @@ import FixedLengthSessionWarning from './FixedLengthSessionWarning';
//
// RTR error in this window: logout
-export const thisWindowRtrError = (_e, stripes, history, queryClient) => {
+export const thisWindowRtrError = (_e, stripes, history) => {
console.warn('rtr error; logging out'); // eslint-disable-line no-console
setUnauthorizedPathToSession();
- return logout(stripes.okapi.url, stripes.store, queryClient)
- .then(() => {
- history.push('/logout-timeout');
- });
+ history.push('/logout-timeout');
};
// idle session timeout in this window: logout
export const thisWindowRtrIstTimeout = (_e, stripes, history) => {
stripes.logger.log('rtr', 'idle session timeout; logging out');
setUnauthorizedPathToSession();
- return logout(stripes.okapi.url, stripes.store, queryClient)
- .then(() => {
- history.push('/logout-timeout');
- });
+ history.push('/logout-timeout');
};
-// fixed-length session warning in this window
+// fixed-length session warning in this window: logout
export const thisWindowRtrFlsWarning = (_e, stripes, setIsFlsVisible) => {
stripes.logger.log('rtr', 'fixed-length session warning');
setIsFlsVisible(true);
@@ -58,14 +52,11 @@ export const thisWindowRtrFlsTimeout = (_e, stripes, history) => {
// logout if it was a timeout event or if SESSION_NAME is being
// removed from localStorage, an indicator that logout is in-progress
// in another window and so must occur here as well
-export const otherWindowStorage = (e, stripes, history, queryClient) => {
+export const otherWindowStorage = (e, stripes, history) => {
if (e.key === RTR_TIMEOUT_EVENT) {
stripes.logger.log('rtr', 'idle session timeout; logging out');
setUnauthorizedPathToSession();
- return logout(stripes.okapi.url, stripes.store, queryClient)
- .then(() => {
- history.push('/logout-timeout');
- });
+ history.push('/logout-timeout');
} else if (!localStorage.getItem(SESSION_NAME)) {
stripes.logger.log('rtr', 'external localstorage change; logging out');
setUnauthorizedPathToSession();
@@ -138,7 +129,7 @@ export const thisWindowActivity = (_e, stripes, timers, broadcastChannel) => {
* @param {object} history
* @returns KeepWorkingModal or null
*/
-const SessionEventContainer = ({ history, queryClient }) => {
+const SessionEventContainer = ({ history }) => {
// is the "keep working?" modal visible?
const [isVisible, setIsVisible] = useState(false);
@@ -220,13 +211,13 @@ const SessionEventContainer = ({ history, queryClient }) => {
timers.current = { showModalIT, logoutIT };
// RTR error in this window: logout
- channels.window[RTR_ERROR_EVENT] = (e) => thisWindowRtrError(e, stripes, history, queryClient);
+ channels.window[RTR_ERROR_EVENT] = (e) => thisWindowRtrError(e, stripes, history);
// idle session timeout in this window: logout
channels.window[RTR_TIMEOUT_EVENT] = (e) => thisWindowRtrIstTimeout(e, stripes, history);
// localstorage change in another window: logout?
- channels.window.storage = (e) => otherWindowStorage(e, stripes, history, queryClient);
+ channels.window.storage = (e) => otherWindowStorage(e, stripes, history);
// activity in another window: send keep-alive to idle-timers.
channels.bc.message = (message) => otherWindowActivity(message, stripes, timers, setIsVisible);
@@ -292,7 +283,6 @@ const SessionEventContainer = ({ history, queryClient }) => {
SessionEventContainer.propTypes = {
history: PropTypes.object,
- queryClient: PropTypes.object,
};
export default SessionEventContainer;
diff --git a/src/components/SessionEventContainer/SessionEventContainer.test.js b/src/components/SessionEventContainer/SessionEventContainer.test.js
index 0001dad7..ddca458c 100644
--- a/src/components/SessionEventContainer/SessionEventContainer.test.js
+++ b/src/components/SessionEventContainer/SessionEventContainer.test.js
@@ -10,7 +10,6 @@ import SessionEventContainer, {
thisWindowRtrIstTimeout,
} from './SessionEventContainer';
import {
- logout,
setUnauthorizedPathToSession,
SESSION_NAME,
} from '../../loginServices';
@@ -73,14 +72,11 @@ describe('SessionEventContainer', () => {
describe('SessionEventContainer event listeners', () => {
it('thisWindowRtrError', async () => {
const history = { push: jest.fn() };
- const logoutMock = logout;
- logoutMock.mockReturnValue(Promise.resolve());
const setUnauthorizedPathToSessionMock = setUnauthorizedPathToSession;
setUnauthorizedPathToSessionMock.mockReturnValue(null);
- await thisWindowRtrError(null, { okapi: { url: 'http' } }, history);
- expect(logout).toHaveBeenCalled();
+ thisWindowRtrError(null, { okapi: { url: 'http' } }, history);
expect(setUnauthorizedPathToSession).toHaveBeenCalled();
expect(history.push).toHaveBeenCalledWith('/logout-timeout');
});
@@ -98,12 +94,7 @@ describe('SessionEventContainer event listeners', () => {
const history = { push: jest.fn() };
- const setUnauthorizedPathToSessionMock = setUnauthorizedPathToSession;
- setUnauthorizedPathToSessionMock.mockReturnValue(null);
-
- await thisWindowRtrIstTimeout(null, s, history);
- expect(logout).toHaveBeenCalled();
- expect(setUnauthorizedPathToSession).toHaveBeenCalled();
+ thisWindowRtrIstTimeout(null, s, history);
expect(history.push).toHaveBeenCalledWith('/logout-timeout');
});
@@ -124,13 +115,8 @@ describe('SessionEventContainer event listeners', () => {
}
};
const history = { push: jest.fn() };
- const qc = {};
- const setUnauthorizedPathToSessionMock = setUnauthorizedPathToSession;
- setUnauthorizedPathToSessionMock.mockReturnValue(null);
- await otherWindowStorage(e, s, history, qc);
- expect(logout).toHaveBeenCalledWith(s.okapi.url, s.store, qc);
- expect(setUnauthorizedPathToSession).toHaveBeenCalled();
+ otherWindowStorage(e, s, history);
expect(history.push).toHaveBeenCalledWith('/logout-timeout');
});
@@ -146,11 +132,9 @@ describe('SessionEventContainer event listeners', () => {
}
};
const history = { push: jest.fn() };
- const qc = {};
- await otherWindowStorage(e, s, history, qc);
- expect(logout).toHaveBeenCalledWith(s.okapi.url, s.store, qc);
- expect(history.push).toHaveBeenCalledWith('/');
+ otherWindowStorage(e, s, history);
+ expect(history.push).toHaveBeenCalledWith('/logout');
});
});