Skip to content

Commit

Permalink
Merge branch 'master' into STCOR-926
Browse files Browse the repository at this point in the history
  • Loading branch information
zburke authored Jan 6, 2025
2 parents c9c13af + f7d2b36 commit 2ba1c73
Show file tree
Hide file tree
Showing 45 changed files with 252 additions and 115 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* @folio-org/stripes-force

2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* 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.
* On resuming session, spread session and `_self` together to preserve session values. Refs STCOR-912.

## [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
16 changes: 16 additions & 0 deletions src/components/BadRequestScreen/BadRequestScreen.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { render, screen } from '@folio/jest-config-stripes/testing-library/react';

import BadRequestScreen from './BadRequestScreen';

jest.mock('../../Pluggable', () => (props) => props.children);

describe('BadRequestScreen', () => {
it('renders expected message', () => {
render(<BadRequestScreen />);

screen.getByText('stripes-core.front.error.header');
screen.getByText(/stripes-core.front.error.general.message/);
});
});


20 changes: 11 additions & 9 deletions src/components/IfInterface/IfInterface.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import { StripesContext } from '../../StripesContext';
import { useStripes } from '../../StripesContext';

const IfInterface = ({ children, name, version }) => (
<StripesContext.Consumer>
{stripes => (
stripes.hasInterface(name, version) ? children : null
)}
</StripesContext.Consumer>
);
const IfInterface = ({ children, name, version }) => {
const stripes = useStripes();
const hasInterface = stripes.hasInterface(name, version);

if (typeof children === 'function') {
return children({ hasInterface });
}

return hasInterface ? children : null;
};

IfInterface.propTypes = {
children: PropTypes.node,
Expand Down
33 changes: 33 additions & 0 deletions src/components/IfInterface/IfInterface.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { render, screen } from '@folio/jest-config-stripes/testing-library/react';

import { useStripes } from '../../StripesContext';
import Stripes from '../../Stripes';
import IfInterface from './IfInterface';

jest.mock('../../StripesContext');
const stripes = new Stripes({
discovery: {
interfaces: {
foo: '1.0'
}
},
logger: {
log: jest.fn(),
}
});

// IfInterface is just a component version of Stripes::hasInterface
// See more extensive tests there.
describe('IfInterface', () => {
it('returns true if interface is present', () => {
useStripes.mockReturnValue(stripes);
render(<IfInterface name="foo">monkey</IfInterface>);
expect(screen.queryByText(/monkey/)).toBeTruthy();
});

it('returns false if interface is absent', () => {
useStripes.mockReturnValue(stripes);
render(<IfInterface name="paul,is,dead">monkey</IfInterface>);
expect(screen.queryByText(/monkey/)).toBeFalsy();
});
});
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
1 change: 1 addition & 0 deletions src/components/Logout/Logout.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getUnauthorizedPathFromSession, logout, setUnauthorizedPathToSession }
jest.mock('../OrganizationLogo');
jest.mock('../../StripesContext');
jest.mock('react-router');
jest.mock('react-query');

