From 86cc520a254ece5c3e524e51c6505ff5674b55e2 Mon Sep 17 00:00:00 2001 From: Philippe Perrin Date: Fri, 11 Oct 2019 09:32:45 +0200 Subject: [PATCH] Improve user profile & unit tests --- .../main/js/app/components/AccountDeleted.tsx | 53 ----- .../__tests__/AccountDeleted-test.tsx | 27 --- .../AccountDeleted-test.tsx.snap | 53 ----- .../src/main/js/app/utils/startReactApp.tsx | 4 - .../src/main/js/apps/account/account.css | 4 +- .../main/js/apps/account/profile/Profile.tsx | 136 ++++++++---- .../account/profile/UserDeleteAccount.tsx | 125 ------------ .../profile/UserDeleteAccountContent.tsx | 148 -------------- .../profile/UserDeleteAccountModal.tsx | 141 ------------- .../account/profile/UserExternalIdentity.tsx | 9 +- .../js/apps/account/profile/UserGroups.tsx | 40 ---- .../apps/account/profile/UserScmAccounts.tsx | 58 ------ .../profile/__tests__/Profile-test.tsx | 55 +++-- .../__tests__/UserDeleteAccount-test.tsx | 87 -------- .../UserDeleteAccountContent-test.tsx | 71 ------- .../__tests__/UserDeleteAccountModal-test.tsx | 86 -------- .../__tests__/UserExternalIdentity-test.tsx | 66 ++++++ .../__snapshots__/Profile-test.tsx.snap | 193 ++++++++++++++---- .../UserDeleteAccount-test.tsx.snap | 118 ----------- .../UserDeleteAccountContent-test.tsx.snap | 128 ------------ .../UserDeleteAccountModal-test.tsx.snap | 19 -- .../UserExternalIdentity-test.tsx.snap | 29 +++ .../resources/org/sonar/l10n/core.properties | 17 +- 23 files changed, 385 insertions(+), 1282 deletions(-) delete mode 100644 server/sonar-web/src/main/js/app/components/AccountDeleted.tsx delete mode 100644 server/sonar-web/src/main/js/app/components/__tests__/AccountDeleted-test.tsx delete mode 100644 server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/AccountDeleted-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccount.tsx delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccountContent.tsx delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccountModal.tsx delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/UserGroups.tsx delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.tsx delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccount-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccountContent-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccountModal-test.tsx create mode 100644 server/sonar-web/src/main/js/apps/account/profile/__tests__/UserExternalIdentity-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccount-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccountContent-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccountModal-test.tsx.snap create mode 100644 server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserExternalIdentity-test.tsx.snap diff --git a/server/sonar-web/src/main/js/app/components/AccountDeleted.tsx b/server/sonar-web/src/main/js/app/components/AccountDeleted.tsx deleted file mode 100644 index d91059bf630..00000000000 --- a/server/sonar-web/src/main/js/app/components/AccountDeleted.tsx +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { Link } from 'react-router'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import { translate } from 'sonar-ui-common/helpers/l10n'; - -export default function AccountDeleted() { - return ( -
- - {translate('my_profile.delete_account.success')} - - -
-

-

{translate('my_profile.delete_account.feedback.reason.explanation')}

-

-

- {translate('footer.contact_us')} - }} - /> -

-

- {translate('go_back_to_homepage')} -

