diff options
author | Jeremy Davis <jeremy.davis@sonarsource.com> | 2020-10-29 18:20:21 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2020-11-04 20:05:48 +0000 |
commit | 52db191b96cdd311706bbf19ced0647d8cad09fe (patch) | |
tree | 4b2b92b92675ed54ddf69a27f034053c09f6875f /server | |
parent | b8c14fb39bab908ec24f40dfd038a0134580d2be (diff) | |
download | sonarqube-52db191b96cdd311706bbf19ced0647d8cad09fe.tar.gz sonarqube-52db191b96cdd311706bbf19ced0647d8cad09fe.zip |
SONAR-13988 better handle errors
Diffstat (limited to 'server')
32 files changed, 784 insertions, 2187 deletions
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx index e335ab9ebbe..74203d53f70 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx @@ -20,16 +20,23 @@ import * as React from 'react'; import { Button } from 'sonar-ui-common/components/controls/buttons'; import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip'; +import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; import AlertErrorIcon from 'sonar-ui-common/components/icons/AlertErrorIcon'; import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon'; import DeleteIcon from 'sonar-ui-common/components/icons/DeleteIcon'; import EditIcon from 'sonar-ui-common/components/icons/EditIcon'; import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { AlmBindingDefinition, AlmSettingsBindingStatus } from '../../../../types/alm-settings'; +import { + AlmBindingDefinition, + AlmKeys, + AlmSettingsBindingStatus, + AlmSettingsBindingStatusType +} from '../../../../types/alm-settings'; +import { VALIDATED_ALMS } from './utils'; export interface AlmBindingDefinitionBoxProps { + alm: AlmKeys; definition: AlmBindingDefinition; multipleDefinitions: boolean; onCheck: (definitionKey: string) => void; @@ -38,9 +45,21 @@ export interface AlmBindingDefinitionBoxProps { status?: AlmSettingsBindingStatus; } -const DEFAULT_STATUS = { alert: false, errorMessage: '', validating: true }; +const DEFAULT_STATUS: AlmSettingsBindingStatus = { + alertSuccess: false, + failureMessage: '', + type: AlmSettingsBindingStatusType.Validating +}; -function getImportFeatureStatus(multipleDefinitions: boolean, error: boolean) { +const STATUS_ICON = { + [AlmSettingsBindingStatusType.Failure]: <AlertErrorIcon className="spacer-left" />, + [AlmSettingsBindingStatusType.Success]: <AlertSuccessIcon className="spacer-left" /> +}; + +function getImportFeatureStatus( + multipleDefinitions: boolean, + type: AlmSettingsBindingStatusType.Success | AlmSettingsBindingStatusType.Failure +) { if (multipleDefinitions) { return ( <div className="display-inline-flex-center"> @@ -54,16 +73,22 @@ function getImportFeatureStatus(multipleDefinitions: boolean, error: boolean) { </div> ); } else { - return error ? ( - <AlertErrorIcon className="spacer-left" /> - ) : ( - <AlertSuccessIcon className="spacer-left" /> - ); + return STATUS_ICON[type]; } } export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxProps) { - const { definition, multipleDefinitions, status = DEFAULT_STATUS } = props; + const { alm, definition, multipleDefinitions, status = DEFAULT_STATUS } = props; + + const importFeatureTitle = + alm === AlmKeys.GitLab + ? translate('settings.almintegration.feature.mr_decoration.title') + : translate('settings.almintegration.feature.pr_decoration.title'); + + const importFeatureDescription = + alm === AlmKeys.GitLab + ? translate('settings.almintegration.feature.mr_decoration.description') + : translate('settings.almintegration.feature.pr_decoration.description'); return ( <div className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"> @@ -83,41 +108,74 @@ export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxPr {definition.url && <span>{definition.url}</span>} </div> - <DeferredSpinner - customSpinner={ - <div> - <i className="deferred-spinner spacer-right" /> - {translate('settings.almintegration.checking_configuration')} - </div> - } - loading={status.validating}> - <div className="display-flex-row spacer-bottom"> - <div className="huge-spacer-right"> - {translate('settings.almintegration.feature.pr_decoration.title')} - {status.errorMessage ? ( - <AlertErrorIcon className="spacer-left" /> - ) : ( - <AlertSuccessIcon className="spacer-left" /> - )} - </div> - <div> - {translate('settings.almintegration.feature.alm_repo_import.title')} - {getImportFeatureStatus(multipleDefinitions, Boolean(status.errorMessage))} + {!VALIDATED_ALMS.includes(alm) && ( + <> + <div className="display-flex-row spacer-bottom"> + <Tooltip overlay={importFeatureDescription}> + <span>{importFeatureTitle}</span> + </Tooltip> + <AlertSuccessIcon className="spacer-left" /> </div> - </div> - {status.alert && ( <div className="width-50"> - <Alert variant={status.errorMessage ? 'error' : 'success'}> - {status.errorMessage || translate('settings.almintegration.configuration_valid')} - </Alert> + <Alert variant="info">{translate('settings.almintegration.no_validation')}</Alert> </div> - )} + </> + )} - <Button className="big-spacer-top" onClick={() => props.onCheck(definition.key)}> - {translate('settings.almintegration.check_configuration')} - </Button> - </DeferredSpinner> + {VALIDATED_ALMS.includes(alm) && + (status.type === AlmSettingsBindingStatusType.Validating ? ( + <> + <i className="spinner spacer-right" /> + {translate('settings.almintegration.checking_configuration')} + </> + ) : ( + <> + {status.type !== AlmSettingsBindingStatusType.Warning && ( + <div className="display-flex-row spacer-bottom"> + <Tooltip overlay={importFeatureDescription}> + <div className="huge-spacer-right"> + {importFeatureTitle} + {STATUS_ICON[status.type]} + </div> + </Tooltip> + <div> + <Tooltip + overlay={translate( + 'settings.almintegration.feature.alm_repo_import.description' + )}> + <span> + {translate('settings.almintegration.feature.alm_repo_import.title')} + </span> + </Tooltip> + {getImportFeatureStatus(multipleDefinitions, status.type)} + </div> + </div> + )} + + <div className="width-50"> + {status.type === AlmSettingsBindingStatusType.Warning && ( + <Alert variant="warning"> + {translate('settings.almintegration.could_not_validate')} + </Alert> + )} + + {status.type === AlmSettingsBindingStatusType.Failure && ( + <Alert variant="error">{status.failureMessage}</Alert> + )} + + {status.type === AlmSettingsBindingStatusType.Success && status.alertSuccess && ( + <Alert variant="success"> + {translate('settings.almintegration.configuration_valid')} + </Alert> + )} + </div> + + <Button className="big-spacer-top" onClick={() => props.onCheck(definition.key)}> + {translate('settings.almintegration.check_configuration')} + </Button> + </> + ))} </div> ); } diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx index a0c132fbf8f..ad555bc1bbe 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx @@ -21,7 +21,6 @@ import { isEqual, omit } from 'lodash'; import * as React from 'react'; import { AlmBindingDefinition } from '../../../../types/alm-settings'; import AlmBindingDefinitionFormModalRenderer from './AlmBindingDefinitionFormModalRenderer'; -import AlmBindingDefinitionFormRenderer from './AlmBindingDefinitionFormRenderer'; export interface AlmBindingDefinitionFormChildrenProps<B> { formData: B; @@ -36,15 +35,11 @@ interface Props<B> { help?: React.ReactNode; hideKeyField?: boolean; isSecondInstance?: boolean; - loading?: boolean; onCancel?: () => void; onDelete?: (definitionKey: string) => void; onEdit?: (definitionKey: string) => void; onSubmit: (data: B, originalKey: string) => void; optionalFields?: Array<keyof B>; - readOnly?: boolean; - showInModal?: boolean; - success?: boolean; } interface State<B> { @@ -118,59 +113,24 @@ export default class AlmBindingDefinitionForm< }; render() { - const { - bindingDefinition, - children, - help, - hideKeyField, - isSecondInstance, - showInModal, - loading = false, - readOnly = false, - success = false - } = this.props; - const { formData, touched } = this.state; - - if (showInModal) { - const action = bindingDefinition.key ? 'edit' : 'create'; - - return ( - <AlmBindingDefinitionFormModalRenderer - action={action} - canSubmit={this.canSubmit} - help={help} - isSecondInstance={Boolean(isSecondInstance)} - onCancel={this.handleCancel} - onSubmit={this.handleFormSubmit}> - {children({ - formData, - onFieldChange: this.handleFieldChange - })} - </AlmBindingDefinitionFormModalRenderer> - ); - } else { - const showEdit = this.props.onEdit !== undefined; - const showCancel = touched || !showEdit; - const showDelete = showEdit && this.props.onDelete !== undefined; - - return ( - <AlmBindingDefinitionFormRenderer - canSubmit={this.canSubmit} - help={help} - loading={loading} - onCancel={showCancel ? this.handleCancel : undefined} - onDelete={showDelete ? this.handleDelete : undefined} - onEdit={showEdit ? this.handleEdit : undefined} - onSubmit={this.handleFormSubmit} - success={success}> - {children({ - formData, - hideKeyField, - onFieldChange: this.handleFieldChange, - readOnly - })} - </AlmBindingDefinitionFormRenderer> - ); - } + const { bindingDefinition, children, help, isSecondInstance } = this.props; + const { formData } = this.state; + + const action = bindingDefinition.key ? 'edit' : 'create'; + + return ( + <AlmBindingDefinitionFormModalRenderer + action={action} + canSubmit={this.canSubmit} + help={help} + isSecondInstance={Boolean(isSecondInstance)} + onCancel={this.handleCancel} + onSubmit={this.handleFormSubmit}> + {children({ + formData, + onFieldChange: this.handleFieldChange + })} + </AlmBindingDefinitionFormModalRenderer> + ); } } diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx deleted file mode 100644 index 812ba48a61a..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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, ResetButtonLink, SubmitButton } from 'sonar-ui-common/components/controls/buttons'; -import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import { translate } from 'sonar-ui-common/helpers/l10n'; - -export interface AlmBindingDefinitionFormRendererProps { - canSubmit: () => boolean; - children: React.ReactNode; - help?: React.ReactNode; - onCancel?: () => void; - onDelete?: () => void; - onEdit?: () => void; - onSubmit: () => void; - loading: boolean; - success: boolean; -} - -export default function AlmBindingDefinitionFormRenderer( - props: AlmBindingDefinitionFormRendererProps -) { - const { children, help, loading, success } = props; - - return ( - <form - className="views-form" - data-test="settings__alm-form" - onSubmit={(e: React.FormEvent<HTMLFormElement>) => { - e.preventDefault(); - props.onSubmit(); - }}> - <div className="display-flex-start"> - <div className="flex-1"> - {children} - - <div className="display-flex-center"> - {props.onEdit === undefined ? ( - <SubmitButton disabled={loading || !props.canSubmit()}> - {translate('settings.almintegration.form.save')} - </SubmitButton> - ) : ( - <Button disabled={loading} onClick={props.onEdit}> - {translate('edit')} - </Button> - )} - {props.onDelete && ( - <Button - className="button-red spacer-left" - disabled={loading} - onClick={props.onDelete}> - {translate('delete')} - </Button> - )} - {props.onCancel && ( - <ResetButtonLink className="spacer-left" onClick={props.onCancel}> - {translate('cancel')} - </ResetButtonLink> - )} - {loading && <DeferredSpinner className="spacer-left" />} - {!loading && success && ( - <span className="text-success spacer-left"> - <AlertSuccessIcon className="spacer-right" /> - {translate('settings.state.saved')} - </span> - )} - </div> - </div> - - {help && ( - <Alert className="huge-spacer-left flex-1" variant="info"> - {help} - </Alert> - )} - </div> - </form> - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionsTable.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionsTable.tsx deleted file mode 100644 index c1bcc5bb36f..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionsTable.tsx +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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, ButtonIcon, DeleteButton } from 'sonar-ui-common/components/controls/buttons'; -import EditIcon from 'sonar-ui-common/components/icons/EditIcon'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { AlmKeys } from '../../../../types/alm-settings'; - -export interface AlmBindingDefinitionsTableProps { - additionalColumnsHeaders: Array<string>; - additionalTableInfo?: React.ReactNode; - alm: AlmKeys; - definitions: Array<{ - key: string; - additionalColumns: Array<string>; - }>; - loading: boolean; - onCreate: () => void; - onDelete: (definitionKey: string) => void; - onEdit: (definitionKey: string) => void; -} - -export default function AlmBindingDefinitionsTable(props: AlmBindingDefinitionsTableProps) { - const { additionalColumnsHeaders, additionalTableInfo, alm, definitions, loading } = props; - - return ( - <> - <div className="spacer-top big-spacer-bottom display-flex-space-between"> - <h2 className="settings-sub-category-name"> - {translate('settings.almintegration.table.title')} - </h2> - <Button data-test="settings__alm-create" disabled={loading} onClick={props.onCreate}> - {translate('settings.almintegration.table.create')} - </Button> - </div> - - {additionalTableInfo} - - <table className="data zebra fixed spacer-bottom"> - <thead> - <tr> - <th>{translate('settings.almintegration.table.column.name')}</th> - {additionalColumnsHeaders.map(h => ( - <th key={h}>{h}</th> - ))} - <th className="action-small text-center"> - {translate('settings.almintegration.table.column.edit')} - </th> - <th className="action text-center"> - {translate('settings.almintegration.table.column.delete')} - </th> - </tr> - </thead> - <tbody> - {definitions.length === 0 ? ( - <tr data-test="settings__alm-empty-table"> - <td colSpan={3 + additionalColumnsHeaders.length}> - {translate('settings.almintegration.table.empty', alm)} - </td> - </tr> - ) : ( - definitions.map(({ key, additionalColumns }) => ( - <tr data-test="settings__alm-table-row" key={key}> - <td className="nowrap hide-overflow" title={key}> - {key} - </td> - {additionalColumns.map(value => ( - <td className="nowrap hide-overflow" key={value} title={value}> - {value} - </td> - ))} - <td className="text-center" data-test="settings__alm-table-row-edit"> - <ButtonIcon disabled={loading} onClick={() => props.onEdit(key)}> - <EditIcon /> - </ButtonIcon> - </td> - <td className="text-center" data-test="settings__alm-table-row-delete"> - <DeleteButton disabled={loading} onClick={() => props.onDelete(key)} /> - </td> - </tr> - )) - )} - </tbody> - </table> - </> - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx index a985b48f733..ed6c0c964f0 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx @@ -29,7 +29,8 @@ import { AlmBindingDefinition, AlmKeys, AlmSettingsBindingDefinitions, - AlmSettingsBindingStatus + AlmSettingsBindingStatus, + AlmSettingsBindingStatusType } from '../../../../types/alm-settings'; import AlmIntegrationRenderer from './AlmIntegrationRenderer'; import { VALIDATED_ALMS } from './utils'; @@ -151,20 +152,30 @@ export class AlmIntegration extends React.PureComponent<Props, State> { this.setState(({ definitionStatus }) => { definitionStatus[definitionKey] = { ...definitionStatus[definitionKey], - validating: true + type: AlmSettingsBindingStatusType.Validating }; return { definitionStatus: { ...definitionStatus } }; }); - const errorMessage = await validateAlmSettings(definitionKey).catch(() => undefined); + let type: AlmSettingsBindingStatusType; + let failureMessage = ''; - if (this.mounted && errorMessage !== undefined) { + try { + failureMessage = await validateAlmSettings(definitionKey); + type = failureMessage + ? AlmSettingsBindingStatusType.Failure + : AlmSettingsBindingStatusType.Success; + } catch (_) { + type = AlmSettingsBindingStatusType.Warning; + } + + if (this.mounted) { this.setState(({ definitionStatus }) => { definitionStatus[definitionKey] = { - alert: alertSuccess || Boolean(errorMessage), - errorMessage, - validating: false + alertSuccess, + failureMessage, + type }; return { definitionStatus: { ...definitionStatus } }; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationFeatureBox.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationFeatureBox.tsx deleted file mode 100644 index dfdeb10bbd5..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationFeatureBox.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 classNames from 'classnames'; -import * as React from 'react'; -import CheckIcon from 'sonar-ui-common/components/icons/CheckIcon'; -import ClearIcon from 'sonar-ui-common/components/icons/ClearIcon'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { colors } from '../../../../app/theme'; - -export interface AlmIntegrationFeatureBoxProps { - active: boolean; - description: React.ReactNode; - inactiveReason?: React.ReactNode; - name: React.ReactNode; -} - -export default function AlmIntegrationFeatureBox(props: AlmIntegrationFeatureBoxProps) { - const { active, description, inactiveReason, name } = props; - - return ( - <div - className={classNames( - 'boxed-group-inner display-flex-start width-30 spacer-right spacer-bottom bordered', - { - 'bg-muted': !active - } - )}> - {active ? ( - <CheckIcon className="little-spacer-top spacer-right" fill={colors.green} /> - ) : ( - <ClearIcon className="little-spacer-top spacer-right" fill={colors.gray60} /> - )} - <div className="display-flex-column abs-height-100"> - <h4>{name}</h4> - - <div className="spacer-top flex-1">{description}</div> - - <div className="spacer-top"> - {active ? ( - <em className="text-success">{translate('settings.almintegration.feature.enabled')}</em> - ) : ( - <em className="text-muted"> - {inactiveReason || translate('settings.almintegration.feature.disabled')} - </em> - )} - </div> - </div> - </div> - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx index d603bd64027..34a31756ac7 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx @@ -24,19 +24,15 @@ import { AlmSettingsBindingStatus } from '../../../../types/alm-settings'; import { AlmBindingDefinitionFormChildrenProps } from './AlmBindingDefinitionForm'; -import { AlmIntegrationFeatureBoxProps } from './AlmIntegrationFeatureBox'; import AlmTabRenderer from './AlmTabRenderer'; +import { VALIDATED_ALMS } from './utils'; interface Props<B> { alm: AlmKeys; - additionalColumnsHeaders?: string[]; - additionalColumnsKeys?: Array<keyof B>; - additionalTableInfo?: React.ReactNode; createConfiguration: (data: B) => Promise<void>; defaultBinding: B; definitions: B[]; definitionStatus: T.Dict<AlmSettingsBindingStatus>; - features?: AlmIntegrationFeatureBoxProps[]; form: (props: AlmBindingDefinitionFormChildrenProps<B>) => React.ReactNode; help?: React.ReactNode; loadingAlmDefinitions: boolean; @@ -101,7 +97,11 @@ export default class AlmTab<B extends AlmBindingDefinition> extends React.PureCo } }) .then(this.props.onUpdateDefinitions) - .then(() => this.props.onCheck(config.key)) + .then(() => { + if (VALIDATED_ALMS.includes(this.props.alm)) { + this.props.onCheck(config.key); + } + }) .catch(() => { if (this.mounted) { this.setState({ submitting: false, success: false }); @@ -111,14 +111,10 @@ export default class AlmTab<B extends AlmBindingDefinition> extends React.PureCo render() { const { - additionalColumnsHeaders = [], - additionalColumnsKeys = [], - additionalTableInfo, alm, defaultBinding, definitions, definitionStatus, - features, form, help, loadingAlmDefinitions, @@ -130,15 +126,11 @@ export default class AlmTab<B extends AlmBindingDefinition> extends React.PureCo return ( <AlmTabRenderer - additionalColumnsHeaders={additionalColumnsHeaders} - additionalColumnsKeys={additionalColumnsKeys} - additionalTableInfo={additionalTableInfo} alm={alm} defaultBinding={defaultBinding} definitions={definitions} definitionStatus={definitionStatus} editedDefinition={editedDefinition} - features={features} form={form} help={help} loadingAlmDefinitions={loadingAlmDefinitions} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx index 0e486688bde..248e3bb8956 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx @@ -21,33 +21,27 @@ import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { Link } from 'react-router'; import { Button } from 'sonar-ui-common/components/controls/buttons'; +import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; import { translate } from 'sonar-ui-common/helpers/l10n'; +import { getEdition, getEditionUrl } from '../../../../helpers/editions'; import { AlmBindingDefinition, AlmKeys, AlmSettingsBindingStatus } from '../../../../types/alm-settings'; +import { EditionKey } from '../../../../types/editions'; import AlmBindingDefinitionBox from './AlmBindingDefinitionBox'; import AlmBindingDefinitionForm, { AlmBindingDefinitionFormChildrenProps } from './AlmBindingDefinitionForm'; -import AlmBindingDefinitionsTable from './AlmBindingDefinitionsTable'; -import AlmIntegrationFeatureBox, { - AlmIntegrationFeatureBoxProps -} from './AlmIntegrationFeatureBox'; -import { VALIDATED_ALMS } from './utils'; export interface AlmTabRendererProps<B> { - additionalColumnsHeaders: string[]; - additionalColumnsKeys: Array<keyof B>; - additionalTableInfo?: React.ReactNode; alm: AlmKeys; definitionStatus: T.Dict<AlmSettingsBindingStatus>; editedDefinition?: B; defaultBinding: B; definitions: B[]; - features?: AlmIntegrationFeatureBoxProps[]; form: (props: AlmBindingDefinitionFormChildrenProps<B>) => React.ReactNode; help?: React.ReactNode; loadingAlmDefinitions: boolean; @@ -64,154 +58,99 @@ export interface AlmTabRendererProps<B> { success: boolean; } -function renderListOfDefinitions<B extends AlmBindingDefinition>(props: AlmTabRendererProps<B>) { - const { - additionalColumnsHeaders, - additionalColumnsKeys, - additionalTableInfo, - alm, - definitions, - definitionStatus, - loadingProjectCount - } = props; - - if (VALIDATED_ALMS.includes(alm)) { - return ( - <> - <div className="spacer-bottom text-right"> - <Button - data-test="settings__alm-create" - disabled={loadingProjectCount} - onClick={props.onCreate}> - {translate('settings.almintegration.table.create')} - </Button> - </div> - {definitions.map(def => ( - <AlmBindingDefinitionBox - definition={def} - key={def.key} - multipleDefinitions={definitions.length > 1} - onCheck={props.onCheck} - onDelete={props.onDelete} - onEdit={props.onEdit} - status={definitionStatus[def.key]} - /> - ))} - </> - ); - } - - const mappedDefinitions = definitions.map(({ key, ...properties }) => { - const additionalColumns = additionalColumnsKeys.map(k => (properties as any)[k]); - return { - key, - additionalColumns - }; - }); - - return ( - <AlmBindingDefinitionsTable - additionalColumnsHeaders={additionalColumnsHeaders} - additionalTableInfo={additionalTableInfo} - alm={alm} - definitions={mappedDefinitions} - loading={loadingProjectCount} - onCreate={props.onCreate} - onDelete={props.onDelete} - onEdit={props.onEdit} - /> - ); -} +const renderDefaultHelp = (alm: AlmKeys) => ( + <FormattedMessage + defaultMessage={translate(`settings.almintegration.${alm}.info`)} + id={`settings.almintegration.${alm}.info`} + values={{ + link: ( + <Link target="_blank" to="/documentation/analysis/pr-decoration/"> + {translate('learn_more')} + </Link> + ) + }} + /> +); export default function AlmTabRenderer<B extends AlmBindingDefinition>( props: AlmTabRendererProps<B> ) { const { alm, - defaultBinding, definitions, + definitionStatus, editedDefinition, - features = [], form, loadingAlmDefinitions, loadingProjectCount, multipleAlmEnabled, optionalFields, - submitting, - success, - help = ( - <FormattedMessage - defaultMessage={translate(`settings.almintegration.${alm}.info`)} - id={`settings.almintegration.${alm}.info`} - values={{ - link: ( - <Link target="_blank" to="/documentation/analysis/pr-decoration/"> - {translate('learn_more')} - </Link> - ) - }} - /> - ) + help = renderDefaultHelp(alm) } = props; - let definition: B | undefined; - let showEdit: boolean | undefined; - - if (!multipleAlmEnabled) { - definition = editedDefinition; - if (definition === undefined && definitions.length > 0) { - definition = definitions[0]; - } - showEdit = definition && editedDefinition === undefined; - } + const preventCreation = loadingProjectCount || (!multipleAlmEnabled && definitions.length > 0); + const creationTooltip = preventCreation ? ( + <FormattedMessage + id="settings.almintegration.create.tooltip" + defaultMessage={translate('settings.almintegration.create.tooltip')} + values={{ + link: ( + <a + href={getEditionUrl(getEdition(EditionKey.enterprise), { + sourceEdition: EditionKey.developer + })} + rel="noopener noreferrer" + target="_blank"> + {translate('settings.almintegration.create.tooltip.link')} + </a> + ), + alm: translate('alm', alm) + }} + /> + ) : null; return ( <div className="big-padded"> - {multipleAlmEnabled ? ( - <DeferredSpinner loading={loadingAlmDefinitions}> - {renderListOfDefinitions(props)} - - {editedDefinition && ( - <AlmBindingDefinitionForm - bindingDefinition={editedDefinition} - help={help} - isSecondInstance={definitions.length === 1} - onCancel={props.onCancel} - onSubmit={props.onSubmit} - optionalFields={optionalFields} - showInModal={true}> - {form} - </AlmBindingDefinitionForm> - )} - </DeferredSpinner> - ) : ( - <AlmBindingDefinitionForm - bindingDefinition={definition || defaultBinding} - help={help} - hideKeyField={true} - loading={loadingAlmDefinitions || loadingProjectCount || submitting} - onCancel={props.onCancel} - onDelete={definition ? props.onDelete : undefined} - onEdit={showEdit ? props.onEdit : undefined} - onSubmit={props.onSubmit} - optionalFields={optionalFields} - readOnly={showEdit} - success={success}> - {form} - </AlmBindingDefinitionForm> - )} - - {!VALIDATED_ALMS.includes(alm) && features.length > 0 && ( - <div className="big-spacer-top big-padded-top bordered-top"> - <h3 className="big-spacer-bottom">{translate('settings.almintegration.features')}</h3> + <DeferredSpinner loading={loadingAlmDefinitions}> + {definitions.length === 0 && ( + <p className="spacer-top">{translate('settings.almintegration.empty', alm)}</p> + )} - <div className="display-flex-wrap"> - {features.map((feature, i) => ( - <AlmIntegrationFeatureBox key={i} {...feature} /> - ))} - </div> + <div className={definitions.length > 0 ? 'spacer-bottom text-right' : 'big-spacer-top'}> + <Tooltip overlay={creationTooltip} mouseLeaveDelay={0.25}> + <Button + data-test="settings__alm-create" + disabled={preventCreation} + onClick={props.onCreate}> + {translate('settings.almintegration.create')} + </Button> + </Tooltip> </div> - )} + {definitions.map(def => ( + <AlmBindingDefinitionBox + alm={alm} + definition={def} + key={def.key} + multipleDefinitions={definitions.length > 1} + onCheck={props.onCheck} + onDelete={props.onDelete} + onEdit={props.onEdit} + status={definitionStatus[def.key]} + /> + ))} + + {editedDefinition && ( + <AlmBindingDefinitionForm + bindingDefinition={editedDefinition} + help={help} + isSecondInstance={definitions.length === 1} + onCancel={props.onCancel} + onSubmit={props.onSubmit} + optionalFields={optionalFields}> + {form} + </AlmBindingDefinitionForm> + )} + </DeferredSpinner> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx index f727d695c2d..f6998962796 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { translate } from 'sonar-ui-common/helpers/l10n'; import { createAzureConfiguration, updateAzureConfiguration } from '../../../../api/alm-settings'; import { AlmKeys, @@ -56,14 +55,6 @@ export default function AzureTab(props: AzureTabProps) { defaultBinding={{ key: '', personalAccessToken: '' }} definitions={definitions} definitionStatus={definitionStatus} - features={[ - { - name: translate('settings.almintegration.feature.pr_decoration.title'), - active: definitions.length > 0, - description: translate('settings.almintegration.feature.pr_decoration.description'), - inactiveReason: translate('settings.almintegration.feature.need_at_least_1_binding') - } - ]} form={childProps => <AzureForm {...childProps} />} loadingAlmDefinitions={loadingAlmDefinitions} loadingProjectCount={loadingProjectCount} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx index 4fc261cfb92..fa0aa6c5950 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx @@ -18,10 +18,8 @@ * 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, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; +import { translate } from 'sonar-ui-common/helpers/l10n'; import { createBitbucketConfiguration, updateBitbucketConfiguration @@ -57,45 +55,11 @@ export default function BitbucketTab(props: BitbucketTabProps) { return ( <div className="bordered"> <AlmTab - additionalColumnsHeaders={[translate('settings.almintegration.table.column.bitbucket.url')]} - additionalColumnsKeys={['url']} - additionalTableInfo={ - <Alert className="big-spacer-bottom width-50" variant="info"> - <FormattedMessage - defaultMessage={translate( - 'settings.almintegration.feature.alm_repo_import.disabled_if_multiple_bbs_instances' - )} - id="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_bbs_instances" - values={{ - feature: ( - <em>{translate('settings.almintegration.feature.alm_repo_import.title')}</em> - ) - }} - /> - </Alert> - } alm={AlmKeys.Bitbucket} createConfiguration={createBitbucketConfiguration} defaultBinding={{ key: '', url: '', personalAccessToken: '' }} definitions={definitions} definitionStatus={definitionStatus} - features={[ - { - name: translate('settings.almintegration.feature.pr_decoration.title'), - active: definitions.length > 0, - description: translate('settings.almintegration.feature.pr_decoration.description'), - inactiveReason: translate('settings.almintegration.feature.need_at_least_1_binding') - }, - { - name: translate('settings.almintegration.feature.alm_repo_import.title'), - active: definitions.length === 1, - description: translate('settings.almintegration.feature.alm_repo_import.description'), - inactiveReason: translateWithParameters( - 'settings.almintegration.feature.alm_repo_import.bitbucket.wrong_count_x', - definitions.length - ) - } - ]} form={childProps => <BitbucketForm {...childProps} />} help={ <> diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx index a44d2e8813e..214f0b87286 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx @@ -18,10 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import WarningIcon from 'sonar-ui-common/components/icons/WarningIcon'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; import { createGithubConfiguration, updateGithubConfiguration } from '../../../../api/alm-settings'; import { AlmKeys, @@ -62,26 +58,6 @@ export default function GithubTab(props: GithubTabProps) { {branchesEnabled && ( <> <AlmTab - additionalColumnsHeaders={[ - translate('settings.almintegration.table.column.github.url'), - translate('settings.almintegration.table.column.app_id') - ]} - additionalColumnsKeys={['url', 'appId']} - additionalTableInfo={ - <Alert className="big-spacer-bottom width-50" variant="info"> - <FormattedMessage - defaultMessage={translate( - 'settings.almintegration.feature.alm_repo_import.disabled_if_multiple_github_instances' - )} - id="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_github_instances" - values={{ - feature: ( - <em>{translate('settings.almintegration.feature.alm_repo_import.title')}</em> - ) - }} - /> - </Alert> - } alm={AlmKeys.GitHub} createConfiguration={createGithubConfiguration} defaultBinding={{ @@ -94,45 +70,6 @@ export default function GithubTab(props: GithubTabProps) { }} definitions={definitions} definitionStatus={definitionStatus} - features={[ - { - name: translate('settings.almintegration.feature.pr_decoration.title'), - active: definitions.length > 0, - description: translate('settings.almintegration.feature.pr_decoration.description'), - inactiveReason: translate('settings.almintegration.feature.need_at_least_1_binding') - }, - { - name: translate('settings.almintegration.feature.alm_repo_import.title'), - active: - definitions.length === 1 && - !!definitions[0].clientId && - !!definitions[0].clientSecret, - description: translate( - 'settings.almintegration.feature.alm_repo_import.description' - ), - inactiveReason: - definitions.length === 1 ? ( - <> - <WarningIcon className="little-spacer-right" /> - <FormattedMessage - id="settings.almintegration.feature.alm_repo_import.github.requires_fields" - defaultMessage={translate( - 'settings.almintegration.feature.alm_repo_import.github.requires_fields' - )} - values={{ - clientId: <strong>clientId</strong>, - clientSecret: <strong>clientSecret</strong> - }} - /> - </> - ) : ( - translateWithParameters( - 'settings.almintegration.feature.alm_repo_import.github.wrong_count_x', - definitions.length - ) - ) - } - ]} form={childProps => <GithubForm {...childProps} />} loadingAlmDefinitions={loadingAlmDefinitions} loadingProjectCount={loadingProjectCount} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx index db7558480d0..552891d9358 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx @@ -18,9 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; import { createGitlabConfiguration, updateGitlabConfiguration } from '../../../../api/alm-settings'; import { AlmKeys, @@ -56,61 +53,16 @@ export default function GitlabTab(props: GitlabTabProps) { loadingProjectCount } = props; - const importFeatureEnabled = Boolean(definitions.length === 1 && definitions[0].url); - return ( <div className="bordered"> {branchesEnabled && ( <> <AlmTab - additionalColumnsHeaders={[ - translate('settings.almintegration.table.column.gitlab.url') - ]} - additionalColumnsKeys={['url']} - additionalTableInfo={ - <Alert className="big-spacer-bottom width-50" variant="info"> - <FormattedMessage - defaultMessage={translate( - 'settings.almintegration.feature.alm_repo_import.disabled_if_multiple_gitlab_instances' - )} - id="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_gitlab_instances" - values={{ - feature: ( - <em>{translate('settings.almintegration.feature.alm_repo_import.title')}</em> - ) - }} - /> - </Alert> - } alm={AlmKeys.GitLab} createConfiguration={createGitlabConfiguration} defaultBinding={{ key: '', personalAccessToken: '', url: '' }} definitions={definitions} definitionStatus={definitionStatus} - features={[ - { - name: translate('settings.almintegration.feature.mr_decoration.title'), - active: definitions.length > 0, - description: translate('settings.almintegration.feature.mr_decoration.description'), - inactiveReason: translate('settings.almintegration.feature.need_at_least_1_binding') - }, - { - name: translate('settings.almintegration.feature.alm_repo_import.title'), - active: importFeatureEnabled, - description: translate( - 'settings.almintegration.feature.alm_repo_import.description' - ), - inactiveReason: - definitions.length === 1 - ? translate( - 'settings.almintegration.feature.alm_repo_import.gitlab.requires_fields' - ) - : translateWithParameters( - 'settings.almintegration.feature.alm_repo_import.gitlab.wrong_count_x', - definitions.length - ) - } - ]} form={childProps => <GitlabForm {...childProps} />} loadingAlmDefinitions={loadingAlmDefinitions} loadingProjectCount={loadingProjectCount} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx index d8c9cbb93d4..89fe0fe5f77 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx @@ -21,44 +21,57 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockAlmSettingsBindingStatus, + mockAzureBindingDefinition, mockGithubBindingDefinition } from '../../../../../helpers/mocks/alm-settings'; +import { AlmKeys, AlmSettingsBindingStatusType } from '../../../../../types/alm-settings'; import AlmBindingDefinitionBox, { AlmBindingDefinitionBoxProps } from '../AlmBindingDefinitionBox'; it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot('default'); expect(shallowRender({ multipleDefinitions: true })).toMatchSnapshot('multiple definitions'); expect( - shallowRender({ status: mockAlmSettingsBindingStatus({ errorMessage: '', validating: false }) }) + shallowRender({ + status: mockAlmSettingsBindingStatus({ + type: AlmSettingsBindingStatusType.Success + }) + }) ).toMatchSnapshot('success'); expect( shallowRender({ status: mockAlmSettingsBindingStatus({ - errorMessage: 'Oops, something went wrong', - validating: false + failureMessage: 'Oops, something went wrong', + type: AlmSettingsBindingStatusType.Failure }) }) ).toMatchSnapshot('error'); expect( shallowRender({ - status: mockAlmSettingsBindingStatus({ alert: true, errorMessage: '', validating: false }) + status: mockAlmSettingsBindingStatus({ + alertSuccess: true, + type: AlmSettingsBindingStatusType.Success + }) }) ).toMatchSnapshot('success with alert'); + expect( shallowRender({ status: mockAlmSettingsBindingStatus({ - alert: true, - errorMessage: 'Oops, something went wrong', - validating: false + type: AlmSettingsBindingStatusType.Warning }) }) - ).toMatchSnapshot('error with alert'); + ).toMatchSnapshot('warning'); + + expect( + shallowRender({ alm: AlmKeys.Azure, definition: mockAzureBindingDefinition() }) + ).toMatchSnapshot('Azure DevOps'); }); function shallowRender(props: Partial<AlmBindingDefinitionBoxProps> = {}) { return shallow( <AlmBindingDefinitionBox + alm={AlmKeys.GitHub} definition={mockGithubBindingDefinition()} multipleDefinitions={false} onCheck={jest.fn()} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionForm-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionForm-test.tsx index ab7e8623cb6..b4849a294ed 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionForm-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionForm-test.tsx @@ -25,12 +25,11 @@ import { GithubBindingDefinition } from '../../../../../types/alm-settings'; import AlmBindingDefinitionForm from '../AlmBindingDefinitionForm'; it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); + expect(shallowRender()).toMatchSnapshot('create'); - expect(shallowRender({ showInModal: true })).toMatchSnapshot('modal'); - expect( - shallowRender({ bindingDefinition: mockGithubBindingDefinition(), showInModal: true }) - ).toMatchSnapshot('modal edit'); + expect(shallowRender({ bindingDefinition: mockGithubBindingDefinition() })).toMatchSnapshot( + 'edit' + ); }); it('should reset if the props change', () => { diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx deleted file mode 100644 index 6774ed436d6..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { SubmitButton } from 'sonar-ui-common/components/controls/buttons'; -import { submit } from 'sonar-ui-common/helpers/testUtils'; -import AlmBindingDefinitionFormRenderer, { - AlmBindingDefinitionFormRendererProps -} from '../AlmBindingDefinitionFormRenderer'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect(shallowRender({ onCancel: jest.fn() })).toMatchSnapshot(); - expect(shallowRender({ onDelete: jest.fn() })).toMatchSnapshot(); - expect(shallowRender({ success: true })).toMatchSnapshot(); - expect(shallowRender({ loading: true })).toMatchSnapshot(); -}); - -it('should correctly block the form submission', () => { - const canSubmit = jest.fn(() => false); - const wrapper = shallowRender({ canSubmit, loading: false }); - - expect(canSubmit).toBeCalled(); - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true); - - wrapper.setProps({ canSubmit: jest.fn(), loading: true }); - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true); - - wrapper.setProps({ canSubmit: () => true, loading: false }); - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(false); -}); - -it('should correctly submit the form', () => { - const onSubmit = jest.fn(); - const wrapper = shallowRender({ onSubmit }); - submit(wrapper.find('form')); - expect(onSubmit).toBeCalled(); -}); - -function shallowRender(props: Partial<AlmBindingDefinitionFormRendererProps> = {}) { - return shallow( - <AlmBindingDefinitionFormRenderer - canSubmit={jest.fn()} - loading={false} - onSubmit={jest.fn()} - success={false} - {...props}> - {() => null} - </AlmBindingDefinitionFormRenderer> - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionsTable-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionsTable-test.tsx deleted file mode 100644 index ab0455f10a9..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionsTable-test.tsx +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 { AlmKeys } from '../../../../../types/alm-settings'; -import AlmBindingDefinitionsTable, { - AlmBindingDefinitionsTableProps -} from '../AlmBindingDefinitionsTable'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect( - shallowRender({ - additionalColumnsHeaders: ['additional1', 'additional2'], - alm: AlmKeys.GitHub, - definitions: [ - { key: 'definition1', additionalColumns: ['def1-v1', 'def1-v2'] }, - { key: 'definition2', additionalColumns: ['def2-v1', 'def2-v2'] } - ] - }) - ).toMatchSnapshot('additional columns'); - expect(shallowRender()).toMatchSnapshot('loading'); - expect(shallowRender({ alm: AlmKeys.GitLab })).toMatchSnapshot('title adjusts for GitLab'); -}); - -it('should correctly trigger create, delete, and edit', () => { - const onCreate = jest.fn(); - const onDelete = jest.fn(); - const onEdit = jest.fn(); - - const wrapper = shallowRender({ - additionalColumnsHeaders: [], - alm: AlmKeys.Bitbucket, - definitions: [{ key: 'defKey', additionalColumns: [] }], - onCreate, - onDelete, - onEdit - }); - - wrapper.find('Button').simulate('click'); - expect(onCreate).toBeCalled(); - - wrapper.find('DeleteButton').simulate('click'); - expect(onDelete).toBeCalledWith('defKey'); - - wrapper.find('ButtonIcon').simulate('click'); - expect(onEdit).toBeCalledWith('defKey'); -}); - -function shallowRender(props: Partial<AlmBindingDefinitionsTableProps> = {}) { - return shallow( - <AlmBindingDefinitionsTable - additionalColumnsHeaders={[]} - alm={AlmKeys.Azure} - definitions={[]} - loading={false} - onCreate={jest.fn()} - onDelete={jest.fn()} - onEdit={jest.fn()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx index fc05d4faaa6..2bb0d844580 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx @@ -26,7 +26,7 @@ import { getAlmDefinitions, validateAlmSettings } from '../../../../../api/alm-settings'; -import { AlmKeys } from '../../../../../types/alm-settings'; +import { AlmKeys, AlmSettingsBindingStatusType } from '../../../../../types/alm-settings'; import { AlmIntegration } from '../AlmIntegration'; jest.mock('../../../../../api/alm-settings', () => ({ @@ -99,38 +99,38 @@ it('should delete configuration', async () => { it('should validate a configuration', async () => { const definitionKey = 'validated-key'; - const errorMessage = 'an error occured'; + const failureMessage = 'an error occured'; const wrapper = shallowRender(); await waitAndUpdate(wrapper); (validateAlmSettings as jest.Mock) - .mockResolvedValueOnce(undefined) - .mockResolvedValueOnce(errorMessage) + .mockRejectedValueOnce(undefined) + .mockResolvedValueOnce(failureMessage) .mockResolvedValueOnce(''); await wrapper.instance().handleCheck(definitionKey); - expect(wrapper.state().definitionStatus[definitionKey]).toEqual( - expect.objectContaining({ - validating: true - }) - ); + expect(wrapper.state().definitionStatus[definitionKey]).toEqual({ + alertSuccess: true, + failureMessage: '', + type: AlmSettingsBindingStatusType.Warning + }); await wrapper.instance().handleCheck(definitionKey); expect(wrapper.state().definitionStatus[definitionKey]).toEqual({ - alert: true, - errorMessage, - validating: false + alertSuccess: true, + failureMessage, + type: AlmSettingsBindingStatusType.Failure }); await wrapper.instance().handleCheck(definitionKey); expect(wrapper.state().definitionStatus[definitionKey]).toEqual({ - alert: true, - errorMessage: '', - validating: false + alertSuccess: true, + failureMessage: '', + type: AlmSettingsBindingStatusType.Success }); }); diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationFeatureBox-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationFeatureBox-test.tsx deleted file mode 100644 index 7366117e6bb..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationFeatureBox-test.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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 AlmIntegrationFeatureBox, { - AlmIntegrationFeatureBoxProps -} from '../AlmIntegrationFeatureBox'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ active: false })).toMatchSnapshot('inactive'); - expect(shallowRender({ active: false, inactiveReason: "Bar is foo'd" })).toMatchSnapshot( - 'inactive, with reason' - ); -}); - -function shallowRender(props: Partial<AlmIntegrationFeatureBoxProps> = {}) { - return shallow<AlmIntegrationFeatureBoxProps>( - <AlmIntegrationFeatureBox active={true} description="Foo bar..." name="Foo" {...props} /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx index 08e55918d2d..3ee492b7694 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx @@ -42,22 +42,6 @@ it('should render correctly for multi-ALM binding', () => { expect(shallowRenderAzure({ editedDefinition: mockAzureBindingDefinition() })).toMatchSnapshot( 'editing a definition' ); - expect( - shallowRenderAzure({ - features: [ - { - active: true, - name: 'Foo', - description: 'Bar' - }, - { - active: false, - name: 'Baz', - description: 'Bim' - } - ] - }) - ).toMatchSnapshot('with features'); }); it('should render correctly for single-ALM binding', () => { @@ -108,8 +92,6 @@ function shallowRender<B extends AlmBindingDefinition>( ) { return shallow( <AlmTabRenderer - additionalColumnsHeaders={[]} - additionalColumnsKeys={[]} alm={AlmKeys.Azure} defaultBinding={{} as any} definitions={[]} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap index 0629f4af3c2..43bc1bfbc5b 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should render correctly: default 1`] = ` +exports[`should render correctly: Azure DevOps 1`] = ` <div className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition" > @@ -31,50 +31,34 @@ exports[`should render correctly: default 1`] = ` <h3> key </h3> - <span> - http://github.enterprise.com - </span> </div> - <DeferredSpinner - customSpinner={ - <div> - <i - className="deferred-spinner spacer-right" - /> - settings.almintegration.checking_configuration - </div> - } - loading={true} + <div + className="display-flex-row spacer-bottom" > - <div - className="display-flex-row spacer-bottom" + <Tooltip + overlay="settings.almintegration.feature.pr_decoration.description" > - <div - className="huge-spacer-right" - > + <span> settings.almintegration.feature.pr_decoration.title - <AlertSuccessIcon - className="spacer-left" - /> - </div> - <div> - settings.almintegration.feature.alm_repo_import.title - <AlertSuccessIcon - className="spacer-left" - /> - </div> - </div> - <Button - className="big-spacer-top" - onClick={[Function]} + </span> + </Tooltip> + <AlertSuccessIcon + className="spacer-left" + /> + </div> + <div + className="width-50" + > + <Alert + variant="info" > - settings.almintegration.check_configuration - </Button> - </DeferredSpinner> + settings.almintegration.no_validation + </Alert> + </div> </div> `; -exports[`should render correctly: error 1`] = ` +exports[`should render correctly: default 1`] = ` <div className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition" > @@ -109,46 +93,14 @@ exports[`should render correctly: error 1`] = ` http://github.enterprise.com </span> </div> - <DeferredSpinner - customSpinner={ - <div> - <i - className="deferred-spinner spacer-right" - /> - settings.almintegration.checking_configuration - </div> - } - loading={false} - > - <div - className="display-flex-row spacer-bottom" - > - <div - className="huge-spacer-right" - > - settings.almintegration.feature.pr_decoration.title - <AlertErrorIcon - className="spacer-left" - /> - </div> - <div> - settings.almintegration.feature.alm_repo_import.title - <AlertErrorIcon - className="spacer-left" - /> - </div> - </div> - <Button - className="big-spacer-top" - onClick={[Function]} - > - settings.almintegration.check_configuration - </Button> - </DeferredSpinner> + <i + className="spinner spacer-right" + /> + settings.almintegration.checking_configuration </div> `; -exports[`should render correctly: error with alert 1`] = ` +exports[`should render correctly: error 1`] = ` <div className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition" > @@ -183,19 +135,11 @@ exports[`should render correctly: error with alert 1`] = ` http://github.enterprise.com </span> </div> - <DeferredSpinner - customSpinner={ - <div> - <i - className="deferred-spinner spacer-right" - /> - settings.almintegration.checking_configuration - </div> - } - loading={false} + <div + className="display-flex-row spacer-bottom" > - <div - className="display-flex-row spacer-bottom" + <Tooltip + overlay="settings.almintegration.feature.pr_decoration.description" > <div className="huge-spacer-right" @@ -205,29 +149,35 @@ exports[`should render correctly: error with alert 1`] = ` className="spacer-left" /> </div> - <div> - settings.almintegration.feature.alm_repo_import.title - <AlertErrorIcon - className="spacer-left" - /> - </div> - </div> - <div - className="width-50" - > - <Alert - variant="error" + </Tooltip> + <div> + <Tooltip + overlay="settings.almintegration.feature.alm_repo_import.description" > - Oops, something went wrong - </Alert> + <span> + settings.almintegration.feature.alm_repo_import.title + </span> + </Tooltip> + <AlertErrorIcon + className="spacer-left" + /> </div> - <Button - className="big-spacer-top" - onClick={[Function]} + </div> + <div + className="width-50" + > + <Alert + variant="error" > - settings.almintegration.check_configuration - </Button> - </DeferredSpinner> + Oops, something went wrong + </Alert> + </div> + <Button + className="big-spacer-top" + onClick={[Function]} + > + settings.almintegration.check_configuration + </Button> </div> `; @@ -266,52 +216,10 @@ exports[`should render correctly: multiple definitions 1`] = ` http://github.enterprise.com </span> </div> - <DeferredSpinner - customSpinner={ - <div> - <i - className="deferred-spinner spacer-right" - /> - settings.almintegration.checking_configuration - </div> - } - loading={true} - > - <div - className="display-flex-row spacer-bottom" - > - <div - className="huge-spacer-right" - > - settings.almintegration.feature.pr_decoration.title - <AlertSuccessIcon - className="spacer-left" - /> - </div> - <div> - settings.almintegration.feature.alm_repo_import.title - <div - className="display-inline-flex-center" - > - <strong - className="spacer-left" - > - settings.almintegration.feature.alm_repo_import.disabled - </strong> - <HelpTooltip - className="little-spacer-left" - overlay="settings.almintegration.feature.alm_repo_import.help" - /> - </div> - </div> - </div> - <Button - className="big-spacer-top" - onClick={[Function]} - > - settings.almintegration.check_configuration - </Button> - </DeferredSpinner> + <i + className="spinner spacer-right" + /> + settings.almintegration.checking_configuration </div> `; @@ -350,19 +258,11 @@ exports[`should render correctly: success 1`] = ` http://github.enterprise.com </span> </div> - <DeferredSpinner - customSpinner={ - <div> - <i - className="deferred-spinner spacer-right" - /> - settings.almintegration.checking_configuration - </div> - } - loading={false} + <div + className="display-flex-row spacer-bottom" > - <div - className="display-flex-row spacer-bottom" + <Tooltip + overlay="settings.almintegration.feature.pr_decoration.description" > <div className="huge-spacer-right" @@ -372,20 +272,29 @@ exports[`should render correctly: success 1`] = ` className="spacer-left" /> </div> - <div> - settings.almintegration.feature.alm_repo_import.title - <AlertSuccessIcon - className="spacer-left" - /> - </div> + </Tooltip> + <div> + <Tooltip + overlay="settings.almintegration.feature.alm_repo_import.description" + > + <span> + settings.almintegration.feature.alm_repo_import.title + </span> + </Tooltip> + <AlertSuccessIcon + className="spacer-left" + /> </div> - <Button - className="big-spacer-top" - onClick={[Function]} - > - settings.almintegration.check_configuration - </Button> - </DeferredSpinner> + </div> + <div + className="width-50" + /> + <Button + className="big-spacer-top" + onClick={[Function]} + > + settings.almintegration.check_configuration + </Button> </div> `; @@ -424,19 +333,11 @@ exports[`should render correctly: success with alert 1`] = ` http://github.enterprise.com </span> </div> - <DeferredSpinner - customSpinner={ - <div> - <i - className="deferred-spinner spacer-right" - /> - settings.almintegration.checking_configuration - </div> - } - loading={false} + <div + className="display-flex-row spacer-bottom" > - <div - className="display-flex-row spacer-bottom" + <Tooltip + overlay="settings.almintegration.feature.pr_decoration.description" > <div className="huge-spacer-right" @@ -446,28 +347,87 @@ exports[`should render correctly: success with alert 1`] = ` className="spacer-left" /> </div> - <div> - settings.almintegration.feature.alm_repo_import.title - <AlertSuccessIcon - className="spacer-left" - /> - </div> - </div> - <div - className="width-50" - > - <Alert - variant="success" + </Tooltip> + <div> + <Tooltip + overlay="settings.almintegration.feature.alm_repo_import.description" > - settings.almintegration.configuration_valid - </Alert> + <span> + settings.almintegration.feature.alm_repo_import.title + </span> + </Tooltip> + <AlertSuccessIcon + className="spacer-left" + /> </div> + </div> + <div + className="width-50" + > + <Alert + variant="success" + > + settings.almintegration.configuration_valid + </Alert> + </div> + <Button + className="big-spacer-top" + onClick={[Function]} + > + settings.almintegration.check_configuration + </Button> +</div> +`; + +exports[`should render correctly: warning 1`] = ` +<div + className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition" +> + <div + className="actions pull-right" + > <Button - className="big-spacer-top" onClick={[Function]} > - settings.almintegration.check_configuration + <EditIcon + className="spacer-right" + /> + edit </Button> - </DeferredSpinner> + <Button + className="button-red spacer-left" + onClick={[Function]} + > + <DeleteIcon + className="spacer-right" + /> + delete + </Button> + </div> + <div + className="big-spacer-bottom" + > + <h3> + key + </h3> + <span> + http://github.enterprise.com + </span> + </div> + <div + className="width-50" + > + <Alert + variant="warning" + > + settings.almintegration.could_not_validate + </Alert> + </div> + <Button + className="big-spacer-top" + onClick={[Function]} + > + settings.almintegration.check_configuration + </Button> </div> `; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap index e489ff7cef5..525258ed31d 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap @@ -1,16 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should render correctly: default 1`] = ` -<AlmBindingDefinitionFormRenderer - canSubmit={[Function]} - loading={false} - onCancel={[Function]} - onSubmit={[Function]} - success={false} -/> -`; - -exports[`should render correctly: modal 1`] = ` +exports[`should render correctly: create 1`] = ` <AlmBindingDefinitionFormModalRenderer action="create" canSubmit={[Function]} @@ -20,7 +10,7 @@ exports[`should render correctly: modal 1`] = ` /> `; -exports[`should render correctly: modal edit 1`] = ` +exports[`should render correctly: edit 1`] = ` <AlmBindingDefinitionFormModalRenderer action="edit" canSubmit={[Function]} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormRenderer-test.tsx.snap deleted file mode 100644 index 5963e4436ee..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormRenderer-test.tsx.snap +++ /dev/null @@ -1,160 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` -<form - className="views-form" - data-test="settings__alm-form" - onSubmit={[Function]} -> - <div - className="display-flex-start" - > - <div - className="flex-1" - > - <Component /> - <div - className="display-flex-center" - > - <SubmitButton - disabled={true} - > - settings.almintegration.form.save - </SubmitButton> - </div> - </div> - </div> -</form> -`; - -exports[`should render correctly 2`] = ` -<form - className="views-form" - data-test="settings__alm-form" - onSubmit={[Function]} -> - <div - className="display-flex-start" - > - <div - className="flex-1" - > - <Component /> - <div - className="display-flex-center" - > - <SubmitButton - disabled={true} - > - settings.almintegration.form.save - </SubmitButton> - <ResetButtonLink - className="spacer-left" - onClick={[MockFunction]} - > - cancel - </ResetButtonLink> - </div> - </div> - </div> -</form> -`; - -exports[`should render correctly 3`] = ` -<form - className="views-form" - data-test="settings__alm-form" - onSubmit={[Function]} -> - <div - className="display-flex-start" - > - <div - className="flex-1" - > - <Component /> - <div - className="display-flex-center" - > - <SubmitButton - disabled={true} - > - settings.almintegration.form.save - </SubmitButton> - <Button - className="button-red spacer-left" - disabled={false} - onClick={[MockFunction]} - > - delete - </Button> - </div> - </div> - </div> -</form> -`; - -exports[`should render correctly 4`] = ` -<form - className="views-form" - data-test="settings__alm-form" - onSubmit={[Function]} -> - <div - className="display-flex-start" - > - <div - className="flex-1" - > - <Component /> - <div - className="display-flex-center" - > - <SubmitButton - disabled={true} - > - settings.almintegration.form.save - </SubmitButton> - <span - className="text-success spacer-left" - > - <AlertSuccessIcon - className="spacer-right" - /> - settings.state.saved - </span> - </div> - </div> - </div> -</form> -`; - -exports[`should render correctly 5`] = ` -<form - className="views-form" - data-test="settings__alm-form" - onSubmit={[Function]} -> - <div - className="display-flex-start" - > - <div - className="flex-1" - > - <Component /> - <div - className="display-flex-center" - > - <SubmitButton - disabled={true} - > - settings.almintegration.form.save - </SubmitButton> - <DeferredSpinner - className="spacer-left" - /> - </div> - </div> - </div> -</form> -`; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionsTable-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionsTable-test.tsx.snap deleted file mode 100644 index 3f2d55a204c..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionsTable-test.tsx.snap +++ /dev/null @@ -1,304 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` -<Fragment> - <div - className="spacer-top big-spacer-bottom display-flex-space-between" - > - <h2 - className="settings-sub-category-name" - > - settings.almintegration.table.title - </h2> - <Button - data-test="settings__alm-create" - disabled={false} - onClick={[MockFunction]} - > - settings.almintegration.table.create - </Button> - </div> - <table - className="data zebra fixed spacer-bottom" - > - <thead> - <tr> - <th> - settings.almintegration.table.column.name - </th> - <th - className="action-small text-center" - > - settings.almintegration.table.column.edit - </th> - <th - className="action text-center" - > - settings.almintegration.table.column.delete - </th> - </tr> - </thead> - <tbody> - <tr - data-test="settings__alm-empty-table" - > - <td - colSpan={3} - > - settings.almintegration.table.empty.azure - </td> - </tr> - </tbody> - </table> -</Fragment> -`; - -exports[`should render correctly: additional columns 1`] = ` -<Fragment> - <div - className="spacer-top big-spacer-bottom display-flex-space-between" - > - <h2 - className="settings-sub-category-name" - > - settings.almintegration.table.title - </h2> - <Button - data-test="settings__alm-create" - disabled={false} - onClick={[MockFunction]} - > - settings.almintegration.table.create - </Button> - </div> - <table - className="data zebra fixed spacer-bottom" - > - <thead> - <tr> - <th> - settings.almintegration.table.column.name - </th> - <th - key="additional1" - > - additional1 - </th> - <th - key="additional2" - > - additional2 - </th> - <th - className="action-small text-center" - > - settings.almintegration.table.column.edit - </th> - <th - className="action text-center" - > - settings.almintegration.table.column.delete - </th> - </tr> - </thead> - <tbody> - <tr - data-test="settings__alm-table-row" - key="definition1" - > - <td - className="nowrap hide-overflow" - title="definition1" - > - definition1 - </td> - <td - className="nowrap hide-overflow" - key="def1-v1" - title="def1-v1" - > - def1-v1 - </td> - <td - className="nowrap hide-overflow" - key="def1-v2" - title="def1-v2" - > - def1-v2 - </td> - <td - className="text-center" - data-test="settings__alm-table-row-edit" - > - <ButtonIcon - disabled={false} - onClick={[Function]} - > - <EditIcon /> - </ButtonIcon> - </td> - <td - className="text-center" - data-test="settings__alm-table-row-delete" - > - <DeleteButton - disabled={false} - onClick={[Function]} - /> - </td> - </tr> - <tr - data-test="settings__alm-table-row" - key="definition2" - > - <td - className="nowrap hide-overflow" - title="definition2" - > - definition2 - </td> - <td - className="nowrap hide-overflow" - key="def2-v1" - title="def2-v1" - > - def2-v1 - </td> - <td - className="nowrap hide-overflow" - key="def2-v2" - title="def2-v2" - > - def2-v2 - </td> - <td - className="text-center" - data-test="settings__alm-table-row-edit" - > - <ButtonIcon - disabled={false} - onClick={[Function]} - > - <EditIcon /> - </ButtonIcon> - </td> - <td - className="text-center" - data-test="settings__alm-table-row-delete" - > - <DeleteButton - disabled={false} - onClick={[Function]} - /> - </td> - </tr> - </tbody> - </table> -</Fragment> -`; - -exports[`should render correctly: loading 1`] = ` -<Fragment> - <div - className="spacer-top big-spacer-bottom display-flex-space-between" - > - <h2 - className="settings-sub-category-name" - > - settings.almintegration.table.title - </h2> - <Button - data-test="settings__alm-create" - disabled={false} - onClick={[MockFunction]} - > - settings.almintegration.table.create - </Button> - </div> - <table - className="data zebra fixed spacer-bottom" - > - <thead> - <tr> - <th> - settings.almintegration.table.column.name - </th> - <th - className="action-small text-center" - > - settings.almintegration.table.column.edit - </th> - <th - className="action text-center" - > - settings.almintegration.table.column.delete - </th> - </tr> - </thead> - <tbody> - <tr - data-test="settings__alm-empty-table" - > - <td - colSpan={3} - > - settings.almintegration.table.empty.azure - </td> - </tr> - </tbody> - </table> -</Fragment> -`; - -exports[`should render correctly: title adjusts for GitLab 1`] = ` -<Fragment> - <div - className="spacer-top big-spacer-bottom display-flex-space-between" - > - <h2 - className="settings-sub-category-name" - > - settings.almintegration.table.title - </h2> - <Button - data-test="settings__alm-create" - disabled={false} - onClick={[MockFunction]} - > - settings.almintegration.table.create - </Button> - </div> - <table - className="data zebra fixed spacer-bottom" - > - <thead> - <tr> - <th> - settings.almintegration.table.column.name - </th> - <th - className="action-small text-center" - > - settings.almintegration.table.column.edit - </th> - <th - className="action text-center" - > - settings.almintegration.table.column.delete - </th> - </tr> - </thead> - <tbody> - <tr - data-test="settings__alm-empty-table" - > - <td - colSpan={3} - > - settings.almintegration.table.empty.gitlab - </td> - </tr> - </tbody> - </table> -</Fragment> -`; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationFeatureBox-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationFeatureBox-test.tsx.snap deleted file mode 100644 index 16a177214ae..00000000000 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationFeatureBox-test.tsx.snap +++ /dev/null @@ -1,97 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` -<div - className="boxed-group-inner display-flex-start width-30 spacer-right spacer-bottom bordered" -> - <CheckIcon - className="little-spacer-top spacer-right" - fill="#00aa00" - /> - <div - className="display-flex-column abs-height-100" - > - <h4> - Foo - </h4> - <div - className="spacer-top flex-1" - > - Foo bar... - </div> - <div - className="spacer-top" - > - <em - className="text-success" - > - settings.almintegration.feature.enabled - </em> - </div> - </div> -</div> -`; - -exports[`should render correctly: inactive 1`] = ` -<div - className="boxed-group-inner display-flex-start width-30 spacer-right spacer-bottom bordered bg-muted" -> - <ClearIcon - className="little-spacer-top spacer-right" - fill="#999" - /> - <div - className="display-flex-column abs-height-100" - > - <h4> - Foo - </h4> - <div - className="spacer-top flex-1" - > - Foo bar... - </div> - <div - className="spacer-top" - > - <em - className="text-muted" - > - settings.almintegration.feature.disabled - </em> - </div> - </div> -</div> -`; - -exports[`should render correctly: inactive, with reason 1`] = ` -<div - className="boxed-group-inner display-flex-start width-30 spacer-right spacer-bottom bordered bg-muted" -> - <ClearIcon - className="little-spacer-top spacer-right" - fill="#999" - /> - <div - className="display-flex-column abs-height-100" - > - <h4> - Foo - </h4> - <div - className="spacer-top flex-1" - > - Foo bar... - </div> - <div - className="spacer-top" - > - <em - className="text-muted" - > - Bar is foo'd - </em> - </div> - </div> -</div> -`; diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap index 68d1d8350fa..fc68bb972d1 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap @@ -2,8 +2,6 @@ exports[`should render correctly 1`] = ` <AlmTabRenderer - additionalColumnsHeaders={Array []} - additionalColumnsKeys={Array []} alm="azure" defaultBinding={ Object { diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap index b8814bc4291..57c0928fdcd 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap @@ -7,19 +7,33 @@ exports[`should render correctly for multi-ALM binding: editing a definition 1`] <DeferredSpinner loading={false} > - <AlmBindingDefinitionsTable - additionalColumnsHeaders={Array []} + <div + className="spacer-bottom text-right" + > + <Tooltip + mouseLeaveDelay={0.25} + overlay={null} + > + <Button + data-test="settings__alm-create" + disabled={false} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> + </div> + <AlmBindingDefinitionBox alm="azure" - definitions={ - Array [ - Object { - "additionalColumns": Array [], - "key": "key", - }, - ] + definition={ + Object { + "key": "key", + "personalAccessToken": "asdf1234", + } } - loading={false} - onCreate={[MockFunction]} + key="key" + multipleDefinitions={false} + onCheck={[MockFunction]} onDelete={[MockFunction]} onEdit={[MockFunction]} /> @@ -51,7 +65,6 @@ exports[`should render correctly for multi-ALM binding: editing a definition 1`] isSecondInstance={true} onCancel={[MockFunction]} onSubmit={[MockFunction]} - showInModal={true} > <Component /> </AlmBindingDefinitionForm> @@ -66,19 +79,33 @@ exports[`should render correctly for multi-ALM binding: loaded 1`] = ` <DeferredSpinner loading={false} > - <AlmBindingDefinitionsTable - additionalColumnsHeaders={Array []} + <div + className="spacer-bottom text-right" + > + <Tooltip + mouseLeaveDelay={0.25} + overlay={null} + > + <Button + data-test="settings__alm-create" + disabled={false} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> + </div> + <AlmBindingDefinitionBox alm="azure" - definitions={ - Array [ - Object { - "additionalColumns": Array [], - "key": "key", - }, - ] + definition={ + Object { + "key": "key", + "personalAccessToken": "asdf1234", + } } - loading={false} - onCreate={[MockFunction]} + key="key" + multipleDefinitions={false} + onCheck={[MockFunction]} onDelete={[MockFunction]} onEdit={[MockFunction]} /> @@ -93,19 +120,33 @@ exports[`should render correctly for multi-ALM binding: loading ALM definitions <DeferredSpinner loading={true} > - <AlmBindingDefinitionsTable - additionalColumnsHeaders={Array []} + <div + className="spacer-bottom text-right" + > + <Tooltip + mouseLeaveDelay={0.25} + overlay={null} + > + <Button + data-test="settings__alm-create" + disabled={false} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> + </div> + <AlmBindingDefinitionBox alm="azure" - definitions={ - Array [ - Object { - "additionalColumns": Array [], - "key": "key", - }, - ] + definition={ + Object { + "key": "key", + "personalAccessToken": "asdf1234", + } } - loading={false} - onCreate={[MockFunction]} + key="key" + multipleDefinitions={false} + onCheck={[MockFunction]} onDelete={[MockFunction]} onEdit={[MockFunction]} /> @@ -120,19 +161,50 @@ exports[`should render correctly for multi-ALM binding: loading project count 1` <DeferredSpinner loading={false} > - <AlmBindingDefinitionsTable - additionalColumnsHeaders={Array []} + <div + className="spacer-bottom text-right" + > + <Tooltip + mouseLeaveDelay={0.25} + overlay={ + <FormattedMessage + defaultMessage="settings.almintegration.create.tooltip" + id="settings.almintegration.create.tooltip" + values={ + Object { + "alm": "alm.azure", + "link": <a + href="https://redirect.sonarsource.com/editions/enterprise.html?sourceEdition=developer" + rel="noopener noreferrer" + target="_blank" + > + settings.almintegration.create.tooltip.link + </a>, + } + } + /> + } + > + <Button + data-test="settings__alm-create" + disabled={true} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> + </div> + <AlmBindingDefinitionBox alm="azure" - definitions={ - Array [ - Object { - "additionalColumns": Array [], - "key": "key", - }, - ] + definition={ + Object { + "key": "key", + "personalAccessToken": "asdf1234", + } } - loading={true} - onCreate={[MockFunction]} + key="key" + multipleDefinitions={false} + onCheck={[MockFunction]} onDelete={[MockFunction]} onEdit={[MockFunction]} /> @@ -147,19 +219,33 @@ exports[`should render correctly for multi-ALM binding: submitting 1`] = ` <DeferredSpinner loading={false} > - <AlmBindingDefinitionsTable - additionalColumnsHeaders={Array []} + <div + className="spacer-bottom text-right" + > + <Tooltip + mouseLeaveDelay={0.25} + overlay={null} + > + <Button + data-test="settings__alm-create" + disabled={false} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> + </div> + <AlmBindingDefinitionBox alm="azure" - definitions={ - Array [ - Object { - "additionalColumns": Array [], - "key": "key", - }, - ] + definition={ + Object { + "key": "key", + "personalAccessToken": "asdf1234", + } } - loading={false} - onCreate={[MockFunction]} + key="key" + multipleDefinitions={false} + onCheck={[MockFunction]} onDelete={[MockFunction]} onEdit={[MockFunction]} /> @@ -167,98 +253,61 @@ exports[`should render correctly for multi-ALM binding: submitting 1`] = ` </div> `; -exports[`should render correctly for multi-ALM binding: with features 1`] = ` +exports[`should render correctly for single-ALM binding 1`] = ` <div className="big-padded" > <DeferredSpinner - loading={false} + loading={true} > - <AlmBindingDefinitionsTable - additionalColumnsHeaders={Array []} + <div + className="spacer-bottom text-right" + > + <Tooltip + mouseLeaveDelay={0.25} + overlay={ + <FormattedMessage + defaultMessage="settings.almintegration.create.tooltip" + id="settings.almintegration.create.tooltip" + values={ + Object { + "alm": "alm.azure", + "link": <a + href="https://redirect.sonarsource.com/editions/enterprise.html?sourceEdition=developer" + rel="noopener noreferrer" + target="_blank" + > + settings.almintegration.create.tooltip.link + </a>, + } + } + /> + } + > + <Button + data-test="settings__alm-create" + disabled={true} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> + </div> + <AlmBindingDefinitionBox alm="azure" - definitions={ - Array [ - Object { - "additionalColumns": Array [], - "key": "key", - }, - ] + definition={ + Object { + "key": "key", + "personalAccessToken": "asdf1234", + } } - loading={false} - onCreate={[MockFunction]} + key="key" + multipleDefinitions={false} + onCheck={[MockFunction]} onDelete={[MockFunction]} onEdit={[MockFunction]} /> </DeferredSpinner> - <div - className="big-spacer-top big-padded-top bordered-top" - > - <h3 - className="big-spacer-bottom" - > - settings.almintegration.features - </h3> - <div - className="display-flex-wrap" - > - <AlmIntegrationFeatureBox - active={true} - description="Bar" - key="0" - name="Foo" - /> - <AlmIntegrationFeatureBox - active={false} - description="Bim" - key="1" - name="Baz" - /> - </div> - </div> -</div> -`; - -exports[`should render correctly for single-ALM binding 1`] = ` -<div - className="big-padded" -> - <AlmBindingDefinitionForm - bindingDefinition={ - Object { - "key": "key", - "personalAccessToken": "asdf1234", - } - } - help={ - <FormattedMessage - defaultMessage="settings.almintegration.azure.info" - id="settings.almintegration.azure.info" - values={ - Object { - "link": <Link - onlyActiveOnIndex={false} - style={Object {}} - target="_blank" - to="/documentation/analysis/pr-decoration/" - > - learn_more - </Link>, - } - } - /> - } - hideKeyField={true} - loading={true} - onCancel={[MockFunction]} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - onSubmit={[MockFunction]} - readOnly={true} - success={false} - > - <Component /> - </AlmBindingDefinitionForm> </div> `; @@ -266,42 +315,57 @@ exports[`should render correctly for single-ALM binding 2`] = ` <div className="big-padded" > - <AlmBindingDefinitionForm - bindingDefinition={ - Object { - "key": "key", - "personalAccessToken": "asdf1234", - } - } - help={ - <FormattedMessage - defaultMessage="settings.almintegration.azure.info" - id="settings.almintegration.azure.info" - values={ - Object { - "link": <Link - onlyActiveOnIndex={false} - style={Object {}} - target="_blank" - to="/documentation/analysis/pr-decoration/" - > - learn_more - </Link>, - } - } - /> - } - hideKeyField={true} - loading={true} - onCancel={[MockFunction]} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - onSubmit={[MockFunction]} - readOnly={true} - success={false} + <DeferredSpinner + loading={false} > - <Component /> - </AlmBindingDefinitionForm> + <div + className="spacer-bottom text-right" + > + <Tooltip + mouseLeaveDelay={0.25} + overlay={ + <FormattedMessage + defaultMessage="settings.almintegration.create.tooltip" + id="settings.almintegration.create.tooltip" + values={ + Object { + "alm": "alm.azure", + "link": <a + href="https://redirect.sonarsource.com/editions/enterprise.html?sourceEdition=developer" + rel="noopener noreferrer" + target="_blank" + > + settings.almintegration.create.tooltip.link + </a>, + } + } + /> + } + > + <Button + data-test="settings__alm-create" + disabled={true} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> + </div> + <AlmBindingDefinitionBox + alm="azure" + definition={ + Object { + "key": "key", + "personalAccessToken": "asdf1234", + } + } + key="key" + multipleDefinitions={false} + onCheck={[MockFunction]} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> </div> `; @@ -309,42 +373,57 @@ exports[`should render correctly for single-ALM binding 3`] = ` <div className="big-padded" > - <AlmBindingDefinitionForm - bindingDefinition={ - Object { - "key": "key", - "personalAccessToken": "asdf1234", - } - } - help={ - <FormattedMessage - defaultMessage="settings.almintegration.azure.info" - id="settings.almintegration.azure.info" - values={ - Object { - "link": <Link - onlyActiveOnIndex={false} - style={Object {}} - target="_blank" - to="/documentation/analysis/pr-decoration/" - > - learn_more - </Link>, - } - } - /> - } - hideKeyField={true} - loading={true} - onCancel={[MockFunction]} - onDelete={[MockFunction]} - onEdit={[MockFunction]} - onSubmit={[MockFunction]} - readOnly={true} - success={false} + <DeferredSpinner + loading={false} > - <Component /> - </AlmBindingDefinitionForm> + <div + className="spacer-bottom text-right" + > + <Tooltip + mouseLeaveDelay={0.25} + overlay={ + <FormattedMessage + defaultMessage="settings.almintegration.create.tooltip" + id="settings.almintegration.create.tooltip" + values={ + Object { + "alm": "alm.azure", + "link": <a + href="https://redirect.sonarsource.com/editions/enterprise.html?sourceEdition=developer" + rel="noopener noreferrer" + target="_blank" + > + settings.almintegration.create.tooltip.link + </a>, + } + } + /> + } + > + <Button + data-test="settings__alm-create" + disabled={true} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> + </div> + <AlmBindingDefinitionBox + alm="azure" + definition={ + Object { + "key": "key", + "personalAccessToken": "asdf1234", + } + } + key="key" + multipleDefinitions={false} + onCheck={[MockFunction]} + onDelete={[MockFunction]} + onEdit={[MockFunction]} + /> + </DeferredSpinner> </div> `; @@ -358,15 +437,21 @@ exports[`should render correctly with validation 1`] = ` <div className="spacer-bottom text-right" > - <Button - data-test="settings__alm-create" - disabled={false} - onClick={[MockFunction]} + <Tooltip + mouseLeaveDelay={0.25} + overlay={null} > - settings.almintegration.table.create - </Button> + <Button + data-test="settings__alm-create" + disabled={false} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> </div> <AlmBindingDefinitionBox + alm="github" definition={ Object { "appId": "123456", @@ -394,16 +479,26 @@ exports[`should render correctly with validation: create a first 1`] = ` <DeferredSpinner loading={false} > + <p + className="spacer-top" + > + settings.almintegration.empty.github + </p> <div - className="spacer-bottom text-right" + className="big-spacer-top" > - <Button - data-test="settings__alm-create" - disabled={false} - onClick={[MockFunction]} + <Tooltip + mouseLeaveDelay={0.25} + overlay={null} > - settings.almintegration.table.create - </Button> + <Button + data-test="settings__alm-create" + disabled={false} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> </div> <AlmBindingDefinitionForm bindingDefinition={ @@ -437,7 +532,6 @@ exports[`should render correctly with validation: create a first 1`] = ` isSecondInstance={false} onCancel={[MockFunction]} onSubmit={[MockFunction]} - showInModal={true} > <Component /> </AlmBindingDefinitionForm> @@ -455,15 +549,21 @@ exports[`should render correctly with validation: create a second 1`] = ` <div className="spacer-bottom text-right" > - <Button - data-test="settings__alm-create" - disabled={false} - onClick={[MockFunction]} + <Tooltip + mouseLeaveDelay={0.25} + overlay={null} > - settings.almintegration.table.create - </Button> + <Button + data-test="settings__alm-create" + disabled={false} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> </div> <AlmBindingDefinitionBox + alm="github" definition={ Object { "appId": "123456", @@ -512,7 +612,6 @@ exports[`should render correctly with validation: create a second 1`] = ` isSecondInstance={true} onCancel={[MockFunction]} onSubmit={[MockFunction]} - showInModal={true} > <Component /> </AlmBindingDefinitionForm> @@ -527,16 +626,26 @@ exports[`should render correctly with validation: empty 1`] = ` <DeferredSpinner loading={false} > + <p + className="spacer-top" + > + settings.almintegration.empty.github + </p> <div - className="spacer-bottom text-right" + className="big-spacer-top" > - <Button - data-test="settings__alm-create" - disabled={false} - onClick={[MockFunction]} + <Tooltip + mouseLeaveDelay={0.25} + overlay={null} > - settings.almintegration.table.create - </Button> + <Button + data-test="settings__alm-create" + disabled={false} + onClick={[MockFunction]} + > + settings.almintegration.create + </Button> + </Tooltip> </div> </DeferredSpinner> </div> diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap index 0ed28e44289..395e569599d 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap @@ -22,16 +22,6 @@ exports[`should render correctly 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.pr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.pr_decoration.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap index 6dc5847e249..2c9e37f15f9 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap @@ -5,34 +5,6 @@ exports[`should render correctly 1`] = ` className="bordered" > <AlmTab - additionalColumnsHeaders={ - Array [ - "settings.almintegration.table.column.bitbucket.url", - ] - } - additionalColumnsKeys={ - Array [ - "url", - ] - } - additionalTableInfo={ - <Alert - className="big-spacer-bottom width-50" - variant="info" - > - <FormattedMessage - defaultMessage="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_bbs_instances" - id="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_bbs_instances" - values={ - Object { - "feature": <em> - settings.almintegration.feature.alm_repo_import.title - </em>, - } - } - /> - </Alert> - } alm="bitbucket" createConfiguration={[Function]} defaultBinding={ @@ -52,22 +24,6 @@ exports[`should render correctly 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.pr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.pr_decoration.title", - }, - Object { - "active": true, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": "settings.almintegration.feature.alm_repo_import.bitbucket.wrong_count_x.1", - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} help={ <React.Fragment> diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap index 0ab619e3f37..0f9cfaacda4 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap @@ -5,36 +5,6 @@ exports[`should render correctly: with branch support 1`] = ` className="bordered" > <AlmTab - additionalColumnsHeaders={ - Array [ - "settings.almintegration.table.column.github.url", - "settings.almintegration.table.column.app_id", - ] - } - additionalColumnsKeys={ - Array [ - "url", - "appId", - ] - } - additionalTableInfo={ - <Alert - className="big-spacer-bottom width-50" - variant="info" - > - <FormattedMessage - defaultMessage="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_github_instances" - id="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_github_instances" - values={ - Object { - "feature": <em> - settings.almintegration.feature.alm_repo_import.title - </em>, - } - } - /> - </Alert> - } alm="github" createConfiguration={[Function]} defaultBinding={ @@ -60,40 +30,6 @@ exports[`should render correctly: with branch support 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.pr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.pr_decoration.title", - }, - Object { - "active": true, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": <React.Fragment> - <WarningIcon - className="little-spacer-right" - /> - <FormattedMessage - defaultMessage="settings.almintegration.feature.alm_repo_import.github.requires_fields" - id="settings.almintegration.feature.alm_repo_import.github.requires_fields" - values={ - Object { - "clientId": <strong> - clientId - </strong>, - "clientSecret": <strong> - clientSecret - </strong>, - } - } - /> - </React.Fragment>, - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap index 2ef3faa1a0d..52116b54658 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap @@ -5,34 +5,6 @@ exports[`should render correctly: with URL 1`] = ` className="bordered" > <AlmTab - additionalColumnsHeaders={ - Array [ - "settings.almintegration.table.column.gitlab.url", - ] - } - additionalColumnsKeys={ - Array [ - "url", - ] - } - additionalTableInfo={ - <Alert - className="big-spacer-bottom width-50" - variant="info" - > - <FormattedMessage - defaultMessage="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_gitlab_instances" - id="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_gitlab_instances" - values={ - Object { - "feature": <em> - settings.almintegration.feature.alm_repo_import.title - </em>, - } - } - /> - </Alert> - } alm="gitlab" createConfiguration={[Function]} defaultBinding={ @@ -52,22 +24,6 @@ exports[`should render correctly: with URL 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.mr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.mr_decoration.title", - }, - Object { - "active": true, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": "settings.almintegration.feature.alm_repo_import.gitlab.requires_fields", - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} @@ -96,34 +52,6 @@ exports[`should render correctly: with branch support 1`] = ` className="bordered" > <AlmTab - additionalColumnsHeaders={ - Array [ - "settings.almintegration.table.column.gitlab.url", - ] - } - additionalColumnsKeys={ - Array [ - "url", - ] - } - additionalTableInfo={ - <Alert - className="big-spacer-bottom width-50" - variant="info" - > - <FormattedMessage - defaultMessage="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_gitlab_instances" - id="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_gitlab_instances" - values={ - Object { - "feature": <em> - settings.almintegration.feature.alm_repo_import.title - </em>, - } - } - /> - </Alert> - } alm="gitlab" createConfiguration={[Function]} defaultBinding={ @@ -142,22 +70,6 @@ exports[`should render correctly: with branch support 1`] = ` }, ] } - features={ - Array [ - Object { - "active": true, - "description": "settings.almintegration.feature.mr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.mr_decoration.title", - }, - Object { - "active": false, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": "settings.almintegration.feature.alm_repo_import.gitlab.requires_fields", - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} @@ -186,34 +98,6 @@ exports[`should render correctly: with no definitions 1`] = ` className="bordered" > <AlmTab - additionalColumnsHeaders={ - Array [ - "settings.almintegration.table.column.gitlab.url", - ] - } - additionalColumnsKeys={ - Array [ - "url", - ] - } - additionalTableInfo={ - <Alert - className="big-spacer-bottom width-50" - variant="info" - > - <FormattedMessage - defaultMessage="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_gitlab_instances" - id="settings.almintegration.feature.alm_repo_import.disabled_if_multiple_gitlab_instances" - values={ - Object { - "feature": <em> - settings.almintegration.feature.alm_repo_import.title - </em>, - } - } - /> - </Alert> - } alm="gitlab" createConfiguration={[Function]} defaultBinding={ @@ -225,22 +109,6 @@ exports[`should render correctly: with no definitions 1`] = ` } definitionStatus={Object {}} definitions={Array []} - features={ - Array [ - Object { - "active": false, - "description": "settings.almintegration.feature.mr_decoration.description", - "inactiveReason": "settings.almintegration.feature.need_at_least_1_binding", - "name": "settings.almintegration.feature.mr_decoration.title", - }, - Object { - "active": false, - "description": "settings.almintegration.feature.alm_repo_import.description", - "inactiveReason": "settings.almintegration.feature.alm_repo_import.gitlab.wrong_count_x.0", - "name": "settings.almintegration.feature.alm_repo_import.title", - }, - ] - } form={[Function]} loadingAlmDefinitions={false} loadingProjectCount={false} diff --git a/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts b/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts index b2bd99f0432..b4a67f72610 100644 --- a/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts +++ b/server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts @@ -20,6 +20,7 @@ import { AlmKeys, AlmSettingsBindingStatus, + AlmSettingsBindingStatusType, AlmSettingsInstance, AzureBindingDefinition, BitbucketBindingDefinition, @@ -135,9 +136,9 @@ export function mockAlmSettingsBindingStatus( overrides: Partial<AlmSettingsBindingStatus> ): AlmSettingsBindingStatus { return { - alert: false, - errorMessage: '', - validating: true, + alertSuccess: false, + failureMessage: '', + type: AlmSettingsBindingStatusType.Validating, ...overrides }; } diff --git a/server/sonar-web/src/main/js/types/alm-settings.ts b/server/sonar-web/src/main/js/types/alm-settings.ts index 8cc38476792..09284f3c8c3 100644 --- a/server/sonar-web/src/main/js/types/alm-settings.ts +++ b/server/sonar-web/src/main/js/types/alm-settings.ts @@ -111,7 +111,14 @@ export interface AlmSettingsBindingDefinitions { } export interface AlmSettingsBindingStatus { - alert: boolean; - errorMessage: string; - validating: boolean; + alertSuccess: boolean; + failureMessage: string; + type: AlmSettingsBindingStatusType; +} + +export enum AlmSettingsBindingStatusType { + Validating, + Success, + Failure, + Warning } |