@axa-fr/react-oidc 7.29.4 → 7.29.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,123 @@
1
+ import { act, render, screen } from '@testing-library/react';
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
+
4
+ import Callback from '../default-component/Callback.component';
5
+ import SilentCallback from '../default-component/SilentCallback.component';
6
+ import SilentLogin from '../default-component/SilentLogin.component';
7
+ import OidcRoutes from './OidcRoutes';
8
+
9
+ vi.mock('../default-component/Callback.component', () => ({
10
+ default: vi.fn(() => <span>Callback</span>),
11
+ }));
12
+ vi.mock('../default-component/SilentCallback.component', () => ({
13
+ default: vi.fn(() => <span>Silent callback</span>),
14
+ }));
15
+ vi.mock('../default-component/SilentLogin.component', () => ({
16
+ default: vi.fn(() => <span>Silent login</span>),
17
+ }));
18
+
19
+ const props = {
20
+ configurationName: 'custom',
21
+ redirect_uri: new URL('/callback', window.location.href).href,
22
+ silent_redirect_uri: new URL('/silent-callback', window.location.href).href,
23
+ silent_login_uri: new URL('/silent-login', window.location.href).href,
24
+ location: {
25
+ getCurrentHref: () => window.location.href,
26
+ getPath: () => window.location.pathname,
27
+ getOrigin: () => window.location.origin,
28
+ open: vi.fn(),
29
+ reload: vi.fn(),
30
+ },
31
+ };
32
+
33
+ describe('OIDC route selection', () => {
34
+ beforeEach(() => {
35
+ vi.clearAllMocks();
36
+ window.history.replaceState(null, '', '/');
37
+ });
38
+
39
+ afterEach(() => {
40
+ window.history.replaceState(null, '', '/');
41
+ vi.restoreAllMocks();
42
+ });
43
+
44
+ it('renders application content on a non-OIDC route', () => {
45
+ render(<OidcRoutes {...props}>Application</OidcRoutes>);
46
+
47
+ expect(screen.getByText('Application')).toBeDefined();
48
+ expect(Callback).not.toHaveBeenCalled();
49
+ expect(SilentCallback).not.toHaveBeenCalled();
50
+ expect(SilentLogin).not.toHaveBeenCalled();
51
+ });
52
+
53
+ it.each([
54
+ ['/callback?code=example#', 'Callback', Callback],
55
+ ['/silent-callback', 'Silent callback', SilentCallback],
56
+ ['/silent-login', 'Silent login', SilentLogin],
57
+ ])('renders the matching handler for %s', (path, text, handler) => {
58
+ window.history.replaceState(null, '', path);
59
+
60
+ render(<OidcRoutes {...props}>Application</OidcRoutes>);
61
+
62
+ expect(screen.getByText(text)).toBeDefined();
63
+ expect(screen.queryByText('Application')).toBeNull();
64
+ expect(vi.mocked(handler).mock.calls[0][0]).toMatchObject({ configurationName: 'custom' });
65
+ });
66
+
67
+ it('gives the silent callback priority when configured paths overlap', () => {
68
+ window.history.replaceState(null, '', '/callback');
69
+
70
+ render(
71
+ <OidcRoutes
72
+ {...props}
73
+ silent_redirect_uri={props.redirect_uri}
74
+ silent_login_uri={props.redirect_uri}
75
+ />,
76
+ );
77
+
78
+ expect(screen.getByText('Silent callback')).toBeDefined();
79
+ expect(Callback).not.toHaveBeenCalled();
80
+ expect(SilentLogin).not.toHaveBeenCalled();
81
+ });
82
+
83
+ it('forwards custom callback components and navigation callbacks unchanged', () => {
84
+ window.history.replaceState(null, '', '/callback');
85
+ const success = (): null => null;
86
+ const error = (): null => null;
87
+ const history = vi.fn();
88
+ const navigate = vi.fn();
89
+
90
+ render(
91
+ <OidcRoutes
92
+ {...props}
93
+ callbackSuccessComponent={success}
94
+ callbackErrorComponent={error}
95
+ withCustomHistory={history}
96
+ navigateAfterCallback={navigate}
97
+ />,
98
+ );
99
+
100
+ expect(vi.mocked(Callback).mock.calls[0][0]).toMatchObject({
101
+ callBackSuccess: success,
102
+ callBackError: error,
103
+ withCustomHistory: history,
104
+ navigateAfterCallback: navigate,
105
+ });
106
+ });
107
+
108
+ it('updates the route on popstate and removes its listener on unmount', () => {
109
+ const addEventListener = vi.spyOn(window, 'addEventListener');
110
+ const removeEventListener = vi.spyOn(window, 'removeEventListener');
111
+ const { unmount } = render(<OidcRoutes {...props}>Application</OidcRoutes>);
112
+ const listener = addEventListener.mock.calls.find(([name]) => name === 'popstate')[1];
113
+
114
+ act(() => {
115
+ window.history.replaceState(null, '', '/silent-login');
116
+ window.dispatchEvent(new PopStateEvent('popstate'));
117
+ });
118
+ expect(screen.getByText('Silent login')).toBeDefined();
119
+
120
+ unmount();
121
+ expect(removeEventListener).toHaveBeenCalledWith('popstate', listener, false);
122
+ });
123
+ });
@@ -44,32 +44,26 @@ const OidcRoutes: FC<PropsWithChildren<OidcRoutesProps>> = ({
44
44
 
45
45
  const callbackPath = getPath(redirect_uri);
46
46
 
47
- if (silent_redirect_uri) {
48
- if (path === getPath(silent_redirect_uri)) {
49
- return <SilentCallbackComponent configurationName={configurationName} />;
50
- }
47
+ if (silent_redirect_uri && path === getPath(silent_redirect_uri)) {
48
+ return <SilentCallbackComponent configurationName={configurationName} />;
51
49
  }
52
50
 
53
- if (silent_login_uri) {
54
- if (path === getPath(silent_login_uri)) {
55
- return <SilentLoginComponent configurationName={configurationName} />;
56
- }
51
+ if (silent_login_uri && path === getPath(silent_login_uri)) {
52
+ return <SilentLoginComponent configurationName={configurationName} />;
57
53
  }
58
54
 
59
- switch (path) {
60
- case callbackPath:
61
- return (
62
- <CallbackComponent
63
- callBackError={callbackErrorComponent}
64
- callBackSuccess={callbackSuccessComponent}
65
- configurationName={configurationName}
66
- withCustomHistory={withCustomHistory}
67
- navigateAfterCallback={navigateAfterCallback}
68
- />
69
- );
70
- default:
71
- return <>{children}</>;
55
+ if (path === callbackPath) {
56
+ return (
57
+ <CallbackComponent
58
+ callBackError={callbackErrorComponent}
59
+ callBackSuccess={callbackSuccessComponent}
60
+ configurationName={configurationName}
61
+ withCustomHistory={withCustomHistory}
62
+ navigateAfterCallback={navigateAfterCallback}
63
+ />
64
+ );
72
65
  }
66
+ return <>{children}</>;
73
67
  };
74
68
 
75
69
  export default React.memo(OidcRoutes);