From 6761c00a19393a0312fbeaaffbaa607f6c1c04f6 Mon Sep 17 00:00:00 2001 From: Ryan Berger Date: Wed, 14 Aug 2024 10:39:00 -0400 Subject: [PATCH] Also adding timeout margin to fixed session warning --- src/components/Root/FFetch.js | 4 ++-- src/components/Root/FFetch.test.js | 6 ++--- src/components/Root/constants.js | 2 +- .../FixedLengthSessionWarning.js | 24 +++++-------------- .../FixedLengthSessionWarning.test.js | 15 +++++++++--- src/components/SessionEventContainer/utils.js | 16 +++++++++++++ 6 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 src/components/SessionEventContainer/utils.js diff --git a/src/components/Root/FFetch.js b/src/components/Root/FFetch.js index 658139dc2..9939260c3 100644 --- a/src/components/Root/FFetch.js +++ b/src/components/Root/FFetch.js @@ -65,7 +65,7 @@ import { RTR_AT_TTL_FRACTION, RTR_ERROR_EVENT, RTR_FLS_TIMEOUT_EVENT, - RTR_TIME_MARGIN_IN_MS, + RTR_TIME_MARGIN, RTR_FLS_WARNING_EVENT, RTR_RT_EXPIRY_IF_UNKNOWN, } from './constants'; @@ -143,7 +143,7 @@ export class FFetch { this.store.dispatch(setRtrFlsTimeout(setTimeout(() => { this.logger.log('rtr-fls', 'emitting RTR_FLS_TIMEOUT_EVENT'); window.dispatchEvent(new Event(RTR_FLS_TIMEOUT_EVENT)); - }, rtTimeoutInterval - RTR_TIME_MARGIN_IN_MS))); // Calling /logout a small margin before cookie is deleted to ensure it is included in the request + }, rtTimeoutInterval - ms(RTR_TIME_MARGIN)))); // Calling /logout a small margin before cookie is deleted to ensure it is included in the request }); }; diff --git a/src/components/Root/FFetch.test.js b/src/components/Root/FFetch.test.js index 461414e91..0ece3c833 100644 --- a/src/components/Root/FFetch.test.js +++ b/src/components/Root/FFetch.test.js @@ -11,7 +11,7 @@ import { RTR_AT_EXPIRY_IF_UNKNOWN, RTR_AT_TTL_FRACTION, RTR_FLS_WARNING_TTL, - RTR_TIME_MARGIN_IN_MS, + RTR_TIME_MARGIN, } from './constants'; jest.mock('../../loginServices', () => ({ @@ -207,7 +207,7 @@ describe('FFetch class', () => { expect(st).toHaveBeenCalledWith(expect.any(Function), (refreshTokenExpiration - whatTimeIsItMrFox) - ms(RTR_FLS_WARNING_TTL)); // FLS timeout - expect(st).toHaveBeenCalledWith(expect.any(Function), (refreshTokenExpiration - whatTimeIsItMrFox - RTR_TIME_MARGIN_IN_MS)); + expect(st).toHaveBeenCalledWith(expect.any(Function), (refreshTokenExpiration - whatTimeIsItMrFox - ms(RTR_TIME_MARGIN))); }); it('handles RTR data in the session', async () => { @@ -380,7 +380,7 @@ describe('FFetch class', () => { expect(st).toHaveBeenCalledWith(expect.any(Function), (refreshTokenExpiration - whatTimeIsItMrFox) - ms(RTR_FLS_WARNING_TTL)); // FLS timeout - expect(st).toHaveBeenCalledWith(expect.any(Function), (refreshTokenExpiration - whatTimeIsItMrFox - RTR_TIME_MARGIN_IN_MS)); + expect(st).toHaveBeenCalledWith(expect.any(Function), (refreshTokenExpiration - whatTimeIsItMrFox - ms(RTR_TIME_MARGIN))); }); }); diff --git a/src/components/Root/constants.js b/src/components/Root/constants.js index a4cb30681..e5831d1cf 100644 --- a/src/components/Root/constants.js +++ b/src/components/Root/constants.js @@ -92,4 +92,4 @@ export const RTR_RT_EXPIRY_IF_UNKNOWN = '10m'; * To account for minor delays between events (such as cookie expiration and API calls), * this is a small amount of time to wait so the proper order can be ensured if they happen simultaneously. */ -export const RTR_TIME_MARGIN_IN_MS = 200; +export const RTR_TIME_MARGIN = '200m'; diff --git a/src/components/SessionEventContainer/FixedLengthSessionWarning.js b/src/components/SessionEventContainer/FixedLengthSessionWarning.js index 09456ca79..d907818f9 100644 --- a/src/components/SessionEventContainer/FixedLengthSessionWarning.js +++ b/src/components/SessionEventContainer/FixedLengthSessionWarning.js @@ -6,6 +6,10 @@ import { MessageBanner } from '@folio/stripes-components'; +import { + RTR_TIME_MARGIN +} from '../Root/constants'; +import { timestampFormatter } from './utils'; import { useStripes } from '../../StripesContext'; /** @@ -17,7 +21,7 @@ import { useStripes } from '../../StripesContext'; */ const FixedLengthSessionWarning = () => { const stripes = useStripes(); - const [remainingMillis, setRemainingMillis] = useState(ms(stripes.config.rtr.fixedLengthSessionWarningTTL)); + const [remainingMillis, setRemainingMillis] = useState(ms(stripes.config.rtr.fixedLengthSessionWarningTTL) - ms(RTR_TIME_MARGIN)); // configure an interval timer that sets state each second, // counting down to 0. @@ -32,23 +36,7 @@ const FixedLengthSessionWarning = () => { }; }, []); - /** - * timestampFormatter - * convert time-remaining to mm:ss. Given the remaining time can easily be - * represented as elapsed-time since the JSDate epoch, convert to a - * Date object, format it, and extract the minutes and seconds. - * That is, given we have 99 seconds left, that converts to a Date - * like `1970-01-01T00:01:39.000Z`; extract the `01:39`. - */ - const timestampFormatter = () => { - if (remainingMillis >= 1000) { - return new Date(remainingMillis).toISOString().substring(14, 19); - } - - return '00:00'; - }; - - return {timestampFormatter()}; + return {timestampFormatter(remainingMillis)}; }; export default FixedLengthSessionWarning; diff --git a/src/components/SessionEventContainer/FixedLengthSessionWarning.test.js b/src/components/SessionEventContainer/FixedLengthSessionWarning.test.js index d20719c9c..ab7859d49 100644 --- a/src/components/SessionEventContainer/FixedLengthSessionWarning.test.js +++ b/src/components/SessionEventContainer/FixedLengthSessionWarning.test.js @@ -1,7 +1,10 @@ import { render, screen, waitFor } from '@folio/jest-config-stripes/testing-library/react'; +import ms from 'ms'; import Harness from '../../../test/jest/helpers/harness'; import FixedLengthSessionWarning from './FixedLengthSessionWarning'; +import { timestampFormatter } from './utils'; +import { RTR_TIME_MARGIN } from '../Root/constants'; jest.mock('../Root/token-util'); @@ -17,7 +20,9 @@ describe('FixedLengthSessionWarning', () => { it('renders a warning with seconds remaining', async () => { render(); screen.getByText(/stripes-core.rtr.fixedLengthSession.timeRemaining/); - screen.getByText(/01:39/); + screen.getByText( + new RegExp(timestampFormatter(ms(stripes.config.rtr.fixedLengthSessionWarningTTL) - ms(RTR_TIME_MARGIN))) + ); }); it('renders 0:00 when time expires', async () => { @@ -31,7 +36,9 @@ describe('FixedLengthSessionWarning', () => { render(); screen.getByText(/stripes-core.rtr.fixedLengthSession.timeRemaining/); - screen.getByText(/0:00/); + screen.getByText( + new RegExp(timestampFormatter(ms(stripes.config.rtr.fixedLengthSessionWarningTTL) - ms(RTR_TIME_MARGIN))) + ); }); // I've never had great luck with jest's fake timers, https://jestjs.io/docs/timer-mocks @@ -53,7 +60,9 @@ describe('FixedLengthSessionWarning', () => { expect(setInterval).toHaveBeenCalledTimes(1); expect(setInterval).toHaveBeenLastCalledWith(expect.any(Function), 1000); - await waitFor(() => screen.getByText(/00:09/), { timeout: 2000 }); + await waitFor(() => screen.getByText( + new RegExp(timestampFormatter(ms(stripes.config.rtr.fixedLengthSessionWarningTTL) - ms(RTR_TIME_MARGIN))) + ), { timeout: 2000 }); }); }); }); diff --git a/src/components/SessionEventContainer/utils.js b/src/components/SessionEventContainer/utils.js new file mode 100644 index 000000000..4dc8dc60e --- /dev/null +++ b/src/components/SessionEventContainer/utils.js @@ -0,0 +1,16 @@ +/** + * timestampFormatter + * convert time-remaining to mm:ss. Given the remaining time can easily be + * represented as elapsed-time since the JSDate epoch, convert to a + * Date object, format it, and extract the minutes and seconds. + * That is, given we have 99 seconds left, that converts to a Date + * like `1970-01-01T00:01:39.000Z`; extract the `01:39`. + */ +// eslint-disable-next-line import/prefer-default-export +export const timestampFormatter = (remainingMillis) => { + if (remainingMillis >= 1000) { + return new Date(remainingMillis).toISOString().substring(14, 19); + } + + return '00:00'; +};