jest.mock('../../loginServices', () => ({
...jest.requireActual('../../loginServices'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { render, screen } from '@folio/jest-config-stripes/testing-library/react';

import BadRequestScreen from './ResetPasswordNotAvailableScreen';

jest.mock('../../Pluggable', () => (props) => props.children);

describe('ResetPasswordNotAvailableScreen', () => {
it('renders expected message', () => {
render(<BadRequestScreen />);

screen.getByText('stripes-core.front.error.header');
screen.getByText('stripes-core.front.error.setPassword.message');
});
});
21 changes: 21 additions & 0 deletions src/components/SSOLogin/SSOLogin.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { render, screen } from '@folio/jest-config-stripes/testing-library/react';
import userEvent from '@folio/jest-config-stripes/testing-library/user-event';

import SSOLogin from './SSOLogin';

describe('Login via SSO', () => {
it('renders a button', () => {
const fx = jest.fn();
render(<SSOLogin handleSSOLogin={fx} />);
screen.getByText('stripes-core.loginViaSSO');
});

it('calls the callback', async () => {
const fx = jest.fn();
render(<SSOLogin handleSSOLogin={fx} />);
await userEvent.click(screen.getByText('stripes-core.loginViaSSO'));

expect(fx).toHaveBeenCalled();
});
});

51 changes: 0 additions & 51 deletions src/components/SSOLogin/tests/SSOLogin-test.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const FixedLengthSessionWarning = () => {
return '00:00';
};

return <MessageBanner show contentClassName={css.fixedSessionBanner}><FormattedMessage id="stripes-core.rtr.fixedLengthSession.timeRemaining" />{timestampFormatter()}</MessageBanner>;
return <MessageBanner show contentClassName={css.fixedSessionBanner}><FormattedMessage id="stripes-core.rtr.fixedLengthSession.timeRemaining" /> {timestampFormatter()}</MessageBanner>;
};

export default FixedLengthSessionWarning;
9 changes: 7 additions & 2 deletions 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 Expand Up @@ -807,7 +809,10 @@ export function validateUser(okapiUrl, store, tenant, session) {
// data isn't provided by _self.
store.dispatch(setSessionData({
isAuthenticated: true,
user,
// spread data from the previous session (which may include session-specific
// values such as the current service point), and the restructured user object
// (which includes permissions in a lookup-friendly way)
user: { ...session.user, ...user },
perms,
tenant: sessionTenant,
token,
Expand Down
33 changes: 31 additions & 2 deletions src/loginServices.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,11 @@ describe('validateUser', () => {
};

const session = {
user: { id: 'id', username: 'username' },
user: {
id: 'id',
username: 'username',
storageOnlyValue: 'is still persisted',
},
perms: { foo: true },
tenant: sessionTenant,
token: 'token',
Expand All @@ -361,7 +365,7 @@ describe('validateUser', () => {
await validateUser('url', store, tenant, session);

const updatedSession = {
user: data.user,
user: { ...session.user, ...data.user },
isAuthenticated: true,
perms: { ask: true, tell: true },
tenant: session.tenant,
Expand Down Expand Up @@ -564,6 +568,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
4 changes: 3 additions & 1 deletion translations/stripes-core/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,7 @@
"tenantChoose": "Select your tenant/library",
"tenantLibrary": "Tenant/Library",
"errors.saml.missingToken": "No <code>code</code> query parameter.",
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:"
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:",
"logoutComplete": "You have logged out.",
"errors.oidc": "Error: server is forbidden, unreachable, or unavailable."
}
4 changes: 3 additions & 1 deletion translations/stripes-core/ber.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,7 @@
"tenantChoose": "Select your tenant/library",
"tenantLibrary": "Tenant/Library",
"errors.saml.missingToken": "No <code>code</code> query parameter.",
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:"
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:",
"logoutComplete": "You have logged out.",
"errors.oidc": "Error: server is forbidden, unreachable, or unavailable."
}
4 changes: 3 additions & 1 deletion translations/stripes-core/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,7 @@
"tenantChoose": "Select your tenant/library",
"tenantLibrary": "Tenant/Library",
"errors.saml.missingToken": "No <code>code</code> query parameter.",
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:"
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:",
"logoutComplete": "You have logged out.",
"errors.oidc": "Error: server is forbidden, unreachable, or unavailable."
}
4 changes: 3 additions & 1 deletion translations/stripes-core/cs_CZ.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,7 @@
"tenantChoose": "Vybrat nájemce/knihovnu",
"tenantLibrary": "Nájemce/Knihovna",
"errors.saml.missingToken": "No <code>code</code> query parameter.",
"rtr.fixedLengthSession.timeRemaining": "Vaše relace brzy skončí! Zbývající čas:"
"rtr.fixedLengthSession.timeRemaining": "Vaše relace brzy skončí! Zbývající čas:",
"logoutComplete": "Odhlásili jste se.",
"errors.oidc": "Error: server is forbidden, unreachable, or unavailable."
}
4 changes: 3 additions & 1 deletion translations/stripes-core/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,7 @@
"tenantChoose": "Select your tenant/library",
"tenantLibrary": "Tenant/Library",
"errors.saml.missingToken": "No <code>code</code> query parameter.",
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:"
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:",
"logoutComplete": "You have logged out.",
"errors.oidc": "Error: server is forbidden, unreachable, or unavailable."
}
6 changes: 4 additions & 2 deletions translations/stripes-core/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"mainnav.topLevelLabel": "Primär",
"mainnav.applicationListLabel": "App-Liste",
"errors.default.error": "Leider stimmen die Angaben nicht mit unserem Datenbestand überein.",
"errors.username.incorrect": "Dieses FOLIO-Konto kann nicht gefunden werden. Bitte wenden Sie sich an Ihre Folio-Systemadministration.",
"errors.username.incorrect": "Dieses FOLIO-Konto kann nicht gefunden werden. Bitte wenden Sie sich an Ihre FOLIO-Systemadministration.",
"errors.password.incorrect": "Anmeldeinformationen stimmen nicht",
"errors.user.blocked": "Aus Sicherheitsgründen wurde Ihr Konto gesperrt. Bitte versuchen Sie es erneut oder wenden Sie sich an Ihre FOLIO-Systemadministration.",
"errors.password.match.error": "Passwort stimmt nicht überein. Passwort erneut eingeben.",
Expand Down Expand Up @@ -158,5 +158,7 @@
"tenantChoose": "Select your tenant/library",
"tenantLibrary": "Tenant/Library",
"errors.saml.missingToken": "No <code>code</code> query parameter.",
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:"
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:",
"logoutComplete": "You have logged out.",
"errors.oidc": "Error: server is forbidden, unreachable, or unavailable."
}
4 changes: 3 additions & 1 deletion translations/stripes-core/en_GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,7 @@
"tenantChoose": "Select your tenant/library",
"tenantLibrary": "Tenant/Library",
"errors.saml.missingToken": "No <code>code</code> query parameter.",
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:"
"rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:",
"logoutComplete": "You have logged out.",
"errors.oidc": "Error: server is forbidden, unreachable, or unavailable."
}
Loading

0 comments on commit 2ba1c73

Please sign in to comment.