Skip to content

Commit

Permalink
fix: avoid build time error when react-router-dom v6 is in app depe…
Browse files Browse the repository at this point in the history
…ndencies

OKTA-472376
<<<Jenkins Check-In of Tested SHA: 53d64f2 for [email protected]>>>
Artifact: okta-react
Files changed count: 5
PR Link: "#213"
  • Loading branch information
flying-sheep authored and eng-prod-CI-bot-okta committed Feb 24, 2022
1 parent 31469df commit cf00f9d
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 3 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# 6.4.3

### Bug Fixes

- [#213](https://github.com/okta/okta-react/pull/213)
- Avoids build time error when `react-router-dom` v6 is in app dependencies
- Throws unsupported error when `SecureRoute` is used with `react-router-dom` v6

# 6.4.2

### Bug Fixes
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
},
"peerDependencies": {
"@okta/okta-auth-js": "^5.3.1 || ^6.0.0",
"@types/react-router-dom": "^5.1.6",
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"react-router-dom": ">=5.1.0"
Expand Down
17 changes: 15 additions & 2 deletions src/SecureRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,22 @@
import * as React from 'react';
import { useOktaAuth, OnAuthRequiredFunction } from './OktaContext';
import * as ReactRouterDom from 'react-router-dom';
import { toRelativeUrl } from '@okta/okta-auth-js';
import { toRelativeUrl, AuthSdkError } from '@okta/okta-auth-js';
import OktaError from './OktaError';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let useMatch: any;
if ('useRouteMatch' in ReactRouterDom) {
// trick static analyzer to avoid "'useRouteMatch' is not exported" error
// eslint-disable-next-line @typescript-eslint/no-explicit-any
useMatch = (ReactRouterDom as any)['useRouteMatch' in ReactRouterDom ? 'useRouteMatch' : ''];
} else {
// throw when useMatch is triggered
useMatch = () => {
throw new AuthSdkError('Unsupported: SecureRoute only works with react-router-dom v5 or any router library with compatible APIs. See examples under the "samples" folder for how to implement your own custom SecureRoute Component.');
};
}

const SecureRoute: React.FC<{
onAuthRequired?: OnAuthRequiredFunction;
errorComponent?: React.ComponentType<{ error: Error }>;
Expand All @@ -25,7 +38,7 @@ const SecureRoute: React.FC<{
...routeProps
}) => {
const { oktaAuth, authState, _onAuthRequired } = useOktaAuth();
const match = ReactRouterDom.useRouteMatch(routeProps);
const match = useMatch(routeProps);
const pendingLogin = React.useRef(false);
const [handleLoginError, setHandleLoginError] = React.useState<Error | null>(null);
const ErrorReporter = errorComponent || OktaError;
Expand Down
88 changes: 88 additions & 0 deletions test/jest/reactRouterV6.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*!
* Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/

import * as React from 'react';
import { act } from 'react-dom/test-utils';
import { render } from 'react-dom';
import SecureRoute from '../../src/SecureRoute';
import OktaContext from '../../src/OktaContext';
import { AuthSdkError } from '@okta/okta-auth-js';

jest.mock('react-router-dom', () => ({
__esModule: true,
useMatch: jest.fn()
}));

class ErrorBoundary extends React.Component {
constructor(props: any) {
super(props);
this.state = {
error: null
} as {
error: AuthSdkError | null
};
}

componentDidCatch(error: AuthSdkError) {
this.setState({ error: error });
}

render() {
if (this.state.error) {
// You can render any custom fallback UI
return <p>{ this.state.error.toString() }</p>;
}

return this.props.children;
}
}

describe('react-router-dom v6', () => {
let oktaAuth: any;
let authState: any;

beforeEach(() => {
authState = null;
oktaAuth = {
options: {},
authStateManager: {
getAuthState: jest.fn().mockImplementation(() => authState),
subscribe: jest.fn(),
unsubscribe: jest.fn(),
updateAuthState: jest.fn(),
},
isLoginRedirect: jest.fn().mockImplementation(() => false),
handleLoginRedirect: jest.fn(),
signInWithRedirect: jest.fn(),
setOriginalUri: jest.fn(),
start: jest.fn(),
};
});

it('throws unsupported error', async () => {
const container = document.createElement('div');
await act(async () => {
render(
<OktaContext.Provider value={{
oktaAuth: oktaAuth,
authState
}}>
<ErrorBoundary>
<SecureRoute path="/" />
</ErrorBoundary>
</OktaContext.Provider>,
container
);
});
expect(container.innerHTML).toBe('<p>AuthSdkError: Unsupported: SecureRoute only works with react-router-dom v5 or any router library with compatible APIs. See examples under the "samples" folder for how to implement your own custom SecureRoute Component.</p>');
})
});

0 comments on commit cf00f9d

Please sign in to comment.