Skip to content

Commit

Permalink
STCOR-906 consume react-query QueryClient in <Logout>
Browse files Browse the repository at this point in the history
Correctly pass all three required arguments from `<Logout>` to
`loginServices::logout()`: gateway URL, redux store, react-query
QueryClient. The third was missing, resulting in an NPE during
`logout()` that caused flow to skip to the `finally` clause, skipping
the code that cleared localforage. Sometimes localforage appears to get
cleared anyway, but sometimes not, in which case the session may fail to
terminate even when the fixed-length session timer reaches 00:00.

This is one of those "How did this ever work?!? And how did we not
notice?!?" situations.

Refs STCOR-906
  • Loading branch information
zburke committed Nov 26, 2024
1 parent 1c73afd commit 9ff9f59
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Provide `<IfAnyPermission>` and `stripes.hasAnyPermission()`. Refs STCOR-910.
* Use the `users-keycloak/_self` endpoint conditionally when the `users-keycloak` interface is present; otherwise, use `bl-users/_self` within `useUserTenantPermissions`. Refs STCOR-905.
* Don't override initial discovery and okapi data in test mocks. Refs STCOR-913.
* `<Logout>` must consume `QueryClient` in order to supply it to `loginServices::logout()`. Refs STCOR-907.

## [10.2.0](https://github.com/folio-org/stripes-core/tree/v10.2.0) (2024-10-11)
[Full Changelog](https://github.com/folio-org/stripes-core/compare/v10.1.1...v10.2.0)
Expand Down
4 changes: 3 additions & 1 deletion src/components/Logout/Logout.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { useLocation } from 'react-router';
import { FormattedMessage } from 'react-intl';
import { useQueryClient } from 'react-query';
import { branding } from 'stripes-config';

import {
Expand Down Expand Up @@ -35,14 +36,15 @@ const Logout = () => {
const stripes = useStripes();
const [didLogout, setDidLogout] = useState(false);
const location = useLocation();
const queryClient = useQueryClient();

const messageId = location.pathName === '/logout-timeout' ? 'stripes-core.rtr.idleSession.sessionExpiredSoSad' : 'stripes-core.logoutComplete';

useEffect(
() => {
if (stripes.okapi.isAuthenticated) {
// returns a promise, which we ignore
logout(stripes.okapi.url, stripes.store)
logout(stripes.okapi.url, stripes.store, queryClient)
.then(setDidLogout(true));
} else {
setDidLogout(true);
Expand Down
4 changes: 3 additions & 1 deletion src/loginServices.js
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,9 @@ export async function logout(okapiUrl, store, queryClient) {
store.dispatch(resetStore());

// clear react-query cache
queryClient.removeQueries();
if (queryClient) {
queryClient.removeQueries();
}
})
// clear shared storage
.then(localforage.removeItem(SESSION_NAME))
Expand Down
25 changes: 25 additions & 0 deletions src/loginServices.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,31 @@ describe('logout', () => {
expect(global.fetch).not.toHaveBeenCalled();
});
});

describe('react-query client', () => {
afterEach(() => {
mockFetchCleanUp();
});

it('calls removeQueries given valid client', async () => {
global.fetch = jest.fn().mockImplementation(() => Promise.resolve());
const store = {
dispatch: jest.fn(),
};
const rqc = {
removeQueries: jest.fn(),
};

let res;
await logout('', store, rqc)
.then(() => {
res = true;
});

expect(res).toBe(true);
expect(rqc.removeQueries).toHaveBeenCalled();
});
});
});

describe('getLocale', () => {
Expand Down

0 comments on commit 9ff9f59

Please sign in to comment.