@truedat/auth 7.5.9 → 7.5.10

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.
Files changed (160) hide show
  1. package/package.json +40 -64
  2. package/src/groups/components/EditGroup.js +0 -1
  3. package/src/groups/components/Group.js +0 -1
  4. package/src/groups/components/GroupBreadcrumbs.js +1 -2
  5. package/src/groups/components/GroupCard.js +3 -3
  6. package/src/groups/components/GroupCards.js +2 -3
  7. package/src/groups/components/GroupForm.js +0 -1
  8. package/src/groups/components/GroupLoader.js +19 -51
  9. package/src/groups/components/GroupUsers.js +4 -3
  10. package/src/groups/components/GroupUsersTable.js +4 -4
  11. package/src/groups/components/GroupsLoader.js +2 -2
  12. package/src/groups/components/GroupsSearchLoader.js +1 -1
  13. package/src/groups/components/NewGroup.js +0 -1
  14. package/src/groups/components/__tests__/Group.spec.js +0 -1
  15. package/src/groups/components/__tests__/GroupCard.spec.js +23 -7
  16. package/src/groups/components/__tests__/GroupCards.spec.js +9 -6
  17. package/src/groups/components/__tests__/GroupLoader.spec.js +71 -0
  18. package/src/groups/components/__tests__/GroupUsers.spec.js +8 -12
  19. package/src/groups/components/__tests__/GroupUsersTable.spec.js +34 -42
  20. package/src/groups/components/__tests__/GroupsSearchLoader.spec.js +0 -1
  21. package/src/groups/components/__tests__/__snapshots__/Group.spec.js.snap +1 -2
  22. package/src/groups/components/__tests__/__snapshots__/GroupCard.spec.js.snap +43 -94
  23. package/src/groups/components/__tests__/__snapshots__/GroupCards.spec.js.snap +118 -53
  24. package/src/groups/components/__tests__/__snapshots__/GroupLoader.spec.js.snap +11 -0
  25. package/src/groups/components/__tests__/__snapshots__/GroupUsers.spec.js.snap +38 -45
  26. package/src/groups/components/__tests__/__snapshots__/GroupUsersTable.spec.js.snap +121 -213
  27. package/src/groups/components/index.js +1 -1
  28. package/src/groups/sagas/__tests__/deleteGroupUser.spec.js +6 -6
  29. package/src/groups/sagas/deleteGroup.js +1 -1
  30. package/src/groups/sagas/deleteGroupUser.js +2 -2
  31. package/src/groups/sagas/fetchGroup.js +1 -1
  32. package/src/groups/sagas/updateGroup.js +1 -1
  33. package/src/roles/components/NewRole.js +0 -1
  34. package/src/roles/components/PermissionGroup.js +0 -1
  35. package/src/roles/components/Role.js +8 -3
  36. package/src/roles/components/RoleCards.js +2 -3
  37. package/src/roles/components/RoleForm.js +1 -1
  38. package/src/roles/components/RoleLoader.js +26 -39
  39. package/src/roles/components/RoleRoutes.js +29 -32
  40. package/src/roles/components/RoleSelector.js +0 -1
  41. package/src/roles/components/Roles.js +1 -3
  42. package/src/roles/components/RolesLoader.js +2 -2
  43. package/src/roles/components/__tests__/PermissionGroup.spec.js +7 -17
  44. package/src/roles/components/__tests__/Role.spec.js +0 -1
  45. package/src/roles/components/__tests__/RoleCards.spec.js +11 -10
  46. package/src/roles/components/__tests__/RoleRoutes.spec.js +53 -7
  47. package/src/roles/components/__tests__/RoleSelector.spec.js +0 -1
  48. package/src/roles/components/__tests__/Roles.spec.js +2 -3
  49. package/src/roles/components/__tests__/__snapshots__/PermissionGroup.spec.js.snap +3 -5
  50. package/src/roles/components/__tests__/__snapshots__/Role.spec.js.snap +4 -4
  51. package/src/roles/components/__tests__/__snapshots__/RoleCards.spec.js.snap +57 -127
  52. package/src/roles/components/__tests__/__snapshots__/RoleRoutes.spec.js.snap +38 -5
  53. package/src/roles/components/__tests__/__snapshots__/RoleSelector.spec.js.snap +1 -1
  54. package/src/roles/components/__tests__/__snapshots__/Roles.spec.js.snap +6 -3
  55. package/src/roles/components/index.js +1 -1
  56. package/src/roles/reducers/rolePermissions.js +1 -1
  57. package/src/roles/reducers/roleRedirect.js +1 -1
  58. package/src/roles/sagas/deleteRole.js +1 -1
  59. package/src/roles/sagas/fetchRole.js +1 -1
  60. package/src/roles/sagas/fetchRolePermissions.js +1 -1
  61. package/src/roles/sagas/updateRole.js +1 -1
  62. package/src/roles/sagas/updateRolePermissions.js +1 -1
  63. package/src/sessions/components/Auth0Callback.js +5 -4
  64. package/src/sessions/components/Auth0LoginButton.js +2 -2
  65. package/src/sessions/components/AuthMethodsLoader.js +10 -19
  66. package/src/sessions/components/LoginButtons.js +4 -4
  67. package/src/sessions/components/NonceCallback.js +21 -38
  68. package/src/sessions/components/OidcLoginButton.js +0 -1
  69. package/src/sessions/components/OpenIDConnect.js +5 -4
  70. package/src/sessions/components/PrivateRoute.js +25 -57
  71. package/src/sessions/components/ProxyLoginCallback.js +0 -2
  72. package/src/sessions/components/SamlCallback.js +0 -2
  73. package/src/sessions/components/UnauthorizedRoute.js +28 -31
  74. package/src/sessions/components/__tests__/Auth0LoginButton.spec.js +12 -12
  75. package/src/sessions/components/__tests__/AuthMethodsLoader.spec.js +15 -12
  76. package/src/sessions/components/__tests__/NonceCallback.spec.js +84 -0
  77. package/src/sessions/components/__tests__/OidcLoginButton.spec.js +10 -10
  78. package/src/sessions/components/__tests__/OpenIDConnect.spec.js +7 -8
  79. package/src/sessions/components/__tests__/PrivateRoute.spec.js +90 -0
  80. package/src/sessions/components/__tests__/UnauthorizedRoute.spec.js +88 -0
  81. package/src/sessions/components/__tests__/__snapshots__/Auth0LoginButton.spec.js.snap +22 -24
  82. package/src/sessions/components/__tests__/__snapshots__/NonceCallback.spec.js.snap +18 -0
  83. package/src/sessions/components/__tests__/__snapshots__/OidcLoginButton.spec.js.snap +18 -18
  84. package/src/sessions/components/__tests__/__snapshots__/PrivateRoute.spec.js.snap +9 -0
  85. package/src/sessions/components/__tests__/__snapshots__/UnauthorizedRoute.spec.js.snap +9 -0
  86. package/src/sessions/components/index.js +1 -1
  87. package/src/sessions/sagas/__tests__/login.spec.js +4 -4
  88. package/src/sessions/sagas/__tests__/refresh.spec.js +2 -2
  89. package/src/sessions/sagas/__tests__/token.spec.js +4 -4
  90. package/src/sessions/sagas/login.js +5 -5
  91. package/src/sessions/sagas/refresh.js +2 -2
  92. package/src/sessions/sagas/token.js +2 -2
  93. package/src/users/components/AdminUserRoutes.js +35 -51
  94. package/src/users/components/EditUser.js +0 -1
  95. package/src/users/components/GroupUserCrumbs.js +8 -8
  96. package/src/users/components/InitialUser.js +0 -1
  97. package/src/users/components/NewUser.js +0 -1
  98. package/src/users/components/Password.js +0 -1
  99. package/src/users/components/User.js +2 -2
  100. package/src/users/components/UserAclRow.js +1 -2
  101. package/src/users/components/UserAcls.js +0 -1
  102. package/src/users/components/UserActions.js +1 -2
  103. package/src/users/components/UserBreadcrumbs.js +2 -3
  104. package/src/users/components/UserCard.js +3 -3
  105. package/src/users/components/UserCards.js +5 -4
  106. package/src/users/components/UserDomainsFilter.js +2 -5
  107. package/src/users/components/UserForm.js +8 -33
  108. package/src/users/components/UserGroupAclRow.js +1 -2
  109. package/src/users/components/UserGroupAcls.js +0 -1
  110. package/src/users/components/UserLoader.js +21 -48
  111. package/src/users/components/UserPassword.js +0 -1
  112. package/src/users/components/UserRoutes.js +73 -7
  113. package/src/users/components/UserSelector.js +0 -1
  114. package/src/users/components/UserTabs.js +1 -2
  115. package/src/users/components/UsersAndGroups.js +6 -6
  116. package/src/users/components/UsersLoader.js +2 -2
  117. package/src/users/components/UsersSearchLoader.js +2 -1
  118. package/src/users/components/__tests__/CanInitLoader.spec.js +6 -13
  119. package/src/users/components/__tests__/EditUser.spec.js +4 -33
  120. package/src/users/components/__tests__/InitialUser.spec.js +4 -34
  121. package/src/users/components/__tests__/NewUser.spec.js +4 -35
  122. package/src/users/components/__tests__/Password.spec.js +59 -69
  123. package/src/users/components/__tests__/User.spec.js +1 -2
  124. package/src/users/components/__tests__/UserAclRow.spec.js +5 -7
  125. package/src/users/components/__tests__/UserAcls.spec.js +8 -9
  126. package/src/users/components/__tests__/UserActions.spec.js +4 -5
  127. package/src/users/components/__tests__/UserCard.spec.js +11 -11
  128. package/src/users/components/__tests__/UserCards.spec.js +39 -31
  129. package/src/users/components/__tests__/UserDomainsFilter.spec.js +12 -22
  130. package/src/users/components/__tests__/UserForm.spec.js +24 -44
  131. package/src/users/components/__tests__/UserGroupAclRow.spec.js +1 -2
  132. package/src/users/components/__tests__/UserGroupAcls.spec.js +8 -9
  133. package/src/users/components/__tests__/UserLoader.spec.js +85 -0
  134. package/src/users/components/__tests__/UserPassword.spec.js +8 -21
  135. package/src/users/components/__tests__/UserRoutes.spec.js +129 -4
  136. package/src/users/components/__tests__/UserSelector.spec.js +0 -1
  137. package/src/users/components/__tests__/UsersAndGroups.spec.js +45 -5
  138. package/src/users/components/__tests__/UsersSearchLoader.spec.js +0 -1
  139. package/src/users/components/__tests__/__snapshots__/EditUser.spec.js.snap +23 -21
  140. package/src/users/components/__tests__/__snapshots__/InitialUser.spec.js.snap +22 -21
  141. package/src/users/components/__tests__/__snapshots__/NewUser.spec.js.snap +25 -23
  142. package/src/users/components/__tests__/__snapshots__/Password.spec.js.snap +8 -7
  143. package/src/users/components/__tests__/__snapshots__/User.spec.js.snap +7 -6
  144. package/src/users/components/__tests__/__snapshots__/UserAclRow.spec.js.snap +12 -11
  145. package/src/users/components/__tests__/__snapshots__/UserActions.spec.js.snap +56 -67
  146. package/src/users/components/__tests__/__snapshots__/UserCard.spec.js.snap +56 -70
  147. package/src/users/components/__tests__/__snapshots__/UserCards.spec.js.snap +117 -83
  148. package/src/users/components/__tests__/__snapshots__/UserDomainsFilter.spec.js.snap +2 -2
  149. package/src/users/components/__tests__/__snapshots__/UserForm.spec.js.snap +21 -20
  150. package/src/users/components/__tests__/__snapshots__/UserLoader.spec.js.snap +3 -0
  151. package/src/users/components/__tests__/__snapshots__/UserPassword.spec.js.snap +9 -7
  152. package/src/users/components/__tests__/__snapshots__/UserRoutes.spec.js.snap +170 -16
  153. package/src/users/components/__tests__/__snapshots__/UserSelector.spec.js.snap +1 -1
  154. package/src/users/components/__tests__/__snapshots__/UsersAndGroups.spec.js.snap +75 -14
  155. package/src/users/sagas/__tests__/fetchUser.spec.js +3 -5
  156. package/src/users/sagas/__tests__/updateUser.spec.js +1 -1
  157. package/src/users/sagas/deleteUser.js +1 -1
  158. package/src/users/sagas/fetchUser.js +1 -1
  159. package/src/users/sagas/updateUser.js +1 -1
  160. package/src/users/components/__tests__/__snapshots__/CanInitLoader.spec.js.snap +0 -3