-
-
- ); -} diff --git a/server/sonar-web/src/main/js/app/components/__tests__/AccountDeleted-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/AccountDeleted-test.tsx deleted file mode 100644 index 608b22dcf2f..00000000000 --- a/server/sonar-web/src/main/js/app/components/__tests__/AccountDeleted-test.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -import { shallow } from 'enzyme'; -import * as React from 'react'; -import AccountDeleted from '../AccountDeleted'; - -it('should render correctly', () => { - expect(shallow()).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/AccountDeleted-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/AccountDeleted-test.tsx.snap deleted file mode 100644 index 8bffcc4ae6e..00000000000 --- a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/AccountDeleted-test.tsx.snap +++ /dev/null @@ -1,53 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` -
- - my_profile.delete_account.success - -
-

-

- my_profile.delete_account.feedback.reason.explanation -

-

-

- - footer.contact_us - , - } - } - /> -

-

- - go_back_to_homepage - -

-
-
-`; diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx index 1eb7843fbcc..0e91d2c37fb 100644 --- a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx +++ b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx @@ -207,10 +207,6 @@ export default function startReactApp( import('../../apps/feedback/downgrade/DowngradeFeedback') )} /> - import('../components/AccountDeleted'))} - /> )} diff --git a/server/sonar-web/src/main/js/apps/account/account.css b/server/sonar-web/src/main/js/apps/account/account.css index eab942f9e5e..f7575bfc714 100644 --- a/server/sonar-web/src/main/js/apps/account/account.css +++ b/server/sonar-web/src/main/js/apps/account/account.css @@ -59,9 +59,7 @@ padding: 40px 0; } -.account-separator { - height: 0; - margin: 40px 0; +.account-profile .boxed-group-inner:not(:first-child) { border-top: 1px solid var(--barBorderColor); } diff --git a/server/sonar-web/src/main/js/apps/account/profile/Profile.tsx b/server/sonar-web/src/main/js/apps/account/profile/Profile.tsx index 4b55078de41..a05a7d04302 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/Profile.tsx +++ b/server/sonar-web/src/main/js/apps/account/profile/Profile.tsx @@ -18,59 +18,123 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip'; import { translate } from 'sonar-ui-common/helpers/l10n'; import { whenLoggedIn } from '../../../components/hoc/whenLoggedIn'; -import { isSonarCloud } from '../../../helpers/system'; -import UserDeleteAccount from './UserDeleteAccount'; import UserExternalIdentity from './UserExternalIdentity'; -import UserGroups from './UserGroups'; -import UserScmAccounts from './UserScmAccounts'; -export interface Props { +export interface ProfileProps { currentUser: T.LoggedInUser; } -export function Profile({ currentUser }: Props) { +export function Profile({ currentUser }: ProfileProps) { + const isExternalProvider = !currentUser.local && currentUser.externalProvider !== 'sonarqube'; + return ( -
-
-
- {translate('login')}: {currentUser.login} -
+
+
+ {renderLogin()} + {renderEmail()} + {renderUserGroups()} + {renderScmAccounts()} +
+
+ ); - {!currentUser.local && currentUser.externalProvider !== 'sonarqube' && ( -
- -
- )} + function renderLogin() { + if (!currentUser.login && !isExternalProvider) { + return null; + } - {Boolean(currentUser.email) && ( -
- {translate('my_profile.email')}: {currentUser.email} -
+ return ( +
+

{translate('my_profile.login')}

+ {currentUser.login && ( +

+ {currentUser.login} +

)} + {isExternalProvider && } +
+ ); + } - {!isSonarCloud() && ( - <> -
- - - )} + function renderEmail() { + if (!currentUser.email) { + return null; + } -
+ return ( +
+

{translate('my_profile.email')}

+
+

{currentUser.email}

+
+
+ ); + } - + function renderUserGroups() { + if (!currentUser.groups || currentUser.groups.length === 0) { + return null; + } - {isSonarCloud() && ( - <> -
+ return ( +
+

{translate('my_profile.groups')}

+
    + {currentUser.groups.map(group => ( +
  • + {group} +
  • + ))} +
+
+ ); + } - - - )} + function renderScmAccounts() { + if ( + !currentUser.login && + !currentUser.email && + (!currentUser.scmAccounts || currentUser.scmAccounts.length === 0) + ) { + return null; + } + + return ( +
+

+ {translate('my_profile.scm_accounts')} + +

+
    + {currentUser.login && ( +
  • + {currentUser.login} +
  • + )} + + {currentUser.email && ( +
  • + {currentUser.email} +
  • + )} + + {currentUser.scmAccounts && + currentUser.scmAccounts.length > 0 && + currentUser.scmAccounts.map(scmAccount => ( +
  • + {scmAccount} +
  • + ))} +
-
- ); + ); + } } export default whenLoggedIn(Profile); diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccount.tsx b/server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccount.tsx deleted file mode 100644 index d114dc9d2fb..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccount.tsx +++ /dev/null @@ -1,125 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { Button } from 'sonar-ui-common/components/controls/buttons'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { getOrganizationsThatPreventDeletion } from '../../../api/organizations'; -import { whenLoggedIn } from '../../../components/hoc/whenLoggedIn'; -import { withUserOrganizations } from '../../../components/hoc/withUserOrganizations'; -import UserDeleteAccountContent from './UserDeleteAccountContent'; -import UserDeleteAccountModal from './UserDeleteAccountModal'; - -interface Props { - user: T.LoggedInUser; - userOrganizations: T.Organization[]; -} - -interface State { - loading: boolean; - organizationsToTransferOrDelete: T.Organization[]; - showModal: boolean; -} - -export class UserDeleteAccount extends React.PureComponent { - mounted = false; - - state: State = { - loading: true, - organizationsToTransferOrDelete: [], - showModal: false - }; - - componentDidMount() { - this.mounted = true; - this.fetchOrganizationsThatPreventDeletion(); - } - - componentWillUnmount() { - this.mounted = false; - } - - fetchOrganizationsThatPreventDeletion = () => { - getOrganizationsThatPreventDeletion().then( - ({ organizations }) => { - if (this.mounted) { - this.setState({ - loading: false, - organizationsToTransferOrDelete: organizations - }); - } - }, - () => {} - ); - }; - - toggleModal = () => { - if (this.mounted) { - this.setState(state => ({ - showModal: !state.showModal - })); - } - }; - - render() { - const { user, userOrganizations } = this.props; - const { organizationsToTransferOrDelete, loading, showModal } = this.state; - - const label = translate('my_profile.delete_account'); - - return ( -
-

{label}

- - - - {!loading && ( - <> - - - - - {showModal && ( - - )} - - )} -
- ); - } -} - -export default whenLoggedIn(withUserOrganizations(UserDeleteAccount)); diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccountContent.tsx b/server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccountContent.tsx deleted file mode 100644 index aaad598307b..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccountContent.tsx +++ /dev/null @@ -1,148 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { Link } from 'react-router'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { getOrganizationUrl } from '../../../helpers/urls'; - -function getOrganizationLink(org: T.Organization, i: number, organizations: T.Organization[]) { - return ( - - {org.name} - {i < organizations.length - 1 && ', '} - - ); -} - -export function ShowOrganizationsToTransferOrDelete({ - organizations -}: { - organizations: T.Organization[]; -}) { - return ( - <> -

- {organizations.map(getOrganizationLink)} - }} - /> -

