aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/settings
diff options
context:
space:
mode:
authorPhilippe Perrin <philippe.perrin@sonarsource.com>2021-06-21 15:09:32 +0200
committersonartech <sonartech@sonarsource.com>2021-06-28 20:03:21 +0000
commitc243a3e78070ab9a1d1038248212151e1b9dd11f (patch)
tree6fc7a9d506869ef3fd26945dd6a2c973718e07ec /server/sonar-web/src/main/js/apps/settings
parent0863e93ba1f4d9d20acb6b4ef3934fbc53e8d615 (diff)
downloadsonarqube-c243a3e78070ab9a1d1038248212151e1b9dd11f.tar.gz
sonarqube-c243a3e78070ab9a1d1038248212151e1b9dd11f.zip
SONAR-14932 Make alm config modal standalone
Diffstat (limited to 'server/sonar-web/src/main/js/apps/settings')
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx228
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormModalRenderer.tsx87
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx141
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx65
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx111
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTab.tsx91
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmTabRenderer.tsx122
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx97
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx89
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketCloudForm.tsx85
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx194
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketServerForm.tsx91
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx186
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTabRenderer.tsx140
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx147
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx110
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx87
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx103
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionForm-test.tsx208
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormModalRenderer-test.tsx57
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx95
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx25
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationRenderer-test.tsx15
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTab-test.tsx55
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx25
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketCloudForm-test.tsx (renamed from server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AzureTab-test.tsx)25
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketForm-test.tsx65
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketServerForm-test.tsx (renamed from server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GithubTab-test.tsx)25
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketTab-test.tsx152
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketTabRenderer-test.tsx63
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GitlabTab-test.tsx54
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap44
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormModalRenderer-test.tsx.snap168
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormRenderer-test.tsx.snap466
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegration-test.tsx.snap8
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationRenderer-test.tsx.snap121
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap8
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap978
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap222
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap55
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketCloudForm-test.tsx.snap54
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap523
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketServerForm-test.tsx.snap59
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap30
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap143
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap322
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap73
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap194
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap190
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/almIntegration/utils.ts28
53 files changed, 3087 insertions, 3653 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 031d7ccee56..73489a02c3d 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
@@ -32,7 +32,7 @@ import { translate } from 'sonar-ui-common/helpers/l10n';
import { ALM_DOCUMENTATION_PATHS, IMPORT_COMPATIBLE_ALMS } from '../../../../helpers/constants';
import { getEdition, getEditionUrl } from '../../../../helpers/editions';
import {
- AlmBindingDefinition,
+ AlmBindingDefinitionBase,
AlmKeys,
AlmSettingsBindingStatus,
AlmSettingsBindingStatusType
@@ -42,7 +42,7 @@ import { EditionKey } from '../../../../types/editions';
export interface AlmBindingDefinitionBoxProps {
alm: AlmKeys;
branchesEnabled: boolean;
- definition: AlmBindingDefinition;
+ definition: AlmBindingDefinitionBase;
multipleDefinitions: boolean;
onCheck: (definitionKey: string) => void;
onDelete: (definitionKey: string) => void;
@@ -105,7 +105,7 @@ function getPRDecorationFeatureStatus(
function getImportFeatureStatus(
alm: AlmKeys,
- definition: AlmBindingDefinition,
+ definition: AlmBindingDefinitionBase,
multipleDefinitions: boolean,
type: AlmSettingsBindingStatusType.Success | AlmSettingsBindingStatusType.Failure
) {
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 fa0a1886544..4d8a17c2d17 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
@@ -17,67 +17,130 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { isEqual, omit } from 'lodash';
import * as React from 'react';
-import { AlmBindingDefinition } from '../../../../types/alm-settings';
-import AlmBindingDefinitionFormModalRenderer from './AlmBindingDefinitionFormModalRenderer';
-
-export interface AlmBindingDefinitionFormChildrenProps<B> {
- formData: B;
- onFieldChange: (fieldId: keyof B, value: string) => void;
+import {
+ createAzureConfiguration,
+ createBitbucketCloudConfiguration,
+ createBitbucketServerConfiguration,
+ createGithubConfiguration,
+ createGitlabConfiguration,
+ updateAzureConfiguration,
+ updateBitbucketCloudConfiguration,
+ updateBitbucketServerConfiguration,
+ updateGithubConfiguration,
+ updateGitlabConfiguration
+} from '../../../../api/alm-settings';
+import {
+ AlmBindingDefinition,
+ AlmBindingDefinitionBase,
+ AlmKeys,
+ AzureBindingDefinition,
+ BitbucketCloudBindingDefinition,
+ BitbucketServerBindingDefinition,
+ GithubBindingDefinition,
+ GitlabBindingDefinition,
+ isBitbucketCloudBindingDefinition
+} from '../../../../types/alm-settings';
+import AlmBindingDefinitionFormRenderer from './AlmBindingDefinitionFormRenderer';
+
+export interface AlmBindingDefinitionFormChildrenProps {
+ formData: AlmBindingDefinition;
+ onFieldChange: (fieldId: string, value: string) => void;
}
-interface Props<B> {
- bindingDefinition: B;
- children: (props: AlmBindingDefinitionFormChildrenProps<B>) => React.ReactNode;
- help?: React.ReactNode;
- isSecondInstance?: boolean;
- onCancel?: () => void;
+interface Props {
+ alm: AlmKeys;
+ bindingDefinition?: AlmBindingDefinition;
+ alreadyHaveInstanceConfigured: boolean;
onDelete?: (definitionKey: string) => void;
onEdit?: (definitionKey: string) => void;
- onSubmit: (data: B, originalKey: string) => void;
- optionalFields?: Array<keyof B>;
+ onCancel?: () => void;
+ afterSubmit?: (data: AlmBindingDefinitionBase) => void;
}
-interface State<B> {
- formData: B;
+interface State {
+ formData: AlmBindingDefinition;
touched: boolean;
+ submitting: boolean;
+ bitbucketVariant?: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud;
}
-export default class AlmBindingDefinitionForm<
- B extends AlmBindingDefinition
-> extends React.PureComponent<Props<B>, State<B>> {
- constructor(props: Props<B>) {
- super(props);
- this.state = { formData: props.bindingDefinition, touched: false };
+const BINDING_PER_ALM = {
+ [AlmKeys.Azure]: {
+ createApi: createAzureConfiguration,
+ updateApi: updateAzureConfiguration,
+ defaultBinding: { key: '', personalAccessToken: '', url: '' } as AzureBindingDefinition
+ },
+ [AlmKeys.GitHub]: {
+ createApi: createGithubConfiguration,
+ updateApi: updateGithubConfiguration,
+ defaultBinding: {
+ key: '',
+ appId: '',
+ clientId: '',
+ clientSecret: '',
+ url: '',
+ privateKey: ''
+ } as GithubBindingDefinition
+ },
+ [AlmKeys.GitLab]: {
+ createApi: createGitlabConfiguration,
+ updateApi: updateGitlabConfiguration,
+ defaultBinding: { key: '', personalAccessToken: '', url: '' } as GitlabBindingDefinition
+ },
+ [AlmKeys.BitbucketServer]: {
+ createApi: createBitbucketServerConfiguration,
+ updateApi: updateBitbucketServerConfiguration,
+ defaultBinding: {
+ key: '',
+ url: '',
+ personalAccessToken: ''
+ } as BitbucketServerBindingDefinition
+ },
+ [AlmKeys.BitbucketCloud]: {
+ createApi: createBitbucketCloudConfiguration,
+ updateApi: updateBitbucketCloudConfiguration,
+ defaultBinding: {
+ key: '',
+ clientId: '',
+ clientSecret: '',
+ workspace: ''
+ } as BitbucketCloudBindingDefinition
}
+};
- componentDidUpdate(prevProps: Props<B>) {
- if (!isEqual(prevProps.bindingDefinition, this.props.bindingDefinition)) {
- this.setState({ formData: this.props.bindingDefinition, touched: false });
- }
- }
+export default class AlmBindingDefinitionForm extends React.PureComponent<Props, State> {
+ mounted = false;
+ constructor(props: Props) {
+ super(props);
- handleCancel = () => {
- this.setState({ formData: this.props.bindingDefinition, touched: false });
- if (this.props.onCancel) {
- this.props.onCancel();
- }
- };
+ let bitbucketVariant: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud | undefined = undefined;
- handleDelete = () => {
- if (this.props.onDelete) {
- this.props.onDelete(this.props.bindingDefinition.key);
+ if (props.bindingDefinition && props.alm === AlmKeys.BitbucketServer) {
+ bitbucketVariant = isBitbucketCloudBindingDefinition(props.bindingDefinition)
+ ? AlmKeys.BitbucketCloud
+ : AlmKeys.BitbucketServer;
}
- };
- handleEdit = () => {
- if (this.props.onEdit) {
- this.props.onEdit(this.props.bindingDefinition.key);
- }
- };
+ const alm = bitbucketVariant || props.alm;
- handleFieldChange = (fieldId: keyof B, value: string) => {
+ this.state = {
+ formData: props.bindingDefinition ?? BINDING_PER_ALM[alm].defaultBinding,
+ touched: false,
+ submitting: false,
+ bitbucketVariant
+ };
+ }
+
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ handleFieldChange = (fieldId: string, value: string) => {
this.setState(({ formData }) => ({
formData: {
...formData,
@@ -87,42 +150,69 @@ export default class AlmBindingDefinitionForm<
}));
};
- handleFormSubmit = () => {
- this.props.onSubmit(this.state.formData, this.props.bindingDefinition.key);
+ handleFormSubmit = async () => {
+ const { alm } = this.props;
+ const { formData, bitbucketVariant } = this.state;
+ const apiAlm = bitbucketVariant ?? alm;
+
+ const apiMethod = this.props.bindingDefinition?.key
+ ? BINDING_PER_ALM[apiAlm].updateApi({
+ newKey: formData.key,
+ ...formData,
+ key: this.props.bindingDefinition.key
+ } as any)
+ : BINDING_PER_ALM[apiAlm].createApi({ ...formData } as any);
+
+ this.setState({ submitting: true });
+
+ try {
+ await apiMethod;
+
+ if (this.props.afterSubmit) {
+ this.props.afterSubmit(formData);
+ }
+ } finally {
+ if (this.mounted) {
+ this.setState({ submitting: false });
+ }
+ }
+ };
+
+ handleBitbucketVariantChange = (
+ bitbucketVariant: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud
+ ) => {
+ this.setState({
+ bitbucketVariant,
+ formData: { ...BINDING_PER_ALM[bitbucketVariant].defaultBinding }
+ });
};
canSubmit = () => {
- const { optionalFields } = this.props;
const { formData, touched } = this.state;
- let values = { ...formData };
-
- if (optionalFields && optionalFields.length > 0) {
- values = omit(values, optionalFields) as B;
- }
-
- return touched && !Object.values(values).some(v => !v);
+ return touched && !Object.values(formData).some(v => !v);
};
render() {
- const { bindingDefinition, children, help, isSecondInstance } = this.props;
- const { formData } = this.state;
+ const { alm, bindingDefinition, alreadyHaveInstanceConfigured } = this.props;
+ const { formData, submitting, bitbucketVariant } = this.state;
- const action = bindingDefinition.key ? 'edit' : 'create';
+ const isUpdate = !!bindingDefinition;
return (
- <AlmBindingDefinitionFormModalRenderer
- action={action}
- canSubmit={this.canSubmit}
- help={help}
- isSecondInstance={Boolean(isSecondInstance)}
- onCancel={this.handleCancel}
- onSubmit={this.handleFormSubmit}>
- {children({
- formData,
- onFieldChange: this.handleFieldChange
- })}
- </AlmBindingDefinitionFormModalRenderer>
+ <AlmBindingDefinitionFormRenderer
+ alm={alm}
+ isUpdate={isUpdate}
+ canSubmit={this.canSubmit()}
+ alreadyHaveInstanceConfigured={alreadyHaveInstanceConfigured}
+ onCancel={() => this.props.onCancel && this.props.onCancel()}
+ onSubmit={this.handleFormSubmit}
+ onFieldChange={this.handleFieldChange}
+ formData={formData}
+ submitting={submitting}
+ bitbucketVariant={bitbucketVariant}
+ onBitbucketVariantChange={this.handleBitbucketVariantChange}
+ />
);
}
}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx
index de5693da0f3..bba6481cf22 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx
@@ -22,9 +22,9 @@ import { ButtonLink } from 'sonar-ui-common/components/controls/buttons';
import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip';
import MandatoryFieldMarker from 'sonar-ui-common/components/ui/MandatoryFieldMarker';
import { translate } from 'sonar-ui-common/helpers/l10n';
-import { AlmBindingDefinition } from '../../../../types/alm-settings';
+import { AlmBindingDefinitionBase } from '../../../../types/alm-settings';
-export interface AlmBindingDefinitionFormFieldProps<B extends AlmBindingDefinition> {
+export interface AlmBindingDefinitionFormFieldProps<B extends AlmBindingDefinitionBase> {
autoFocus?: boolean;
help?: React.ReactNode;
id: string;
@@ -37,7 +37,7 @@ export interface AlmBindingDefinitionFormFieldProps<B extends AlmBindingDefiniti
value: string;
}
-export function AlmBindingDefinitionFormField<B extends AlmBindingDefinition>(
+export function AlmBindingDefinitionFormField<B extends AlmBindingDefinitionBase>(
props: AlmBindingDefinitionFormFieldProps<B>
) {
const {
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormModalRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormModalRenderer.tsx
deleted file mode 100644
index f6ec74d3180..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormModalRenderer.tsx
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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 { ResetButtonLink, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
-import Modal from 'sonar-ui-common/components/controls/Modal';
-import { Alert } from 'sonar-ui-common/components/ui/Alert';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-
-export interface AlmBindingDefinitionFormModalProps {
- action: 'edit' | 'create';
- canSubmit: () => boolean;
- children: React.ReactNode;
- help?: React.ReactNode;
- isSecondInstance: boolean;
- onCancel: () => void;
- onSubmit: () => void | Promise<void | Response>;
-}
-
-export default function AlmBindingDefinitionFormModalRenderer(
- props: AlmBindingDefinitionFormModalProps
-) {
- const { action, children, help, isSecondInstance } = props;
- const header = translate('settings.almintegration.form.header', action);
-
- const handleSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
- event.preventDefault();
- props.onSubmit();
- };
-
- return (
- <Modal
- contentLabel={header}
- onRequestClose={props.onCancel}
- shouldCloseOnOverlayClick={false}
- size="medium">
- <form className="views-form" onSubmit={handleSubmit}>
- <div className="modal-head">
- <h2>{header}</h2>
- </div>
-
- <div className="modal-body modal-container">
- {isSecondInstance && action === 'create' && (
- <Alert className="big-spacer-bottom" variant="warning">
- {translate('settings.almintegration.form.second_instance_warning')}
- </Alert>
- )}
-
- <div className="display-flex-start">
- <div className="flex-1">{children}</div>
-
- {help ? (
- <Alert className="huge-spacer-left flex-1" variant="info">
- {help}
- </Alert>
- ) : (
- <div className="flex-1" />
- )}
- </div>
- </div>
-
- <div className="modal-foot">
- <SubmitButton disabled={!props.canSubmit()}>
- {translate('settings.almintegration.form.save')}
- </SubmitButton>
- <ResetButtonLink onClick={props.onCancel}>{translate('cancel')}</ResetButtonLink>
- </div>
- </form>
- </Modal>
- );
-}
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
new file mode 100644
index 00000000000..c50f5d2ed4e
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx
@@ -0,0 +1,141 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { ResetButtonLink, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
+import Modal from 'sonar-ui-common/components/controls/Modal';
+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,
+ AlmKeys,
+ AzureBindingDefinition,
+ BitbucketCloudBindingDefinition,
+ BitbucketServerBindingDefinition,
+ GithubBindingDefinition,
+ GitlabBindingDefinition
+} from '../../../../types/alm-settings';
+import AzureForm from './AzureForm';
+import BitbucketForm from './BitbucketForm';
+import GithubForm from './GithubForm';
+import GitlabForm from './GitlabForm';
+
+export interface AlmBindingDefinitionFormProps {
+ alm: AlmKeys;
+ isUpdate: boolean;
+ canSubmit: boolean;
+ alreadyHaveInstanceConfigured: boolean;
+ onCancel: () => void;
+ onSubmit: () => void;
+ onFieldChange: (fieldId: keyof AlmBindingDefinition, value: string) => void;
+ formData: AlmBindingDefinition;
+ submitting: boolean;
+ bitbucketVariant?: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud;
+ onBitbucketVariantChange: (
+ bitbucketVariant: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud
+ ) => void;
+}
+
+export default class AlmBindingDefinitionFormRenderer extends React.PureComponent<
+ AlmBindingDefinitionFormProps
+> {
+ renderForm = () => {
+ const { alm, formData, isUpdate, bitbucketVariant } = this.props;
+
+ switch (alm) {
+ case AlmKeys.GitLab:
+ return (
+ <GitlabForm
+ onFieldChange={this.props.onFieldChange}
+ formData={formData as GitlabBindingDefinition}
+ />
+ );
+ case AlmKeys.Azure:
+ return (
+ <AzureForm
+ onFieldChange={this.props.onFieldChange}
+ formData={formData as AzureBindingDefinition}
+ />
+ );
+ case AlmKeys.GitHub:
+ return (
+ <GithubForm
+ onFieldChange={this.props.onFieldChange}
+ formData={formData as GithubBindingDefinition}
+ />
+ );
+ case AlmKeys.BitbucketServer:
+ return (
+ <BitbucketForm
+ onFieldChange={this.props.onFieldChange}
+ formData={
+ formData as BitbucketServerBindingDefinition | BitbucketCloudBindingDefinition
+ }
+ isUpdate={isUpdate}
+ variant={bitbucketVariant}
+ onVariantChange={this.props.onBitbucketVariantChange}
+ />
+ );
+ default:
+ return null;
+ }
+ };
+
+ render() {
+ const { isUpdate, alreadyHaveInstanceConfigured, canSubmit, submitting } = this.props;
+ const header = translate('settings.almintegration.form.header', isUpdate ? 'edit' : 'create');
+
+ const handleSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
+ event.preventDefault();
+ this.props.onSubmit();
+ };
+
+ return (
+ <Modal
+ contentLabel={header}
+ onRequestClose={this.props.onCancel}
+ shouldCloseOnOverlayClick={false}
+ size="medium">
+ <form className="views-form" onSubmit={handleSubmit}>
+ <div className="modal-head">
+ <h2>{header}</h2>
+ </div>
+
+ <div className="modal-body modal-container">
+ {alreadyHaveInstanceConfigured && !isUpdate && (
+ <Alert className="big-spacer-bottom" variant="warning">
+ {translate('settings.almintegration.form.second_instance_warning')}
+ </Alert>
+ )}
+ {this.renderForm()}
+ </div>
+
+ <div className="modal-foot">
+ <SubmitButton disabled={!canSubmit || submitting}>
+ {translate('settings.almintegration.form.save')}
+ <DeferredSpinner className="spacer-left" loading={submitting} />
+ </SubmitButton>
+ <ResetButtonLink onClick={this.props.onCancel}>{translate('cancel')}</ResetButtonLink>
+ </div>
+ </form>
+ </Modal>
+ );
+ }
+}
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 8a17bcfa442..d1570b2a4c4 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
@@ -28,22 +28,22 @@ import {
import { withAppState } from '../../../../components/hoc/withAppState';
import { withRouter } from '../../../../components/hoc/withRouter';
import {
- AlmBindingDefinition,
+ AlmBindingDefinitionBase,
AlmKeys,
AlmSettingsBindingDefinitions,
AlmSettingsBindingStatus,
AlmSettingsBindingStatusType
} from '../../../../types/alm-settings';
import AlmIntegrationRenderer from './AlmIntegrationRenderer';
-import { ALM_KEY_LIST } from './utils';
interface Props extends Pick<WithRouterProps, 'location'> {
appState: Pick<T.AppState, 'branchesEnabled' | 'multipleAlmEnabled'>;
- component?: T.Component;
}
+export type AlmTabs = AlmKeys.Azure | AlmKeys.GitHub | AlmKeys.GitLab | AlmKeys.BitbucketServer;
+
interface State {
- currentAlm: AlmKeys;
+ currentAlmTab: AlmTabs;
definitionKeyForDeletion?: string;
definitions: AlmSettingsBindingDefinitions;
definitionStatus: T.Dict<AlmSettingsBindingStatus>;
@@ -59,13 +59,13 @@ export class AlmIntegration extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
- let currentAlm = props.location.query.alm || AlmKeys.GitHub;
- if (currentAlm === AlmKeys.BitbucketCloud) {
- currentAlm = AlmKeys.BitbucketServer;
+ let currentAlmTab = props.location.query.alm || AlmKeys.GitHub;
+ if (currentAlmTab === AlmKeys.BitbucketCloud) {
+ currentAlmTab = AlmKeys.BitbucketServer;
}
this.state = {
- currentAlm,
+ currentAlmTab,
definitions: {
[AlmKeys.Azure]: [],
[AlmKeys.BitbucketServer]: [],
@@ -84,8 +84,14 @@ export class AlmIntegration extends React.PureComponent<Props, State> {
return this.fetchPullRequestDecorationSetting().then(definitions => {
if (definitions) {
// Validate all alms on load:
- ALM_KEY_LIST.forEach(alm => {
- this.state.definitions[alm].forEach((def: AlmBindingDefinition) =>
+ [
+ AlmKeys.Azure,
+ AlmKeys.BitbucketCloud,
+ AlmKeys.BitbucketServer,
+ AlmKeys.GitHub,
+ AlmKeys.GitLab
+ ].forEach(alm => {
+ this.state.definitions[alm].forEach((def: AlmBindingDefinitionBase) =>
this.handleCheck(def.key, false)
);
});
@@ -97,7 +103,7 @@ export class AlmIntegration extends React.PureComponent<Props, State> {
this.mounted = false;
}
- deleteConfiguration = (definitionKey: string) => {
+ handleConfirmDelete = (definitionKey: string) => {
return deleteConfiguration(definitionKey)
.then(() => {
if (this.mounted) {
@@ -118,7 +124,6 @@ export class AlmIntegration extends React.PureComponent<Props, State> {
});
return definitions;
}
- return undefined;
})
.catch(() => {
if (this.mounted) {
@@ -127,11 +132,11 @@ export class AlmIntegration extends React.PureComponent<Props, State> {
});
};
- handleSelectAlm = (currentAlm: AlmKeys) => {
- this.setState({ currentAlm });
+ handleSelectAlm = (currentAlmTab: AlmTabs) => {
+ this.setState({ currentAlmTab });
};
- handleCancel = () => {
+ handleCancelDelete = () => {
this.setState({ definitionKeyForDeletion: undefined, projectCount: undefined });
};
@@ -191,21 +196,35 @@ export class AlmIntegration extends React.PureComponent<Props, State> {
render() {
const {
- appState: { branchesEnabled, multipleAlmEnabled },
- component
+ appState: { branchesEnabled, multipleAlmEnabled }
} = this.props;
+ const {
+ currentAlmTab,
+ definitionKeyForDeletion,
+ definitions,
+ definitionStatus,
+ loadingAlmDefinitions,
+ loadingProjectCount,
+ projectCount
+ } = this.state;
+
return (
<AlmIntegrationRenderer
branchesEnabled={Boolean(branchesEnabled)}
- component={component}
multipleAlmEnabled={Boolean(multipleAlmEnabled)}
- onCancel={this.handleCancel}
- onConfirmDelete={this.deleteConfiguration}
- onCheck={this.handleCheck}
+ onCancelDelete={this.handleCancelDelete}
+ onConfirmDelete={this.handleConfirmDelete}
+ onCheckConfiguration={this.handleCheck}
onDelete={this.handleDelete}
- onSelectAlm={this.handleSelectAlm}
+ onSelectAlmTab={this.handleSelectAlm}
onUpdateDefinitions={this.fetchPullRequestDecorationSetting}
- {...this.state}
+ currentAlmTab={currentAlmTab}
+ definitionKeyForDeletion={definitionKeyForDeletion}
+ definitions={definitions}
+ definitionStatus={definitionStatus}
+ loadingAlmDefinitions={loadingAlmDefinitions}
+ loadingProjectCount={loadingProjectCount}
+ projectCount={projectCount}
/>
);
}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx
index 92ced87796c..f0289cb6318 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx
@@ -26,27 +26,24 @@ import {
AlmSettingsBindingDefinitions,
AlmSettingsBindingStatus
} from '../../../../types/alm-settings';
-import AzureTab from './AzureTab';
-import BitbucketTab from './BitbucketTab';
+import { AlmTabs } from './AlmIntegration';
+import AlmTab from './AlmTab';
import DeleteModal from './DeleteModal';
-import GithubTab from './GithubTab';
-import GitlabTab from './GitlabTab';
export interface AlmIntegrationRendererProps {
branchesEnabled: boolean;
- component?: T.Component;
- currentAlm: AlmKeys;
+ currentAlmTab: AlmTabs;
definitionKeyForDeletion?: string;
definitions: AlmSettingsBindingDefinitions;
definitionStatus: T.Dict<AlmSettingsBindingStatus>;
loadingAlmDefinitions: boolean;
loadingProjectCount: boolean;
multipleAlmEnabled: boolean;
- onCancel: () => void;
- onCheck: (definitionKey: string) => void;
+ onCancelDelete: () => void;
+ onCheckConfiguration: (definitionKey: string) => void;
onConfirmDelete: (definitionKey: string) => void;
onDelete: (definitionKey: string) => void;
- onSelectAlm: (alm: AlmKeys) => void;
+ onSelectAlmTab: (alm: AlmTabs) => void;
onUpdateDefinitions: () => void;
projectCount?: number;
}
@@ -64,8 +61,7 @@ const tabs = [
/>
GitHub
</>
- ),
- requiresBranchesEnabled: false
+ )
},
{
key: AlmKeys.BitbucketServer,
@@ -79,8 +75,7 @@ const tabs = [
/>
Bitbucket
</>
- ),
- requiresBranchesEnabled: false
+ )
},
{
key: AlmKeys.Azure,
@@ -94,8 +89,7 @@ const tabs = [
/>
Azure DevOps
</>
- ),
- requiresBranchesEnabled: false
+ )
},
{
key: AlmKeys.GitLab,
@@ -109,18 +103,16 @@ const tabs = [
/>
GitLab
</>
- ),
- requiresBranchesEnabled: false
+ )
}
];
export default function AlmIntegrationRenderer(props: AlmIntegrationRendererProps) {
const {
- component,
definitionKeyForDeletion,
definitions,
definitionStatus,
- currentAlm,
+ currentAlmTab,
loadingAlmDefinitions,
loadingProjectCount,
branchesEnabled,
@@ -128,6 +120,13 @@ export default function AlmIntegrationRenderer(props: AlmIntegrationRendererProp
projectCount
} = props;
+ const bindingDefinitions = {
+ [AlmKeys.Azure]: definitions.azure,
+ [AlmKeys.GitLab]: definitions.gitlab,
+ [AlmKeys.GitHub]: definitions.github,
+ [AlmKeys.BitbucketServer]: [...definitions.bitbucket, ...definitions.bitbucketcloud]
+ };
+
return (
<>
<header className="page-header">
@@ -137,70 +136,26 @@ export default function AlmIntegrationRenderer(props: AlmIntegrationRendererProp
<div className="markdown small spacer-top big-spacer-bottom">
{translate('settings.almintegration.description')}
</div>
- <BoxedTabs
- onSelect={props.onSelectAlm}
- selected={currentAlm}
- tabs={tabs.filter(tab => !(tab.requiresBranchesEnabled && !branchesEnabled))}
- />
- {currentAlm === AlmKeys.Azure && (
- <AzureTab
- branchesEnabled={branchesEnabled}
- definitions={definitions.azure}
- definitionStatus={definitionStatus}
- loadingAlmDefinitions={loadingAlmDefinitions}
- loadingProjectCount={loadingProjectCount}
- multipleAlmEnabled={multipleAlmEnabled}
- onCheck={props.onCheck}
- onDelete={props.onDelete}
- onUpdateDefinitions={props.onUpdateDefinitions}
- />
- )}
- {currentAlm === AlmKeys.BitbucketServer && (
- <BitbucketTab
- branchesEnabled={branchesEnabled}
- definitions={[...definitions.bitbucket, ...definitions.bitbucketcloud]}
- definitionStatus={definitionStatus}
- loadingAlmDefinitions={loadingAlmDefinitions}
- loadingProjectCount={loadingProjectCount}
- multipleAlmEnabled={multipleAlmEnabled}
- onCheck={props.onCheck}
- onDelete={props.onDelete}
- onUpdateDefinitions={props.onUpdateDefinitions}
- />
- )}
- {currentAlm === AlmKeys.GitHub && (
- <GithubTab
- branchesEnabled={branchesEnabled}
- component={component}
- definitions={definitions.github}
- definitionStatus={definitionStatus}
- loadingAlmDefinitions={loadingAlmDefinitions}
- loadingProjectCount={loadingProjectCount}
- multipleAlmEnabled={multipleAlmEnabled}
- onCheck={props.onCheck}
- onDelete={props.onDelete}
- onUpdateDefinitions={props.onUpdateDefinitions}
- />
- )}
- {currentAlm === AlmKeys.GitLab && (
- <GitlabTab
- branchesEnabled={branchesEnabled}
- definitions={definitions.gitlab}
- definitionStatus={definitionStatus}
- loadingAlmDefinitions={loadingAlmDefinitions}
- loadingProjectCount={loadingProjectCount}
- multipleAlmEnabled={multipleAlmEnabled}
- onCheck={props.onCheck}
- onDelete={props.onDelete}
- onUpdateDefinitions={props.onUpdateDefinitions}
- />
- )}
+ <BoxedTabs onSelect={props.onSelectAlmTab} selected={currentAlmTab} tabs={tabs} />
+
+ <AlmTab
+ almTab={currentAlmTab}
+ branchesEnabled={branchesEnabled}
+ definitions={bindingDefinitions[currentAlmTab]}
+ definitionStatus={definitionStatus}
+ loadingAlmDefinitions={loadingAlmDefinitions}
+ loadingProjectCount={loadingProjectCount}
+ multipleAlmEnabled={multipleAlmEnabled}
+ onCheck={props.onCheckConfiguration}
+ onDelete={props.onDelete}
+ onUpdateDefinitions={props.onUpdateDefinitions}
+ />
{definitionKeyForDeletion && (
<DeleteModal
id={definitionKeyForDeletion}
- onCancel={props.onCancel}
+ onCancel={props.onCancelDelete}
onDelete={props.onConfirmDelete}
projectCount={projectCount}
/>
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 6e54d53897d..1dd264c83b7 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
@@ -20,43 +20,33 @@
import * as React from 'react';
import {
AlmBindingDefinition,
- AlmKeys,
+ AlmBindingDefinitionBase,
AlmSettingsBindingStatus
} from '../../../../types/alm-settings';
-import { AlmBindingDefinitionFormChildrenProps } from './AlmBindingDefinitionForm';
+import { AlmTabs } from './AlmIntegration';
import AlmTabRenderer from './AlmTabRenderer';
-interface Props<B> {
- alm: AlmKeys;
+interface Props {
+ almTab: AlmTabs;
branchesEnabled: boolean;
- createConfiguration: (data: B) => Promise<void>;
- defaultBinding: B;
- definitions: B[];
+ definitions: AlmBindingDefinition[];
definitionStatus: T.Dict<AlmSettingsBindingStatus>;
- form: (props: AlmBindingDefinitionFormChildrenProps<B>) => React.ReactNode;
- help: React.ReactNode;
loadingAlmDefinitions: boolean;
loadingProjectCount: boolean;
multipleAlmEnabled: boolean;
onCheck: (definitionKey: string) => void;
onDelete: (definitionKey: string) => void;
onUpdateDefinitions: () => void;
- optionalFields?: Array<keyof B>;
- updateConfiguration: (data: B & { newKey?: string }) => Promise<void>;
}
-interface State<B> {
- editedDefinition?: B;
- submitting: boolean;
- success: boolean;
+interface State {
+ editedDefinition?: AlmBindingDefinition;
+ editDefinition?: boolean;
}
-export default class AlmTab<B extends AlmBindingDefinition> extends React.PureComponent<
- Props<B>,
- State<B>
-> {
+export default class AlmTab extends React.PureComponent<Props, State> {
+ state: State = {};
mounted = false;
- state: State<B> = { submitting: false, success: false };
componentDidMount() {
this.mounted = true;
@@ -67,81 +57,60 @@ export default class AlmTab<B extends AlmBindingDefinition> extends React.PureCo
}
handleCancel = () => {
- this.setState({ editedDefinition: undefined, success: false });
+ this.setState({ editDefinition: false, editedDefinition: undefined });
};
handleCreate = () => {
- this.setState({ editedDefinition: this.props.defaultBinding, success: false });
+ this.setState({ editDefinition: true, editedDefinition: undefined });
};
handleEdit = (definitionKey: string) => {
const editedDefinition = this.props.definitions.find(d => d.key === definitionKey);
- this.setState({ editedDefinition, success: false });
+ this.setState({ editDefinition: true, editedDefinition });
};
- handleSubmit = (config: B, originalKey: string) => {
- const call = originalKey
- ? this.props.updateConfiguration({ newKey: config.key, ...config, key: originalKey })
- : this.props.createConfiguration({ ...config });
-
- this.setState({ submitting: true });
- return call
- .then(() => {
- if (this.mounted) {
- this.setState({
- editedDefinition: undefined,
- submitting: false,
- success: true
- });
- }
- })
- .then(this.props.onUpdateDefinitions)
- .then(() => {
- this.props.onCheck(config.key);
- })
- .catch(() => {
- if (this.mounted) {
- this.setState({ submitting: false, success: false });
- }
+ handleAfterSubmit = (config: AlmBindingDefinitionBase) => {
+ if (this.mounted) {
+ this.setState({
+ editDefinition: false,
+ editedDefinition: undefined
});
+ }
+
+ this.props.onUpdateDefinitions();
+
+ this.props.onCheck(config.key);
};
render() {
const {
- alm,
+ almTab,
branchesEnabled,
definitions,
definitionStatus,
- form,
- help,
loadingAlmDefinitions,
loadingProjectCount,
- multipleAlmEnabled,
- optionalFields
+ multipleAlmEnabled
} = this.props;
- const { editedDefinition, submitting, success } = this.state;
+ const { editDefinition, editedDefinition } = this.state;
return (
<AlmTabRenderer
- alm={alm}
+ almTab={almTab}
branchesEnabled={branchesEnabled}
definitions={definitions}
definitionStatus={definitionStatus}
+ editDefinition={editDefinition}
editedDefinition={editedDefinition}
- form={form}
- help={help}
loadingAlmDefinitions={loadingAlmDefinitions}
loadingProjectCount={loadingProjectCount}
multipleAlmEnabled={multipleAlmEnabled}
- onCancel={this.handleCancel}
onCheck={this.props.onCheck}
onCreate={this.handleCreate}
onDelete={this.props.onDelete}
onEdit={this.handleEdit}
- onSubmit={this.handleSubmit}
- optionalFields={optionalFields}
- submitting={submitting}
- success={success}
+ onCancel={this.handleCancel}
+ afterSubmit={this.handleAfterSubmit}
/>
);
}
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 2e8380d91d4..667059ef4fb 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
@@ -23,24 +23,25 @@ import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { translate } from 'sonar-ui-common/helpers/l10n';
import {
AlmBindingDefinition,
+ AlmBindingDefinitionBase,
AlmKeys,
AlmSettingsBindingStatus,
isBitbucketCloudBindingDefinition
} from '../../../../types/alm-settings';
+import { ALM_INTEGRATION } from '../AdditionalCategoryKeys';
+import CategoryDefinitionsList from '../CategoryDefinitionsList';
import AlmBindingDefinitionBox from './AlmBindingDefinitionBox';
-import AlmBindingDefinitionForm, {
- AlmBindingDefinitionFormChildrenProps
-} from './AlmBindingDefinitionForm';
+import AlmBindingDefinitionForm from './AlmBindingDefinitionForm';
+import { AlmTabs } from './AlmIntegration';
import CreationTooltip from './CreationTooltip';
-export interface AlmTabRendererProps<B> {
- alm: AlmKeys;
+export interface AlmTabRendererProps {
+ almTab: AlmTabs;
branchesEnabled: boolean;
definitionStatus: T.Dict<AlmSettingsBindingStatus>;
- editedDefinition?: B;
- definitions: B[];
- form: (props: AlmBindingDefinitionFormChildrenProps<B>) => React.ReactNode;
- help: React.ReactNode;
+ editDefinition?: boolean;
+ editedDefinition?: AlmBindingDefinition;
+ definitions: AlmBindingDefinition[];
loadingAlmDefinitions: boolean;
loadingProjectCount: boolean;
multipleAlmEnabled: boolean;
@@ -49,74 +50,73 @@ export interface AlmTabRendererProps<B> {
onCreate: () => void;
onDelete: (definitionKey: string) => void;
onEdit: (definitionKey: string) => void;
- onSubmit: (config: B, originalKey: string) => void;
- optionalFields?: Array<keyof B>;
- submitting: boolean;
- success: boolean;
+ afterSubmit: (config: AlmBindingDefinitionBase) => void;
}
-export default function AlmTabRenderer<B extends AlmBindingDefinition>(
- props: AlmTabRendererProps<B>
-) {
+export default function AlmTabRenderer(props: AlmTabRendererProps) {
const {
- alm,
+ almTab,
branchesEnabled,
definitions,
definitionStatus,
+ editDefinition,
editedDefinition,
- form,
loadingAlmDefinitions,
loadingProjectCount,
- multipleAlmEnabled,
- optionalFields,
- help
+ multipleAlmEnabled
} = props;
const preventCreation = loadingProjectCount || (!multipleAlmEnabled && definitions.length > 0);
return (
- <div className="big-padded">
- <DeferredSpinner loading={loadingAlmDefinitions}>
- {definitions.length === 0 && (
- <p className="spacer-top">{translate('settings.almintegration.empty', alm)}</p>
- )}
+ <div className="bordered">
+ <div className="big-padded">
+ <DeferredSpinner loading={loadingAlmDefinitions}>
+ {definitions.length === 0 && (
+ <p className="spacer-top">{translate('settings.almintegration.empty', almTab)}</p>
+ )}
- <div className={definitions.length > 0 ? 'spacer-bottom text-right' : 'big-spacer-top'}>
- <CreationTooltip alm={alm} preventCreation={preventCreation}>
- <Button
- data-test="settings__alm-create"
- disabled={preventCreation}
- onClick={props.onCreate}>
- {translate('settings.almintegration.create')}
- </Button>
- </CreationTooltip>
- </div>
- {definitions.map(def => (
- <AlmBindingDefinitionBox
- alm={isBitbucketCloudBindingDefinition(def) ? AlmKeys.BitbucketCloud : alm}
- branchesEnabled={branchesEnabled}
- definition={def}
- key={def.key}
- multipleDefinitions={definitions.length > 1}
- onCheck={props.onCheck}
- onDelete={props.onDelete}
- onEdit={props.onEdit}
- status={definitionStatus[def.key]}
- />
- ))}
+ <div className={definitions.length > 0 ? 'spacer-bottom text-right' : 'big-spacer-top'}>
+ <CreationTooltip alm={almTab} preventCreation={preventCreation}>
+ <Button
+ data-test="settings__alm-create"
+ disabled={preventCreation}
+ onClick={props.onCreate}>
+ {translate('settings.almintegration.create')}
+ </Button>
+ </CreationTooltip>
+ </div>
+ {definitions.map(def => (
+ <AlmBindingDefinitionBox
+ alm={isBitbucketCloudBindingDefinition(def) ? AlmKeys.BitbucketCloud : almTab}
+ branchesEnabled={branchesEnabled}
+ 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>
+ {editDefinition && (
+ <AlmBindingDefinitionForm
+ alm={almTab}
+ bindingDefinition={editedDefinition}
+ alreadyHaveInstanceConfigured={definitions.length > 0}
+ onCancel={props.onCancel}
+ afterSubmit={props.afterSubmit}
+ />
+ )}
+ </DeferredSpinner>
+ </div>
+
+ <div className="huge-spacer-top huge-spacer-bottom bordered-top" />
+
+ <div className="big-padded">
+ <CategoryDefinitionsList category={ALM_INTEGRATION} subCategory={almTab} />
+ </div>
</div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx
index 24eacd2886a..f6638de1817 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureForm.tsx
@@ -18,8 +18,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
-import { AzureBindingDefinition } from '../../../../types/alm-settings';
+import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
+import { AlmKeys, AzureBindingDefinition } from '../../../../types/alm-settings';
import { AlmBindingDefinitionFormField } from './AlmBindingDefinitionFormField';
export interface AzureFormProps {
@@ -31,43 +35,58 @@ export default function AzureForm(props: AzureFormProps) {
const { formData, onFieldChange } = props;
return (
- <>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help={translate('settings.almintegration.form.name.azure.help')}
- id="name.azure"
- onFieldChange={onFieldChange}
- propKey="key"
- value={formData.key}
- />
- <AlmBindingDefinitionFormField
- help={
- <>
- {translate('settings.almintegration.form.url.azure.help1')}
- <br />
- <em>https://ado.your-company.com/your_collection</em>
- <br />
- <br />
- {translate('settings.almintegration.form.url.azure.help2')}
- <br />
- <em>https://dev.azure.com/your_organization</em>
- </>
- }
- id="url.azure"
- maxLength={2000}
- onFieldChange={onFieldChange}
- propKey="url"
- value={formData.url || ''}
- />
- <AlmBindingDefinitionFormField
- help={translate('settings.almintegration.form.personal_access_token.azure.help')}
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={onFieldChange}
- overwriteOnly={Boolean(formData.key)}
- propKey="personalAccessToken"
- value={formData.personalAccessToken}
- />
- </>
+ <div className="display-flex-start">
+ <div className="flex-1">
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help={translate('settings.almintegration.form.name.azure.help')}
+ id="name.azure"
+ onFieldChange={onFieldChange}
+ propKey="key"
+ value={formData.key}
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <>
+ {translate('settings.almintegration.form.url.azure.help1')}
+ <br />
+ <em>https://ado.your-company.com/your_collection</em>
+ <br />
+ <br />
+ {translate('settings.almintegration.form.url.azure.help2')}
+ <br />
+ <em>https://dev.azure.com/your_organization</em>
+ </>
+ }
+ id="url.azure"
+ maxLength={2000}
+ onFieldChange={onFieldChange}
+ propKey="url"
+ value={formData.url || ''}
+ />
+ <AlmBindingDefinitionFormField
+ help={translate('settings.almintegration.form.personal_access_token.azure.help')}
+ id="personal_access_token"
+ isTextArea={true}
+ onFieldChange={onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
+ propKey="personalAccessToken"
+ value={formData.personalAccessToken}
+ />
+ </div>
+ <Alert className="huge-spacer-left flex-1" variant="info">
+ <FormattedMessage
+ defaultMessage={translate(`settings.almintegration.azure.info`)}
+ id="settings.almintegration.azure.info"
+ values={{
+ link: (
+ <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.Azure]}>
+ {translate('learn_more')}
+ </Link>
+ )
+ }}
+ />
+ </Alert>
+ </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
deleted file mode 100644
index 5be30a1be4b..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AzureTab.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import { Link } from 'react-router';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import { createAzureConfiguration, updateAzureConfiguration } from '../../../../api/alm-settings';
-import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
-import {
- AlmKeys,
- AlmSettingsBindingStatus,
- AzureBindingDefinition
-} from '../../../../types/alm-settings';
-import AlmTab from './AlmTab';
-import AzureForm from './AzureForm';
-
-export interface AzureTabProps {
- branchesEnabled: boolean;
- definitions: AzureBindingDefinition[];
- definitionStatus: T.Dict<AlmSettingsBindingStatus>;
- loadingAlmDefinitions: boolean;
- loadingProjectCount: boolean;
- multipleAlmEnabled: boolean;
- onCheck: (definitionKey: string) => void;
- onDelete: (definitionKey: string) => void;
- onUpdateDefinitions: () => void;
-}
-
-export default function AzureTab(props: AzureTabProps) {
- const {
- branchesEnabled,
- multipleAlmEnabled,
- definitions,
- definitionStatus,
- loadingAlmDefinitions,
- loadingProjectCount
- } = props;
-
- return (
- <div className="bordered">
- <AlmTab
- alm={AlmKeys.Azure}
- branchesEnabled={branchesEnabled}
- createConfiguration={createAzureConfiguration}
- defaultBinding={{ key: '', personalAccessToken: '', url: '' }}
- definitions={definitions}
- definitionStatus={definitionStatus}
- form={childProps => <AzureForm {...childProps} />}
- help={
- <FormattedMessage
- defaultMessage={translate(`settings.almintegration.azure.info`)}
- id="settings.almintegration.azure.info"
- values={{
- link: (
- <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.Azure]}>
- {translate('learn_more')}
- </Link>
- )
- }}
- />
- }
- loadingAlmDefinitions={loadingAlmDefinitions}
- loadingProjectCount={loadingProjectCount}
- multipleAlmEnabled={multipleAlmEnabled}
- onCheck={props.onCheck}
- onDelete={props.onDelete}
- onUpdateDefinitions={props.onUpdateDefinitions}
- updateConfiguration={updateAzureConfiguration}
- />
- </div>
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketCloudForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketCloudForm.tsx
new file mode 100644
index 00000000000..c1ec4713ff5
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketCloudForm.tsx
@@ -0,0 +1,85 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { BitbucketCloudBindingDefinition } from '../../../../types/alm-settings';
+import { AlmBindingDefinitionFormField } from './AlmBindingDefinitionFormField';
+
+export interface BitbucketCloudFormProps {
+ formData: BitbucketCloudBindingDefinition;
+ onFieldChange: (fieldId: keyof BitbucketCloudBindingDefinition, value: string) => void;
+}
+
+export default function BitbucketCloudForm(props: BitbucketCloudFormProps) {
+ const { formData } = props;
+
+ return (
+ <>
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help={translate('settings.almintegration.form.name.bitbucketcloud.help')}
+ id="name.bitbucket"
+ maxLength={100}
+ onFieldChange={props.onFieldChange}
+ propKey="key"
+ value={formData.key || ''}
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <FormattedMessage
+ defaultMessage={translate('settings.almintegration.form.workspace.bitbucketcloud.help')}
+ id="settings.almintegration.form.workspace.bitbucketcloud.help"
+ values={{
+ example: (
+ <>
+ {'https://bitbucket.org/'}
+ <strong>{'{workspace}'}</strong>
+ {'/{repository}'}
+ </>
+ )
+ }}
+ />
+ }
+ id="workspace.bitbucketcloud"
+ maxLength={2000}
+ onFieldChange={props.onFieldChange}
+ propKey="workspace"
+ value={formData.workspace || ''}
+ />
+ <AlmBindingDefinitionFormField
+ id="client_id.bitbucketcloud"
+ help={translate('settings.almintegration.form.oauth_key.bitbucketcloud.help')}
+ onFieldChange={props.onFieldChange}
+ propKey="clientId"
+ value={formData.clientId || ''}
+ />
+ <AlmBindingDefinitionFormField
+ id="client_secret.bitbucketcloud"
+ help={translate('settings.almintegration.form.oauth_secret.bitbucketcloud.help')}
+ onFieldChange={props.onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
+ propKey="clientSecret"
+ value={formData.clientSecret || ''}
+ />
+ </>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx
index 3fd09b75508..08612473b58 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx
@@ -19,40 +19,42 @@
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
import RadioToggle from 'sonar-ui-common/components/controls/RadioToggle';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
+import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
import {
AlmKeys,
- BitbucketBindingDefinition,
BitbucketCloudBindingDefinition,
- isBitbucketBindingDefinition,
- isBitbucketCloudBindingDefinition
+ BitbucketServerBindingDefinition
} from '../../../../types/alm-settings';
-import { AlmBindingDefinitionFormField } from './AlmBindingDefinitionFormField';
+import BitbucketCloudForm from './BitbucketCloudForm';
+import BitbucketServerForm from './BitbucketServerForm';
export interface BitbucketFormProps {
- formData: BitbucketBindingDefinition | BitbucketCloudBindingDefinition;
- isCreating: boolean;
+ formData: BitbucketServerBindingDefinition | BitbucketCloudBindingDefinition;
+ isUpdate: boolean;
onFieldChange: (
- fieldId: keyof (BitbucketBindingDefinition & BitbucketCloudBindingDefinition),
+ fieldId: keyof (BitbucketServerBindingDefinition & BitbucketCloudBindingDefinition),
value: string
) => void;
- onSelectVariant: (variant: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud) => void;
variant?: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud;
+ onVariantChange: (variant: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud) => void;
}
export default function BitbucketForm(props: BitbucketFormProps) {
- const { formData, isCreating, variant } = props;
+ const { isUpdate, formData, variant } = props;
return (
- <div>
- {isCreating && (
- <>
+ <>
+ {!isUpdate && (
+ <div className="display-flex-column">
<strong>{translate('settings.almintegration.form.choose_bitbucket_variant')}</strong>
<RadioToggle
className="little-spacer-top big-spacer-bottom"
name="variant"
- onCheck={props.onSelectVariant}
+ onCheck={props.onVariantChange}
options={[
{
label: 'Bitbucket Server',
@@ -62,117 +64,67 @@ export default function BitbucketForm(props: BitbucketFormProps) {
]}
value={variant}
/>
- </>
- )}
-
- {variant === AlmKeys.BitbucketServer && isBitbucketBindingDefinition(formData) && (
- <div>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help={translate('settings.almintegration.form.name.bitbucket.help')}
- id="name.bitbucket"
- maxLength={100}
- onFieldChange={props.onFieldChange}
- propKey="key"
- value={formData.key}
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage={translate('settings.almintegration.form.url.bitbucket.help')}
- id="settings.almintegration.form.url.bitbucket.help"
- values={{ example: 'https://bitbucket-server.your-company.com' }}
- />
- }
- id="url.bitbucket"
- maxLength={2000}
- onFieldChange={props.onFieldChange}
- propKey="url"
- value={formData.url}
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage={translate(
- 'settings.almintegration.form.personal_access_token.bitbucket.help'
- )}
- id="settings.almintegration.form.personal_access_token.bitbucket.help"
- values={{
- pat: (
- <a
- href="https://confluence.atlassian.com/bitbucketserver0515/personal-access-tokens-961275199.html"
- rel="noopener noreferrer"
- target="_blank">
- {translate(
- 'settings.almintegration.form.personal_access_token.bitbucket.help.url'
- )}
- </a>
- )
- }}
- />
- }
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={props.onFieldChange}
- overwriteOnly={Boolean(formData.key)}
- propKey="personalAccessToken"
- value={formData.personalAccessToken}
- />
</div>
)}
- {variant === AlmKeys.BitbucketCloud && isBitbucketCloudBindingDefinition(formData) && (
- <div>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help={translate('settings.almintegration.form.name.bitbucketcloud.help')}
- id="name.bitbucket"
- maxLength={100}
- onFieldChange={props.onFieldChange}
- propKey="key"
- value={formData.key}
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage={translate(
- 'settings.almintegration.form.workspace.bitbucketcloud.help'
- )}
- id="settings.almintegration.form.workspace.bitbucketcloud.help"
- values={{
- example: (
- <>
- {'https://bitbucket.org/'}
- <strong>{'{workspace}'}</strong>
- {'/{repository}'}
- </>
- )
- }}
- />
- }
- id="workspace.bitbucketcloud"
- maxLength={2000}
- onFieldChange={props.onFieldChange}
- propKey="workspace"
- value={formData.workspace}
- />
- <AlmBindingDefinitionFormField
- help={translate('settings.almintegration.form.oauth_key.bitbucketcloud.help')}
- id="client_id.bitbucketcloud"
- onFieldChange={props.onFieldChange}
- propKey="clientId"
- value={formData.clientId}
- />
- <AlmBindingDefinitionFormField
- help={translate('settings.almintegration.form.oauth_secret.bitbucketcloud.help')}
- id="client_secret.bitbucketcloud"
- onFieldChange={props.onFieldChange}
- overwriteOnly={Boolean(formData.key)}
- propKey="clientSecret"
- value={formData.clientSecret}
- />
- </div>
+ {variant !== undefined && (
+ <>
+ {variant === AlmKeys.BitbucketServer && (
+ <div className="display-flex-start">
+ <div className="flex-1">
+ <BitbucketServerForm
+ onFieldChange={props.onFieldChange}
+ formData={formData as BitbucketServerBindingDefinition}
+ />
+ </div>
+ <Alert className="huge-spacer-left flex-1" variant="info">
+ <>
+ <h3>{translate('onboarding.create_project.pat_help.title')}</h3>
+
+ <p className="big-spacer-top">
+ {translate('settings.almintegration.bitbucket.help_1')}
+ </p>
+
+ <ul className="big-spacer-top list-styled">
+ <li>{translate('settings.almintegration.bitbucket.help_2')}</li>
+ <li>{translate('settings.almintegration.bitbucket.help_3')}</li>
+ </ul>
+
+ <p className="big-spacer-top big-spacer-bottom">
+ <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.BitbucketServer]}>
+ {translate('learn_more')}
+ </Link>
+ </p>
+ </>
+ </Alert>
+ </div>
+ )}
+
+ {variant === AlmKeys.BitbucketCloud && (
+ <div className="display-flex-start">
+ <div className="flex-1">
+ <BitbucketCloudForm
+ onFieldChange={props.onFieldChange}
+ formData={formData as BitbucketCloudBindingDefinition}
+ />
+ </div>
+ <Alert className="huge-spacer-left flex-1" variant="info">
+ <FormattedMessage
+ defaultMessage={translate(`settings.almintegration.bitbucketcloud.info`)}
+ id="settings.almintegration.bitbucketcloud.info"
+ values={{
+ link: (
+ <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.BitbucketCloud]}>
+ {translate('learn_more')}
+ </Link>
+ )
+ }}
+ />
+ </Alert>
+ </div>
+ )}
+ </>
)}
- </div>
+ </>
);
}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketServerForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketServerForm.tsx
new file mode 100644
index 00000000000..d2ac778e29a
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketServerForm.tsx
@@ -0,0 +1,91 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { BitbucketServerBindingDefinition } from '../../../../types/alm-settings';
+import { AlmBindingDefinitionFormField } from './AlmBindingDefinitionFormField';
+
+export interface BitbucketServerFormProps {
+ formData: BitbucketServerBindingDefinition;
+ onFieldChange: (fieldId: keyof BitbucketServerBindingDefinition, value: string) => void;
+}
+
+export default function BitbucketServerForm(props: BitbucketServerFormProps) {
+ const { formData } = props;
+
+ return (
+ <>
+ {' '}
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help={translate('settings.almintegration.form.name.bitbucket.help')}
+ id="name.bitbucket"
+ maxLength={100}
+ onFieldChange={props.onFieldChange}
+ propKey="key"
+ value={formData.key || ''}
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <FormattedMessage
+ defaultMessage={translate('settings.almintegration.form.url.bitbucket.help')}
+ id="settings.almintegration.form.url.bitbucket.help"
+ values={{ example: 'https://bitbucket-server.your-company.com' }}
+ />
+ }
+ id="url.bitbucket"
+ maxLength={2000}
+ onFieldChange={props.onFieldChange}
+ propKey="url"
+ value={formData.url || ''}
+ />
+ <AlmBindingDefinitionFormField
+ id="personal_access_token"
+ help={
+ <FormattedMessage
+ defaultMessage={translate(
+ 'settings.almintegration.form.personal_access_token.bitbucket.help'
+ )}
+ id="settings.almintegration.form.personal_access_token.bitbucket.help"
+ values={{
+ pat: (
+ <a
+ href="https://confluence.atlassian.com/bitbucketserver0515/personal-access-tokens-961275199.html"
+ rel="noopener noreferrer"
+ target="_blank">
+ {translate(
+ 'settings.almintegration.form.personal_access_token.bitbucket.help.url'
+ )}
+ </a>
+ )
+ }}
+ />
+ }
+ isTextArea={true}
+ onFieldChange={props.onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
+ propKey="personalAccessToken"
+ value={formData.personalAccessToken || ''}
+ />
+ </>
+ );
+}
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
deleted file mode 100644
index df05024ece7..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTab.tsx
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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 {
- createBitbucketCloudConfiguration,
- createBitbucketConfiguration,
- updateBitbucketCloudConfiguration,
- updateBitbucketConfiguration
-} from '../../../../api/alm-settings';
-import {
- AlmKeys,
- AlmSettingsBindingStatus,
- BitbucketBindingDefinition,
- BitbucketCloudBindingDefinition,
- isBitbucketBindingDefinition
-} from '../../../../types/alm-settings';
-import BitbucketTabRenderer from './BitbucketTabRenderer';
-
-interface Props {
- branchesEnabled: boolean;
- definitions: Array<BitbucketBindingDefinition | BitbucketCloudBindingDefinition>;
- definitionStatus: T.Dict<AlmSettingsBindingStatus>;
- loadingAlmDefinitions: boolean;
- loadingProjectCount: boolean;
- multipleAlmEnabled: boolean;
- onCheck: (definitionKey: string) => void;
- onDelete: (definitionKey: string) => void;
- onUpdateDefinitions: () => void;
-}
-
-interface State {
- editedDefinition?: BitbucketBindingDefinition | BitbucketCloudBindingDefinition;
- isCreating: boolean;
- submitting: boolean;
- success: boolean;
- variant?: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud;
-}
-
-export const DEFAULT_SERVER_BINDING = { key: '', url: '', personalAccessToken: '' };
-export const DEFAULT_CLOUD_BINDING = { key: '', clientId: '', clientSecret: '', workspace: '' };
-
-export default class BitbucketTab extends React.PureComponent<Props, State> {
- mounted = false;
- state: State = { isCreating: false, submitting: false, success: false };
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- handleCancel = () => {
- this.setState({
- editedDefinition: undefined,
- isCreating: false,
- success: false,
- variant: undefined
- });
- };
-
- handleCreate = () => {
- this.setState({
- editedDefinition: DEFAULT_SERVER_BINDING, // Default to Bitbucket Server.
- isCreating: true,
- success: false,
- variant: undefined
- });
- };
-
- handleSelectVariant = (variant: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud) => {
- this.setState({
- variant,
- editedDefinition:
- variant === AlmKeys.BitbucketServer ? DEFAULT_SERVER_BINDING : DEFAULT_CLOUD_BINDING
- });
- };
-
- handleEdit = (definitionKey: string) => {
- const editedDefinition = this.props.definitions.find(d => d.key === definitionKey);
- const variant = isBitbucketBindingDefinition(editedDefinition)
- ? AlmKeys.BitbucketServer
- : AlmKeys.BitbucketCloud;
- this.setState({ editedDefinition, variant, success: false });
- };
-
- handleSubmit = (
- config: BitbucketBindingDefinition | BitbucketCloudBindingDefinition,
- originalKey: string
- ) => {
- const call = originalKey
- ? this.updateConfiguration({ newKey: config.key, ...config, key: originalKey })
- : this.createConfiguration({ ...config });
-
- this.setState({ submitting: true });
- return call
- .then(() => {
- if (this.mounted) {
- this.setState({
- editedDefinition: undefined,
- isCreating: false,
- submitting: false,
- success: true
- });
- }
- })
- .then(this.props.onUpdateDefinitions)
- .then(() => {
- this.props.onCheck(config.key);
- })
- .catch(() => {
- if (this.mounted) {
- this.setState({ submitting: false, success: false });
- }
- });
- };
-
- updateConfiguration = (
- config: (BitbucketBindingDefinition | BitbucketCloudBindingDefinition) & { newKey: string }
- ) => {
- if (isBitbucketBindingDefinition(config)) {
- return updateBitbucketConfiguration(config);
- }
- return updateBitbucketCloudConfiguration(config);
- };
-
- createConfiguration = (config: BitbucketBindingDefinition | BitbucketCloudBindingDefinition) => {
- if (isBitbucketBindingDefinition(config)) {
- return createBitbucketConfiguration(config);
- }
- return createBitbucketCloudConfiguration(config);
- };
-
- render() {
- const {
- branchesEnabled,
- definitions,
- definitionStatus,
- loadingAlmDefinitions,
- loadingProjectCount,
- multipleAlmEnabled
- } = this.props;
- const { editedDefinition, isCreating, submitting, success, variant } = this.state;
-
- return (
- <BitbucketTabRenderer
- branchesEnabled={branchesEnabled}
- definitions={definitions}
- definitionStatus={definitionStatus}
- editedDefinition={editedDefinition}
- isCreating={isCreating}
- loadingAlmDefinitions={loadingAlmDefinitions}
- loadingProjectCount={loadingProjectCount}
- multipleAlmEnabled={multipleAlmEnabled}
- onCancel={this.handleCancel}
- onCheck={this.props.onCheck}
- onCreate={this.handleCreate}
- onDelete={this.props.onDelete}
- onEdit={this.handleEdit}
- onSelectVariant={this.handleSelectVariant}
- onSubmit={this.handleSubmit}
- submitting={submitting}
- success={success}
- variant={variant}
- />
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTabRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTabRenderer.tsx
deleted file mode 100644
index e586f2b8d36..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketTabRenderer.tsx
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import { Link } from 'react-router';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
-import {
- AlmKeys,
- AlmSettingsBindingStatus,
- BitbucketBindingDefinition,
- BitbucketCloudBindingDefinition
-} from '../../../../types/alm-settings';
-import AlmTabRenderer from './AlmTabRenderer';
-import BitbucketForm from './BitbucketForm';
-
-export interface BitbucketTabRendererProps {
- branchesEnabled: boolean;
- definitionStatus: T.Dict<AlmSettingsBindingStatus>;
- editedDefinition?: BitbucketBindingDefinition | BitbucketCloudBindingDefinition;
- definitions: Array<BitbucketBindingDefinition | BitbucketCloudBindingDefinition>;
- isCreating: boolean;
- loadingAlmDefinitions: boolean;
- loadingProjectCount: boolean;
- multipleAlmEnabled: boolean;
- onCancel: () => void;
- onCheck: (definitionKey: string) => void;
- onCreate: () => void;
- onDelete: (definitionKey: string) => void;
- onEdit: (definitionKey: string) => void;
- onSelectVariant: (variant: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud) => void;
- onSubmit: (
- config: BitbucketBindingDefinition | BitbucketCloudBindingDefinition,
- originalKey: string
- ) => void;
- submitting: boolean;
- success: boolean;
- variant?: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud;
-}
-
-export default function BitbucketTabRenderer(props: BitbucketTabRendererProps) {
- const {
- branchesEnabled,
- editedDefinition,
- definitions,
- definitionStatus,
- isCreating,
- loadingAlmDefinitions,
- loadingProjectCount,
- multipleAlmEnabled,
- submitting,
- success,
- variant
- } = props;
-
- let help;
- if (variant === AlmKeys.BitbucketServer) {
- help = (
- <>
- <h3>{translate('onboarding.create_project.pat_help.title')}</h3>
-
- <p className="big-spacer-top">{translate('settings.almintegration.bitbucket.help_1')}</p>
-
- <ul className="big-spacer-top list-styled">
- <li>{translate('settings.almintegration.bitbucket.help_2')}</li>
- <li>{translate('settings.almintegration.bitbucket.help_3')}</li>
- </ul>
-
- <p className="big-spacer-top big-spacer-bottom">
- <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.BitbucketServer]}>
- {translate('learn_more')}
- </Link>
- </p>
- </>
- );
- } else if (variant === AlmKeys.BitbucketCloud) {
- help = (
- <FormattedMessage
- defaultMessage={translate(`settings.almintegration.bitbucketcloud.info`)}
- id="settings.almintegration.bitbucketcloud.info"
- values={{
- link: (
- <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.BitbucketCloud]}>
- {translate('learn_more')}
- </Link>
- )
- }}
- />
- );
- }
-
- return (
- <div className="bordered">
- <AlmTabRenderer
- branchesEnabled={branchesEnabled}
- alm={AlmKeys.BitbucketServer} // Always use Bitbucket Server for the translation keys.
- definitions={definitions}
- definitionStatus={definitionStatus}
- editedDefinition={editedDefinition}
- form={childProps => (
- <BitbucketForm
- isCreating={isCreating}
- onSelectVariant={props.onSelectVariant}
- variant={variant}
- {...childProps}
- />
- )}
- help={help}
- loadingAlmDefinitions={loadingAlmDefinitions}
- loadingProjectCount={loadingProjectCount}
- multipleAlmEnabled={multipleAlmEnabled}
- onCancel={props.onCancel}
- onCheck={props.onCheck}
- onCreate={props.onCreate}
- onDelete={props.onDelete}
- onEdit={props.onEdit}
- onSubmit={props.onSubmit}
- submitting={submitting}
- success={success}
- />
- </div>
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx
index a1a782a2241..bf75e18c801 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubForm.tsx
@@ -18,8 +18,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
-import { GithubBindingDefinition } from '../../../../types/alm-settings';
+import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
+import { AlmKeys, GithubBindingDefinition } from '../../../../types/alm-settings';
import { AlmBindingDefinitionFormField } from './AlmBindingDefinitionFormField';
export interface GithubFormProps {
@@ -31,68 +35,83 @@ export default function GithubForm(props: GithubFormProps) {
const { formData, onFieldChange } = props;
return (
- <>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help={translate('settings.almintegration.form.name.github.help')}
- id="name.github"
- onFieldChange={onFieldChange}
- propKey="key"
- value={formData.key}
- />
- <AlmBindingDefinitionFormField
- help={
- <>
- {translate('settings.almintegration.form.url.github.help1')}
- <br />
- <em>https://github.company.com/api/v3</em>
- <br />
- <br />
- {translate('settings.almintegration.form.url.github.help2')}
- <br />
- <em>https://api.github.com/</em>
- </>
- }
- id="url.github"
- maxLength={2000}
- onFieldChange={onFieldChange}
- propKey="url"
- value={formData.url}
- />
- <AlmBindingDefinitionFormField
- help={translate('settings.almintegration.form.app_id.github.help')}
- id="app_id"
- maxLength={80}
- onFieldChange={onFieldChange}
- propKey="appId"
- value={formData.appId}
- />
- <AlmBindingDefinitionFormField
- help={translate('settings.almintegration.form.client_id.github.help')}
- id="client_id.github"
- maxLength={80}
- onFieldChange={onFieldChange}
- propKey="clientId"
- value={formData.clientId}
- />
- <AlmBindingDefinitionFormField
- help={translate('settings.almintegration.form.client_secret.github.help')}
- id="client_secret.github"
- maxLength={80}
- onFieldChange={onFieldChange}
- overwriteOnly={Boolean(formData.key)}
- propKey="clientSecret"
- value={formData.clientSecret}
- />
- <AlmBindingDefinitionFormField
- help={translate('settings.almintegration.form.private_key.github.help')}
- id="private_key"
- isTextArea={true}
- onFieldChange={onFieldChange}
- overwriteOnly={Boolean(formData.key)}
- propKey="privateKey"
- value={formData.privateKey}
- />
- </>
+ <div className="display-flex-start">
+ <div className="flex-1">
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help={translate('settings.almintegration.form.name.github.help')}
+ id="name.github"
+ onFieldChange={onFieldChange}
+ propKey="key"
+ value={formData.key}
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <>
+ {translate('settings.almintegration.form.url.github.help1')}
+ <br />
+ <em>https://github.company.com/api/v3</em>
+ <br />
+ <br />
+ {translate('settings.almintegration.form.url.github.help2')}
+ <br />
+ <em>https://api.github.com/</em>
+ </>
+ }
+ id="url.github"
+ maxLength={2000}
+ onFieldChange={onFieldChange}
+ propKey="url"
+ value={formData.url}
+ />
+ <AlmBindingDefinitionFormField
+ id="app_id"
+ help={translate('settings.almintegration.form.app_id.github.help')}
+ maxLength={80}
+ onFieldChange={onFieldChange}
+ propKey="appId"
+ value={formData.appId}
+ />
+ <AlmBindingDefinitionFormField
+ id="client_id.github"
+ help={translate('settings.almintegration.form.client_id.github.help')}
+ maxLength={80}
+ onFieldChange={onFieldChange}
+ propKey="clientId"
+ value={formData.clientId}
+ />
+ <AlmBindingDefinitionFormField
+ id="client_secret.github"
+ help={translate('settings.almintegration.form.client_secret.github.help')}
+ maxLength={80}
+ onFieldChange={onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
+ propKey="clientSecret"
+ value={formData.clientSecret}
+ />
+ <AlmBindingDefinitionFormField
+ id="private_key"
+ help={translate('settings.almintegration.form.private_key.github.help')}
+ isTextArea={true}
+ onFieldChange={onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
+ propKey="privateKey"
+ value={formData.privateKey}
+ />
+ </div>
+ <Alert className="huge-spacer-left flex-1" variant="info">
+ <FormattedMessage
+ defaultMessage={translate(`settings.almintegration.github.info`)}
+ id="settings.almintegration.github.info"
+ values={{
+ link: (
+ <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.GitHub]}>
+ {translate('learn_more')}
+ </Link>
+ )
+ }}
+ />
+ </Alert>
+ </div>
);
}
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
deleted file mode 100644
index 5a2371242da..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GithubTab.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import { Link } from 'react-router';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import { createGithubConfiguration, updateGithubConfiguration } from '../../../../api/alm-settings';
-import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
-import {
- AlmKeys,
- AlmSettingsBindingStatus,
- GithubBindingDefinition
-} from '../../../../types/alm-settings';
-import { ALM_INTEGRATION } from '../AdditionalCategoryKeys';
-import CategoryDefinitionsList from '../CategoryDefinitionsList';
-import AlmTab from './AlmTab';
-import GithubForm from './GithubForm';
-
-export interface GithubTabProps {
- branchesEnabled: boolean;
- component?: T.Component;
- definitions: GithubBindingDefinition[];
- definitionStatus: T.Dict<AlmSettingsBindingStatus>;
- loadingAlmDefinitions: boolean;
- loadingProjectCount: boolean;
- multipleAlmEnabled: boolean;
- onCheck: (definitionKey: string) => void;
- onDelete: (definitionKey: string) => void;
- onUpdateDefinitions: () => void;
-}
-
-export default function GithubTab(props: GithubTabProps) {
- const {
- branchesEnabled,
- component,
- multipleAlmEnabled,
- definitions,
- definitionStatus,
- loadingAlmDefinitions,
- loadingProjectCount
- } = props;
-
- return (
- <div className="bordered">
- <AlmTab
- alm={AlmKeys.GitHub}
- branchesEnabled={branchesEnabled}
- createConfiguration={createGithubConfiguration}
- defaultBinding={{
- key: '',
- appId: '',
- clientId: '',
- clientSecret: '',
- url: '',
- privateKey: ''
- }}
- definitions={definitions}
- definitionStatus={definitionStatus}
- form={childProps => <GithubForm {...childProps} />}
- help={
- <FormattedMessage
- defaultMessage={translate(`settings.almintegration.github.info`)}
- id="settings.almintegration.github.info"
- values={{
- link: (
- <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.GitHub]}>
- {translate('learn_more')}
- </Link>
- )
- }}
- />
- }
- loadingAlmDefinitions={loadingAlmDefinitions}
- loadingProjectCount={loadingProjectCount}
- multipleAlmEnabled={multipleAlmEnabled}
- onCheck={props.onCheck}
- onDelete={props.onDelete}
- onUpdateDefinitions={props.onUpdateDefinitions}
- updateConfiguration={updateGithubConfiguration}
- />
-
- <div className="huge-spacer-top huge-spacer-bottom bordered-top" />
-
- <div className="big-padded">
- <CategoryDefinitionsList
- category={ALM_INTEGRATION}
- component={component}
- subCategory={AlmKeys.GitHub}
- />
- </div>
- </div>
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx
index 62b8daf8db7..34406e9ae7c 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabForm.tsx
@@ -18,8 +18,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
-import { GitlabBindingDefinition } from '../../../../types/alm-settings';
+import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
+import { AlmKeys, GitlabBindingDefinition } from '../../../../types/alm-settings';
import { AlmBindingDefinitionFormField } from './AlmBindingDefinitionFormField';
export interface GitlabFormProps {
@@ -31,38 +35,53 @@ export default function GitlabForm(props: GitlabFormProps) {
const { formData, onFieldChange } = props;
return (
- <>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help={translate('settings.almintegration.form.name.gitlab.help')}
- id="name.gitlab"
- onFieldChange={onFieldChange}
- propKey="key"
- value={formData.key}
- />
- <AlmBindingDefinitionFormField
- help={
- <>
- {translate('settings.almintegration.form.url.gitlab.help')}
- <br />
- <em>https://gitlab.com/api/v4</em>
- </>
- }
- id="url.gitlab"
- maxLength={2000}
- onFieldChange={onFieldChange}
- propKey="url"
- value={formData.url || ''}
- />
- <AlmBindingDefinitionFormField
- help={translate('settings.almintegration.form.personal_access_token.gitlab.help')}
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={onFieldChange}
- overwriteOnly={Boolean(formData.key)}
- propKey="personalAccessToken"
- value={formData.personalAccessToken}
- />
- </>
+ <div className="display-flex-start">
+ <div className="flex-1">
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help={translate('settings.almintegration.form.name.gitlab.help')}
+ id="name.gitlab"
+ onFieldChange={onFieldChange}
+ propKey="key"
+ value={formData.key}
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <>
+ {translate('settings.almintegration.form.url.gitlab.help')}
+ <br />
+ <em>https://gitlab.com/api/v4</em>
+ </>
+ }
+ id="url.gitlab"
+ maxLength={2000}
+ onFieldChange={onFieldChange}
+ propKey="url"
+ value={formData.url || ''}
+ />
+ <AlmBindingDefinitionFormField
+ help={translate('settings.almintegration.form.personal_access_token.gitlab.help')}
+ id="personal_access_token"
+ isTextArea={true}
+ onFieldChange={onFieldChange}
+ overwriteOnly={Boolean(formData.key)}
+ propKey="personalAccessToken"
+ value={formData.personalAccessToken}
+ />
+ </div>
+ <Alert className="huge-spacer-left flex-1" variant="info">
+ <FormattedMessage
+ defaultMessage={translate(`settings.almintegration.gitlab.info`)}
+ id="settings.almintegration.gitlab.info"
+ values={{
+ link: (
+ <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.GitLab]}>
+ {translate('learn_more')}
+ </Link>
+ )
+ }}
+ />
+ </Alert>
+ </div>
);
}
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
deleted file mode 100644
index 993b6214b70..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/GitlabTab.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import { Link } from 'react-router';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import { createGitlabConfiguration, updateGitlabConfiguration } from '../../../../api/alm-settings';
-import { ALM_DOCUMENTATION_PATHS } from '../../../../helpers/constants';
-import {
- AlmKeys,
- AlmSettingsBindingStatus,
- GitlabBindingDefinition
-} from '../../../../types/alm-settings';
-import { ALM_INTEGRATION } from '../AdditionalCategoryKeys';
-import CategoryDefinitionsList from '../CategoryDefinitionsList';
-import AlmTab from './AlmTab';
-import GitlabForm from './GitlabForm';
-
-export interface GitlabTabProps {
- branchesEnabled: boolean;
- component?: T.Component;
- definitions: GitlabBindingDefinition[];
- definitionStatus: T.Dict<AlmSettingsBindingStatus>;
- loadingAlmDefinitions: boolean;
- loadingProjectCount: boolean;
- multipleAlmEnabled: boolean;
- onCheck: (definitionKey: string) => void;
- onDelete: (definitionKey: string) => void;
- onUpdateDefinitions: () => void;
-}
-
-export default function GitlabTab(props: GitlabTabProps) {
- const {
- branchesEnabled,
- component,
- multipleAlmEnabled,
- definitions,
- definitionStatus,
- loadingAlmDefinitions,
- loadingProjectCount
- } = props;
-
- return (
- <div className="bordered">
- <AlmTab
- alm={AlmKeys.GitLab}
- branchesEnabled={branchesEnabled}
- createConfiguration={createGitlabConfiguration}
- defaultBinding={{ key: '', personalAccessToken: '', url: '' }}
- definitions={definitions}
- definitionStatus={definitionStatus}
- form={childProps => <GitlabForm {...childProps} />}
- help={
- <FormattedMessage
- defaultMessage={translate(`settings.almintegration.gitlab.info`)}
- id="settings.almintegration.gitlab.info"
- values={{
- link: (
- <Link target="_blank" to={ALM_DOCUMENTATION_PATHS[AlmKeys.GitLab]}>
- {translate('learn_more')}
- </Link>
- )
- }}
- />
- }
- loadingAlmDefinitions={loadingAlmDefinitions}
- loadingProjectCount={loadingProjectCount}
- multipleAlmEnabled={multipleAlmEnabled}
- onCheck={props.onCheck}
- onDelete={props.onDelete}
- onUpdateDefinitions={props.onUpdateDefinitions}
- updateConfiguration={updateGitlabConfiguration}
- />
-
- <div className="huge-spacer-top huge-spacer-bottom bordered-top" />
-
- <div className="big-padded">
- <CategoryDefinitionsList
- category={ALM_INTEGRATION}
- component={component}
- subCategory={AlmKeys.GitLab}
- />
- </div>
- </div>
- );
-}
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 6c2d2acb59f..09f5f58c8a3 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
@@ -20,41 +20,57 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
-import { mockGithubBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
-import { GithubBindingDefinition } from '../../../../../types/alm-settings';
+import {
+ createAzureConfiguration,
+ createBitbucketCloudConfiguration,
+ createBitbucketServerConfiguration,
+ createGithubConfiguration,
+ createGitlabConfiguration,
+ updateAzureConfiguration,
+ updateBitbucketCloudConfiguration,
+ updateBitbucketServerConfiguration,
+ updateGithubConfiguration,
+ updateGitlabConfiguration
+} from '../../../../../api/alm-settings';
+import {
+ mockAzureBindingDefinition,
+ mockBitbucketCloudBindingDefinition,
+ mockBitbucketServerBindingDefinition,
+ mockGithubBindingDefinition,
+ mockGitlabBindingDefinition
+} from '../../../../../helpers/mocks/alm-settings';
+import { AlmBindingDefinition, AlmKeys } from '../../../../../types/alm-settings';
import AlmBindingDefinitionForm from '../AlmBindingDefinitionForm';
+import AlmBindingDefinitionFormRenderer from '../AlmBindingDefinitionFormRenderer';
+
+jest.mock('../../../../../api/alm-settings', () => ({
+ createAzureConfiguration: jest.fn().mockResolvedValue({}),
+ createBitbucketCloudConfiguration: jest.fn().mockResolvedValue({}),
+ createBitbucketServerConfiguration: jest.fn().mockResolvedValue({}),
+ createGithubConfiguration: jest.fn().mockResolvedValue({}),
+ createGitlabConfiguration: jest.fn().mockResolvedValue({}),
+ updateAzureConfiguration: jest.fn().mockResolvedValue({}),
+ updateBitbucketCloudConfiguration: jest.fn().mockResolvedValue({}),
+ updateBitbucketServerConfiguration: jest.fn().mockResolvedValue({}),
+ updateGithubConfiguration: jest.fn().mockResolvedValue({}),
+ updateGitlabConfiguration: jest.fn().mockResolvedValue({})
+}));
+
+beforeEach(() => {
+ jest.clearAllMocks();
+});
it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot('create');
-
+ expect(shallowRender({ bindingDefinition: undefined })).toMatchSnapshot('create');
expect(shallowRender({ bindingDefinition: mockGithubBindingDefinition() })).toMatchSnapshot(
'edit'
);
});
-it('should reset if the props change', () => {
- const bindingDefinition = mockGithubBindingDefinition();
- const wrapper = shallowRender({ bindingDefinition });
-
- wrapper.setState({ formData: { ...bindingDefinition, appId: 'newAppId' }, touched: true });
- wrapper.setProps({ bindingDefinition: { ...bindingDefinition } });
- expect(wrapper.state('touched')).toBe(true);
-
- wrapper.setProps({ bindingDefinition: mockGithubBindingDefinition({ key: 'diffKey' }) });
- expect(wrapper.state('touched')).toBe(false);
-});
-
it('should handle field changes', () => {
- const wrapper = shallowRender();
+ const formData = mockGithubBindingDefinition();
- const formData = {
- key: 'github - example',
- url: 'http://github.com',
- appId: '34812568251',
- clientId: 'cid',
- clientSecret: 'csecret',
- privateKey: 'gs7df9g7d9fsg7x9df7g9xdg'
- };
+ const wrapper = shallowRender();
wrapper.instance().handleFieldChange('key', formData.key);
wrapper.instance().handleFieldChange('url', formData.url);
@@ -63,69 +79,81 @@ it('should handle field changes', () => {
wrapper.instance().handleFieldChange('clientSecret', formData.clientSecret);
wrapper.instance().handleFieldChange('privateKey', formData.privateKey);
expect(wrapper.state().formData).toEqual(formData);
+ expect(wrapper.state().touched).toBe(true);
});
it('should handle form submit', async () => {
- const onSubmit = jest.fn();
- const wrapper = shallowRender({
- onSubmit,
- bindingDefinition: {
- key: 'originalKey',
- appId: '',
- clientId: '',
- clientSecret: '',
- privateKey: '',
- url: ''
- }
- });
- const formData = {
- key: 'github instance',
- url: 'http://github.enterprise.com',
- appId: '34812568251',
- clientId: 'client1234',
- clientSecret: 'secret',
- privateKey: 'gs7df9g7d9fsg7x9df7g9xdg'
- };
- wrapper.setState({ formData });
- await waitAndUpdate(wrapper);
+ const afterSubmit = jest.fn();
+ const formData = mockGithubBindingDefinition();
- wrapper.instance().handleFormSubmit();
+ const wrapper = shallowRender({ afterSubmit });
- expect(onSubmit).toHaveBeenCalledWith(formData, 'originalKey');
+ wrapper.instance().setState({ formData });
+ await waitAndUpdate(wrapper);
+ await wrapper.instance().handleFormSubmit();
+ await waitAndUpdate(wrapper);
+ expect(afterSubmit).toHaveBeenCalledWith(formData);
});
-it('should handle cancelling', () => {
- const onCancel = jest.fn();
- const bindingDefinition = {
- appId: 'foo',
- clientId: 'cid',
- clientSecret: 'cs',
- key: 'bar',
- privateKey: 'baz',
- url: 'http://github.enterprise.com'
- };
- const wrapper = shallowRender({
- bindingDefinition,
- onCancel
- });
+it.each([
+ [AlmKeys.Azure, undefined, createAzureConfiguration],
+ [AlmKeys.Azure, mockAzureBindingDefinition(), updateAzureConfiguration],
+ [AlmKeys.GitLab, undefined, createGitlabConfiguration],
+ [AlmKeys.GitLab, mockGitlabBindingDefinition(), updateGitlabConfiguration],
+ [AlmKeys.GitHub, undefined, createGithubConfiguration],
+ [AlmKeys.GitHub, mockGithubBindingDefinition(), updateGithubConfiguration],
+ [AlmKeys.BitbucketServer, undefined, createBitbucketServerConfiguration],
+ [
+ AlmKeys.BitbucketServer,
+ mockBitbucketServerBindingDefinition(),
+ updateBitbucketServerConfiguration
+ ]
+])(
+ 'should call the proper api on submit for %s | %s',
+ async (
+ alm: AlmKeys,
+ bindingDefinition: AlmBindingDefinition | undefined,
+ api: (def: AlmBindingDefinition) => any
+ ) => {
+ const wrapper = shallowRender({ alm, bindingDefinition });
+
+ await waitAndUpdate(wrapper);
+ await wrapper.instance().handleFormSubmit();
+ expect(api).toHaveBeenCalled();
+ }
+);
+
+it('should call the proper api for BBC', async () => {
+ const wrapper = shallowRender({ alm: AlmKeys.BitbucketServer, bindingDefinition: undefined });
+
+ wrapper.instance().handleBitbucketVariantChange(AlmKeys.BitbucketCloud);
- wrapper.setState({ formData: mockGithubBindingDefinition() });
- wrapper.instance().handleCancel();
+ await waitAndUpdate(wrapper);
+ await wrapper.instance().handleFormSubmit();
+ expect(createBitbucketCloudConfiguration).toHaveBeenCalled();
- expect(wrapper.state().formData).toBe(bindingDefinition);
- expect(onCancel).toHaveBeenCalled();
+ wrapper.setProps({ bindingDefinition: mockBitbucketCloudBindingDefinition() });
+ await wrapper.instance().handleFormSubmit();
+ expect(updateBitbucketCloudConfiguration).toHaveBeenCalled();
});
-it('should handle deleting', () => {
- const onDelete = jest.fn();
- const bindingDefinition = mockGithubBindingDefinition();
- const wrapper = shallowRender({
- bindingDefinition,
- onDelete
- });
+it('should store bitbucket variant', async () => {
+ const wrapper = shallowRender();
+
+ wrapper
+ .find(AlmBindingDefinitionFormRenderer)
+ .props()
+ .onBitbucketVariantChange(AlmKeys.BitbucketCloud);
- wrapper.instance().handleDelete();
- expect(onDelete).toHaveBeenCalledWith(bindingDefinition.key);
+ await waitAndUpdate(wrapper);
+
+ expect(wrapper.state().bitbucketVariant).toBe(AlmKeys.BitbucketCloud);
+ expect(wrapper.state().formData).toEqual({
+ clientId: '',
+ clientSecret: '',
+ key: '',
+ workspace: ''
+ });
});
it('should (dis)allow submit by validating its state', () => {
@@ -134,29 +162,17 @@ it('should (dis)allow submit by validating its state', () => {
wrapper.setState({ formData: mockGithubBindingDefinition(), touched: true });
expect(wrapper.instance().canSubmit()).toBe(true);
-
- wrapper.setState({ formData: mockGithubBindingDefinition({ url: '' }), touched: true });
- wrapper.setProps({ optionalFields: ['url'] });
- expect(wrapper.instance().canSubmit()).toBe(true);
});
-function shallowRender(
- props: Partial<AlmBindingDefinitionForm<GithubBindingDefinition>['props']> = {}
-) {
- return shallow<AlmBindingDefinitionForm<GithubBindingDefinition>>(
+function shallowRender(props: Partial<AlmBindingDefinitionForm['props']> = {}) {
+ return shallow<AlmBindingDefinitionForm>(
<AlmBindingDefinitionForm
- bindingDefinition={{
- appId: '',
- clientId: '',
- clientSecret: '',
- key: '',
- privateKey: '',
- url: ''
- }}
+ alm={AlmKeys.GitHub}
+ bindingDefinition={mockGithubBindingDefinition()}
+ alreadyHaveInstanceConfigured={false}
onCancel={jest.fn()}
- onSubmit={jest.fn()}
- {...props}>
- {() => null}
- </AlmBindingDefinitionForm>
+ afterSubmit={jest.fn()}
+ {...props}
+ />
);
}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx
index 1137b35be28..ceccda088f0 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx
@@ -21,7 +21,7 @@ import { shallow } from 'enzyme';
import * as React from 'react';
import { ButtonLink } from 'sonar-ui-common/components/controls/buttons';
import { click } from 'sonar-ui-common/helpers/testUtils';
-import { AlmBindingDefinition } from '../../../../../types/alm-settings';
+import { AlmBindingDefinitionBase } from '../../../../../types/alm-settings';
import {
AlmBindingDefinitionFormField,
AlmBindingDefinitionFormFieldProps
@@ -60,7 +60,7 @@ it('should correctly toggle visibility for secret fields', () => {
});
function shallowRender(
- props: Partial<AlmBindingDefinitionFormFieldProps<AlmBindingDefinition>> = {}
+ props: Partial<AlmBindingDefinitionFormFieldProps<AlmBindingDefinitionBase>> = {}
) {
return shallow(
<AlmBindingDefinitionFormField
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormModalRenderer-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormModalRenderer-test.tsx
deleted file mode 100644
index 6201ec060dc..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormModalRenderer-test.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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 { mockEvent } from '../../../../../helpers/testMocks';
-import AlmBindingDefinitionFormModalRenderer, {
- AlmBindingDefinitionFormModalProps
-} from '../AlmBindingDefinitionFormModalRenderer';
-
-it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot();
- expect(shallowRender({ help: <span>Help me</span> })).toMatchSnapshot('with help');
- expect(shallowRender({ isSecondInstance: true })).toMatchSnapshot('second instance');
-});
-
-it('should submit properly', () => {
- const onSubmit = jest.fn().mockResolvedValue({});
- const wrapper = shallowRender({ onSubmit });
-
- const event: React.SyntheticEvent<HTMLFormElement> = mockEvent({ preventDefault: jest.fn() });
-
- wrapper.find('form').simulate('submit', event);
-
- expect(event.preventDefault).toBeCalled();
- expect(onSubmit).toBeCalled();
-});
-
-function shallowRender(props: Partial<AlmBindingDefinitionFormModalProps> = {}) {
- return shallow(
- <AlmBindingDefinitionFormModalRenderer
- action="create"
- canSubmit={jest.fn()}
- isSecondInstance={false}
- onCancel={jest.fn()}
- onSubmit={jest.fn()}
- {...props}>
- {() => null}
- </AlmBindingDefinitionFormModalRenderer>
- );
-}
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
new file mode 100644
index 00000000000..a28503cd58c
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx
@@ -0,0 +1,95 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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 { ResetButtonLink } from 'sonar-ui-common/components/controls/buttons';
+import { click } from 'sonar-ui-common/helpers/testUtils';
+import { mockGithubBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
+import { mockEvent } from '../../../../../helpers/testMocks';
+import { AlmKeys } from '../../../../../types/alm-settings';
+import AlmBindingDefinitionFormRenderer, {
+ AlmBindingDefinitionFormProps
+} from '../AlmBindingDefinitionFormRenderer';
+import GithubForm from '../GithubForm';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+ expect(shallowRender({ alreadyHaveInstanceConfigured: true })).toMatchSnapshot('second instance');
+ expect(shallowRender({ submitting: true })).toMatchSnapshot('submitting');
+ expect(shallowRender({ isUpdate: true })).toMatchSnapshot('editing');
+});
+
+it.each([[AlmKeys.Azure], [AlmKeys.GitHub], [AlmKeys.GitLab], [AlmKeys.BitbucketServer]])(
+ 'should render correctly for %s',
+ alm => {
+ expect(shallowRender({ alm })).toMatchSnapshot();
+ }
+);
+
+it('should cancel properly', () => {
+ const onCancel = jest.fn();
+ const wrapper = shallowRender({ onCancel });
+
+ click(wrapper.find(ResetButtonLink));
+ expect(onCancel).toHaveBeenCalled();
+});
+
+it('should submit properly', () => {
+ const onSubmit = jest.fn();
+ const wrapper = shallowRender({ onSubmit });
+
+ const event: React.SyntheticEvent<HTMLFormElement> = mockEvent({ preventDefault: jest.fn() });
+
+ wrapper.find('form').simulate('submit', event);
+
+ expect(event.preventDefault).toBeCalled();
+ expect(onSubmit).toHaveBeenCalled();
+});
+
+it('should handle field change', () => {
+ const onFieldChange = jest.fn();
+ const wrapper = shallowRender({ onFieldChange });
+
+ wrapper
+ .find(GithubForm)
+ .props()
+ .onFieldChange('key', 'test');
+
+ expect(onFieldChange).toHaveBeenCalledWith('key', 'test');
+});
+
+function shallowRender(props: Partial<AlmBindingDefinitionFormProps> = {}) {
+ return shallow(
+ <AlmBindingDefinitionFormRenderer
+ alm={AlmKeys.GitHub}
+ isUpdate={false}
+ canSubmit={false}
+ alreadyHaveInstanceConfigured={false}
+ submitting={false}
+ formData={mockGithubBindingDefinition()}
+ onCancel={jest.fn()}
+ onSubmit={jest.fn()}
+ onFieldChange={jest.fn()}
+ bitbucketVariant={AlmKeys.BitbucketServer}
+ onBitbucketVariantChange={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 c4853b9ed18..110e538ff99 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
@@ -29,6 +29,7 @@ import {
import { mockLocation } from '../../../../../helpers/testMocks';
import { AlmKeys, AlmSettingsBindingStatusType } from '../../../../../types/alm-settings';
import { AlmIntegration } from '../AlmIntegration';
+import AlmIntegrationRenderer from '../AlmIntegrationRenderer';
jest.mock('../../../../../api/alm-settings', () => ({
countBindedProjects: jest.fn().mockResolvedValue(0),
@@ -72,13 +73,13 @@ it('should validate existing configurations', async () => {
it('should handle alm selection', async () => {
const wrapper = shallowRender();
- wrapper.setState({ currentAlm: AlmKeys.Azure });
+ wrapper.setState({ currentAlmTab: AlmKeys.Azure });
wrapper.instance().handleSelectAlm(AlmKeys.GitHub);
await waitAndUpdate(wrapper);
- expect(wrapper.state().currentAlm).toBe(AlmKeys.GitHub);
+ expect(wrapper.state().currentAlmTab).toBe(AlmKeys.GitHub);
});
it('should handle delete', async () => {
@@ -86,17 +87,27 @@ it('should handle delete', async () => {
(countBindedProjects as jest.Mock).mockResolvedValueOnce(7);
const wrapper = shallowRender();
- wrapper.instance().handleDelete(toBeDeleted);
+ wrapper
+ .find(AlmIntegrationRenderer)
+ .props()
+ .onDelete(toBeDeleted);
await waitAndUpdate(wrapper);
-
expect(wrapper.state().projectCount).toBe(7);
expect(wrapper.state().definitionKeyForDeletion).toBe(toBeDeleted);
+
+ wrapper
+ .find(AlmIntegrationRenderer)
+ .props()
+ .onCancelDelete();
+ await waitAndUpdate(wrapper);
+ expect(wrapper.state().projectCount).toBeUndefined();
+ expect(wrapper.state().definitionKeyForDeletion).toBeUndefined();
});
it('should delete configuration', async () => {
(deleteConfiguration as jest.Mock).mockResolvedValueOnce(undefined);
const wrapper = shallowRender();
- wrapper.instance().deleteConfiguration('8345678');
+ wrapper.instance().handleConfirmDelete('8345678');
await waitAndUpdate(wrapper);
expect(wrapper.state().projectCount).toBeUndefined();
@@ -164,10 +175,10 @@ it('should fetch settings', async () => {
it('should detect the current ALM from the query', () => {
let wrapper = shallowRender({ location: mockLocation() });
- expect(wrapper.state().currentAlm).toBe(AlmKeys.GitHub);
+ expect(wrapper.state().currentAlmTab).toBe(AlmKeys.GitHub);
wrapper = shallowRender({ location: mockLocation({ query: { alm: AlmKeys.BitbucketCloud } }) });
- expect(wrapper.state().currentAlm).toBe(AlmKeys.BitbucketServer);
+ expect(wrapper.state().currentAlmTab).toBe(AlmKeys.BitbucketServer);
});
function shallowRender(props: Partial<AlmIntegration['props']> = {}) {
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationRenderer-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationRenderer-test.tsx
index 6b33832d728..e6c3a7b7353 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationRenderer-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationRenderer-test.tsx
@@ -30,27 +30,26 @@ it('should render correctly', () => {
expect(shallowRender({ definitionKeyForDeletion: 'keyToDelete' })).toMatchSnapshot(
'delete modal'
);
- expect(shallowRender({ currentAlm: AlmKeys.Azure })).toMatchSnapshot('azure');
- expect(shallowRender({ currentAlm: AlmKeys.BitbucketServer })).toMatchSnapshot('bitbucket');
- expect(shallowRender({ currentAlm: AlmKeys.BitbucketCloud })).toMatchSnapshot('bitbucketcloud');
- expect(shallowRender({ currentAlm: AlmKeys.GitLab })).toMatchSnapshot('gitlab');
+ expect(shallowRender({ currentAlmTab: AlmKeys.Azure })).toMatchSnapshot('azure');
+ expect(shallowRender({ currentAlmTab: AlmKeys.BitbucketServer })).toMatchSnapshot('bitbucket');
+ expect(shallowRender({ currentAlmTab: AlmKeys.GitLab })).toMatchSnapshot('gitlab');
});
function shallowRender(props: Partial<AlmIntegrationRendererProps> = {}) {
return shallow(
<AlmIntegrationRenderer
branchesEnabled={true}
- currentAlm={AlmKeys.GitHub}
+ currentAlmTab={AlmKeys.GitHub}
definitions={{ azure: [], bitbucket: [], bitbucketcloud: [], github: [], gitlab: [] }}
definitionStatus={{}}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={false}
- onCancel={jest.fn()}
- onCheck={jest.fn()}
+ onCancelDelete={jest.fn()}
+ onCheckConfiguration={jest.fn()}
onConfirmDelete={jest.fn()}
onDelete={jest.fn()}
- onSelectAlm={jest.fn()}
+ onSelectAlmTab={jest.fn()}
onUpdateDefinitions={jest.fn()}
{...props}
/>
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTab-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTab-test.tsx
index dbabfdadf5b..c66da1da1aa 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTab-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTab-test.tsx
@@ -21,15 +21,9 @@ import { shallow } from 'enzyme';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { mockAzureBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
-import { AlmKeys, AzureBindingDefinition } from '../../../../../types/alm-settings';
+import { AlmKeys } from '../../../../../types/alm-settings';
import AlmTab from '../AlmTab';
-const DEFAULT_BINDING = {
- key: '',
- personalAccessToken: '',
- url: undefined
-};
-
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});
@@ -51,64 +45,47 @@ it('should handle cancel', async () => {
it('should handle edit', async () => {
const config = mockAzureBindingDefinition();
const wrapper = shallowRender({ definitions: [config] });
+
wrapper.instance().handleEdit(config.key);
await waitAndUpdate(wrapper);
expect(wrapper.state().editedDefinition).toEqual(config);
});
-it('should create config', async () => {
- const onUpdateDefinitions = jest.fn();
- const createConfiguration = jest.fn(() => Promise.resolve());
- const config = mockAzureBindingDefinition();
- const wrapper = shallowRender({ createConfiguration, onUpdateDefinitions });
+it('should handle create', async () => {
+ const wrapper = shallowRender();
wrapper.instance().handleCreate();
- expect(wrapper.state().editedDefinition).toBe(DEFAULT_BINDING);
-
- wrapper.setState({ editedDefinition: config });
- await wrapper.instance().handleSubmit(config, '');
-
- expect(createConfiguration).toBeCalledWith(config);
- expect(onUpdateDefinitions).toBeCalled();
+ await waitAndUpdate(wrapper);
expect(wrapper.state().editedDefinition).toBeUndefined();
});
-it('should update config', async () => {
+it('should handle afterSubmit', async () => {
const onUpdateDefinitions = jest.fn();
- const updateConfiguration = jest.fn(() => Promise.resolve());
- const config = mockAzureBindingDefinition();
- const wrapper = shallowRender({ onUpdateDefinitions, updateConfiguration });
- wrapper.setState({ editedDefinition: config });
+ const onCheck = jest.fn();
+ const binding = mockAzureBindingDefinition();
- await wrapper.instance().handleSubmit(config, 'originalKey');
+ const wrapper = shallowRender({ onUpdateDefinitions, onCheck });
- expect(updateConfiguration).toBeCalledWith({
- newKey: 'key',
- ...config,
- key: 'originalKey'
- });
- expect(onUpdateDefinitions).toBeCalled();
+ wrapper.instance().handleAfterSubmit(binding);
+ await waitAndUpdate(wrapper);
expect(wrapper.state().editedDefinition).toBeUndefined();
+ expect(onUpdateDefinitions).toHaveBeenCalled();
+ expect(onCheck).toHaveBeenCalledWith(binding.key);
});
-function shallowRender(props: Partial<AlmTab<AzureBindingDefinition>['props']> = {}) {
- return shallow<AlmTab<AzureBindingDefinition>>(
+function shallowRender(props: Partial<AlmTab['props']> = {}) {
+ return shallow<AlmTab>(
<AlmTab
- alm={AlmKeys.Azure}
+ almTab={AlmKeys.Azure}
branchesEnabled={true}
- createConfiguration={jest.fn()}
- defaultBinding={DEFAULT_BINDING}
definitions={[mockAzureBindingDefinition()]}
definitionStatus={{}}
- form={jest.fn()}
- help={<div />}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={true}
onCheck={jest.fn()}
onDelete={jest.fn()}
onUpdateDefinitions={jest.fn()}
- updateConfiguration={jest.fn()}
{...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 8d35c9a6bb8..e1afdbd2aa5 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
@@ -24,11 +24,7 @@ import {
mockBitbucketCloudBindingDefinition,
mockGithubBindingDefinition
} from '../../../../../helpers/mocks/alm-settings';
-import {
- AlmBindingDefinition,
- AlmKeys,
- AzureBindingDefinition
-} from '../../../../../types/alm-settings';
+import { AlmKeys } from '../../../../../types/alm-settings';
import AlmTabRenderer, { AlmTabRendererProps } from '../AlmTabRenderer';
it('should render correctly for multi-ALM binding', () => {
@@ -38,8 +34,7 @@ it('should render correctly for multi-ALM binding', () => {
expect(shallowRenderAzure({ loadingProjectCount: true })).toMatchSnapshot(
'loading project count'
);
- expect(shallowRenderAzure({ submitting: true })).toMatchSnapshot('submitting');
- expect(shallowRenderAzure()).toMatchSnapshot('loaded');
+ expect(shallowRenderAzure({})).toMatchSnapshot('loaded');
expect(shallowRenderAzure({ editedDefinition: mockAzureBindingDefinition() })).toMatchSnapshot(
'editing a definition'
);
@@ -80,30 +75,26 @@ it('should render correctly with validation', () => {
expect(
shallowRender({
- alm: AlmKeys.BitbucketServer, // BitbucketServer will be passed for both Bitbucket variants.
+ almTab: AlmKeys.BitbucketServer, // BitbucketServer will be passed for both Bitbucket variants.
definitions: [mockBitbucketCloudBindingDefinition()]
})
).toMatchSnapshot('pass the correct key for bitbucket cloud');
});
-function shallowRenderAzure(props: Partial<AlmTabRendererProps<AzureBindingDefinition>> = {}) {
+function shallowRenderAzure(props: Partial<AlmTabRendererProps>) {
return shallowRender({
definitions: [mockAzureBindingDefinition()],
...props
});
}
-function shallowRender<B extends AlmBindingDefinition>(
- props: Partial<AlmTabRendererProps<B>> = {}
-) {
+function shallowRender(props: Partial<AlmTabRendererProps> = {}) {
return shallow(
<AlmTabRenderer
- alm={AlmKeys.Azure}
+ almTab={AlmKeys.Azure}
branchesEnabled={true}
definitions={[]}
definitionStatus={{}}
- form={jest.fn()}
- help={<div />}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={true}
@@ -112,9 +103,7 @@ function shallowRender<B extends AlmBindingDefinition>(
onCreate={jest.fn()}
onDelete={jest.fn()}
onEdit={jest.fn()}
- onSubmit={jest.fn()}
- submitting={true}
- success={false}
+ afterSubmit={jest.fn()}
{...props}
/>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AzureTab-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketCloudForm-test.tsx
index ab62239c83a..01aaf0e10ce 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AzureTab-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketCloudForm-test.tsx
@@ -17,27 +17,22 @@
* 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 { mockAzureBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
-import AzureTab, { AzureTabProps } from '../AzureTab';
+import { mockBitbucketCloudBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
+import BitbucketCloudForm, { BitbucketCloudFormProps } from '../BitbucketCloudForm';
it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot();
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot();
});
-function shallowRender(props: Partial<AzureTabProps> = {}) {
- return shallow(
- <AzureTab
- branchesEnabled={true}
- definitions={[mockAzureBindingDefinition()]}
- definitionStatus={{}}
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCheck={jest.fn()}
- onDelete={jest.fn()}
- onUpdateDefinitions={jest.fn()}
+function shallowRender(props: Partial<BitbucketCloudFormProps> = {}) {
+ return shallow<BitbucketCloudFormProps>(
+ <BitbucketCloudForm
+ onFieldChange={jest.fn()}
+ formData={mockBitbucketCloudBindingDefinition()}
{...props}
/>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketForm-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketForm-test.tsx
index daa8f83f497..21bf6410a6e 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketForm-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketForm-test.tsx
@@ -19,41 +19,62 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import RadioToggle from 'sonar-ui-common/components/controls/RadioToggle';
import {
- mockBitbucketBindingDefinition,
- mockBitbucketCloudBindingDefinition
+ mockBitbucketCloudBindingDefinition,
+ mockBitbucketServerBindingDefinition
} from '../../../../../helpers/mocks/alm-settings';
import { AlmKeys } from '../../../../../types/alm-settings';
import BitbucketForm, { BitbucketFormProps } from '../BitbucketForm';
it('should render correctly', () => {
- expect(shallowRender({ isCreating: true })).toMatchSnapshot('variant select');
- expect(shallowRender()).toMatchSnapshot('bitbucket server, empty');
- expect(shallowRender({ formData: mockBitbucketBindingDefinition() })).toMatchSnapshot(
- 'bitbucket server, edit'
- );
- expect(
- shallowRender({
- formData: { key: '', clientId: '', clientSecret: '', workspace: '' },
- variant: AlmKeys.BitbucketCloud
- })
- ).toMatchSnapshot('bitbucket cloud, empty');
- expect(
- shallowRender({
- variant: AlmKeys.BitbucketCloud,
- formData: mockBitbucketCloudBindingDefinition()
- })
- ).toMatchSnapshot('bitbucket cloud, edit');
+ let wrapper = shallowRender({
+ variant: AlmKeys.BitbucketServer,
+ formData: mockBitbucketServerBindingDefinition()
+ });
+ expect(wrapper).toMatchSnapshot('bbs');
+
+ wrapper = shallowRender({
+ variant: AlmKeys.BitbucketCloud,
+ formData: mockBitbucketCloudBindingDefinition()
+ });
+ expect(wrapper).toMatchSnapshot('bbc');
+
+ wrapper = shallowRender({
+ isUpdate: true,
+ variant: AlmKeys.BitbucketServer,
+ formData: mockBitbucketServerBindingDefinition()
+ });
+ expect(wrapper).toMatchSnapshot('update bbs');
+
+ wrapper = shallowRender({
+ isUpdate: true,
+ variant: AlmKeys.BitbucketCloud,
+ formData: mockBitbucketCloudBindingDefinition()
+ });
+ expect(wrapper).toMatchSnapshot('update bbc');
+});
+
+it('should render propagete variant properly', () => {
+ const onVariantChange = jest.fn();
+ const wrapper = shallowRender({ onVariantChange });
+
+ wrapper
+ .find(RadioToggle)
+ .props()
+ .onCheck(AlmKeys.BitbucketServer);
+
+ expect(onVariantChange).toHaveBeenCalledWith(AlmKeys.BitbucketServer);
});
function shallowRender(props: Partial<BitbucketFormProps> = {}) {
return shallow(
<BitbucketForm
- formData={{ key: '', personalAccessToken: '', url: '' }}
- isCreating={false}
+ formData={mockBitbucketServerBindingDefinition()}
+ isUpdate={false}
onFieldChange={jest.fn()}
- onSelectVariant={jest.fn()}
variant={AlmKeys.BitbucketServer}
+ onVariantChange={jest.fn()}
{...props}
/>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GithubTab-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketServerForm-test.tsx
index 3785bb78608..1bedcf6ba53 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GithubTab-test.tsx
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketServerForm-test.tsx
@@ -17,27 +17,22 @@
* 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 { mockGithubBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
-import GithubTab, { GithubTabProps } from '../GithubTab';
+import { mockBitbucketServerBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
+import BitbucketServerForm, { BitbucketServerFormProps } from '../BitbucketServerForm';
it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot('with branch support');
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot();
});
-function shallowRender(props: Partial<GithubTabProps> = {}) {
- return shallow(
- <GithubTab
- branchesEnabled={true}
- definitions={[mockGithubBindingDefinition()]}
- definitionStatus={{}}
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCheck={jest.fn()}
- onDelete={jest.fn()}
- onUpdateDefinitions={jest.fn()}
+function shallowRender(props: Partial<BitbucketServerFormProps> = {}) {
+ return shallow<BitbucketServerFormProps>(
+ <BitbucketServerForm
+ onFieldChange={jest.fn()}
+ formData={mockBitbucketServerBindingDefinition()}
{...props}
/>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketTab-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketTab-test.tsx
deleted file mode 100644
index 5a95099ac5f..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketTab-test.tsx
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-import { shallow } from 'enzyme';
-import * as React from 'react';
-import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
-import {
- createBitbucketCloudConfiguration,
- createBitbucketConfiguration,
- updateBitbucketCloudConfiguration,
- updateBitbucketConfiguration
-} from '../../../../../api/alm-settings';
-import {
- mockBitbucketBindingDefinition,
- mockBitbucketCloudBindingDefinition
-} from '../../../../../helpers/mocks/alm-settings';
-import { AlmKeys } from '../../../../../types/alm-settings';
-import BitbucketTab, { DEFAULT_CLOUD_BINDING, DEFAULT_SERVER_BINDING } from '../BitbucketTab';
-
-jest.mock('../../../../../api/alm-settings', () => ({
- createBitbucketConfiguration: jest.fn().mockResolvedValue(null),
- createBitbucketCloudConfiguration: jest.fn().mockResolvedValue(null),
- updateBitbucketConfiguration: jest.fn().mockResolvedValue(null),
- updateBitbucketCloudConfiguration: jest.fn().mockResolvedValue(null)
-}));
-
-it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should handle cancel', async () => {
- const wrapper = shallowRender();
-
- wrapper.setState({
- editedDefinition: mockBitbucketBindingDefinition()
- });
-
- wrapper.instance().handleCancel();
-
- await waitAndUpdate(wrapper);
-
- expect(wrapper.state().editedDefinition).toBeUndefined();
-});
-
-it('should handle edit', async () => {
- const config = mockBitbucketBindingDefinition();
- const wrapper = shallowRender({ definitions: [config] });
- wrapper.instance().handleEdit(config.key);
- await waitAndUpdate(wrapper);
- expect(wrapper.state().editedDefinition).toEqual(config);
-});
-
-it('should create config for Bitbucket Server', async () => {
- const onUpdateDefinitions = jest.fn();
- const config = mockBitbucketBindingDefinition();
- const wrapper = shallowRender({ onUpdateDefinitions });
-
- wrapper.instance().handleCreate();
- wrapper.instance().handleSelectVariant(AlmKeys.BitbucketServer);
- expect(wrapper.state().editedDefinition).toBe(DEFAULT_SERVER_BINDING);
-
- wrapper.setState({ editedDefinition: config });
- await wrapper.instance().handleSubmit(config, '');
-
- expect(createBitbucketConfiguration).toBeCalledWith(config);
- expect(onUpdateDefinitions).toBeCalled();
- expect(wrapper.state().editedDefinition).toBeUndefined();
-});
-
-it('should create config for Bitbucket Cloud', async () => {
- const onUpdateDefinitions = jest.fn();
- const config = mockBitbucketCloudBindingDefinition();
- const wrapper = shallowRender({ onUpdateDefinitions });
-
- wrapper.instance().handleCreate();
- wrapper.instance().handleSelectVariant(AlmKeys.BitbucketCloud);
- expect(wrapper.state().editedDefinition).toBe(DEFAULT_CLOUD_BINDING);
-
- wrapper.setState({ editedDefinition: config });
- await wrapper.instance().handleSubmit(config, '');
-
- expect(createBitbucketCloudConfiguration).toBeCalledWith(config);
- expect(onUpdateDefinitions).toBeCalled();
- expect(wrapper.state().editedDefinition).toBeUndefined();
-});
-
-it('should update config for Bitbucket Server', async () => {
- const onUpdateDefinitions = jest.fn();
- const config = mockBitbucketBindingDefinition();
- const wrapper = shallowRender({ onUpdateDefinitions });
- wrapper.setState({ editedDefinition: config });
-
- await wrapper.instance().handleSubmit(config, 'originalKey');
-
- expect(updateBitbucketConfiguration).toBeCalledWith({
- newKey: 'key',
- ...config,
- key: 'originalKey'
- });
- expect(onUpdateDefinitions).toBeCalled();
- expect(wrapper.state().editedDefinition).toBeUndefined();
-});
-
-it('should update config for Bitbucket Cloud', async () => {
- const onUpdateDefinitions = jest.fn();
- const config = mockBitbucketCloudBindingDefinition();
- const wrapper = shallowRender({ onUpdateDefinitions });
- wrapper.setState({ editedDefinition: config });
-
- await wrapper.instance().handleSubmit(config, 'originalKey');
-
- expect(updateBitbucketCloudConfiguration).toBeCalledWith({
- newKey: 'key',
- ...config,
- key: 'originalKey'
- });
- expect(onUpdateDefinitions).toBeCalled();
- expect(wrapper.state().editedDefinition).toBeUndefined();
-});
-
-function shallowRender(props: Partial<BitbucketTab['props']> = {}) {
- return shallow<BitbucketTab>(
- <BitbucketTab
- branchesEnabled={true}
- definitions={[mockBitbucketBindingDefinition()]}
- definitionStatus={{}}
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCheck={jest.fn()}
- onDelete={jest.fn()}
- onUpdateDefinitions={jest.fn()}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketTabRenderer-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketTabRenderer-test.tsx
deleted file mode 100644
index 09ac75ce188..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketTabRenderer-test.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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 { mockBitbucketBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
-import { AlmKeys, BitbucketBindingDefinition } from '../../../../../types/alm-settings';
-import AlmTabRenderer, { AlmTabRendererProps } from '../AlmTabRenderer';
-import BitbucketTabRenderer, { BitbucketTabRendererProps } from '../BitbucketTabRenderer';
-
-it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot('default');
- expect(shallowRender({ variant: AlmKeys.BitbucketServer })).toMatchSnapshot('bitbucket server');
- expect(shallowRender({ variant: AlmKeys.BitbucketCloud })).toMatchSnapshot('bitbucket cloud');
-
- const almTab = shallowRender().find<AlmTabRendererProps<BitbucketBindingDefinition>>(
- AlmTabRenderer
- );
- expect(
- almTab.props().form({ formData: mockBitbucketBindingDefinition(), onFieldChange: jest.fn() })
- ).toMatchSnapshot('bitbucket form');
-});
-
-function shallowRender(props: Partial<BitbucketTabRendererProps> = {}) {
- return shallow<BitbucketTabRendererProps>(
- <BitbucketTabRenderer
- branchesEnabled={true}
- definitions={[]}
- definitionStatus={{}}
- isCreating={false}
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCancel={jest.fn()}
- onCheck={jest.fn()}
- onCreate={jest.fn()}
- onDelete={jest.fn()}
- onEdit={jest.fn()}
- onSelectVariant={jest.fn()}
- onSubmit={jest.fn()}
- submitting={true}
- success={false}
- variant={undefined}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GitlabTab-test.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GitlabTab-test.tsx
deleted file mode 100644
index a3a9b6e80a3..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GitlabTab-test.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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 { mockGitlabBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
-import GitlabTab, { GitlabTabProps } from '../GitlabTab';
-
-it('should render correctly', () => {
- expect(shallowRender()).toMatchSnapshot('with branch support');
- expect(
- shallowRender({
- definitions: [mockGitlabBindingDefinition({ url: 'https://gitlab.com/api/v4' })]
- })
- ).toMatchSnapshot('with URL');
- expect(
- shallowRender({
- definitions: []
- })
- ).toMatchSnapshot('with no definitions');
-});
-
-function shallowRender(props: Partial<GitlabTabProps> = {}) {
- return shallow(
- <GitlabTab
- branchesEnabled={true}
- definitions={[mockGitlabBindingDefinition()]}
- definitionStatus={{}}
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCheck={jest.fn()}
- onDelete={jest.fn()}
- onUpdateDefinitions={jest.fn()}
- {...props}
- />
- );
-}
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 525258ed31d..edd60829d06 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,21 +1,49 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render correctly: create 1`] = `
-<AlmBindingDefinitionFormModalRenderer
- action="create"
- canSubmit={[Function]}
- isSecondInstance={false}
+<AlmBindingDefinitionFormRenderer
+ alm="github"
+ alreadyHaveInstanceConfigured={false}
+ canSubmit={false}
+ formData={
+ Object {
+ "appId": "",
+ "clientId": "",
+ "clientSecret": "",
+ "key": "",
+ "privateKey": "",
+ "url": "",
+ }
+ }
+ isUpdate={false}
+ onBitbucketVariantChange={[Function]}
onCancel={[Function]}
+ onFieldChange={[Function]}
onSubmit={[Function]}
+ submitting={false}
/>
`;
exports[`should render correctly: edit 1`] = `
-<AlmBindingDefinitionFormModalRenderer
- action="edit"
- canSubmit={[Function]}
- isSecondInstance={false}
+<AlmBindingDefinitionFormRenderer
+ alm="github"
+ alreadyHaveInstanceConfigured={false}
+ canSubmit={false}
+ formData={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
+ }
+ isUpdate={true}
+ onBitbucketVariantChange={[Function]}
onCancel={[Function]}
+ onFieldChange={[Function]}
onSubmit={[Function]}
+ submitting={false}
/>
`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormModalRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormModalRenderer-test.tsx.snap
deleted file mode 100644
index a5410979b1b..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormModalRenderer-test.tsx.snap
+++ /dev/null
@@ -1,168 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<Modal
- contentLabel="settings.almintegration.form.header.create"
- onRequestClose={[MockFunction]}
- shouldCloseOnOverlayClick={false}
- size="medium"
->
- <form
- className="views-form"
- onSubmit={[Function]}
- >
- <div
- className="modal-head"
- >
- <h2>
- settings.almintegration.form.header.create
- </h2>
- </div>
- <div
- className="modal-body modal-container"
- >
- <div
- className="display-flex-start"
- >
- <div
- className="flex-1"
- >
- <Component />
- </div>
- <div
- className="flex-1"
- />
- </div>
- </div>
- <div
- className="modal-foot"
- >
- <SubmitButton
- disabled={true}
- >
- settings.almintegration.form.save
- </SubmitButton>
- <ResetButtonLink
- onClick={[MockFunction]}
- >
- cancel
- </ResetButtonLink>
- </div>
- </form>
-</Modal>
-`;
-
-exports[`should render correctly: second instance 1`] = `
-<Modal
- contentLabel="settings.almintegration.form.header.create"
- onRequestClose={[MockFunction]}
- shouldCloseOnOverlayClick={false}
- size="medium"
->
- <form
- className="views-form"
- onSubmit={[Function]}
- >
- <div
- className="modal-head"
- >
- <h2>
- settings.almintegration.form.header.create
- </h2>
- </div>
- <div
- className="modal-body modal-container"
- >
- <Alert
- className="big-spacer-bottom"
- variant="warning"
- >
- settings.almintegration.form.second_instance_warning
- </Alert>
- <div
- className="display-flex-start"
- >
- <div
- className="flex-1"
- >
- <Component />
- </div>
- <div
- className="flex-1"
- />
- </div>
- </div>
- <div
- className="modal-foot"
- >
- <SubmitButton
- disabled={true}
- >
- settings.almintegration.form.save
- </SubmitButton>
- <ResetButtonLink
- onClick={[MockFunction]}
- >
- cancel
- </ResetButtonLink>
- </div>
- </form>
-</Modal>
-`;
-
-exports[`should render correctly: with help 1`] = `
-<Modal
- contentLabel="settings.almintegration.form.header.create"
- onRequestClose={[MockFunction]}
- shouldCloseOnOverlayClick={false}
- size="medium"
->
- <form
- className="views-form"
- onSubmit={[Function]}
- >
- <div
- className="modal-head"
- >
- <h2>
- settings.almintegration.form.header.create
- </h2>
- </div>
- <div
- className="modal-body modal-container"
- >
- <div
- className="display-flex-start"
- >
- <div
- className="flex-1"
- >
- <Component />
- </div>
- <Alert
- className="huge-spacer-left flex-1"
- variant="info"
- >
- <span>
- Help me
- </span>
- </Alert>
- </div>
- </div>
- <div
- className="modal-foot"
- >
- <SubmitButton
- disabled={true}
- >
- settings.almintegration.form.save
- </SubmitButton>
- <ResetButtonLink
- onClick={[MockFunction]}
- >
- cancel
- </ResetButtonLink>
- </div>
- </form>
-</Modal>
-`;
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
new file mode 100644
index 00000000000..ef718f37281
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormRenderer-test.tsx.snap
@@ -0,0 +1,466 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Modal
+ contentLabel="settings.almintegration.form.header.create"
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+ size="medium"
+>
+ <form
+ className="views-form"
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-head"
+ >
+ <h2>
+ settings.almintegration.form.header.create
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <GithubForm
+ formData={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <SubmitButton
+ disabled={true}
+ >
+ settings.almintegration.form.save
+ <DeferredSpinner
+ className="spacer-left"
+ loading={false}
+ />
+ </SubmitButton>
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ cancel
+ </ResetButtonLink>
+ </div>
+ </form>
+</Modal>
+`;
+
+exports[`should render correctly for azure 1`] = `
+<Modal
+ contentLabel="settings.almintegration.form.header.create"
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+ size="medium"
+>
+ <form
+ className="views-form"
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-head"
+ >
+ <h2>
+ settings.almintegration.form.header.create
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <AzureForm
+ formData={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <SubmitButton
+ disabled={true}
+ >
+ settings.almintegration.form.save
+ <DeferredSpinner
+ className="spacer-left"
+ loading={false}
+ />
+ </SubmitButton>
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ cancel
+ </ResetButtonLink>
+ </div>
+ </form>
+</Modal>
+`;
+
+exports[`should render correctly for bitbucket 1`] = `
+<Modal
+ contentLabel="settings.almintegration.form.header.create"
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+ size="medium"
+>
+ <form
+ className="views-form"
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-head"
+ >
+ <h2>
+ settings.almintegration.form.header.create
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <BitbucketForm
+ formData={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
+ }
+ isUpdate={false}
+ onFieldChange={[MockFunction]}
+ onVariantChange={[MockFunction]}
+ variant="bitbucket"
+ />
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <SubmitButton
+ disabled={true}
+ >
+ settings.almintegration.form.save
+ <DeferredSpinner
+ className="spacer-left"
+ loading={false}
+ />
+ </SubmitButton>
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ cancel
+ </ResetButtonLink>
+ </div>
+ </form>
+</Modal>
+`;
+
+exports[`should render correctly for github 1`] = `
+<Modal
+ contentLabel="settings.almintegration.form.header.create"
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+ size="medium"
+>
+ <form
+ className="views-form"
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-head"
+ >
+ <h2>
+ settings.almintegration.form.header.create
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <GithubForm
+ formData={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <SubmitButton
+ disabled={true}
+ >
+ settings.almintegration.form.save
+ <DeferredSpinner
+ className="spacer-left"
+ loading={false}
+ />
+ </SubmitButton>
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ cancel
+ </ResetButtonLink>
+ </div>
+ </form>
+</Modal>
+`;
+
+exports[`should render correctly for gitlab 1`] = `
+<Modal
+ contentLabel="settings.almintegration.form.header.create"
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+ size="medium"
+>
+ <form
+ className="views-form"
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-head"
+ >
+ <h2>
+ settings.almintegration.form.header.create
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <GitlabForm
+ formData={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <SubmitButton
+ disabled={true}
+ >
+ settings.almintegration.form.save
+ <DeferredSpinner
+ className="spacer-left"
+ loading={false}
+ />
+ </SubmitButton>
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ cancel
+ </ResetButtonLink>
+ </div>
+ </form>
+</Modal>
+`;
+
+exports[`should render correctly: editing 1`] = `
+<Modal
+ contentLabel="settings.almintegration.form.header.edit"
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+ size="medium"
+>
+ <form
+ className="views-form"
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-head"
+ >
+ <h2>
+ settings.almintegration.form.header.edit
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <GithubForm
+ formData={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <SubmitButton
+ disabled={true}
+ >
+ settings.almintegration.form.save
+ <DeferredSpinner
+ className="spacer-left"
+ loading={false}
+ />
+ </SubmitButton>
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ cancel
+ </ResetButtonLink>
+ </div>
+ </form>
+</Modal>
+`;
+
+exports[`should render correctly: second instance 1`] = `
+<Modal
+ contentLabel="settings.almintegration.form.header.create"
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+ size="medium"
+>
+ <form
+ className="views-form"
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-head"
+ >
+ <h2>
+ settings.almintegration.form.header.create
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <Alert
+ className="big-spacer-bottom"
+ variant="warning"
+ >
+ settings.almintegration.form.second_instance_warning
+ </Alert>
+ <GithubForm
+ formData={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <SubmitButton
+ disabled={true}
+ >
+ settings.almintegration.form.save
+ <DeferredSpinner
+ className="spacer-left"
+ loading={false}
+ />
+ </SubmitButton>
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ cancel
+ </ResetButtonLink>
+ </div>
+ </form>
+</Modal>
+`;
+
+exports[`should render correctly: submitting 1`] = `
+<Modal
+ contentLabel="settings.almintegration.form.header.create"
+ onRequestClose={[MockFunction]}
+ shouldCloseOnOverlayClick={false}
+ size="medium"
+>
+ <form
+ className="views-form"
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-head"
+ >
+ <h2>
+ settings.almintegration.form.header.create
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <GithubForm
+ formData={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <SubmitButton
+ disabled={true}
+ >
+ settings.almintegration.form.save
+ <DeferredSpinner
+ className="spacer-left"
+ loading={true}
+ />
+ </SubmitButton>
+ <ResetButtonLink
+ onClick={[MockFunction]}
+ >
+ cancel
+ </ResetButtonLink>
+ </div>
+ </form>
+</Modal>
+`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegration-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegration-test.tsx.snap
index 2494c7dca20..193dfaf0360 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegration-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegration-test.tsx.snap
@@ -3,7 +3,7 @@
exports[`should render correctly 1`] = `
<AlmIntegrationRenderer
branchesEnabled={true}
- currentAlm="github"
+ currentAlmTab="github"
definitionStatus={Object {}}
definitions={
Object {
@@ -17,11 +17,11 @@ exports[`should render correctly 1`] = `
loadingAlmDefinitions={true}
loadingProjectCount={false}
multipleAlmEnabled={false}
- onCancel={[Function]}
- onCheck={[Function]}
+ onCancelDelete={[Function]}
+ onCheckConfiguration={[Function]}
onConfirmDelete={[Function]}
onDelete={[Function]}
- onSelectAlm={[Function]}
+ onSelectAlmTab={[Function]}
onUpdateDefinitions={[Function]}
/>
`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationRenderer-test.tsx.snap
index 14df1c80a7a..dbbe5ea825c 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationRenderer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationRenderer-test.tsx.snap
@@ -32,7 +32,6 @@ exports[`should render correctly: azure 1`] = `
/>
GitHub
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "bitbucket",
@@ -45,7 +44,6 @@ exports[`should render correctly: azure 1`] = `
/>
Bitbucket
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "azure",
@@ -58,7 +56,6 @@ exports[`should render correctly: azure 1`] = `
/>
Azure DevOps
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "gitlab",
@@ -71,12 +68,12 @@ exports[`should render correctly: azure 1`] = `
/>
GitLab
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
]
}
/>
- <AzureTab
+ <AlmTab
+ almTab="azure"
branchesEnabled={true}
definitionStatus={Object {}}
definitions={Array []}
@@ -122,7 +119,6 @@ exports[`should render correctly: bitbucket 1`] = `
/>
GitHub
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "bitbucket",
@@ -135,7 +131,6 @@ exports[`should render correctly: bitbucket 1`] = `
/>
Bitbucket
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "azure",
@@ -148,7 +143,6 @@ exports[`should render correctly: bitbucket 1`] = `
/>
Azure DevOps
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "gitlab",
@@ -161,12 +155,12 @@ exports[`should render correctly: bitbucket 1`] = `
/>
GitLab
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
]
}
/>
- <BitbucketTab
+ <AlmTab
+ almTab="bitbucket"
branchesEnabled={true}
definitionStatus={Object {}}
definitions={Array []}
@@ -180,85 +174,6 @@ exports[`should render correctly: bitbucket 1`] = `
</Fragment>
`;
-exports[`should render correctly: bitbucketcloud 1`] = `
-<Fragment>
- <header
- className="page-header"
- >
- <h1
- className="page-title"
- >
- settings.almintegration.title
- </h1>
- </header>
- <div
- className="markdown small spacer-top big-spacer-bottom"
- >
- settings.almintegration.description
- </div>
- <BoxedTabs
- onSelect={[MockFunction]}
- selected="bitbucketcloud"
- tabs={
- Array [
- Object {
- "key": "github",
- "label": <React.Fragment>
- <img
- alt="github"
- className="spacer-right"
- height={16}
- src="/images/alm/github.svg"
- />
- GitHub
- </React.Fragment>,
- "requiresBranchesEnabled": false,
- },
- Object {
- "key": "bitbucket",
- "label": <React.Fragment>
- <img
- alt="bitbucket"
- className="spacer-right"
- height={16}
- src="/images/alm/bitbucket.svg"
- />
- Bitbucket
- </React.Fragment>,
- "requiresBranchesEnabled": false,
- },
- Object {
- "key": "azure",
- "label": <React.Fragment>
- <img
- alt="azure"
- className="spacer-right"
- height={16}
- src="/images/alm/azure.svg"
- />
- Azure DevOps
- </React.Fragment>,
- "requiresBranchesEnabled": false,
- },
- Object {
- "key": "gitlab",
- "label": <React.Fragment>
- <img
- alt="gitlab"
- className="spacer-right"
- height={16}
- src="/images/alm/gitlab.svg"
- />
- GitLab
- </React.Fragment>,
- "requiresBranchesEnabled": false,
- },
- ]
- }
- />
-</Fragment>
-`;
-
exports[`should render correctly: default 1`] = `
<Fragment>
<header
@@ -291,7 +206,6 @@ exports[`should render correctly: default 1`] = `
/>
GitHub
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "bitbucket",
@@ -304,7 +218,6 @@ exports[`should render correctly: default 1`] = `
/>
Bitbucket
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "azure",
@@ -317,7 +230,6 @@ exports[`should render correctly: default 1`] = `
/>
Azure DevOps
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "gitlab",
@@ -330,12 +242,12 @@ exports[`should render correctly: default 1`] = `
/>
GitLab
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
]
}
/>
- <GithubTab
+ <AlmTab
+ almTab="github"
branchesEnabled={true}
definitionStatus={Object {}}
definitions={Array []}
@@ -381,7 +293,6 @@ exports[`should render correctly: delete modal 1`] = `
/>
GitHub
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "bitbucket",
@@ -394,7 +305,6 @@ exports[`should render correctly: delete modal 1`] = `
/>
Bitbucket
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "azure",
@@ -407,7 +317,6 @@ exports[`should render correctly: delete modal 1`] = `
/>
Azure DevOps
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "gitlab",
@@ -420,12 +329,12 @@ exports[`should render correctly: delete modal 1`] = `
/>
GitLab
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
]
}
/>
- <GithubTab
+ <AlmTab
+ almTab="github"
branchesEnabled={true}
definitionStatus={Object {}}
definitions={Array []}
@@ -476,7 +385,6 @@ exports[`should render correctly: gitlab 1`] = `
/>
GitHub
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "bitbucket",
@@ -489,7 +397,6 @@ exports[`should render correctly: gitlab 1`] = `
/>
Bitbucket
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "azure",
@@ -502,7 +409,6 @@ exports[`should render correctly: gitlab 1`] = `
/>
Azure DevOps
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "gitlab",
@@ -515,12 +421,12 @@ exports[`should render correctly: gitlab 1`] = `
/>
GitLab
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
]
}
/>
- <GitlabTab
+ <AlmTab
+ almTab="gitlab"
branchesEnabled={true}
definitionStatus={Object {}}
definitions={Array []}
@@ -566,7 +472,6 @@ exports[`should render correctly: loading 1`] = `
/>
GitHub
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "bitbucket",
@@ -579,7 +484,6 @@ exports[`should render correctly: loading 1`] = `
/>
Bitbucket
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "azure",
@@ -592,7 +496,6 @@ exports[`should render correctly: loading 1`] = `
/>
Azure DevOps
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
Object {
"key": "gitlab",
@@ -605,12 +508,12 @@ exports[`should render correctly: loading 1`] = `
/>
GitLab
</React.Fragment>,
- "requiresBranchesEnabled": false,
},
]
}
/>
- <GithubTab
+ <AlmTab
+ almTab="github"
branchesEnabled={true}
definitionStatus={Object {}}
definitions={Array []}
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 9822401deaf..ae9342d08d0 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,7 +2,8 @@
exports[`should render correctly 1`] = `
<AlmTabRenderer
- alm="azure"
+ afterSubmit={[Function]}
+ almTab="azure"
branchesEnabled={true}
definitionStatus={Object {}}
definitions={
@@ -13,8 +14,6 @@ exports[`should render correctly 1`] = `
},
]
}
- form={[MockFunction]}
- help={<div />}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={true}
@@ -23,8 +22,5 @@ exports[`should render correctly 1`] = `
onCreate={[Function]}
onDelete={[MockFunction]}
onEdit={[Function]}
- onSubmit={[Function]}
- submitting={false}
- success={false}
/>
`;
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 f0ff2da8675..a6d97e1ac03 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
@@ -2,586 +2,674 @@
exports[`should render correctly for multi-ALM binding: editing a definition 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="azure"
- preventCreation={false}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={false}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={false}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="azure"
- branchesEnabled={true}
- definition={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
+ <Button
+ data-test="settings__alm-create"
+ disabled={false}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
+ alm="azure"
+ branchesEnabled={true}
+ definition={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
/>
- <AlmBindingDefinitionForm
- bindingDefinition={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- }
- }
- help={<div />}
- isSecondInstance={true}
- onCancel={[MockFunction]}
- onSubmit={[MockFunction]}
- >
- <Component />
- </AlmBindingDefinitionForm>
- </DeferredSpinner>
+ </div>
</div>
`;
exports[`should render correctly for multi-ALM binding: loaded 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="azure"
- preventCreation={false}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={false}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={false}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="azure"
- branchesEnabled={true}
- definition={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
+ <Button
+ data-test="settings__alm-create"
+ disabled={false}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
+ alm="azure"
+ branchesEnabled={true}
+ definition={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
/>
- </DeferredSpinner>
+ </div>
</div>
`;
exports[`should render correctly for multi-ALM binding: loading ALM definitions 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={true}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={true}
>
- <Connect(withAppState(CreationTooltip))
- alm="azure"
- preventCreation={false}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={false}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={false}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="azure"
- branchesEnabled={true}
- definition={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
+ <Button
+ data-test="settings__alm-create"
+ disabled={false}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
+ alm="azure"
+ branchesEnabled={true}
+ definition={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
/>
- </DeferredSpinner>
+ </div>
</div>
`;
exports[`should render correctly for multi-ALM binding: loading project count 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="azure"
- preventCreation={true}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={true}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={true}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="azure"
- branchesEnabled={true}
- definition={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- }
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- />
- </DeferredSpinner>
-</div>
-`;
-
-exports[`should render correctly for multi-ALM binding: submitting 1`] = `
-<div
- className="big-padded"
->
- <DeferredSpinner
- loading={false}
- >
- <div
- className="spacer-bottom text-right"
- >
- <Connect(withAppState(CreationTooltip))
+ <Button
+ data-test="settings__alm-create"
+ disabled={true}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
alm="azure"
- preventCreation={false}
- >
- <Button
- data-test="settings__alm-create"
- disabled={false}
- onClick={[MockFunction]}
- >
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="azure"
- branchesEnabled={true}
- definition={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
+ branchesEnabled={true}
+ definition={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
/>
- </DeferredSpinner>
+ </div>
</div>
`;
exports[`should render correctly for single-ALM binding 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={true}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={true}
>
- <Connect(withAppState(CreationTooltip))
- alm="azure"
- preventCreation={true}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={true}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={true}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="azure"
- branchesEnabled={true}
- definition={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
+ <Button
+ data-test="settings__alm-create"
+ disabled={true}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
+ alm="azure"
+ branchesEnabled={true}
+ definition={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
/>
- </DeferredSpinner>
+ </div>
</div>
`;
exports[`should render correctly for single-ALM binding 2`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="azure"
- preventCreation={true}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={true}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={true}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="azure"
- branchesEnabled={true}
- definition={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
+ <Button
+ data-test="settings__alm-create"
+ disabled={true}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
+ alm="azure"
+ branchesEnabled={true}
+ definition={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
/>
- </DeferredSpinner>
+ </div>
</div>
`;
exports[`should render correctly for single-ALM binding 3`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="azure"
- preventCreation={true}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={true}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={true}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="azure"
- branchesEnabled={true}
- definition={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
+ <Button
+ data-test="settings__alm-create"
+ disabled={true}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
+ alm="azure"
+ branchesEnabled={true}
+ definition={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
/>
- </DeferredSpinner>
+ </div>
</div>
`;
exports[`should render correctly with validation: create a first 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <p
- className="spacer-top"
- >
- settings.almintegration.empty.github
- </p>
- <div
- className="big-spacer-top"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="github"
- preventCreation={false}
+ <p
+ className="spacer-top"
+ >
+ settings.almintegration.empty.azure
+ </p>
+ <div
+ className="big-spacer-top"
>
- <Button
- data-test="settings__alm-create"
- disabled={false}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={false}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionForm
- bindingDefinition={
- Object {
- "appId": "123456",
- "clientId": "client1",
- "clientSecret": "**clientsecret**",
- "key": "key",
- "privateKey": "asdf1234",
- "url": "http://github.enterprise.com",
- }
- }
- help={<div />}
- isSecondInstance={false}
- onCancel={[MockFunction]}
- onSubmit={[MockFunction]}
- >
- <Component />
- </AlmBindingDefinitionForm>
- </DeferredSpinner>
+ <Button
+ data-test="settings__alm-create"
+ disabled={false}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
+ />
+ </div>
</div>
`;
exports[`should render correctly with validation: create a second 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="github"
- preventCreation={false}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={false}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={false}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="github"
- branchesEnabled={true}
- definition={
- Object {
- "appId": "123456",
- "clientId": "client1",
- "clientSecret": "**clientsecret**",
- "key": "key",
- "privateKey": "asdf1234",
- "url": "http://github.enterprise.com",
+ <Button
+ data-test="settings__alm-create"
+ disabled={false}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
+ alm="azure"
+ branchesEnabled={true}
+ definition={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
/>
- <AlmBindingDefinitionForm
- bindingDefinition={
- Object {
- "appId": "123456",
- "clientId": "client1",
- "clientSecret": "**clientsecret**",
- "key": "key",
- "privateKey": "asdf1234",
- "url": "http://github.enterprise.com",
- }
- }
- help={<div />}
- isSecondInstance={true}
- onCancel={[MockFunction]}
- onSubmit={[MockFunction]}
- >
- <Component />
- </AlmBindingDefinitionForm>
- </DeferredSpinner>
+ </div>
</div>
`;
exports[`should render correctly with validation: default 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="github"
- preventCreation={false}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={false}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={false}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="github"
- branchesEnabled={true}
- definition={
- Object {
- "appId": "123456",
- "clientId": "client1",
- "clientSecret": "**clientsecret**",
- "key": "key",
- "privateKey": "asdf1234",
- "url": "http://github.enterprise.com",
+ <Button
+ data-test="settings__alm-create"
+ disabled={false}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
+ alm="azure"
+ branchesEnabled={true}
+ definition={
+ Object {
+ "appId": "123456",
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "privateKey": "asdf1234",
+ "url": "http://github.enterprise.com",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
/>
- </DeferredSpinner>
+ </div>
</div>
`;
exports[`should render correctly with validation: empty 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <p
- className="spacer-top"
- >
- settings.almintegration.empty.github
- </p>
- <div
- className="big-spacer-top"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="github"
- preventCreation={false}
+ <p
+ className="spacer-top"
+ >
+ settings.almintegration.empty.azure
+ </p>
+ <div
+ className="big-spacer-top"
>
- <Button
- data-test="settings__alm-create"
- disabled={false}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="azure"
+ preventCreation={false}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- </DeferredSpinner>
+ <Button
+ data-test="settings__alm-create"
+ disabled={false}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="azure"
+ />
+ </div>
</div>
`;
exports[`should render correctly with validation: pass the correct key for bitbucket cloud 1`] = `
<div
- className="big-padded"
+ className="bordered"
>
- <DeferredSpinner
- loading={false}
+ <div
+ className="big-padded"
>
- <div
- className="spacer-bottom text-right"
+ <DeferredSpinner
+ loading={false}
>
- <Connect(withAppState(CreationTooltip))
- alm="bitbucket"
- preventCreation={false}
+ <div
+ className="spacer-bottom text-right"
>
- <Button
- data-test="settings__alm-create"
- disabled={false}
- onClick={[MockFunction]}
+ <Connect(withAppState(CreationTooltip))
+ alm="bitbucket"
+ preventCreation={false}
>
- settings.almintegration.create
- </Button>
- </Connect(withAppState(CreationTooltip))>
- </div>
- <AlmBindingDefinitionBox
- alm="bitbucketcloud"
- branchesEnabled={true}
- definition={
- Object {
- "clientId": "client1",
- "clientSecret": "**clientsecret**",
- "key": "key",
- "workspace": "workspace",
+ <Button
+ data-test="settings__alm-create"
+ disabled={false}
+ onClick={[MockFunction]}
+ >
+ settings.almintegration.create
+ </Button>
+ </Connect(withAppState(CreationTooltip))>
+ </div>
+ <AlmBindingDefinitionBox
+ alm="bitbucketcloud"
+ branchesEnabled={true}
+ definition={
+ Object {
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "workspace": "workspace",
+ }
}
- }
- key="key"
- multipleDefinitions={false}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
+ key="key"
+ multipleDefinitions={false}
+ onCheck={[MockFunction]}
+ onDelete={[MockFunction]}
+ onEdit={[MockFunction]}
+ />
+ </DeferredSpinner>
+ </div>
+ <div
+ className="huge-spacer-top huge-spacer-bottom bordered-top"
+ />
+ <div
+ className="big-padded"
+ >
+ <Connect(SubCategoryDefinitionsList)
+ category="almintegration"
+ subCategory="bitbucket"
/>
- </DeferredSpinner>
+ </div>
</div>
`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap
index 69f49790db3..433536d09a7 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap
@@ -1,91 +1,145 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render correctly: create 1`] = `
-<Fragment>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.azure.help"
- id="name.azure"
- onFieldChange={[MockFunction]}
- propKey="key"
- value=""
- />
- <AlmBindingDefinitionFormField
- help={
- <React.Fragment>
- settings.almintegration.form.url.azure.help1
- <br />
- <em>
- https://ado.your-company.com/your_collection
- </em>
- <br />
- <br />
- settings.almintegration.form.url.azure.help2
- <br />
- <em>
- https://dev.azure.com/your_organization
- </em>
- </React.Fragment>
- }
- id="url.azure"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="url"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.personal_access_token.azure.help"
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={[MockFunction]}
- overwriteOnly={false}
- propKey="personalAccessToken"
- value=""
- />
-</Fragment>
+<div
+ className="display-flex-start"
+>
+ <div
+ className="flex-1"
+ >
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help="settings.almintegration.form.name.azure.help"
+ id="name.azure"
+ onFieldChange={[MockFunction]}
+ propKey="key"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <React.Fragment>
+ settings.almintegration.form.url.azure.help1
+ <br />
+ <em>
+ https://ado.your-company.com/your_collection
+ </em>
+ <br />
+ <br />
+ settings.almintegration.form.url.azure.help2
+ <br />
+ <em>
+ https://dev.azure.com/your_organization
+ </em>
+ </React.Fragment>
+ }
+ id="url.azure"
+ maxLength={2000}
+ onFieldChange={[MockFunction]}
+ propKey="url"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.personal_access_token.azure.help"
+ id="personal_access_token"
+ isTextArea={true}
+ onFieldChange={[MockFunction]}
+ overwriteOnly={false}
+ propKey="personalAccessToken"
+ value=""
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <FormattedMessage
+ defaultMessage="settings.almintegration.azure.info"
+ id="settings.almintegration.azure.info"
+ values={
+ Object {
+ "link": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/azuredevops-integration/"
+ >
+ learn_more
+ </Link>,
+ }
+ }
+ />
+ </Alert>
+</div>
`;
exports[`should render correctly: edit 1`] = `
-<Fragment>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.azure.help"
- id="name.azure"
- onFieldChange={[MockFunction]}
- propKey="key"
- value="key"
- />
- <AlmBindingDefinitionFormField
- help={
- <React.Fragment>
- settings.almintegration.form.url.azure.help1
- <br />
- <em>
- https://ado.your-company.com/your_collection
- </em>
- <br />
- <br />
- settings.almintegration.form.url.azure.help2
- <br />
- <em>
- https://dev.azure.com/your_organization
- </em>
- </React.Fragment>
- }
- id="url.azure"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="url"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.personal_access_token.azure.help"
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={[MockFunction]}
- overwriteOnly={true}
- propKey="personalAccessToken"
- value="asdf1234"
- />
-</Fragment>
+<div
+ className="display-flex-start"
+>
+ <div
+ className="flex-1"
+ >
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help="settings.almintegration.form.name.azure.help"
+ id="name.azure"
+ onFieldChange={[MockFunction]}
+ propKey="key"
+ value="key"
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <React.Fragment>
+ settings.almintegration.form.url.azure.help1
+ <br />
+ <em>
+ https://ado.your-company.com/your_collection
+ </em>
+ <br />
+ <br />
+ settings.almintegration.form.url.azure.help2
+ <br />
+ <em>
+ https://dev.azure.com/your_organization
+ </em>
+ </React.Fragment>
+ }
+ id="url.azure"
+ maxLength={2000}
+ onFieldChange={[MockFunction]}
+ propKey="url"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.personal_access_token.azure.help"
+ id="personal_access_token"
+ isTextArea={true}
+ onFieldChange={[MockFunction]}
+ overwriteOnly={true}
+ propKey="personalAccessToken"
+ value="asdf1234"
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <FormattedMessage
+ defaultMessage="settings.almintegration.azure.info"
+ id="settings.almintegration.azure.info"
+ values={
+ Object {
+ "link": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/azuredevops-integration/"
+ >
+ learn_more
+ </Link>,
+ }
+ }
+ />
+ </Alert>
+</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
deleted file mode 100644
index b282c815654..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureTab-test.tsx.snap
+++ /dev/null
@@ -1,55 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<div
- className="bordered"
->
- <AlmTab
- alm="azure"
- branchesEnabled={true}
- createConfiguration={[Function]}
- defaultBinding={
- Object {
- "key": "",
- "personalAccessToken": "",
- "url": "",
- }
- }
- definitionStatus={Object {}}
- definitions={
- Array [
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- },
- ]
- }
- form={[Function]}
- 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/azuredevops-integration/"
- >
- learn_more
- </Link>,
- }
- }
- />
- }
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onUpdateDefinitions={[MockFunction]}
- updateConfiguration={[Function]}
- />
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketCloudForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketCloudForm-test.tsx.snap
new file mode 100644
index 00000000000..7ead8a21fcc
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketCloudForm-test.tsx.snap
@@ -0,0 +1,54 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help="settings.almintegration.form.name.bitbucketcloud.help"
+ id="name.bitbucket"
+ maxLength={100}
+ onFieldChange={[MockFunction]}
+ propKey="key"
+ value="key"
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <FormattedMessage
+ defaultMessage="settings.almintegration.form.workspace.bitbucketcloud.help"
+ id="settings.almintegration.form.workspace.bitbucketcloud.help"
+ values={
+ Object {
+ "example": <React.Fragment>
+ https://bitbucket.org/
+ <strong>
+ {workspace}
+ </strong>
+ /{repository}
+ </React.Fragment>,
+ }
+ }
+ />
+ }
+ id="workspace.bitbucketcloud"
+ maxLength={2000}
+ onFieldChange={[MockFunction]}
+ propKey="workspace"
+ value="workspace"
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.oauth_key.bitbucketcloud.help"
+ id="client_id.bitbucketcloud"
+ onFieldChange={[MockFunction]}
+ propKey="clientId"
+ value="client1"
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.oauth_secret.bitbucketcloud.help"
+ id="client_secret.bitbucketcloud"
+ onFieldChange={[MockFunction]}
+ overwriteOnly={true}
+ propKey="clientSecret"
+ value="**clientsecret**"
+ />
+</Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap
index 5a7f57de670..d8914665ebc 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap
@@ -1,310 +1,259 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should render correctly: bitbucket cloud, edit 1`] = `
-<div>
- <div>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.bitbucketcloud.help"
- id="name.bitbucket"
- maxLength={100}
- onFieldChange={[MockFunction]}
- propKey="key"
- value="key"
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.form.workspace.bitbucketcloud.help"
- id="settings.almintegration.form.workspace.bitbucketcloud.help"
- values={
- Object {
- "example": <React.Fragment>
- https://bitbucket.org/
- <strong>
- {workspace}
- </strong>
- /{repository}
- </React.Fragment>,
- }
- }
- />
+exports[`should render correctly: bbc 1`] = `
+<Fragment>
+ <div
+ className="display-flex-column"
+ >
+ <strong>
+ settings.almintegration.form.choose_bitbucket_variant
+ </strong>
+ <RadioToggle
+ className="little-spacer-top big-spacer-bottom"
+ disabled={false}
+ name="variant"
+ onCheck={[MockFunction]}
+ options={
+ Array [
+ Object {
+ "label": "Bitbucket Server",
+ "value": "bitbucket",
+ },
+ Object {
+ "label": "Bitbucket Cloud",
+ "value": "bitbucketcloud",
+ },
+ ]
}
- id="workspace.bitbucketcloud"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="workspace"
- value="workspace"
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.oauth_key.bitbucketcloud.help"
- id="client_id.bitbucketcloud"
- onFieldChange={[MockFunction]}
- propKey="clientId"
- value="client1"
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.oauth_secret.bitbucketcloud.help"
- id="client_secret.bitbucketcloud"
- onFieldChange={[MockFunction]}
- overwriteOnly={true}
- propKey="clientSecret"
- value="**clientsecret**"
+ value="bitbucketcloud"
/>
</div>
-</div>
-`;
-
-exports[`should render correctly: bitbucket cloud, empty 1`] = `
-<div>
- <div>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.bitbucketcloud.help"
- id="name.bitbucket"
- maxLength={100}
- onFieldChange={[MockFunction]}
- propKey="key"
- value=""
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.form.workspace.bitbucketcloud.help"
- id="settings.almintegration.form.workspace.bitbucketcloud.help"
- values={
- Object {
- "example": <React.Fragment>
- https://bitbucket.org/
- <strong>
- {workspace}
- </strong>
- /{repository}
- </React.Fragment>,
- }
+ <div
+ className="display-flex-start"
+ >
+ <div
+ className="flex-1"
+ >
+ <BitbucketCloudForm
+ formData={
+ Object {
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "workspace": "workspace",
}
- />
- }
- id="workspace.bitbucketcloud"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="workspace"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.oauth_key.bitbucketcloud.help"
- id="client_id.bitbucketcloud"
- onFieldChange={[MockFunction]}
- propKey="clientId"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.oauth_secret.bitbucketcloud.help"
- id="client_secret.bitbucketcloud"
- onFieldChange={[MockFunction]}
- overwriteOnly={false}
- propKey="clientSecret"
- value=""
- />
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <FormattedMessage
+ defaultMessage="settings.almintegration.bitbucketcloud.info"
+ id="settings.almintegration.bitbucketcloud.info"
+ values={
+ Object {
+ "link": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/bitbucket-cloud-integration/"
+ >
+ learn_more
+ </Link>,
+ }
+ }
+ />
+ </Alert>
</div>
-</div>
+</Fragment>
`;
-exports[`should render correctly: bitbucket server, edit 1`] = `
-<div>
- <div>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.bitbucket.help"
- id="name.bitbucket"
- maxLength={100}
- onFieldChange={[MockFunction]}
- propKey="key"
- value="key"
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.form.url.bitbucket.help"
- id="settings.almintegration.form.url.bitbucket.help"
- values={
- Object {
- "example": "https://bitbucket-server.your-company.com",
- }
- }
- />
+exports[`should render correctly: bbs 1`] = `
+<Fragment>
+ <div
+ className="display-flex-column"
+ >
+ <strong>
+ settings.almintegration.form.choose_bitbucket_variant
+ </strong>
+ <RadioToggle
+ className="little-spacer-top big-spacer-bottom"
+ disabled={false}
+ name="variant"
+ onCheck={[MockFunction]}
+ options={
+ Array [
+ Object {
+ "label": "Bitbucket Server",
+ "value": "bitbucket",
+ },
+ Object {
+ "label": "Bitbucket Cloud",
+ "value": "bitbucketcloud",
+ },
+ ]
}
- id="url.bitbucket"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="url"
- value="http://bbs.enterprise.com"
+ value="bitbucket"
/>
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.form.personal_access_token.bitbucket.help"
- id="settings.almintegration.form.personal_access_token.bitbucket.help"
- values={
- Object {
- "pat": <a
- href="https://confluence.atlassian.com/bitbucketserver0515/personal-access-tokens-961275199.html"
- rel="noopener noreferrer"
- target="_blank"
- >
- settings.almintegration.form.personal_access_token.bitbucket.help.url
- </a>,
- }
+ </div>
+ <div
+ className="display-flex-start"
+ >
+ <div
+ className="flex-1"
+ >
+ <BitbucketServerForm
+ formData={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ "url": "http://bbs.enterprise.com",
}
- />
- }
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={[MockFunction]}
- overwriteOnly={true}
- propKey="personalAccessToken"
- value="asdf1234"
- />
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <h3>
+ onboarding.create_project.pat_help.title
+ </h3>
+ <p
+ className="big-spacer-top"
+ >
+ settings.almintegration.bitbucket.help_1
+ </p>
+ <ul
+ className="big-spacer-top list-styled"
+ >
+ <li>
+ settings.almintegration.bitbucket.help_2
+ </li>
+ <li>
+ settings.almintegration.bitbucket.help_3
+ </li>
+ </ul>
+ <p
+ className="big-spacer-top big-spacer-bottom"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/bitbucket-integration/"
+ >
+ learn_more
+ </Link>
+ </p>
+ </Alert>
</div>
-</div>
+</Fragment>
`;
-exports[`should render correctly: bitbucket server, empty 1`] = `
-<div>
- <div>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.bitbucket.help"
- id="name.bitbucket"
- maxLength={100}
- onFieldChange={[MockFunction]}
- propKey="key"
- value=""
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.form.url.bitbucket.help"
- id="settings.almintegration.form.url.bitbucket.help"
- values={
- Object {
- "example": "https://bitbucket-server.your-company.com",
- }
+exports[`should render correctly: update bbc 1`] = `
+<Fragment>
+ <div
+ className="display-flex-start"
+ >
+ <div
+ className="flex-1"
+ >
+ <BitbucketCloudForm
+ formData={
+ Object {
+ "clientId": "client1",
+ "clientSecret": "**clientsecret**",
+ "key": "key",
+ "workspace": "workspace",
}
- />
- }
- id="url.bitbucket"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="url"
- value=""
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.form.personal_access_token.bitbucket.help"
- id="settings.almintegration.form.personal_access_token.bitbucket.help"
- values={
- Object {
- "pat": <a
- href="https://confluence.atlassian.com/bitbucketserver0515/personal-access-tokens-961275199.html"
- rel="noopener noreferrer"
- target="_blank"
- >
- settings.almintegration.form.personal_access_token.bitbucket.help.url
- </a>,
- }
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <FormattedMessage
+ defaultMessage="settings.almintegration.bitbucketcloud.info"
+ id="settings.almintegration.bitbucketcloud.info"
+ values={
+ Object {
+ "link": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/bitbucket-cloud-integration/"
+ >
+ learn_more
+ </Link>,
}
- />
- }
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={[MockFunction]}
- overwriteOnly={false}
- propKey="personalAccessToken"
- value=""
- />
+ }
+ />
+ </Alert>
</div>
-</div>
+</Fragment>
`;
-exports[`should render correctly: variant select 1`] = `
-<div>
- <strong>
- settings.almintegration.form.choose_bitbucket_variant
- </strong>
- <RadioToggle
- className="little-spacer-top big-spacer-bottom"
- disabled={false}
- name="variant"
- onCheck={[MockFunction]}
- options={
- Array [
- Object {
- "label": "Bitbucket Server",
- "value": "bitbucket",
- },
- Object {
- "label": "Bitbucket Cloud",
- "value": "bitbucketcloud",
- },
- ]
- }
- value="bitbucket"
- />
- <div>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.bitbucket.help"
- id="name.bitbucket"
- maxLength={100}
- onFieldChange={[MockFunction]}
- propKey="key"
- value=""
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.form.url.bitbucket.help"
- id="settings.almintegration.form.url.bitbucket.help"
- values={
- Object {
- "example": "https://bitbucket-server.your-company.com",
- }
+exports[`should render correctly: update bbs 1`] = `
+<Fragment>
+ <div
+ className="display-flex-start"
+ >
+ <div
+ className="flex-1"
+ >
+ <BitbucketServerForm
+ formData={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ "url": "http://bbs.enterprise.com",
}
- />
- }
- id="url.bitbucket"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="url"
- value=""
- />
- <AlmBindingDefinitionFormField
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.form.personal_access_token.bitbucket.help"
- id="settings.almintegration.form.personal_access_token.bitbucket.help"
- values={
- Object {
- "pat": <a
- href="https://confluence.atlassian.com/bitbucketserver0515/personal-access-tokens-961275199.html"
- rel="noopener noreferrer"
- target="_blank"
- >
- settings.almintegration.form.personal_access_token.bitbucket.help.url
- </a>,
- }
- }
- />
- }
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={[MockFunction]}
- overwriteOnly={false}
- propKey="personalAccessToken"
- value=""
- />
+ }
+ onFieldChange={[MockFunction]}
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <h3>
+ onboarding.create_project.pat_help.title
+ </h3>
+ <p
+ className="big-spacer-top"
+ >
+ settings.almintegration.bitbucket.help_1
+ </p>
+ <ul
+ className="big-spacer-top list-styled"
+ >
+ <li>
+ settings.almintegration.bitbucket.help_2
+ </li>
+ <li>
+ settings.almintegration.bitbucket.help_3
+ </li>
+ </ul>
+ <p
+ className="big-spacer-top big-spacer-bottom"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/bitbucket-integration/"
+ >
+ learn_more
+ </Link>
+ </p>
+ </Alert>
</div>
-</div>
+</Fragment>
`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketServerForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketServerForm-test.tsx.snap
new file mode 100644
index 00000000000..718829ab486
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketServerForm-test.tsx.snap
@@ -0,0 +1,59 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help="settings.almintegration.form.name.bitbucket.help"
+ id="name.bitbucket"
+ maxLength={100}
+ onFieldChange={[MockFunction]}
+ propKey="key"
+ value="key"
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <FormattedMessage
+ defaultMessage="settings.almintegration.form.url.bitbucket.help"
+ id="settings.almintegration.form.url.bitbucket.help"
+ values={
+ Object {
+ "example": "https://bitbucket-server.your-company.com",
+ }
+ }
+ />
+ }
+ id="url.bitbucket"
+ maxLength={2000}
+ onFieldChange={[MockFunction]}
+ propKey="url"
+ value="http://bbs.enterprise.com"
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <FormattedMessage
+ defaultMessage="settings.almintegration.form.personal_access_token.bitbucket.help"
+ id="settings.almintegration.form.personal_access_token.bitbucket.help"
+ values={
+ Object {
+ "pat": <a
+ href="https://confluence.atlassian.com/bitbucketserver0515/personal-access-tokens-961275199.html"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ settings.almintegration.form.personal_access_token.bitbucket.help.url
+ </a>,
+ }
+ }
+ />
+ }
+ id="personal_access_token"
+ isTextArea={true}
+ onFieldChange={[MockFunction]}
+ overwriteOnly={true}
+ propKey="personalAccessToken"
+ value="asdf1234"
+ />
+</Fragment>
+`;
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
deleted file mode 100644
index 8100d78442d..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTab-test.tsx.snap
+++ /dev/null
@@ -1,30 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<BitbucketTabRenderer
- branchesEnabled={true}
- definitionStatus={Object {}}
- definitions={
- Array [
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- "url": "http://bbs.enterprise.com",
- },
- ]
- }
- isCreating={false}
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCancel={[Function]}
- onCheck={[MockFunction]}
- onCreate={[Function]}
- onDelete={[MockFunction]}
- onEdit={[Function]}
- onSelectVariant={[Function]}
- onSubmit={[Function]}
- submitting={false}
- success={false}
-/>
-`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap
deleted file mode 100644
index e742c9c3f31..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketTabRenderer-test.tsx.snap
+++ /dev/null
@@ -1,143 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: bitbucket cloud 1`] = `
-<div
- className="bordered"
->
- <AlmTabRenderer
- alm="bitbucket"
- branchesEnabled={true}
- definitionStatus={Object {}}
- definitions={Array []}
- form={[Function]}
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.bitbucketcloud.info"
- id="settings.almintegration.bitbucketcloud.info"
- values={
- Object {
- "link": <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to="/documentation/analysis/bitbucket-cloud-integration/"
- >
- learn_more
- </Link>,
- }
- }
- />
- }
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCancel={[MockFunction]}
- onCheck={[MockFunction]}
- onCreate={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- onSubmit={[MockFunction]}
- submitting={true}
- success={false}
- />
-</div>
-`;
-
-exports[`should render correctly: bitbucket form 1`] = `
-<BitbucketForm
- formData={
- Object {
- "key": "key",
- "personalAccessToken": "asdf1234",
- "url": "http://bbs.enterprise.com",
- }
- }
- isCreating={false}
- onFieldChange={[MockFunction]}
- onSelectVariant={[MockFunction]}
-/>
-`;
-
-exports[`should render correctly: bitbucket server 1`] = `
-<div
- className="bordered"
->
- <AlmTabRenderer
- alm="bitbucket"
- branchesEnabled={true}
- definitionStatus={Object {}}
- definitions={Array []}
- form={[Function]}
- help={
- <React.Fragment>
- <h3>
- onboarding.create_project.pat_help.title
- </h3>
- <p
- className="big-spacer-top"
- >
- settings.almintegration.bitbucket.help_1
- </p>
- <ul
- className="big-spacer-top list-styled"
- >
- <li>
- settings.almintegration.bitbucket.help_2
- </li>
- <li>
- settings.almintegration.bitbucket.help_3
- </li>
- </ul>
- <p
- className="big-spacer-top big-spacer-bottom"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to="/documentation/analysis/bitbucket-integration/"
- >
- learn_more
- </Link>
- </p>
- </React.Fragment>
- }
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCancel={[MockFunction]}
- onCheck={[MockFunction]}
- onCreate={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- onSubmit={[MockFunction]}
- submitting={true}
- success={false}
- />
-</div>
-`;
-
-exports[`should render correctly: default 1`] = `
-<div
- className="bordered"
->
- <AlmTabRenderer
- alm="bitbucket"
- branchesEnabled={true}
- definitionStatus={Object {}}
- definitions={Array []}
- form={[Function]}
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCancel={[MockFunction]}
- onCheck={[MockFunction]}
- onCreate={[MockFunction]}
- onDelete={[MockFunction]}
- onEdit={[MockFunction]}
- onSubmit={[MockFunction]}
- submitting={true}
- success={false}
- />
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap
index 5727233d11d..86fe6664f75 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap
@@ -1,141 +1,195 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render correctly 1`] = `
-<Fragment>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.github.help"
- id="name.github"
- onFieldChange={[MockFunction]}
- propKey="key"
- value=""
- />
- <AlmBindingDefinitionFormField
- help={
- <React.Fragment>
- settings.almintegration.form.url.github.help1
- <br />
- <em>
- https://github.company.com/api/v3
- </em>
- <br />
- <br />
- settings.almintegration.form.url.github.help2
- <br />
- <em>
- https://api.github.com/
- </em>
- </React.Fragment>
- }
- id="url.github"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="url"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.app_id.github.help"
- id="app_id"
- maxLength={80}
- onFieldChange={[MockFunction]}
- propKey="appId"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.client_id.github.help"
- id="client_id.github"
- maxLength={80}
- onFieldChange={[MockFunction]}
- propKey="clientId"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.client_secret.github.help"
- id="client_secret.github"
- maxLength={80}
- onFieldChange={[MockFunction]}
- overwriteOnly={false}
- propKey="clientSecret"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.private_key.github.help"
- id="private_key"
- isTextArea={true}
- onFieldChange={[MockFunction]}
- overwriteOnly={false}
- propKey="privateKey"
- value=""
- />
-</Fragment>
+<div
+ className="display-flex-start"
+>
+ <div
+ className="flex-1"
+ >
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help="settings.almintegration.form.name.github.help"
+ id="name.github"
+ onFieldChange={[MockFunction]}
+ propKey="key"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <React.Fragment>
+ settings.almintegration.form.url.github.help1
+ <br />
+ <em>
+ https://github.company.com/api/v3
+ </em>
+ <br />
+ <br />
+ settings.almintegration.form.url.github.help2
+ <br />
+ <em>
+ https://api.github.com/
+ </em>
+ </React.Fragment>
+ }
+ id="url.github"
+ maxLength={2000}
+ onFieldChange={[MockFunction]}
+ propKey="url"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.app_id.github.help"
+ id="app_id"
+ maxLength={80}
+ onFieldChange={[MockFunction]}
+ propKey="appId"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.client_id.github.help"
+ id="client_id.github"
+ maxLength={80}
+ onFieldChange={[MockFunction]}
+ propKey="clientId"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.client_secret.github.help"
+ id="client_secret.github"
+ maxLength={80}
+ onFieldChange={[MockFunction]}
+ overwriteOnly={false}
+ propKey="clientSecret"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.private_key.github.help"
+ id="private_key"
+ isTextArea={true}
+ onFieldChange={[MockFunction]}
+ overwriteOnly={false}
+ propKey="privateKey"
+ value=""
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <FormattedMessage
+ defaultMessage="settings.almintegration.github.info"
+ id="settings.almintegration.github.info"
+ values={
+ Object {
+ "link": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/github-integration/"
+ >
+ learn_more
+ </Link>,
+ }
+ }
+ />
+ </Alert>
+</div>
`;
exports[`should render correctly 2`] = `
-<Fragment>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.github.help"
- id="name.github"
- onFieldChange={[MockFunction]}
- propKey="key"
- value="key"
- />
- <AlmBindingDefinitionFormField
- help={
- <React.Fragment>
- settings.almintegration.form.url.github.help1
- <br />
- <em>
- https://github.company.com/api/v3
- </em>
- <br />
- <br />
- settings.almintegration.form.url.github.help2
- <br />
- <em>
- https://api.github.com/
- </em>
- </React.Fragment>
- }
- id="url.github"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="url"
- value="http://github.enterprise.com"
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.app_id.github.help"
- id="app_id"
- maxLength={80}
- onFieldChange={[MockFunction]}
- propKey="appId"
- value="123456"
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.client_id.github.help"
- id="client_id.github"
- maxLength={80}
- onFieldChange={[MockFunction]}
- propKey="clientId"
- value="client1"
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.client_secret.github.help"
- id="client_secret.github"
- maxLength={80}
- onFieldChange={[MockFunction]}
- overwriteOnly={true}
- propKey="clientSecret"
- value="**clientsecret**"
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.private_key.github.help"
- id="private_key"
- isTextArea={true}
- onFieldChange={[MockFunction]}
- overwriteOnly={true}
- propKey="privateKey"
- value="asdf1234"
- />
-</Fragment>
+<div
+ className="display-flex-start"
+>
+ <div
+ className="flex-1"
+ >
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help="settings.almintegration.form.name.github.help"
+ id="name.github"
+ onFieldChange={[MockFunction]}
+ propKey="key"
+ value="key"
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <React.Fragment>
+ settings.almintegration.form.url.github.help1
+ <br />
+ <em>
+ https://github.company.com/api/v3
+ </em>
+ <br />
+ <br />
+ settings.almintegration.form.url.github.help2
+ <br />
+ <em>
+ https://api.github.com/
+ </em>
+ </React.Fragment>
+ }
+ id="url.github"
+ maxLength={2000}
+ onFieldChange={[MockFunction]}
+ propKey="url"
+ value="http://github.enterprise.com"
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.app_id.github.help"
+ id="app_id"
+ maxLength={80}
+ onFieldChange={[MockFunction]}
+ propKey="appId"
+ value="123456"
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.client_id.github.help"
+ id="client_id.github"
+ maxLength={80}
+ onFieldChange={[MockFunction]}
+ propKey="clientId"
+ value="client1"
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.client_secret.github.help"
+ id="client_secret.github"
+ maxLength={80}
+ onFieldChange={[MockFunction]}
+ overwriteOnly={true}
+ propKey="clientSecret"
+ value="**clientsecret**"
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.private_key.github.help"
+ id="private_key"
+ isTextArea={true}
+ onFieldChange={[MockFunction]}
+ overwriteOnly={true}
+ propKey="privateKey"
+ value="asdf1234"
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <FormattedMessage
+ defaultMessage="settings.almintegration.github.info"
+ id="settings.almintegration.github.info"
+ values={
+ Object {
+ "link": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/github-integration/"
+ >
+ learn_more
+ </Link>,
+ }
+ }
+ />
+ </Alert>
+</div>
`;
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
deleted file mode 100644
index 7ad5b337f71..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubTab-test.tsx.snap
+++ /dev/null
@@ -1,73 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: with branch support 1`] = `
-<div
- className="bordered"
->
- <AlmTab
- alm="github"
- branchesEnabled={true}
- createConfiguration={[Function]}
- defaultBinding={
- Object {
- "appId": "",
- "clientId": "",
- "clientSecret": "",
- "key": "",
- "privateKey": "",
- "url": "",
- }
- }
- definitionStatus={Object {}}
- definitions={
- Array [
- Object {
- "appId": "123456",
- "clientId": "client1",
- "clientSecret": "**clientsecret**",
- "key": "key",
- "privateKey": "asdf1234",
- "url": "http://github.enterprise.com",
- },
- ]
- }
- form={[Function]}
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.github.info"
- id="settings.almintegration.github.info"
- values={
- Object {
- "link": <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to="/documentation/analysis/github-integration/"
- >
- learn_more
- </Link>,
- }
- }
- />
- }
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onUpdateDefinitions={[MockFunction]}
- updateConfiguration={[Function]}
- />
- <div
- className="huge-spacer-top huge-spacer-bottom bordered-top"
- />
- <div
- className="big-padded"
- >
- <Connect(SubCategoryDefinitionsList)
- category="almintegration"
- subCategory="github"
- />
- </div>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap
index 10b9473011a..d68ef50b519 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap
@@ -1,77 +1,131 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render correctly 1`] = `
-<Fragment>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.gitlab.help"
- id="name.gitlab"
- onFieldChange={[MockFunction]}
- propKey="key"
- value=""
- />
- <AlmBindingDefinitionFormField
- help={
- <React.Fragment>
- settings.almintegration.form.url.gitlab.help
- <br />
- <em>
- https://gitlab.com/api/v4
- </em>
- </React.Fragment>
- }
- id="url.gitlab"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="url"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.personal_access_token.gitlab.help"
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={[MockFunction]}
- overwriteOnly={false}
- propKey="personalAccessToken"
- value=""
- />
-</Fragment>
+<div
+ className="display-flex-start"
+>
+ <div
+ className="flex-1"
+ >
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help="settings.almintegration.form.name.gitlab.help"
+ id="name.gitlab"
+ onFieldChange={[MockFunction]}
+ propKey="key"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <React.Fragment>
+ settings.almintegration.form.url.gitlab.help
+ <br />
+ <em>
+ https://gitlab.com/api/v4
+ </em>
+ </React.Fragment>
+ }
+ id="url.gitlab"
+ maxLength={2000}
+ onFieldChange={[MockFunction]}
+ propKey="url"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.personal_access_token.gitlab.help"
+ id="personal_access_token"
+ isTextArea={true}
+ onFieldChange={[MockFunction]}
+ overwriteOnly={false}
+ propKey="personalAccessToken"
+ value=""
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <FormattedMessage
+ defaultMessage="settings.almintegration.gitlab.info"
+ id="settings.almintegration.gitlab.info"
+ values={
+ Object {
+ "link": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/gitlab-integration/"
+ >
+ learn_more
+ </Link>,
+ }
+ }
+ />
+ </Alert>
+</div>
`;
exports[`should render correctly 2`] = `
-<Fragment>
- <AlmBindingDefinitionFormField
- autoFocus={true}
- help="settings.almintegration.form.name.gitlab.help"
- id="name.gitlab"
- onFieldChange={[MockFunction]}
- propKey="key"
- value="foo"
- />
- <AlmBindingDefinitionFormField
- help={
- <React.Fragment>
- settings.almintegration.form.url.gitlab.help
- <br />
- <em>
- https://gitlab.com/api/v4
- </em>
- </React.Fragment>
- }
- id="url.gitlab"
- maxLength={2000}
- onFieldChange={[MockFunction]}
- propKey="url"
- value=""
- />
- <AlmBindingDefinitionFormField
- help="settings.almintegration.form.personal_access_token.gitlab.help"
- id="personal_access_token"
- isTextArea={true}
- onFieldChange={[MockFunction]}
- overwriteOnly={true}
- propKey="personalAccessToken"
- value="foobar"
- />
-</Fragment>
+<div
+ className="display-flex-start"
+>
+ <div
+ className="flex-1"
+ >
+ <AlmBindingDefinitionFormField
+ autoFocus={true}
+ help="settings.almintegration.form.name.gitlab.help"
+ id="name.gitlab"
+ onFieldChange={[MockFunction]}
+ propKey="key"
+ value="foo"
+ />
+ <AlmBindingDefinitionFormField
+ help={
+ <React.Fragment>
+ settings.almintegration.form.url.gitlab.help
+ <br />
+ <em>
+ https://gitlab.com/api/v4
+ </em>
+ </React.Fragment>
+ }
+ id="url.gitlab"
+ maxLength={2000}
+ onFieldChange={[MockFunction]}
+ propKey="url"
+ value=""
+ />
+ <AlmBindingDefinitionFormField
+ help="settings.almintegration.form.personal_access_token.gitlab.help"
+ id="personal_access_token"
+ isTextArea={true}
+ onFieldChange={[MockFunction]}
+ overwriteOnly={true}
+ propKey="personalAccessToken"
+ value="foobar"
+ />
+ </div>
+ <Alert
+ className="huge-spacer-left flex-1"
+ variant="info"
+ >
+ <FormattedMessage
+ defaultMessage="settings.almintegration.gitlab.info"
+ id="settings.almintegration.gitlab.info"
+ values={
+ Object {
+ "link": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/gitlab-integration/"
+ >
+ learn_more
+ </Link>,
+ }
+ }
+ />
+ </Alert>
+</div>
`;
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
deleted file mode 100644
index dfbd667ff1c..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabTab-test.tsx.snap
+++ /dev/null
@@ -1,190 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly: with URL 1`] = `
-<div
- className="bordered"
->
- <AlmTab
- alm="gitlab"
- branchesEnabled={true}
- createConfiguration={[Function]}
- defaultBinding={
- Object {
- "key": "",
- "personalAccessToken": "",
- "url": "",
- }
- }
- definitionStatus={Object {}}
- definitions={
- Array [
- Object {
- "key": "foo",
- "personalAccessToken": "foobar",
- "url": "https://gitlab.com/api/v4",
- },
- ]
- }
- form={[Function]}
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.gitlab.info"
- id="settings.almintegration.gitlab.info"
- values={
- Object {
- "link": <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to="/documentation/analysis/gitlab-integration/"
- >
- learn_more
- </Link>,
- }
- }
- />
- }
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onUpdateDefinitions={[MockFunction]}
- updateConfiguration={[Function]}
- />
- <div
- className="huge-spacer-top huge-spacer-bottom bordered-top"
- />
- <div
- className="big-padded"
- >
- <Connect(SubCategoryDefinitionsList)
- category="almintegration"
- subCategory="gitlab"
- />
- </div>
-</div>
-`;
-
-exports[`should render correctly: with branch support 1`] = `
-<div
- className="bordered"
->
- <AlmTab
- alm="gitlab"
- branchesEnabled={true}
- createConfiguration={[Function]}
- defaultBinding={
- Object {
- "key": "",
- "personalAccessToken": "",
- "url": "",
- }
- }
- definitionStatus={Object {}}
- definitions={
- Array [
- Object {
- "key": "foo",
- "personalAccessToken": "foobar",
- },
- ]
- }
- form={[Function]}
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.gitlab.info"
- id="settings.almintegration.gitlab.info"
- values={
- Object {
- "link": <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to="/documentation/analysis/gitlab-integration/"
- >
- learn_more
- </Link>,
- }
- }
- />
- }
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onUpdateDefinitions={[MockFunction]}
- updateConfiguration={[Function]}
- />
- <div
- className="huge-spacer-top huge-spacer-bottom bordered-top"
- />
- <div
- className="big-padded"
- >
- <Connect(SubCategoryDefinitionsList)
- category="almintegration"
- subCategory="gitlab"
- />
- </div>
-</div>
-`;
-
-exports[`should render correctly: with no definitions 1`] = `
-<div
- className="bordered"
->
- <AlmTab
- alm="gitlab"
- branchesEnabled={true}
- createConfiguration={[Function]}
- defaultBinding={
- Object {
- "key": "",
- "personalAccessToken": "",
- "url": "",
- }
- }
- definitionStatus={Object {}}
- definitions={Array []}
- form={[Function]}
- help={
- <FormattedMessage
- defaultMessage="settings.almintegration.gitlab.info"
- id="settings.almintegration.gitlab.info"
- values={
- Object {
- "link": <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to="/documentation/analysis/gitlab-integration/"
- >
- learn_more
- </Link>,
- }
- }
- />
- }
- loadingAlmDefinitions={false}
- loadingProjectCount={false}
- multipleAlmEnabled={true}
- onCheck={[MockFunction]}
- onDelete={[MockFunction]}
- onUpdateDefinitions={[MockFunction]}
- updateConfiguration={[Function]}
- />
- <div
- className="huge-spacer-top huge-spacer-bottom bordered-top"
- />
- <div
- className="big-padded"
- >
- <Connect(SubCategoryDefinitionsList)
- category="almintegration"
- subCategory="gitlab"
- />
- </div>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/utils.ts b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/utils.ts
deleted file mode 100644
index 5e118230c4b..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/utils.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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 { AlmKeys } from '../../../../types/alm-settings';
-
-export const ALM_KEY_LIST = [
- AlmKeys.Azure,
- AlmKeys.BitbucketServer,
- AlmKeys.BitbucketCloud,
- AlmKeys.GitHub,
- AlmKeys.GitLab
-];