@@ -1,8 +1,9 @@
1
1
  import _ from "lodash/fp";
2
- import React, { useEffect } from "react";
2
+ import { useEffect } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
- import { useLocation, Redirect } from "react-router-dom";
5
+ import { useLocation } from "react-router";
6
+ import { Navigate } from "react-router";
6
7
  import auth0 from "auth0-js";
7
8
  import { Loading } from "@truedat/core/components";
8
9
  import queryString from "query-string";
@@ -41,9 +42,9 @@ export const CallbackOrRedirect = ({
41
42
  }, [token, auth0Config, auth0Login, location.hash]);
42
43
 
43
44
  if (token) {
44
- return <Redirect to={to} />;
45
+ return <Navigate to={to} />;
45
46
  } else if (authRedirect) {
46
- return <Redirect to={authRedirect} />;
47
+ return <Navigate to={authRedirect} />;
47
48
  } else {
48
49
  return <Loading size="massive" />;
49
50
  }
@@ -1,11 +1,11 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
2
+ import { Component } from "react";
3
3
  import auth0 from "auth0-js";
4
4
  import PropTypes from "prop-types";
5
5
  import { connect } from "react-redux";
6
6
  import { FormattedMessage } from "react-intl";
7
7
 
8
- export class Auth0LoginButton extends React.Component {
8
+ export class Auth0LoginButton extends Component {
9
9
  static propTypes = {
10
10
  icon: PropTypes.string,
11
11
  };
@@ -1,25 +1,16 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
3
- import PropTypes from "prop-types";
4
- import { connect } from "react-redux";
5
- import { withRouter } from "react-router-dom";
2
+ import { useEffect } from "react";
3
+ import { useDispatch } from "react-redux";
4
+ import { useLocation } from "react-router";
6
5
  import { fetchAuthMethods } from "../routines";
7
6
 
8
- export class AuthMethodsLoader extends React.Component {
9
- static propTypes = {
10
- fetchAuthMethods: PropTypes.func,
11
- };
7
+ export default function AuthMethodsLoader() {
8
+ const location = useLocation();
9
+ const dispatch = useDispatch();
12
10
 
13
- componentDidMount() {
14
- const { fetchAuthMethods, location } = this.props;
15
- if (fetchAuthMethods) {
16
- fetchAuthMethods(location);
17
- }
18
- }
11
+ useEffect(() => {
12
+ dispatch(fetchAuthMethods(location));
13
+ }, [dispatch, location]);
19
14
 
20
- render = () => null;
15
+ return null;
21
16
  }
22
-
23
- export default connect(() => ({}), { fetchAuthMethods })(
24
- withRouter(AuthMethodsLoader)
25
- );
@@ -1,5 +1,5 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
2
+ import { Component } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
5
  import { FormattedMessage } from "react-intl";
@@ -16,7 +16,7 @@ const toButton = ([method, url], i) => (
16
16
  </a>
17
17
  );
18
18
 
19
- export class LoginButtons extends React.Component {
19
+ export class LoginButtons extends Component {
20
20
  render() {
21
21
  const { authMethods } = this.props;
22
22
  return _.isEmpty(authMethods)
@@ -26,11 +26,11 @@ export class LoginButtons extends React.Component {
26
26
  }
27
27
 
28
28
  LoginButtons.propTypes = {
29
- authMethods: PropTypes.object
29
+ authMethods: PropTypes.object,
30
30
  };
31
31
 
32
32
  const mapStateToProps = ({ authMethods }) => ({
33
- authMethods
33
+ authMethods,
34
34
  });
35
35
 
36
36
  export default connect(mapStateToProps)(LoginButtons);
@@ -1,49 +1,32 @@
1
- import React from "react";
1
+ import { useEffect } from "react";
2
2
  import PropTypes from "prop-types";
3
- import { compose } from "redux";
4
- import { connect } from "react-redux";
5
- import { withRouter, Redirect } from "react-router-dom";
3
+ import { useLocation, Navigate } from "react-router";
4
+ import { useDispatch, useSelector } from "react-redux";
6
5
  import queryString from "query-string";
7
6
  import { Loading } from "@truedat/core/components";
8
7
  import { nonceLogin } from "../routines";
9
8
 
10
- export class NonceCallback extends React.Component {
11
- static propTypes = {
12
- authMethod: PropTypes.string,
13
- authentication: PropTypes.object,
14
- authRedirect: PropTypes.string,
15
- location: PropTypes.object,
16
- nonceLogin: PropTypes.func,
17
- };
9
+ export default function NonceCallback({ authMethod }) {
10
+ const dispatch = useDispatch();
11
+ const location = useLocation();
12
+ const authentication = useSelector((state) => state.authentication);
13
+ const authRedirect = useSelector((state) => state.authRedirect);
18
14
 
19
- componentDidMount() {
20
- const {
21
- location: { hash },
22
- nonceLogin,
23
- authMethod,
24
- } = this.props;
15
+ useEffect(() => {
16
+ const { hash } = location;
25
17
  const opts = queryString.parse(hash);
26
- nonceLogin({ ...opts, auth_realm: authMethod });
27
- }
18
+ dispatch(nonceLogin({ ...opts, auth_realm: authMethod }));
19
+ }, [location, dispatch, authMethod]);
28
20
 
29
- render() {
30
- const { authentication, authRedirect } = this.props;
31
- if (authentication?.token) {
32
- return <Redirect to="/" />;
33
- } else if (authRedirect) {
34
- return <Redirect to={authRedirect} />;
35
- } else {
36
- return <Loading size="massive" />;
37
- }
21
+ if (authentication?.token) {
22
+ return <Navigate to="/" />;
23
+ } else if (authRedirect) {
24
+ return <Navigate to={authRedirect} />;
25
+ } else {
26
+ return <Loading size="massive" />;
38
27
  }
39
28
  }
40
29
 
41
- const mapStateToProps = ({ authentication, authRedirect }) => ({
42
- authentication,
43
- authRedirect,
44
- });
45
-
46
- export default compose(
47
- withRouter,
48
- connect(mapStateToProps, { nonceLogin })
49
- )(NonceCallback);
30
+ NonceCallback.propTypes = {
31
+ authMethod: PropTypes.string,
32
+ };
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  import PropTypes from "prop-types";
3
2
  import { connect } from "react-redux";
4
3
  import { FormattedMessage } from "react-intl";
@@ -1,9 +1,10 @@
1
1
  import _ from "lodash/fp";
2
- import React, { useEffect } from "react";
2
+ import { useEffect } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import queryString from "query-string";
5
5
  import { connect } from "react-redux";
6
- import { Redirect, useLocation } from "react-router-dom";
6
+ import { useLocation } from "react-router";
7
+ import { Navigate } from "react-router";
7
8
  import { Loading } from "@truedat/core/components";
8
9
  import { SEARCH } from "@truedat/core/routes";
9
10
  import { openIdLogin } from "../routines";
@@ -27,9 +28,9 @@ export const OpenIDConnect = ({
27
28
  }, [authentication, openIdLogin, opts]);
28
29
 
29
30
  if (authentication?.token) {
30
- return <Redirect to={to} />;
31
+ return <Navigate to={to} />;
31
32
  } else if (authRedirect) {
32
- return <Redirect to={authRedirect} />;
33
+ return <Navigate to={authRedirect} />;
33
34
  } else {
34
35
  return <Loading size="massive" />;
35
36
  }
@@ -1,69 +1,37 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
2
+ import React, { useEffect } from "react";
3
3
  import PropTypes from "prop-types";
4
- import { compose } from "redux";
5
- import { connect } from "react-redux";
6
- import { Route, Redirect, withRouter } from "react-router-dom";
4
+ import { useLocation } from "react-router";
5
+ import { useDispatch, useSelector } from "react-redux";
6
+ import { Navigate } from "react-router";
7
7
  import { LOGIN, UNAUTHORIZED } from "@truedat/core/routes";
8
8
  import { retrieveToken } from "../routines";
9
9
 
10
- class PrivateRoute extends React.Component {
11
- static propTypes = {
12
- token: PropTypes.string,
13
- component: PropTypes.func,
14
- hasPermissions: PropTypes.bool,
15
- location: PropTypes.object,
16
- retrieveToken: PropTypes.func,
17
- };
10
+ function PrivateRoute({ component: Component }) {
11
+ const dispatch = useDispatch();
12
+ const location = useLocation();
13
+ const { token, hasPermissions } = useSelector(({ authentication }) => ({
14
+ token: authentication.token,
15
+ hasPermissions: !_.isEmpty(authentication.entitlements),
16
+ }));
18
17
 
19
- componentDidMount() {
20
- const { token, retrieveToken } = this.props;
18
+ useEffect(() => {
21
19
  if (token === undefined) {
22
- retrieveToken();
20
+ dispatch(retrieveToken());
23
21
  }
24
- }
22
+ }, [token, dispatch]);
25
23
 
26
- render() {
27
- const {
28
- component: Component,
29
- token,
30
- hasPermissions,
31
- location,
32
- ...rest
33
- } = this.props;
34
-
35
- return (
36
- <Route
37
- {...rest}
38
- render={(props) => {
39
- if (token && !hasPermissions) {
40
- return (
41
- <Redirect
42
- to={{
43
- pathname: UNAUTHORIZED,
44
- state: { from: location },
45
- }}
46
- />
47
- );
48
- } else if (token) {
49
- return <Component {...props} />;
50
- } else {
51
- return (
52
- <Redirect to={{ pathname: LOGIN, state: { from: location } }} />
53
- );
54
- }
55
- }}
56
- />
57
- );
58
- }
24
+ return token && !hasPermissions ? (
25
+ <Navigate to={{ pathname: UNAUTHORIZED }} state={{ from: location }} />
26
+ ) : token ? (
27
+ <Component />
28
+ ) : (
29
+ <Navigate to={{ pathname: LOGIN }} state={{ from: location }} />
30
+ );
59
31
  }
60
32
 
61
- const mapStateToProps = ({ authentication }) => ({
62
- token: authentication.token,
63
- hasPermissions: !_.isEmpty(authentication.entitlements),
64
- });
33
+ PrivateRoute.propTypes = {
34
+ component: PropTypes.func,
35
+ };
65
36
 
66
- export default compose(
67
- withRouter,
68
- connect(mapStateToProps, { retrieveToken })
69
- )(PrivateRoute);
37
+ export default PrivateRoute;
@@ -1,5 +1,3 @@
1
- import React from "react";
2
-
3
1
  import NonceCallback from "./NonceCallback";
4
2
 
5
3
  export const ProxyLoginCallback = () => (
@@ -1,5 +1,3 @@
1
- import React from "react";
2
-
3
1
  import NonceCallback from "./NonceCallback";
4
2
 
5
3
  export const SamlCallback = () => <NonceCallback authMethod="saml" />;
@@ -1,45 +1,42 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
2
+ import React, { useEffect } from "react";
3
3
  import PropTypes from "prop-types";
4
- import { connect } from "react-redux";
5
- import { Route, Redirect } from "react-router-dom";
4
+ import { useDispatch, useSelector } from "react-redux";
5
+ import { Routes, Route, Navigate } from "react-router";
6
6
  import { LOGIN } from "@truedat/core/routes";
7
7
  import { retrieveToken } from "../routines";
8
8
 
9
- class UnauthorizedRoute extends React.Component {
10
- static propTypes = {
11
- token: PropTypes.string,
12
- component: PropTypes.func,
13
- retrieveToken: PropTypes.func,
14
- hasPermissions: PropTypes.bool,
15
- };
9
+ function UnauthorizedRoute({ component: Component, path = "/" }) {
10
+ const dispatch = useDispatch();
11
+ const { token, hasPermissions } = useSelector(({ authentication }) => ({
12
+ token: authentication.token,
13
+ hasPermissions: !_.isEmpty(authentication.entitlements),
14
+ }));
16
15
 
17
- componentDidMount() {
18
- const { token, retrieveToken } = this.props;
16
+ useEffect(() => {
19
17
  if (token === undefined) {
20
- retrieveToken();
18
+ dispatch(retrieveToken());
21
19
  }
22
- }
20
+ }, [token, dispatch]);
23
21
 
24
- render() {
25
- const { component: Component, token, hasPermissions, ...rest } = this.props;
26
- return (
22
+ return (
23
+ <Routes>
27
24
  <Route
28
- {...rest}
29
- render={(props) => {
30
- if (token && !hasPermissions) {
31
- return <Component {...props} />;
32
- }
33
- return <Redirect to={{ pathname: LOGIN }} />;
34
- }}
25
+ path={path}
26
+ element={
27
+ token && !hasPermissions ? (
28
+ <Component />
29
+ ) : (
30
+ <Navigate to={{ pathname: LOGIN }} />
31
+ )
32
+ }
35
33
  />
36
- );
37
- }
34
+ </Routes>
35
+ );
38
36
  }
39
37
 
40
- const mapStateToProps = ({ authentication }) => ({
41
- token: authentication.token,
42
- hasPermissions: !_.isEmpty(authentication.entitlements),
43
- });
38
+ UnauthorizedRoute.propTypes = {
39
+ component: PropTypes.func,
40
+ };
44
41
 
45
- export default connect(mapStateToProps, { retrieveToken })(UnauthorizedRoute);
42
+ export default UnauthorizedRoute;
@@ -1,25 +1,25 @@
1
- import React from "react";
2
- import { shallow } from "enzyme";
1
+ import { render } from "@truedat/test/render";
3
2
  import { Auth0LoginButton } from "../Auth0LoginButton";
4
3
 
5
4
  describe("<Auth0LoginButton />", () => {
6
5
  const auth0_config = {
7
- domain: "0"
6
+ domain: "0",
8
7
  };
9
- const invalid_auth0_config = {};
10
8
  const icon = "user icon";
11
9
 
12
- it("matches the latest snapshot", () => {
10
+ it("matches the latest snapshot with custom icon", async () => {
13
11
  const props = { auth0_config, icon };
14
- const wrapper = shallow(<Auth0LoginButton {...props} />);
15
- expect(wrapper).toMatchSnapshot();
16
- expect(wrapper.find("i.user.icon").length).toBe(1);
12
+ const rendered = render(<Auth0LoginButton {...props} />);
13
+ expect(rendered.container).toMatchSnapshot();
14
+ expect(rendered.container.querySelector("i.user.icon")).toBeInTheDocument();
17
15
  });
18
16
 
19
- it("matches the latest snapshot with a default icon", () => {
17
+ it("matches the latest snapshot with a default icon", async () => {
20
18
  const props = { auth0_config };
21
- const wrapper = shallow(<Auth0LoginButton {...props} />);
22
- expect(wrapper).toMatchSnapshot();
23
- expect(wrapper.find("i.sign-in.icon").length).toBe(1);
19
+ const rendered = render(<Auth0LoginButton {...props} />);
20
+ expect(rendered.container).toMatchSnapshot();
21
+ expect(
22
+ rendered.container.querySelector("i.sign-in.icon")
23
+ ).toBeInTheDocument();
24
24
  });
25
25
  });
@@ -1,16 +1,19 @@
1
- import React from "react";
2
- import { shallow } from "enzyme";
3
- import { AuthMethodsLoader } from "../AuthMethodsLoader";
1
+ import { render } from "@truedat/test/render";
2
+ import AuthMethodsLoader from "../AuthMethodsLoader";
3
+
4
+ jest.mock("react-router", () => ({
5
+ ...jest.requireActual("react-router"),
6
+ useLocation: jest.fn().mockReturnValue({}),
7
+ }));
4
8
 
5
9
  describe("<AuthMethodsLoader />", () => {
6
- it("triggers fetchAuthMethods on mount", () => {
7
- const fetchAuthMethods = jest.fn();
8
- const props = { fetchAuthMethods };
9
- jest.spyOn(AuthMethodsLoader.prototype, "componentDidMount");
10
- shallow(<AuthMethodsLoader {...props} />);
11
- expect(
12
- AuthMethodsLoader.prototype.componentDidMount.mock.calls.length
13
- ).toBe(1);
14
- expect(fetchAuthMethods.mock.calls.length).toBe(1);
10
+ it("triggers fetchAuthMethods on mount", async () => {
11
+ const dispatch = jest.fn();
12
+ const rendered = render(<AuthMethodsLoader />, {
13
+ dispatch,
14
+ fallback: false,
15
+ });
16
+
17
+ expect(dispatch).toHaveBeenCalledTimes(1);
15
18
  });
16
19
  });
@@ -0,0 +1,84 @@
1
+ import React from "react";
2
+ import { render, waitForLoad } from "@truedat/test/render";
3
+ import queryString from "query-string";
4
+ import NonceCallback from "../NonceCallback";
5
+ import { nonceLogin } from "../../routines";
6
+
7
+ jest.mock("react-router", () => ({
8
+ ...jest.requireActual("react-router"),
9
+ useLocation: jest.fn().mockReturnValue({ hash: "#token=test-token" }),
10
+ Navigate: jest
11
+ .fn()
12
+ .mockImplementation(({ to }) => <div>Navigate to {to}</div>),
13
+ }));
14
+
15
+ jest.mock("query-string", () => ({
16
+ parse: jest.fn().mockReturnValue({ token: "test-token" }),
17
+ }));
18
+
19
+ describe("<NonceCallback />", () => {
20
+ it("matches the latest snapshot", async () => {
21
+ const rendered = render(<NonceCallback authMethod="test-method" />, {
22
+ state: {
23
+ authentication: {
24
+ token: "valid-token",
25
+ },
26
+ },
27
+ });
28
+ await waitForLoad(rendered);
29
+ expect(rendered.container).toMatchSnapshot();
30
+ });
31
+
32
+ it("dispatches nonceLogin with parsed hash and auth method", async () => {
33
+ const mockDispatch = jest.fn();
34
+ const rendered = render(<NonceCallback authMethod="test-method" />, {
35
+ dispatch: mockDispatch,
36
+ });
37
+
38
+ expect(queryString.parse).toHaveBeenCalledWith("#token=test-token");
39
+ expect(mockDispatch).toHaveBeenCalledWith(
40
+ nonceLogin({ token: "test-token", auth_realm: "test-method" })
41
+ );
42
+ });
43
+
44
+ it("navigates to root when token exists", async () => {
45
+ const rendered = render(<NonceCallback authMethod="test-method" />, {
46
+ state: {
47
+ authentication: {
48
+ token: "valid-token",
49
+ },
50
+ },
51
+ });
52
+ await waitForLoad(rendered);
53
+
54
+ expect(rendered.getByText(/navigate to \//i)).toBeInTheDocument();
55
+ });
56
+
57
+ it("navigates to authRedirect when it exists", async () => {
58
+ const rendered = render(<NonceCallback authMethod="test-method" />, {
59
+ state: {
60
+ authentication: {
61
+ token: null,
62
+ },
63
+ authRedirect: "/redirect-path",
64
+ },
65
+ });
66
+ await waitForLoad(rendered);
67
+
68
+ expect(
69
+ rendered.getByText(/navigate to \/redirect-path/i)
70
+ ).toBeInTheDocument();
71
+ });
72
+
73
+ it("shows loading when no token or redirect exists", async () => {
74
+ const rendered = render(<NonceCallback authMethod="test-method" />, {
75
+ state: {
76
+ authentication: {
77
+ token: null,
78
+ },
79
+ },
80
+ });
81
+
82
+ expect(rendered.container).toMatchSnapshot();
83
+ });
84
+ });
@@ -1,20 +1,20 @@
1
- import React from "react";
2
- import { shallow } from "enzyme";
1
+ import { render } from "@truedat/test/render";
3
2
  import { OidcLoginButton } from "../OidcLoginButton";
4
3
 
5
4
  describe("<OidcLoginButton />", () => {
6
5
  const url = "https://auth.oidc.org/authorize?foo=bar";
7
- const icon = "google icon";
8
6
 
9
- it("matches the latest snapshot", () => {
10
- const props = { url, icon };
11
- const wrapper = shallow(<OidcLoginButton {...props} />);
12
- expect(wrapper).toMatchSnapshot();
7
+ it("matches the latest snapshot with custom icon", async () => {
8
+ const props = { url };
9
+ const rendered = render(<OidcLoginButton {...props} />);
10
+ expect(rendered.container).toMatchSnapshot();
13
11
  });
14
12
 
15
- it("matches the latest snapshot with a default icon", () => {
13
+ it("matches the latest snapshot with a default icon", async () => {
16
14
  const props = { url };
17
- const wrapper = shallow(<OidcLoginButton {...props} />);
18
- expect(wrapper).toMatchSnapshot();
15
+ const rendered = render(<OidcLoginButton {...props} />);
16
+ expect(rendered.container).toMatchSnapshot();
17
+
18
+ expect(rendered.container.querySelector("a")).toBeInTheDocument();
19
19
  });
20
20
  });
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  import { render } from "@truedat/test/render";
3
2
  import { waitFor } from "@testing-library/react";
4
3
  import OpenIDConnect from "../OpenIDConnect";
@@ -6,27 +5,27 @@ import OpenIDConnect from "../OpenIDConnect";
6
5
  const landingUrl = "/landingUrl";
7
6
  const authentication = { token: "token" };
8
7
 
9
- jest.mock("react-router-dom", () => ({
10
- ...jest.requireActual("react-router-dom"),
11
- Redirect: jest.fn(({ to }) => `Redirect to ${to}`),
8
+ jest.mock("react-router", () => ({
9
+ ...jest.requireActual("react-router"),
10
+ Navigate: jest.fn(({ to }) => `Navigate to ${to}`),
12
11
  }));
13
12
 
14
13
  describe("<OpenIDConnect />", () => {
15
- it("redirects to the defined landing URL", async () => {
14
+ it("Navigates to the defined landing URL", async () => {
16
15
  const state = { landingUrl, authentication };
17
16
  const renderOpts = { state };
18
17
  const { getByText } = render(<OpenIDConnect />, renderOpts);
19
18
  await waitFor(() =>
20
- expect(getByText("Redirect to /landingUrl")).not.toBeNull()
19
+ expect(getByText("Navigate to /landingUrl")).not.toBeNull()
21
20
  );
22
21
  });
23
22
 
24
- it("redirects to /search if landingUrl is not defined", async () => {
23
+ it("Navigates to /search if landingUrl is not defined", async () => {
25
24
  const state = { authentication };
26
25
  const renderOpts = { state };
27
26
  const { getByText } = render(<OpenIDConnect />, renderOpts);
28
27
  await waitFor(() =>
29
- expect(getByText("Redirect to /search")).not.toBeNull()
28
+ expect(getByText("Navigate to /search")).not.toBeNull()
30
29
  );
31
30
  });
32
31
  });