- - - - {translate('my_profile.delete_account.info.orgs_to_transfer_or_delete.info.link')} - - ) - }} - /> - - - ); -} - -export function ShowOrganizations({ - className, - organizations -}: { - className?: string; - organizations: T.Organization[]; -}) { - const organizationsIAdministrate = organizations.filter(o => o.actions && o.actions.admin); - - return ( -
    -
  • {translate('my_profile.delete_account.info')}
  • - -
  • - - {translate('learn_more')} - - ) - }} - /> -
  • - - {organizations.length > 0 && ( -
  • - {organizations.map(getOrganizationLink)} - }} - /> -
  • - )} - - {organizationsIAdministrate.length > 0 && ( -
  • - {organizationsIAdministrate.map(getOrganizationLink)} - }} - /> -
  • - )} -
- ); -} - -interface UserDeleteAccountContentProps { - className?: string; - organizationsSafeToDelete: T.Organization[]; - organizationsToTransferOrDelete: T.Organization[]; -} - -export default function UserDeleteAccountContent({ - className, - organizationsSafeToDelete, - organizationsToTransferOrDelete -}: UserDeleteAccountContentProps) { - if (organizationsToTransferOrDelete.length > 0) { - return ; - } - - return ; -} diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccountModal.tsx b/server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccountModal.tsx deleted file mode 100644 index 80ea464225e..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/UserDeleteAccountModal.tsx +++ /dev/null @@ -1,141 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import { connect } from 'react-redux'; -import InputValidationField from 'sonar-ui-common/components/controls/InputValidationField'; -import ValidationModal from 'sonar-ui-common/components/controls/ValidationModal'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; -import { deactivateUser } from '../../../api/users'; -import RecentHistory from '../../../app/components/RecentHistory'; -import { Router, withRouter } from '../../../components/hoc/withRouter'; -import { doLogout } from '../../../store/rootActions'; -import UserDeleteAccountContent from './UserDeleteAccountContent'; - -interface Values { - login: string; -} - -interface DeleteModalProps { - doLogout: () => Promise; - label: string; - organizationsSafeToDelete: T.Organization[]; - organizationsToTransferOrDelete: T.Organization[]; - router: Pick; - toggleModal: VoidFunction; - user: T.LoggedInUser; -} - -export class UserDeleteAccountModal extends React.PureComponent { - handleSubmit = () => { - const { user } = this.props; - - return deactivateUser({ login: user.login }) - .then(this.props.doLogout) - .then(() => { - RecentHistory.clear(); - window.location.replace('/account-deleted'); - }); - }; - - handleValidate = ({ login }: Values) => { - const { user } = this.props; - const errors: { login?: string } = {}; - const trimmedLogin = login.trim(); - - if (!trimmedLogin) { - errors.login = translate('my_profile.delete_account.login.required'); - } else if (user.externalIdentity && trimmedLogin !== user.externalIdentity.trim()) { - errors.login = translate('my_profile.delete_account.login.wrong_value'); - } - - return errors; - }; - - render() { - const { - label, - organizationsSafeToDelete, - organizationsToTransferOrDelete, - toggleModal, - user - } = this.props; - - return ( - - {({ dirty, errors, handleBlur, handleChange, isSubmitting, touched, values }) => ( - <> - - {translate('my_profile.warning_message')} - - - - - - {translate('my_profile.delete_account.verify')} - * - - } - name="login" - onBlur={handleBlur} - onChange={handleChange} - touched={touched.login} - type="text" - value={values.login} - /> - - )} - - ); - } -} - -const mapStateToProps = () => ({}); - -const mapDispatchToProps = { doLogout: doLogout as any }; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(withRouter(UserDeleteAccountModal)); diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx b/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx index 523529ae9ca..a4add5f55e1 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx +++ b/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx @@ -23,7 +23,7 @@ import { getBaseUrl } from 'sonar-ui-common/helpers/urls'; import { getIdentityProviders } from '../../../api/users'; import { colors } from '../../../app/theme'; -interface Props { +export interface UserExternalIdentityProps { user: T.LoggedInUser; } @@ -32,7 +32,10 @@ interface State { loading: boolean; } -export default class UserExternalIdentity extends React.PureComponent { +export default class UserExternalIdentity extends React.PureComponent< + UserExternalIdentityProps, + State +> { mounted = false; state: State = { loading: true @@ -43,7 +46,7 @@ export default class UserExternalIdentity extends React.PureComponent -

{translate('my_profile.groups')}

-
    - {groups.map(group => ( -
  • - {group} -
  • - ))} -
-
- ); -} diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.tsx b/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.tsx deleted file mode 100644 index 9055fc5de7f..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip'; -import { translate } from 'sonar-ui-common/helpers/l10n'; - -interface Props { - scmAccounts: string[]; - user: T.LoggedInUser; -} - -export default function UserScmAccounts({ user, scmAccounts }: Props) { - return ( -
-

- {translate('my_profile.scm_accounts')} - -

-
    -
  • - {user.login} -
  • - - {user.email && ( -
  • - {user.email} -
  • - )} - - {scmAccounts.map(scmAccount => ( -
  • - {scmAccount} -
  • - ))} -
-
- ); -} diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/Profile-test.tsx b/server/sonar-web/src/main/js/apps/account/profile/__tests__/Profile-test.tsx index 479effa96fb..175fada451d 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/__tests__/Profile-test.tsx +++ b/server/sonar-web/src/main/js/apps/account/profile/__tests__/Profile-test.tsx @@ -19,41 +19,36 @@ */ import { shallow } from 'enzyme'; import * as React from 'react'; -import { isSonarCloud } from '../../../../helpers/system'; import { mockLoggedInUser } from '../../../../helpers/testMocks'; -import { Profile, Props } from '../Profile'; +import { Profile, ProfileProps } from '../Profile'; -jest.mock('../../../../helpers/system', () => ({ isSonarCloud: jest.fn().mockReturnValue(false) })); - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -it('should render email', () => { - expect( - shallowRender(mockLoggedInUser({ email: 'john@doe.com' })) - .find('#email') - .exists() - ).toBe(true); -}); - -it('should render external identity', () => { - expect( - shallowRender(mockLoggedInUser({ local: false, externalProvider: 'github' })) - .find('UserExternalIdentity') - .exists() - ).toBe(true); +it('should render correctly a local user', () => { + expect(shallowRender({ local: true, externalProvider: 'sonarqube' })).toMatchSnapshot(); }); -it('should not display user groups', () => { - (isSonarCloud as jest.Mock).mockReturnValueOnce(true); +it('should render correctly a IDP user', () => { expect( - shallowRender() - .find('UserGroups') - .exists() - ).toBe(false); + shallowRender({ + local: false, + externalProvider: 'github', + email: undefined, + login: undefined, + scmAccounts: [] + }) + ).toMatchSnapshot(); }); -function shallowRender(currentUser: Props['currentUser'] = mockLoggedInUser()) { - return shallow(); +function shallowRender(userOverrides?: Partial) { + return shallow( + + ); } diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccount-test.tsx b/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccount-test.tsx deleted file mode 100644 index 215e94f194d..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccount-test.tsx +++ /dev/null @@ -1,87 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { click, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; -import { getOrganizationsThatPreventDeletion } from '../../../../api/organizations'; -import { mockLoggedInUser, mockOrganization } from '../../../../helpers/testMocks'; -import { UserDeleteAccount } from '../UserDeleteAccount'; - -jest.mock('../../../../api/organizations', () => ({ - getOrganizationsThatPreventDeletion: jest.fn().mockResolvedValue({ organizations: [] }) -})); - -beforeEach(() => { - jest.clearAllMocks(); -}); - -const organizationToTransferOrDelete = { - key: 'luke-leia', - name: 'Luke and Leia' -}; - -it('should render correctly', async () => { - const wrapper = shallowRender(); - expect(wrapper).toMatchSnapshot(); - - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot(); - - click(wrapper.find('Button')); - expect(wrapper).toMatchSnapshot(); -}); - -it('should get some organizations', async () => { - (getOrganizationsThatPreventDeletion as jest.Mock).mockResolvedValue({ - organizations: [organizationToTransferOrDelete] - }); - - const wrapper = shallowRender(); - - await waitAndUpdate(wrapper); - - expect(wrapper.state('loading')).toBeFalsy(); - expect(wrapper.state('organizationsToTransferOrDelete')).toEqual([ - organizationToTransferOrDelete - ]); - expect(getOrganizationsThatPreventDeletion).toBeCalled(); - expect(wrapper.find('Button').prop('disabled')).toBe(true); -}); - -it('should toggle modal', () => { - const wrapper = shallowRender(); - wrapper.setState({ loading: false }); - expect(wrapper.find('Connect(withRouter(UserDeleteAccountModal))').exists()).toBe(false); - click(wrapper.find('Button')); - expect(wrapper.find('Connect(withRouter(UserDeleteAccountModal))').exists()).toBe(true); -}); - -function shallowRender(props: Partial = {}) { - const user = mockLoggedInUser({ externalIdentity: 'luke' }); - - const userOrganizations = [ - mockOrganization({ key: 'luke-leia', name: 'Luke and Leia' }), - mockOrganization({ key: 'luke', name: 'Luke Skywalker' }) - ]; - - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccountContent-test.tsx b/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccountContent-test.tsx deleted file mode 100644 index 37aa8ec4321..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccountContent-test.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import UserDeleteAccountContent, { - ShowOrganizations, - ShowOrganizationsToTransferOrDelete -} from '../UserDeleteAccountContent'; - -const organizationSafeToDelete = { - key: 'luke', - name: 'Luke Skywalker' -}; - -const organizationToTransferOrDelete = { - key: 'luke-leia', - name: 'Luke and Leia' -}; - -it('should render content correctly', () => { - expect( - shallow( - - ) - ).toMatchSnapshot(); - - expect( - shallow( - - ) - ).toMatchSnapshot(); -}); - -it('should render correctly ShowOrganizationsToTransferOrDelete', () => { - expect( - shallow( - - ) - ).toMatchSnapshot(); -}); - -it('should render correctly ShowOrganizations', () => { - expect( - shallow() - ).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccountModal-test.tsx b/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccountModal-test.tsx deleted file mode 100644 index 0ad5db24db2..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserDeleteAccountModal-test.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; -import { deactivateUser } from '../../../../api/users'; -import { mockLoggedInUser, mockRouter } from '../../../../helpers/testMocks'; -import { UserDeleteAccountModal } from '../UserDeleteAccountModal'; - -jest.mock('../../../../api/users', () => ({ - deactivateUser: jest.fn() -})); - -const organizationSafeToDelete = { - key: 'luke', - name: 'Luke Skywalker' -}; - -const organizationToTransferOrDelete = { - key: 'luke-leia', - name: 'Luke and Leia' -}; - -it('should render modal correctly', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -it('should handle submit', async () => { - (deactivateUser as jest.Mock).mockResolvedValue(true); - window.location.replace = jest.fn(); - - const wrapper = shallowRender(); - const instance = wrapper.instance(); - - instance.handleSubmit(); - await waitAndUpdate(wrapper); - - expect(deactivateUser).toBeCalled(); - expect(window.location.replace).toHaveBeenCalledWith('/account-deleted'); -}); - -it('should validate user input', () => { - const wrapper = shallowRender(); - const instance = wrapper.instance(); - const { handleValidate } = instance; - - expect(handleValidate({ login: '' }).login).toBe('my_profile.delete_account.login.required'); - expect(handleValidate({ login: 'abc' }).login).toBe( - 'my_profile.delete_account.login.wrong_value' - ); - expect(handleValidate({ login: 'luke' }).login).toBeUndefined(); -}); - -function shallowRender(props: Partial = {}) { - const user = mockLoggedInUser({ externalIdentity: 'luke' }); - - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserExternalIdentity-test.tsx b/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserExternalIdentity-test.tsx new file mode 100644 index 00000000000..bbb6e43168b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/profile/__tests__/UserExternalIdentity-test.tsx @@ -0,0 +1,66 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { shallow } from 'enzyme'; +import * as React from 'react'; +import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; +import { mockLoggedInUser } from '../../../../helpers/testMocks'; +import UserExternalIdentity, { UserExternalIdentityProps } from '../UserExternalIdentity'; + +jest.mock('../../../../api/users', () => ({ + getIdentityProviders: jest.fn().mockResolvedValue({ + identityProviders: [ + { + backgroundColor: '#444444', + iconPath: '/images/github.svg', + key: 'github', + name: 'GitHub' + } + ] + }) +})); + +it('should render correctly', async () => { + const wrapper = shallowRender(); + await waitAndUpdate(wrapper); + expect(wrapper).toMatchSnapshot(); +}); + +it('should render a fallback when idp is not listed', async () => { + const wrapper = shallowRender({ externalProvider: 'ggithub' }); + await waitAndUpdate(wrapper); + expect(wrapper).toMatchSnapshot(); +}); + +function shallowRender(userOverrides?: Partial) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/Profile-test.tsx.snap b/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/Profile-test.tsx.snap index e896064c035..3612928afed 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/Profile-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/Profile-test.tsx.snap @@ -1,58 +1,179 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should render correctly 1`] = ` +exports[`should render correctly a IDP user 1`] = `
- login - : - - luke - -
-
+ my_profile.login +
-
- -
- +
+

+ my_profile.groups +

+
    +
  • + G1 +
  • +
  • + G2 +
  • +
+
+
+
+`; + +exports[`should render correctly a local user 1`] = ` +
+
+
+

+ my_profile.login +

+

+ luke +

+
+
+

+ my_profile.email +

+
+

+ john@doe.com +

+
+
+
+

+ my_profile.groups +

+
    +
  • + G1 +
  • +
  • + G2 +
  • +
+
+
+

+ my_profile.scm_accounts + +

+
    +
  • + luke +
  • +
  • + john@doe.com +
  • +
  • + SCM1 +
  • +
  • + SCM2 +
  • +
+
`; diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccount-test.tsx.snap b/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccount-test.tsx.snap deleted file mode 100644 index 05a4397a565..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccount-test.tsx.snap +++ /dev/null @@ -1,118 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` -
-

- my_profile.delete_account -

- -
-`; - -exports[`should render correctly 2`] = ` -
-

- my_profile.delete_account -

- - - -
-`; - -exports[`should render correctly 3`] = ` -
-

- my_profile.delete_account -

- - - - -
-`; diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccountContent-test.tsx.snap b/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccountContent-test.tsx.snap deleted file mode 100644 index 56ac708fb53..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccountContent-test.tsx.snap +++ /dev/null @@ -1,128 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render content correctly 1`] = ` - -`; - -exports[`should render content correctly 2`] = ` - -`; - -exports[`should render correctly ShowOrganizations 1`] = ` -
    -
  • - my_profile.delete_account.info -
  • -
  • - - learn_more - , - } - } - /> -
  • -
  • - - - - Luke Skywalker - - - , - } - } - /> -
  • -
-`; - -exports[`should render correctly ShowOrganizationsToTransferOrDelete 1`] = ` - -

- - - - Luke and Leia - - - , - } - } - /> -

- - - my_profile.delete_account.info.orgs_to_transfer_or_delete.info.link - , - } - } - /> - -
-`; diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccountModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccountModal-test.tsx.snap deleted file mode 100644 index 5ba1d10e4ad..00000000000 --- a/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserDeleteAccountModal-test.tsx.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render modal correctly 1`] = ` - - - -`; diff --git a/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserExternalIdentity-test.tsx.snap b/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserExternalIdentity-test.tsx.snap new file mode 100644 index 00000000000..9ded81f8129 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/account/profile/__tests__/__snapshots__/UserExternalIdentity-test.tsx.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render a fallback when idp is not listed 1`] = ` +
+ ggithub + : +
+`; + +exports[`should render correctly 1`] = ` +
+ GitHub + +
+`; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 28684bdc758..f8bb2c4d807 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1553,21 +1553,7 @@ groups.remove.confirmation=Are you sure you want to remove group "{user}"? # MY PROFILE & MY ACCOUNT # #------------------------------------------------------------------------------ -my_profile.delete_account=Delete your user account -my_profile.delete_account.success=Account successfully deleted -my_profile.delete_account.feedback.reason.explanation=We are sorry to see you leave. -my_profile.delete_account.feedback.call_to_action={link} to help improve our product or offer. -my_profile.delete_account.info=We will immediately delete your account. -my_profile.delete_account.data.info=All your data will be removed except your login. {help} -my_profile.delete_account.info.orgs.members=You will be removed from the members of: {organizations}. -my_profile.delete_account.info.orgs.administrators=You will be removed from the administrators of: {organizations}. -my_profile.delete_account.info.orgs_to_transfer_or_delete=Your account is the only administrator for the following organization(s): {organizations}. -my_profile.delete_account.info.orgs_to_transfer_or_delete.info=You must transfer administration permissions or delete these organizations before you can delete your SonarCloud account. {link}. -my_profile.delete_account.info.orgs_to_transfer_or_delete.info.link=See Organization Admin Guide -my_profile.delete_account.modal.header={0}: {1} -my_profile.delete_account.login.required=Login is required -my_profile.delete_account.login.wrong_value=Please type your login to confirm -my_profile.delete_account.verify=To verify, please type your user account name below +my_profile.login=Login my_profile.email=Email my_profile.groups=Groups my_profile.scm_accounts=SCM Accounts @@ -1584,7 +1570,6 @@ my_profile.sonarcloud_feature_notifications.title=SonarCloud new feature notific my_profile.sonarcloud_feature_notifications.description=Display a notification in the header when new features are deployed my_profile.per_project_notifications.title=Notifications per project my_profile.per_project_notifications.add=Add a project -my_profile.warning_message=This is a definitive action. No account recovery will be possible. my_account.page=My Account my_account.notifications=Notifications -- 2.39.5