Browse Source

SONAR-18581 Migrate RTL for EncryptionApp & components/AlmIntegration

tags/10.0.0.68432
stanislavh 1 year ago
parent
commit
cd543e4a4e
53 changed files with 661 additions and 5258 deletions
  1. 1
    1
      server/sonar-web/src/main/js/api/alm-settings.ts
  2. 214
    37
      server/sonar-web/src/main/js/api/mocks/AlmSettingsServiceMock.ts
  3. 25
    0
      server/sonar-web/src/main/js/api/mocks/SettingsServiceMock.ts
  4. 28
    4
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx
  5. 6
    3
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx
  6. 5
    1
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx
  7. 2
    2
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx
  8. 3
    4
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx
  9. 4
    4
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx
  10. 2
    2
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx
  11. 0
    114
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx
  12. 44
    183
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionForm-test.tsx
  13. 0
    80
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx
  14. 0
    92
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx
  15. 239
    0
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-it.tsx
  16. 0
    192
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx
  17. 0
    57
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationRenderer-test.tsx
  18. 0
    92
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTab-test.tsx
  19. 0
    110
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx
  20. 0
    38
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AzureForm-test.tsx
  21. 0
    40
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketCloudForm-test.tsx
  22. 0
    78
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketForm-test.tsx
  23. 0
    38
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketServerForm-test.tsx
  24. 0
    43
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/CreationTooltip-test.tsx
  25. 0
    33
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/DeleteModal-test.tsx
  26. 0
    46
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GithubForm-test.tsx
  27. 0
    38
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GitlabForm-test.tsx
  28. 0
    679
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap
  29. 0
    49
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap
  30. 0
    277
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormField-test.tsx.snap
  31. 0
    484
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormRenderer-test.tsx.snap
  32. 0
    27
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegration-test.tsx.snap
  33. 0
    528
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationRenderer-test.tsx.snap
  34. 0
    26
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap
  35. 0
    594
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap
  36. 0
    143
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap
  37. 0
    170
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketCloudForm-test.tsx.snap
  38. 0
    119
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap
  39. 0
    67
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketServerForm-test.tsx.snap
  40. 0
    40
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/CreationTooltip-test.tsx.snap
  41. 0
    62
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/DeleteModal-test.tsx.snap
  42. 0
    207
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap
  43. 0
    135
      server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap
  44. 3
    1
      server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.tsx
  45. 4
    1
      server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx
  46. 73
    0
      server/sonar-web/src/main/js/apps/settings/encryption/__tests__/EncryptionApp-it.tsx
  47. 0
    59
      server/sonar-web/src/main/js/apps/settings/encryption/__tests__/EncryptionApp-test.tsx
  48. 0
    30
      server/sonar-web/src/main/js/apps/settings/encryption/__tests__/EncryptionForm-test.tsx
  49. 0
    30
      server/sonar-web/src/main/js/apps/settings/encryption/__tests__/GenerateSecretKeyForm-test.tsx
  50. 0
    85
      server/sonar-web/src/main/js/apps/settings/encryption/__tests__/__snapshots__/EncryptionApp-test.tsx.snap
  51. 0
    74
      server/sonar-web/src/main/js/apps/settings/encryption/__tests__/__snapshots__/EncryptionForm-test.tsx.snap
  52. 0
    39
      server/sonar-web/src/main/js/apps/settings/encryption/__tests__/__snapshots__/GenerateSecretKeyForm-test.tsx.snap
  53. 8
    0
      sonar-core/src/main/resources/org/sonar/l10n/core.properties

+ 1
- 1
server/sonar-web/src/main/js/api/alm-settings.ts View File

@@ -110,7 +110,7 @@ export function deleteConfiguration(key: string) {
return post('/api/alm_settings/delete', { key }).catch(throwGlobalError);
}

export function countBindedProjects(almSetting: string) {
export function countBoundProjects(almSetting: string) {
return getJSON('/api/alm_settings/count_binding', { almSetting })
.then(({ projects }) => projects)
.catch(throwGlobalError);

+ 214
- 37
server/sonar-web/src/main/js/api/mocks/AlmSettingsServiceMock.ts View File

@@ -19,51 +19,228 @@
*/
import { cloneDeep } from 'lodash';
import { mockAlmSettingsInstance } from '../../helpers/mocks/alm-settings';
import { AlmKeys, AlmSettingsInstance } from '../../types/alm-settings';
import { getAlmSettings } from '../alm-settings';
import {
AlmKeys,
AlmSettingsBindingDefinitions,
AlmSettingsInstance,
AzureBindingDefinition,
BitbucketCloudBindingDefinition,
BitbucketServerBindingDefinition,
GithubBindingDefinition,
GitlabBindingDefinition,
} from '../../types/alm-settings';
import {
countBoundProjects,
createAzureConfiguration,
createBitbucketCloudConfiguration,
createBitbucketServerConfiguration,
createGithubConfiguration,
createGitlabConfiguration,
deleteConfiguration,
getAlmDefinitions,
getAlmSettings,
updateAzureConfiguration,
updateBitbucketCloudConfiguration,
updateBitbucketServerConfiguration,
updateGithubConfiguration,
updateGitlabConfiguration,
validateAlmSettings,
} from '../alm-settings';

const defaultAlmDefinitions = {
[AlmKeys.Azure]: [],
[AlmKeys.BitbucketServer]: [],
[AlmKeys.BitbucketCloud]: [],
[AlmKeys.GitHub]: [],
[AlmKeys.GitLab]: [],
};

const defaultAlmSettings = [
mockAlmSettingsInstance({ key: 'conf-final-1', alm: AlmKeys.GitLab }),
mockAlmSettingsInstance({ key: 'conf-final-2', alm: AlmKeys.GitLab }),
mockAlmSettingsInstance({ key: 'conf-github-1', alm: AlmKeys.GitHub, url: 'http://url' }),
mockAlmSettingsInstance({ key: 'conf-github-2', alm: AlmKeys.GitHub, url: 'http://url' }),
mockAlmSettingsInstance({ key: 'conf-github-3', alm: AlmKeys.GitHub, url: 'javascript://url' }),
mockAlmSettingsInstance({ key: 'conf-azure-1', alm: AlmKeys.Azure, url: 'url' }),
mockAlmSettingsInstance({ key: 'conf-azure-2', alm: AlmKeys.Azure, url: 'url' }),
mockAlmSettingsInstance({
key: 'conf-bitbucketcloud-1',
alm: AlmKeys.BitbucketCloud,
url: 'url',
}),
mockAlmSettingsInstance({
key: 'conf-bitbucketcloud-2',
alm: AlmKeys.BitbucketCloud,
url: 'url',
}),
mockAlmSettingsInstance({
key: 'conf-bitbucketserver-1',
alm: AlmKeys.BitbucketServer,
url: 'url',
}),
mockAlmSettingsInstance({
key: 'conf-bitbucketserver-2',
alm: AlmKeys.BitbucketServer,
url: 'url',
}),
];

export default class AlmSettingsServiceMock {
almSettings: AlmSettingsInstance[];
defaultSetting: AlmSettingsInstance[] = [
mockAlmSettingsInstance({ key: 'conf-final-1', alm: AlmKeys.GitLab }),
mockAlmSettingsInstance({ key: 'conf-final-2', alm: AlmKeys.GitLab }),
mockAlmSettingsInstance({ key: 'conf-github-1', alm: AlmKeys.GitHub, url: 'http://url' }),
mockAlmSettingsInstance({ key: 'conf-github-2', alm: AlmKeys.GitHub, url: 'http://url' }),
mockAlmSettingsInstance({ key: 'conf-github-3', alm: AlmKeys.GitHub, url: 'javascript://url' }),
mockAlmSettingsInstance({ key: 'conf-azure-1', alm: AlmKeys.Azure, url: 'url' }),
mockAlmSettingsInstance({ key: 'conf-azure-2', alm: AlmKeys.Azure, url: 'url' }),
mockAlmSettingsInstance({
key: 'conf-bitbucketcloud-1',
alm: AlmKeys.BitbucketCloud,
url: 'url',
}),
mockAlmSettingsInstance({
key: 'conf-bitbucketcloud-2',
alm: AlmKeys.BitbucketCloud,
url: 'url',
}),
mockAlmSettingsInstance({
key: 'conf-bitbucketserver-1',
alm: AlmKeys.BitbucketServer,
url: 'url',
}),
mockAlmSettingsInstance({
key: 'conf-bitbucketserver-2',
alm: AlmKeys.BitbucketServer,
url: 'url',
}),
];
#almDefinitions: AlmSettingsBindingDefinitions;
#almSettings: AlmSettingsInstance[];
#definitionError = '';

constructor() {
this.almSettings = cloneDeep(this.defaultSetting);
jest.mocked(getAlmSettings).mockImplementation(this.getAlmSettingsHandler);
this.#almSettings = cloneDeep(defaultAlmSettings);
this.#almDefinitions = cloneDeep(defaultAlmDefinitions);
jest.mocked(getAlmSettings).mockImplementation(this.handleGetAlmSettings);
jest.mocked(getAlmDefinitions).mockImplementation(this.handleGetAlmDefinitions);
jest.mocked(countBoundProjects).mockImplementation(this.handleCountBoundProjects);
jest.mocked(validateAlmSettings).mockImplementation(this.handleValidateAlmSettings);
jest.mocked(deleteConfiguration).mockImplementation(this.handleDeleteConfiguration);
jest.mocked(createGithubConfiguration).mockImplementation(this.handleCreateGithubConfiguration);
jest.mocked(createGitlabConfiguration).mockImplementation(this.handleCreateGitlabConfiguration);
jest.mocked(createAzureConfiguration).mockImplementation(this.handleCreateAzureConfiguration);
jest
.mocked(createBitbucketServerConfiguration)
.mockImplementation(this.handleCreateBitbucketServerConfiguration);
jest
.mocked(createBitbucketCloudConfiguration)
.mockImplementation(this.handleCreateBitbucketCloudConfiguration);
jest.mocked(updateGithubConfiguration).mockImplementation(this.handleUpdateGithubConfiguration);
jest.mocked(updateGitlabConfiguration).mockImplementation(this.handleUpdateGitlabConfiguration);
jest.mocked(updateAzureConfiguration).mockImplementation(this.handleUpdateAzureConfiguration);
jest
.mocked(updateBitbucketServerConfiguration)
.mockImplementation(this.handleUpdateBitbucketServerConfiguration);
jest
.mocked(updateBitbucketCloudConfiguration)
.mockImplementation(this.handleUpdateBitbucketCloudConfiguration);
}

getAlmSettingsHandler = () => {
return Promise.resolve(this.almSettings);
handleGetAlmDefinitions = () => {
return this.reply(this.#almDefinitions);
};

handleGetAlmSettings = () => {
return this.reply(this.#almSettings);
};

handleValidateAlmSettings = () => {
return this.reply(this.#definitionError);
};

handleCountBoundProjects = () => {
return this.reply({ projects: 5 });
};

setDefinitionErrorMessage = (message: string) => {
this.#definitionError = message;
};

handleDeleteConfiguration = (key: string) => {
for (const definitionsGroup of Object.values(this.#almDefinitions) as [
GithubBindingDefinition[],
GitlabBindingDefinition[],
AzureBindingDefinition[],
BitbucketCloudBindingDefinition[],
BitbucketServerBindingDefinition[]
]) {
const foundIndex = definitionsGroup.findIndex((definition) => definition.key === key);
if (foundIndex !== -1) {
definitionsGroup.splice(foundIndex, 1);
break;
}
}
return this.reply(undefined);
};

handleCreateGithubConfiguration = (data: GithubBindingDefinition) => {
this.#almDefinitions[AlmKeys.GitHub].push(data);

return this.reply(undefined);
};

handleCreateGitlabConfiguration = (data: GitlabBindingDefinition) => {
this.#almDefinitions[AlmKeys.GitLab].push(data);

return this.reply(undefined);
};

handleCreateAzureConfiguration = (data: AzureBindingDefinition) => {
this.#almDefinitions[AlmKeys.Azure].push(data);

return this.reply(undefined);
};

handleCreateBitbucketServerConfiguration = (data: BitbucketServerBindingDefinition) => {
this.#almDefinitions[AlmKeys.BitbucketServer].push(data);

return this.reply(undefined);
};

handleCreateBitbucketCloudConfiguration = (data: BitbucketCloudBindingDefinition) => {
this.#almDefinitions[AlmKeys.BitbucketCloud].push(data);

return this.reply(undefined);
};

handleUpdateGithubConfiguration = (data: GithubBindingDefinition & { newKey: string }) => {
const definition = this.#almDefinitions[AlmKeys.GitHub].find(
(item) => item.key === data.key
) as GithubBindingDefinition;
Object.assign(definition, { ...data, key: data.newKey });

return this.reply(undefined);
};

handleUpdateGitlabConfiguration = (data: GitlabBindingDefinition & { newKey: string }) => {
const definition = this.#almDefinitions[AlmKeys.GitLab].find(
(item) => item.key === data.key
) as GitlabBindingDefinition;
Object.assign(definition, { ...data, key: data.newKey });

return this.reply(undefined);
};

handleUpdateAzureConfiguration = (data: AzureBindingDefinition & { newKey: string }) => {
const definition = this.#almDefinitions[AlmKeys.Azure].find(
(item) => item.key === data.key
) as AzureBindingDefinition;
Object.assign(definition, { ...data, key: data.newKey });

return this.reply(undefined);
};

handleUpdateBitbucketServerConfiguration = (
data: BitbucketServerBindingDefinition & { newKey: string }
) => {
const definition = this.#almDefinitions[AlmKeys.BitbucketServer].find(
(item) => item.key === data.key
) as BitbucketServerBindingDefinition;
Object.assign(definition, { ...data, key: data.newKey });

return this.reply(undefined);
};

handleUpdateBitbucketCloudConfiguration = (
data: BitbucketCloudBindingDefinition & { newKey: string }
) => {
const definition = this.#almDefinitions[AlmKeys.BitbucketCloud].find(
(item) => item.key === data.key
) as BitbucketCloudBindingDefinition;
Object.assign(definition, { ...data, key: data.newKey });

return this.reply(undefined);
};

reset = () => {
this.almSettings = cloneDeep(this.defaultSetting);
this.#almSettings = cloneDeep(defaultAlmSettings);
this.#almDefinitions = cloneDeep(defaultAlmDefinitions);
this.setDefinitionErrorMessage('');
};

reply<T>(response: T): Promise<T> {
return Promise.resolve(cloneDeep(response));
}
}

+ 25
- 0
server/sonar-web/src/main/js/api/mocks/SettingsServiceMock.ts View File

@@ -29,6 +29,9 @@ import {
SettingValue,
} from '../../types/settings';
import {
checkSecretKey,
encryptValue,
generateSecretKey,
getAllValues,
getDefinitions,
getValue,
@@ -113,6 +116,8 @@ export default class SettingsServiceMock {

#definitions: ExtendedSettingDefinition[] = cloneDeep(DEFAULT_DEFINITIONS_MOCK);

#secretKeyAvailable: boolean = false;

constructor() {
jest.mocked(getDefinitions).mockImplementation(this.handleGetDefinitions);
jest.mocked(getValue).mockImplementation(this.handleGetValue);
@@ -120,6 +125,9 @@ export default class SettingsServiceMock {
jest.mocked(getAllValues).mockImplementation(this.handleGetAllValues);
jest.mocked(setSettingValue).mockImplementation(this.handleSetSettingValue);
jest.mocked(resetSettingValue).mockImplementation(this.handleResetSettingValue);
jest.mocked(checkSecretKey).mockImplementation(this.handleCheckSecretKey);
jest.mocked(generateSecretKey).mockImplementation(this.handleGenerateSecretKey);
jest.mocked(encryptValue).mockImplementation(this.handleEcnryptValue);
}

handleGetValue = (data: { key: string; component?: string } & BranchParameters) => {
@@ -193,9 +201,26 @@ export default class SettingsServiceMock {
this.#definitions.push(definition);
};

handleCheckSecretKey = () => {
return this.reply({ secretKeyAvailable: this.#secretKeyAvailable });
};

handleGenerateSecretKey = () => {
return this.reply({ secretKey: 'secretKey' });
};

handleEcnryptValue = () => {
return this.reply({ encryptedValue: 'encryptedValue' });
};

setSecretKeyAvailable = (val = false) => {
this.#secretKeyAvailable = val;
};

reset = () => {
this.#settingValues = cloneDeep(this.#defaultValues);
this.#definitions = cloneDeep(DEFAULT_DEFINITIONS_MOCK);
this.#secretKeyAvailable = false;
return this;
};


+ 28
- 4
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionBox.tsx View File

@@ -30,7 +30,7 @@ import EditIcon from '../../../../components/icons/EditIcon';
import { Alert } from '../../../../components/ui/Alert';
import { ALM_DOCUMENTATION_PATHS, IMPORT_COMPATIBLE_ALMS } from '../../../../helpers/constants';
import { getEdition, getEditionUrl } from '../../../../helpers/editions';
import { translate } from '../../../../helpers/l10n';
import { translate, translateWithParameters } from '../../../../helpers/l10n';
import {
AlmBindingDefinitionBase,
AlmKeys,
@@ -144,11 +144,28 @@ export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxPr
return (
<div className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition">
<div className="actions pull-right">
<Button onClick={() => props.onEdit(definition.key)}>
<Button
aria-label={translateWithParameters(
'settings.almintegration.edit_configuration',
definition.key
)}
onClick={() => {
props.onEdit(definition.key);
}}
>
<EditIcon className="spacer-right" />
{translate('edit')}
</Button>
<Button className="button-red spacer-left" onClick={() => props.onDelete(definition.key)}>
<Button
aria-label={translateWithParameters(
'settings.almintegration.delete_configuration',
definition.key
)}
className="button-red spacer-left"
onClick={() => {
props.onDelete(definition.key);
}}
>
<DeleteIcon className="spacer-right" />
{translate('delete')}
</Button>
@@ -228,7 +245,14 @@ export default function AlmBindingDefinitionBox(props: AlmBindingDefinitionBoxPr
)}
</div>

<Button className="big-spacer-top" onClick={() => props.onCheck(definition.key)}>
<Button
aria-label={translateWithParameters(
'settings.almintegration.check_configuration_x',
definition.key
)}
className="big-spacer-top"
onClick={() => props.onCheck(definition.key)}
>
{translate('settings.almintegration.check_configuration')}
</Button>
</>

+ 6
- 3
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionForm.tsx View File

@@ -47,7 +47,7 @@ import { Dict } from '../../../../types/types';
import { BITBUCKET_CLOUD_WORKSPACE_ID_FORMAT } from '../../constants';
import AlmBindingDefinitionFormRenderer from './AlmBindingDefinitionFormRenderer';

interface Props {
export interface AlmBindingDefinitionFormProps {
alm: AlmKeys;
bindingDefinition?: AlmBindingDefinition;
onCancel: () => void;
@@ -121,9 +121,12 @@ const BINDING_PER_ALM: {
},
};

export default class AlmBindingDefinitionForm extends React.PureComponent<Props, State> {
export default class AlmBindingDefinitionForm extends React.PureComponent<
AlmBindingDefinitionFormProps,
State
> {
mounted = false;
constructor(props: Props) {
constructor(props: AlmBindingDefinitionFormProps) {
super(props);

let bitbucketVariant: AlmKeys.BitbucketServer | AlmKeys.BitbucketCloud | undefined = undefined;

+ 5
- 1
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormField.tsx View File

@@ -26,7 +26,7 @@ import ValidationInput, {
} from '../../../../components/controls/ValidationInput';
import { Alert } from '../../../../components/ui/Alert';
import MandatoryFieldMarker from '../../../../components/ui/MandatoryFieldMarker';
import { translate } from '../../../../helpers/l10n';
import { translate, translateWithParameters } from '../../../../helpers/l10n';
import { AlmBindingDefinitionBase } from '../../../../types/alm-settings';
import '../../styles.css';

@@ -79,6 +79,10 @@ export function AlmBindingDefinitionFormField<B extends AlmBindingDefinitionBase
<div>
<p>{translate('settings.almintegration.form.secret.field')}</p>
<ButtonLink
aria-label={translateWithParameters(
'settings.almintegration.form.secret.update_field_x',
translate('settings.almintegration.form', id)
)}
onClick={() => {
props.onFieldChange(propKey, '');
setShowField(true);

+ 2
- 2
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmBindingDefinitionFormRenderer.tsx View File

@@ -37,7 +37,7 @@ import BitbucketForm from './BitbucketForm';
import GithubForm from './GithubForm';
import GitlabForm from './GitlabForm';

export interface AlmBindingDefinitionFormProps {
export interface Props {
alm: AlmKeys;
isUpdate: boolean;
canSubmit: boolean;
@@ -53,7 +53,7 @@ export interface AlmBindingDefinitionFormProps {
validationError?: string;
}

export default class AlmBindingDefinitionFormRenderer extends React.PureComponent<AlmBindingDefinitionFormProps> {
export default class AlmBindingDefinitionFormRenderer extends React.PureComponent<Props> {
renderForm = () => {
const { alm, formData, isUpdate, bitbucketVariant } = this.props;


+ 3
- 4
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegration.tsx View File

@@ -19,7 +19,7 @@
*/
import * as React from 'react';
import {
countBindedProjects,
countBoundProjects,
deleteConfiguration,
getAlmDefinitions,
validateAlmSettings,
@@ -159,7 +159,7 @@ export class AlmIntegration extends React.PureComponent<Props, State> {

handleDelete = (definitionKey: string) => {
this.setState({ loadingProjectCount: true });
return countBindedProjects(definitionKey)
return countBoundProjects(definitionKey)
.then((projectCount) => {
if (this.mounted) {
this.setState({
@@ -212,7 +212,6 @@ export class AlmIntegration extends React.PureComponent<Props, State> {
};

render() {
const { hasFeature } = this.props;
const {
currentAlmTab,
definitionKeyForDeletion,
@@ -226,7 +225,7 @@ export class AlmIntegration extends React.PureComponent<Props, State> {
return (
<AlmIntegrationRenderer
branchesEnabled={this.props.hasFeature(Feature.BranchSupport)}
multipleAlmEnabled={hasFeature(Feature.MultipleAlm)}
multipleAlmEnabled={this.props.hasFeature(Feature.MultipleAlm)}
onCancelDelete={this.handleCancelDelete}
onConfirmDelete={this.handleConfirmDelete}
onCheckConfiguration={this.handleCheck}

+ 4
- 4
server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx View File

@@ -60,7 +60,7 @@ const tabs = [
height={16}
src={`${getBaseUrl()}/images/alm/github.svg`}
/>
GitHub
{translate('settings.almintegration.tab.github')}
</>
),
},
@@ -74,7 +74,7 @@ const tabs = [
height={16}
src={`${getBaseUrl()}/images/alm/bitbucket.svg`}
/>
Bitbucket
{translate('settings.almintegration.tab.bitbucket')}
</>
),
},
@@ -88,7 +88,7 @@ const tabs = [
height={16}
src={`${getBaseUrl()}/images/alm/azure.svg`}
/>
Azure DevOps
{translate('settings.almintegration.tab.azure')}
</>
),
},
@@ -102,7 +102,7 @@ const tabs = [
height={16}
src={`${getBaseUrl()}/images/alm/gitlab.svg`}
/>
GitLab
{translate('settings.almintegration.tab.gitlab')}
</>
),
},

+ 2
- 2
server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx View File

@@ -53,10 +53,10 @@ export default function BitbucketForm(props: BitbucketFormProps) {
onCheck={props.onVariantChange}
options={[
{
label: 'Bitbucket Server',
label: translate('alm.bitbucket.long'),
value: AlmKeys.BitbucketServer,
},
{ label: 'Bitbucket Cloud', value: AlmKeys.BitbucketCloud },
{ label: translate('alm.bitbucketcloud.long'), value: AlmKeys.BitbucketCloud },
]}
value={variant}
/>

+ 0
- 114
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionBox-test.tsx View File

@@ -1,114 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 {
mockAlmSettingsBindingStatus,
mockAzureBindingDefinition,
mockBitbucketCloudBindingDefinition,
mockGithubBindingDefinition,
mockGitlabBindingDefinition,
} from '../../../../../helpers/mocks/alm-settings';
import { AlmKeys, AlmSettingsBindingStatusType } from '../../../../../types/alm-settings';
import AlmBindingDefinitionBox, { AlmBindingDefinitionBoxProps } from '../AlmBindingDefinitionBox';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(
shallowRender({
status: mockAlmSettingsBindingStatus({
type: AlmSettingsBindingStatusType.Success,
}),
})
).toMatchSnapshot('success');
expect(
shallowRender({
status: mockAlmSettingsBindingStatus({
failureMessage: 'Oops, something went wrong',
type: AlmSettingsBindingStatusType.Failure,
}),
})
).toMatchSnapshot('error');

expect(
shallowRender({
status: mockAlmSettingsBindingStatus({
alertSuccess: true,
type: AlmSettingsBindingStatusType.Success,
}),
})
).toMatchSnapshot('success with alert');

expect(
shallowRender({
status: mockAlmSettingsBindingStatus({
type: AlmSettingsBindingStatusType.Warning,
}),
})
).toMatchSnapshot('warning');

expect(
shallowRender({ alm: AlmKeys.Azure, definition: mockAzureBindingDefinition() })
).toMatchSnapshot('Azure DevOps');

expect(
shallowRender({
status: mockAlmSettingsBindingStatus({
type: AlmSettingsBindingStatusType.Success,
}),
alm: AlmKeys.GitLab,
definition: mockGitlabBindingDefinition(),
})
).toMatchSnapshot('success for GitLab');

expect(
shallowRender({
status: mockAlmSettingsBindingStatus({
type: AlmSettingsBindingStatusType.Success,
}),
alm: AlmKeys.BitbucketCloud,
definition: mockBitbucketCloudBindingDefinition(),
})
).toMatchSnapshot('success for Bitbucket Cloud');

expect(
shallowRender({
branchesEnabled: false,
status: mockAlmSettingsBindingStatus({
alertSuccess: true,
type: AlmSettingsBindingStatusType.Success,
}),
})
).toMatchSnapshot('success with branches disabled');
});

function shallowRender(props: Partial<AlmBindingDefinitionBoxProps> = {}) {
return shallow(
<AlmBindingDefinitionBox
alm={AlmKeys.GitHub}
branchesEnabled={true}
definition={mockGithubBindingDefinition()}
onCheck={jest.fn()}
onDelete={jest.fn()}
onEdit={jest.fn()}
{...props}
/>
);
}

+ 44
- 183
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionForm-test.tsx View File

@@ -17,202 +17,63 @@
* 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 {
createAzureConfiguration,
createBitbucketCloudConfiguration,
createBitbucketServerConfiguration,
createGithubConfiguration,
createGitlabConfiguration,
deleteConfiguration,
updateAzureConfiguration,
updateBitbucketCloudConfiguration,
updateBitbucketServerConfiguration,
updateGithubConfiguration,
updateGitlabConfiguration,
validateAlmSettings,
} from '../../../../../api/alm-settings';
import {
mockAzureBindingDefinition,
mockBitbucketCloudBindingDefinition,
mockBitbucketServerBindingDefinition,
mockGithubBindingDefinition,
mockGitlabBindingDefinition,
} from '../../../../../helpers/mocks/alm-settings';
import { waitAndUpdate } from '../../../../../helpers/testUtils';
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({}),
validateAlmSettings: jest.fn().mockResolvedValue(undefined),
deleteConfiguration: jest.fn().mockResolvedValue(undefined),
}));

beforeEach(() => {
jest.clearAllMocks();
});

it('should render correctly', () => {
expect(shallowRender({ bindingDefinition: undefined })).toMatchSnapshot('create');
expect(shallowRender({ bindingDefinition: mockGithubBindingDefinition() })).toMatchSnapshot(
'edit'
);
});

it('should handle field changes', () => {
const formData = mockGithubBindingDefinition();

const wrapper = shallowRender();

wrapper.instance().handleFieldChange('key', formData.key);
wrapper.instance().handleFieldChange('url', formData.url);
wrapper.instance().handleFieldChange('appId', formData.appId);
wrapper.instance().handleFieldChange('clientId', formData.clientId);
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 afterSubmit = jest.fn();
const formData = mockGithubBindingDefinition();

const wrapper = shallowRender({ afterSubmit });

wrapper.instance().setState({ formData });
await wrapper.instance().handleFormSubmit();
expect(afterSubmit).toHaveBeenCalledWith(formData);
});

it('should handle validation error during submit, and cancellation', async () => {
const afterSubmit = jest.fn();
const formData = mockGithubBindingDefinition();
const error = 'This a test error message';
(validateAlmSettings as jest.Mock).mockResolvedValueOnce(error);

const wrapper = shallowRender({ afterSubmit, enforceValidation: true });

wrapper.instance().setState({ formData });
await wrapper.instance().handleFormSubmit();
expect(validateAlmSettings).toHaveBeenCalledWith(formData.key);
expect(wrapper.state().validationError).toBe(error);
expect(afterSubmit).not.toHaveBeenCalledWith();

wrapper.find(AlmBindingDefinitionFormRenderer).props().onCancel();
expect(deleteConfiguration).toHaveBeenCalledWith(formData.key);
import userEvent from '@testing-library/user-event';
import React from 'react';
import { byRole } from 'testing-library-selector';
import AlmSettingsServiceMock from '../../../../../api/mocks/AlmSettingsServiceMock';
import { renderComponent } from '../../../../../helpers/testReactTestingUtils';
import { AlmKeys } from '../../../../../types/alm-settings';
import AlmBindingDefinitionForm, {
AlmBindingDefinitionFormProps,
} from '../AlmBindingDefinitionForm';

jest.mock('../../../../../api/alm-settings');

let almSettings: AlmSettingsServiceMock;

beforeAll(() => {
almSettings = new AlmSettingsServiceMock();
});

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({
// Reminder: due to the way the settings app works, we never pass AlmKeys.BitbucketCloud as `alm`.
alm: AlmKeys.BitbucketServer,
bindingDefinition: undefined,
});

wrapper.instance().handleBitbucketVariantChange(AlmKeys.BitbucketCloud);

await waitAndUpdate(wrapper);
await wrapper.instance().handleFormSubmit();
expect(createBitbucketCloudConfiguration).toHaveBeenCalled();

wrapper.setProps({ bindingDefinition: mockBitbucketCloudBindingDefinition() });
await wrapper.instance().handleFormSubmit();
expect(updateBitbucketCloudConfiguration).toHaveBeenCalled();
afterEach(() => {
almSettings.reset();
});

it('should store bitbucket variant', async () => {
const wrapper = shallowRender();
const ui = {
bitbucketConfiguration: (almKey: AlmKeys.BitbucketCloud | AlmKeys.BitbucketServer) =>
byRole('button', { name: `alm.${almKey}.long` }),
configurationInput: (id: string) =>
byRole('textbox', { name: `settings.almintegration.form.${id}` }),
saveConfigurationButton: byRole('button', { name: 'settings.almintegration.form.save' }),
cancelButton: byRole('button', { name: 'cancel' }),
validationError: byRole('alert'),
};

wrapper
.find(AlmBindingDefinitionFormRenderer)
.props()
.onBitbucketVariantChange(AlmKeys.BitbucketCloud);
const onCancel = jest.fn();

await waitAndUpdate(wrapper);

expect(wrapper.state().bitbucketVariant).toBe(AlmKeys.BitbucketCloud);
expect(wrapper.state().formData).toEqual({
clientId: '',
clientSecret: '',
key: '',
workspace: '',
});
});
it('enforceValidation enabled', async () => {
almSettings.setDefinitionErrorMessage('Validation Error');
renderAlmBindingDefinitionForm();

it('should (dis)allow submit by validating its state (Bitbucket Cloud)', () => {
const wrapper = shallowRender({
// Reminder: due to the way the settings app works, we never pass AlmKeys.BitbucketCloud as `alm`.
alm: AlmKeys.BitbucketServer,
bindingDefinition: mockBitbucketCloudBindingDefinition(),
});
expect(wrapper.instance().canSubmit()).toBe(false);

wrapper.setState({
formData: mockBitbucketCloudBindingDefinition({ workspace: 'foo/bar' }),
touched: true,
});
expect(wrapper.instance().canSubmit()).toBe(false);

wrapper.setState({ formData: mockBitbucketCloudBindingDefinition() });
expect(wrapper.instance().canSubmit()).toBe(true);
});
// Fill in form
await userEvent.type(await ui.configurationInput('name.gitlab').find(), 'Name');
await userEvent.type(ui.configurationInput('url.gitlab').get(), 'https://api.alm.com');
await userEvent.type(ui.configurationInput('personal_access_token').get(), 'Access Token');

it('should (dis)allow submit by validating its state (others)', () => {
const wrapper = shallowRender();
expect(wrapper.instance().canSubmit()).toBe(false);
await userEvent.click(ui.saveConfigurationButton.get());
expect(ui.validationError.get()).toHaveTextContent('Validation Error');

wrapper.setState({ formData: mockGithubBindingDefinition(), touched: true });
expect(wrapper.instance().canSubmit()).toBe(true);
await userEvent.click(ui.cancelButton.get());
expect(onCancel).toHaveBeenCalled();
});

function shallowRender(props: Partial<AlmBindingDefinitionForm['props']> = {}) {
return shallow<AlmBindingDefinitionForm>(
function renderAlmBindingDefinitionForm(props: Partial<AlmBindingDefinitionFormProps> = {}) {
return renderComponent(
<AlmBindingDefinitionForm
alm={AlmKeys.GitHub}
bindingDefinition={mockGithubBindingDefinition()}
onCancel={jest.fn()}
onCancel={onCancel}
afterSubmit={jest.fn()}
enforceValidation={true}
alm={AlmKeys.GitLab}
{...props}
/>
);

+ 0
- 80
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormField-test.tsx View File

@@ -1,80 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { ButtonLink } from '../../../../../components/controls/buttons';
import { click } from '../../../../../helpers/testUtils';
import { AlmBindingDefinitionBase } from '../../../../../types/alm-settings';
import {
AlmBindingDefinitionFormField,
AlmBindingDefinitionFormFieldProps,
} from '../AlmBindingDefinitionFormField';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ help: 'help' })).toMatchSnapshot('with help');
expect(shallowRender({ isTextArea: true })).toMatchSnapshot('textarea');
expect(shallowRender({ optional: true })).toMatchSnapshot('optional');
expect(shallowRender({ overwriteOnly: true })).toMatchSnapshot('secret');
expect(shallowRender({ isSecret: true })).toMatchSnapshot('encryptable');
expect(shallowRender({ error: 'some error message', isInvalid: true })).toMatchSnapshot(
'invalid with error'
);
});

it('should call onFieldChange', () => {
const onInputChange = jest.fn();
shallowRender({ onFieldChange: onInputChange })
.find('input')
.simulate('change', { currentTarget: { value: '' } });
expect(onInputChange).toHaveBeenCalled();

const onTextAreaChange = jest.fn();
shallowRender({ isTextArea: true, onFieldChange: onTextAreaChange })
.find('textarea')
.simulate('change', { currentTarget: { value: '' } });
expect(onTextAreaChange).toHaveBeenCalled();
});

it('should correctly toggle visibility for secret fields', () => {
const onFieldChange = jest.fn();
const wrapper = shallowRender({ onFieldChange, overwriteOnly: true });
expect(wrapper.find('input').exists()).toBe(false);

click(wrapper.find(ButtonLink));
expect(onFieldChange).toHaveBeenCalledWith('key', '');
expect(wrapper.find('input').exists()).toBe(true);
});

function shallowRender(
props: Partial<AlmBindingDefinitionFormFieldProps<AlmBindingDefinitionBase>> = {}
) {
return shallow(
<AlmBindingDefinitionFormField
id="key"
isTextArea={false}
maxLength={40}
onFieldChange={jest.fn()}
propKey="key"
value="key"
{...props}
/>
);
}

+ 0
- 92
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmBindingDefinitionFormRenderer-test.tsx View File

@@ -1,92 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 '../../../../../components/controls/buttons';
import { mockGithubBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
import { click, mockEvent } from '../../../../../helpers/testUtils';
import { AlmKeys } from '../../../../../types/alm-settings';
import AlmBindingDefinitionFormRenderer, {
AlmBindingDefinitionFormProps,
} from '../AlmBindingDefinitionFormRenderer';
import GithubForm from '../GithubForm';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ submitting: true })).toMatchSnapshot('submitting');
expect(shallowRender({ isUpdate: true })).toMatchSnapshot('editing');
expect(shallowRender({ validationError: 'this is a validation error' })).toMatchSnapshot(
'with validation error'
);
});

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).toHaveBeenCalled();
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}
submitting={false}
formData={mockGithubBindingDefinition()}
onCancel={jest.fn()}
onSubmit={jest.fn()}
onFieldChange={jest.fn()}
bitbucketVariant={AlmKeys.BitbucketServer}
onBitbucketVariantChange={jest.fn()}
{...props}
/>
);
}

+ 239
- 0
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-it.tsx View File

@@ -0,0 +1,239 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { byRole, byText } from 'testing-library-selector';
import AlmSettingsServiceMock from '../../../../../api/mocks/AlmSettingsServiceMock';
import { AvailableFeaturesContext } from '../../../../../app/components/available-features/AvailableFeaturesContext';
import { renderComponent } from '../../../../../helpers/testReactTestingUtils';
import { AlmKeys } from '../../../../../types/alm-settings';
import { Feature } from '../../../../../types/features';
import AlmIntegration from '../AlmIntegration';

jest.mock('../../../../../api/alm-settings');

let almSettings: AlmSettingsServiceMock;

beforeAll(() => {
almSettings = new AlmSettingsServiceMock();
});

afterEach(() => {
almSettings.reset();
});

const ui = {
almHeading: byRole('heading', { name: 'settings.almintegration.title' }),
emptyIntro: (almKey: AlmKeys) => byText(`settings.almintegration.empty.${almKey}`),
createConfigurationButton: byRole('button', { name: 'settings.almintegration.create' }),
tab: (almKey: AlmKeys) =>
byRole('tab', { name: `${almKey} settings.almintegration.tab.${almKey}` }),
bitbucketConfiguration: (almKey: AlmKeys.BitbucketCloud | AlmKeys.BitbucketServer) =>
byRole('button', { name: `alm.${almKey}.long` }),
configurationInput: (id: string) =>
byRole('textbox', { name: `settings.almintegration.form.${id}` }),
updateSecretValueButton: (key: string) =>
byRole('button', {
name: `settings.almintegration.form.secret.update_field_x.settings.almintegration.form.${key}`,
}),
saveConfigurationButton: byRole('button', { name: 'settings.almintegration.form.save' }),
editConfigurationButton: (key: string) =>
byRole('button', { name: `settings.almintegration.edit_configuration.${key}` }),
deleteConfigurationButton: (key: string) =>
byRole('button', { name: `settings.almintegration.delete_configuration.${key}` }),
cancelButton: byRole('button', { name: 'cancel' }),
confirmDelete: byRole('button', { name: 'delete' }),
checkConfigurationButton: (key: string) =>
byRole('button', { name: `settings.almintegration.check_configuration_x.${key}` }),
validationErrorMessage: byRole('alert'),
validationSuccessMessage: byRole('status'),
};

describe('github tab', () => {
it('can create/edit/delete new configuration', async () => {
const { rerender } = renderAlmIntegration();
expect(await ui.almHeading.find()).toBeInTheDocument();
expect(ui.emptyIntro(AlmKeys.GitHub).get()).toBeInTheDocument();

// Create new configuration
await createConfiguration('Name', {
'name.github': 'Name',
'url.github': 'https://api.github.com',
app_id: 'Github App ID',
'client_id.github': 'Github Client ID',
'client_secret.github': 'Client Secret',
private_key: 'Key',
});

await editConfiguration('New Name', 'Name', 'client_secret.github', AlmKeys.GitHub);

await checkConfiguration('New Name');

rerender(<AlmIntegration />);
expect(await screen.findByRole('heading', { name: 'New Name' })).toBeInTheDocument();

await deleteConfiguration('New Name');
expect(ui.emptyIntro(AlmKeys.GitHub).get()).toBeInTheDocument();
});
});

describe.each([AlmKeys.GitLab, AlmKeys.Azure])(
'%s tab',
(almKey: AlmKeys.Azure | AlmKeys.GitLab) => {
it('can create/edit/delete new configuration', async () => {
renderAlmIntegration();
expect(await ui.almHeading.find()).toBeInTheDocument();

await userEvent.click(ui.tab(almKey).get());
expect(ui.emptyIntro(almKey).get()).toBeInTheDocument();

// Create new configuration
await createConfiguration('Name', {
[`name.${almKey}`]: 'Name',
[`url.${almKey}`]: 'https://api.alm.com',
personal_access_token: 'Access Token',
});

// Cannot create another configuration without Multiple Alm feature
expect(ui.createConfigurationButton.get()).toBeDisabled();

await editConfiguration('New Name', 'Name', 'personal_access_token', almKey);

await checkConfiguration('New Name');

await deleteConfiguration('New Name');
expect(ui.emptyIntro(almKey).get()).toBeInTheDocument();
});
}
);

describe('bitbucket tab', () => {
it('can create/edit/delete new configuration', async () => {
renderAlmIntegration([Feature.MultipleAlm]);
expect(await ui.almHeading.find()).toBeInTheDocument();

await userEvent.click(ui.tab(AlmKeys.BitbucketServer).get());
expect(ui.emptyIntro(AlmKeys.BitbucketServer).get()).toBeInTheDocument();

// Create new Bitbucket Server configuration
await createConfiguration(
'Name',
{
'name.bitbucket': 'Name',
'url.bitbucket': 'https://api.bitbucket.com',
personal_access_token: 'Access Token',
},
AlmKeys.BitbucketServer
);

// Create new Bitbucket Cloud configuration
await createConfiguration(
'Name Cloud',
{
'name.bitbucket': 'Name Cloud',
'workspace.bitbucketcloud': 'workspace',
'client_id.bitbucketcloud': 'Client ID',
'client_secret.bitbucketcloud': 'Client Secret',
},
AlmKeys.BitbucketCloud
);

// Edit, check delete Bitbucket Server configuration
await editConfiguration('New Name', 'Name', 'personal_access_token', AlmKeys.BitbucketServer);

await checkConfiguration('New Name');

await deleteConfiguration('New Name');

// Cloud configuration still exists
expect(screen.getByRole('heading', { name: 'Name Cloud' })).toBeInTheDocument();
});
});

async function createConfiguration(
name: string,
params: { [key: string]: string },
almKey?: AlmKeys.BitbucketCloud | AlmKeys.BitbucketServer
) {
await userEvent.click(ui.createConfigurationButton.get());
expect(ui.saveConfigurationButton.get()).toBeDisabled();

if (almKey) {
await userEvent.click(ui.bitbucketConfiguration(almKey).get());
}

for (const [key, value] of Object.entries(params)) {
// eslint-disable-next-line no-await-in-loop
await userEvent.type(ui.configurationInput(key).get(), value);
}
expect(ui.saveConfigurationButton.get()).toBeEnabled();
await userEvent.click(ui.saveConfigurationButton.get());

// New configuration is created
expect(screen.getByRole('heading', { name })).toBeInTheDocument();
}

async function editConfiguration(
newName: string,
currentName: string,
secretId: string,
almKey: AlmKeys
) {
almSettings.setDefinitionErrorMessage('Something is wrong');
await userEvent.click(ui.editConfigurationButton(currentName).get());
expect(ui.configurationInput(secretId).query()).not.toBeInTheDocument();
await userEvent.click(ui.updateSecretValueButton(secretId).get());
await userEvent.type(ui.configurationInput(secretId).get(), 'New Secret Value');
await userEvent.clear(ui.configurationInput(`name.${almKey}`).get());
await userEvent.type(ui.configurationInput(`name.${almKey}`).get(), newName);
await userEvent.click(ui.saveConfigurationButton.get());

// Existing configuration is edited
expect(screen.queryByRole('heading', { name: currentName })).not.toBeInTheDocument();
expect(screen.getByRole('heading', { name: newName })).toBeInTheDocument();
expect(ui.validationErrorMessage.get()).toHaveTextContent('Something is wrong');
}

async function checkConfiguration(name: string) {
almSettings.setDefinitionErrorMessage('');
await userEvent.click(ui.checkConfigurationButton(name).get());
expect(ui.validationSuccessMessage.getAll()[0]).toHaveTextContent(
'alert.tooltip.successsettings.almintegration.configuration_valid'
);
}

async function deleteConfiguration(name: string) {
await userEvent.click(ui.deleteConfigurationButton(name).get());
await userEvent.click(ui.cancelButton.get());
expect(screen.getByRole('heading', { name })).toBeInTheDocument();

await userEvent.click(ui.deleteConfigurationButton(name).get());
await userEvent.click(ui.confirmDelete.get());
expect(screen.queryByRole('heading', { name })).not.toBeInTheDocument();
}

function renderAlmIntegration(features: Feature[] = []) {
return renderComponent(
<AvailableFeaturesContext.Provider value={features}>
<AlmIntegration />
</AvailableFeaturesContext.Provider>
);
}

+ 0
- 192
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegration-test.tsx View File

@@ -1,192 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 {
countBindedProjects,
deleteConfiguration,
getAlmDefinitions,
validateAlmSettings,
} from '../../../../../api/alm-settings';
import { mockLocation, mockRouter } from '../../../../../helpers/testMocks';
import { waitAndUpdate } from '../../../../../helpers/testUtils';
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),
deleteConfiguration: jest.fn().mockResolvedValue(undefined),
getAlmDefinitions: jest
.fn()
.mockResolvedValue({ azure: [], bitbucket: [], bitbucketcloud: [], github: [], gitlab: [] }),
validateAlmSettings: jest.fn().mockResolvedValue(''),
}));

beforeEach(() => {
jest.clearAllMocks();
});

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should validate existing configurations', async () => {
(getAlmDefinitions as jest.Mock).mockResolvedValueOnce({
[AlmKeys.Azure]: [{ key: 'a1' }],
[AlmKeys.BitbucketServer]: [{ key: 'b1' }],
[AlmKeys.BitbucketCloud]: [{ key: 'bc1' }],
[AlmKeys.GitHub]: [{ key: 'gh1' }, { key: 'gh2' }],
[AlmKeys.GitLab]: [{ key: 'gl1' }],
});

const wrapper = shallowRender();

await waitAndUpdate(wrapper);

expect(validateAlmSettings).toHaveBeenCalledTimes(6);
expect(validateAlmSettings).toHaveBeenCalledWith('a1');
expect(validateAlmSettings).toHaveBeenCalledWith('b1');
expect(validateAlmSettings).toHaveBeenCalledWith('bc1');
expect(validateAlmSettings).toHaveBeenCalledWith('gh1');
expect(validateAlmSettings).toHaveBeenCalledWith('gh2');
expect(validateAlmSettings).toHaveBeenCalledWith('gl1');
});

it('should handle alm selection', async () => {
const router = mockRouter();
const wrapper = shallowRender({ router });

wrapper.setState({ currentAlmTab: AlmKeys.Azure });

wrapper.instance().handleSelectAlm(AlmKeys.GitHub);

await waitAndUpdate(wrapper);

expect(wrapper.state().currentAlmTab).toBe(AlmKeys.GitHub);
expect(router.push).toHaveBeenCalled();
});

it('should handle delete', async () => {
const toBeDeleted = '45672';
(countBindedProjects as jest.Mock).mockResolvedValueOnce(7);
const wrapper = shallowRender();

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().handleConfirmDelete('8345678');

await waitAndUpdate(wrapper);
expect(wrapper.state().projectCount).toBeUndefined();
expect(wrapper.state().definitionKeyForDeletion).toBeUndefined();
});

it('should validate a configuration', async () => {
const definitionKey = 'validated-key';
const failureMessage = 'an error occured';

const wrapper = shallowRender();
await waitAndUpdate(wrapper);

(validateAlmSettings as jest.Mock)
.mockRejectedValueOnce(undefined)
.mockResolvedValueOnce(failureMessage)
.mockResolvedValueOnce('')
.mockResolvedValueOnce('');

await wrapper.instance().handleCheck(definitionKey);

expect(wrapper.state().definitionStatus[definitionKey]).toEqual({
alertSuccess: true,
failureMessage: '',
type: AlmSettingsBindingStatusType.Warning,
});

await wrapper.instance().handleCheck(definitionKey);

expect(wrapper.state().definitionStatus[definitionKey]).toEqual({
alertSuccess: true,
failureMessage,
type: AlmSettingsBindingStatusType.Failure,
});

await wrapper.instance().handleCheck(definitionKey);

expect(wrapper.state().definitionStatus[definitionKey]).toEqual({
alertSuccess: true,
failureMessage: '',
type: AlmSettingsBindingStatusType.Success,
});
});

it('should fetch settings', async () => {
const definitions = {
[AlmKeys.Azure]: [{ key: 'a1' }],
[AlmKeys.BitbucketServer]: [{ key: 'b1' }],
[AlmKeys.BitbucketCloud]: [{ key: 'bc1' }],
[AlmKeys.GitHub]: [{ key: 'gh1' }],
[AlmKeys.GitLab]: [{ key: 'gl1' }],
};

const wrapper = shallowRender();
await waitAndUpdate(wrapper);

(getAlmDefinitions as jest.Mock).mockResolvedValueOnce(definitions);

await wrapper.instance().fetchPullRequestDecorationSetting();

expect(getAlmDefinitions).toHaveBeenCalled();
expect(wrapper.state().definitions).toEqual(definitions);
expect(wrapper.state().loadingAlmDefinitions).toBe(false);
});

it('should detect the current ALM from the query', () => {
let wrapper = shallowRender({ location: mockLocation() });
expect(wrapper.state().currentAlmTab).toBe(AlmKeys.GitHub);

wrapper = shallowRender({ location: mockLocation({ query: { alm: AlmKeys.BitbucketCloud } }) });
expect(wrapper.state().currentAlmTab).toBe(AlmKeys.BitbucketServer);

wrapper.setProps({ location: mockLocation({ query: { alm: AlmKeys.GitLab } }) });
expect(wrapper.state().currentAlmTab).toBe(AlmKeys.GitLab);
});

function shallowRender(props: Partial<AlmIntegration['props']> = {}) {
return shallow<AlmIntegration>(
<AlmIntegration
hasFeature={jest.fn().mockReturnValue(true)}
location={mockLocation()}
router={mockRouter()}
{...props}
/>
);
}

+ 0
- 57
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmIntegrationRenderer-test.tsx View File

@@ -1,57 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { AlmKeys } from '../../../../../types/alm-settings';
import AlmIntegrationRenderer, { AlmIntegrationRendererProps } from '../AlmIntegrationRenderer';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ loadingAlmDefinitions: true, loadingProjectCount: true })).toMatchSnapshot(
'loading'
);
expect(shallowRender({ definitionKeyForDeletion: 'keyToDelete' })).toMatchSnapshot(
'delete modal'
);
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}
currentAlmTab={AlmKeys.GitHub}
definitions={{ azure: [], bitbucket: [], bitbucketcloud: [], github: [], gitlab: [] }}
definitionStatus={{}}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={false}
onCancelDelete={jest.fn()}
onCheckConfiguration={jest.fn()}
onConfirmDelete={jest.fn()}
onDelete={jest.fn()}
onSelectAlmTab={jest.fn()}
onUpdateDefinitions={jest.fn()}
{...props}
/>
);
}

+ 0
- 92
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTab-test.tsx View File

@@ -1,92 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockAzureBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
import { waitAndUpdate } from '../../../../../helpers/testUtils';
import { AlmKeys } from '../../../../../types/alm-settings';
import AlmTab from '../AlmTab';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should handle cancel', async () => {
const wrapper = shallowRender();

wrapper.setState({
editedDefinition: mockAzureBindingDefinition(),
});

wrapper.instance().handleCancel();

await waitAndUpdate(wrapper);

expect(wrapper.state().editedDefinition).toBeUndefined();
});

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 handle create', async () => {
const wrapper = shallowRender();

wrapper.instance().handleCreate();
await waitAndUpdate(wrapper);
expect(wrapper.state().editedDefinition).toBeUndefined();
});

it('should handle afterSubmit', async () => {
const onUpdateDefinitions = jest.fn();
const onCheck = jest.fn();
const binding = mockAzureBindingDefinition();

const wrapper = shallowRender({ onUpdateDefinitions, onCheck });

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['props']> = {}) {
return shallow<AlmTab>(
<AlmTab
almTab={AlmKeys.Azure}
branchesEnabled={true}
definitions={[mockAzureBindingDefinition()]}
definitionStatus={{}}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={true}
onCheck={jest.fn()}
onDelete={jest.fn()}
onUpdateDefinitions={jest.fn()}
{...props}
/>
);
}

+ 0
- 110
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AlmTabRenderer-test.tsx View File

@@ -1,110 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 {
mockAzureBindingDefinition,
mockBitbucketCloudBindingDefinition,
mockGithubBindingDefinition,
} from '../../../../../helpers/mocks/alm-settings';
import { AlmKeys } from '../../../../../types/alm-settings';
import AlmTabRenderer, { AlmTabRendererProps } from '../AlmTabRenderer';

it('should render correctly for multi-ALM binding', () => {
expect(shallowRenderAzure({ loadingAlmDefinitions: true })).toMatchSnapshot(
'loading ALM definitions'
);
expect(shallowRenderAzure({ loadingProjectCount: true })).toMatchSnapshot(
'loading project count'
);
expect(shallowRenderAzure({})).toMatchSnapshot('loaded');
expect(shallowRenderAzure({ editedDefinition: mockAzureBindingDefinition() })).toMatchSnapshot(
'editing a definition'
);
});

it('should render correctly for single-ALM binding', () => {
expect(
shallowRenderAzure({ loadingAlmDefinitions: true, multipleAlmEnabled: false })
).toMatchSnapshot();
expect(shallowRenderAzure({ multipleAlmEnabled: false })).toMatchSnapshot();
expect(
shallowRenderAzure({ definitions: [mockAzureBindingDefinition()], multipleAlmEnabled: false })
).toMatchSnapshot();
});

it('should render correctly with validation', () => {
const githubProps = {
alm: AlmKeys.GitHub,
definitions: [mockGithubBindingDefinition()],
};
expect(shallowRender(githubProps)).toMatchSnapshot('default');
expect(shallowRender({ ...githubProps, definitions: [] })).toMatchSnapshot('empty');

expect(
shallowRender({
...githubProps,
editedDefinition: mockGithubBindingDefinition(),
})
).toMatchSnapshot('create a second');

expect(
shallowRender({
...githubProps,
definitions: [],
editedDefinition: mockGithubBindingDefinition(),
})
).toMatchSnapshot('create a first');

expect(
shallowRender({
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>) {
return shallowRender({
definitions: [mockAzureBindingDefinition()],
...props,
});
}

function shallowRender(props: Partial<AlmTabRendererProps> = {}) {
return shallow(
<AlmTabRenderer
almTab={AlmKeys.Azure}
branchesEnabled={true}
definitions={[]}
definitionStatus={{}}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={true}
onCancel={jest.fn()}
onCheck={jest.fn()}
onCreate={jest.fn()}
onDelete={jest.fn()}
onEdit={jest.fn()}
afterSubmit={jest.fn()}
{...props}
/>
);
}

+ 0
- 38
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/AzureForm-test.tsx View File

@@ -1,38 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockAzureBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
import AzureForm, { AzureFormProps } from '../AzureForm';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('create');
expect(shallowRender({ formData: mockAzureBindingDefinition() })).toMatchSnapshot('edit');
});

function shallowRender(props: Partial<AzureFormProps> = {}) {
return shallow(
<AzureForm
formData={{ key: '', personalAccessToken: '' }}
onFieldChange={jest.fn()}
{...props}
/>
);
}

+ 0
- 40
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketCloudForm-test.tsx View File

@@ -1,40 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockBitbucketCloudBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
import BitbucketCloudForm, { BitbucketCloudFormProps } from '../BitbucketCloudForm';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(
shallowRender({ formData: mockBitbucketCloudBindingDefinition({ workspace: 'my/workspace' }) })
).toMatchSnapshot('invalid workspace ID');
});

function shallowRender(props: Partial<BitbucketCloudFormProps> = {}) {
return shallow<BitbucketCloudFormProps>(
<BitbucketCloudForm
onFieldChange={jest.fn()}
formData={mockBitbucketCloudBindingDefinition()}
{...props}
/>
);
}

+ 0
- 78
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketForm-test.tsx View File

@@ -1,78 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 ButtonToggle from '../../../../../components/controls/ButtonToggle';
import {
mockBitbucketCloudBindingDefinition,
mockBitbucketServerBindingDefinition,
} from '../../../../../helpers/mocks/alm-settings';
import { AlmKeys } from '../../../../../types/alm-settings';
import BitbucketForm, { BitbucketFormProps } from '../BitbucketForm';

it('should render correctly', () => {
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(ButtonToggle).props().onCheck(AlmKeys.BitbucketServer);

expect(onVariantChange).toHaveBeenCalledWith(AlmKeys.BitbucketServer);
});

function shallowRender(props: Partial<BitbucketFormProps> = {}) {
return shallow(
<BitbucketForm
formData={mockBitbucketServerBindingDefinition()}
isUpdate={false}
onFieldChange={jest.fn()}
variant={AlmKeys.BitbucketServer}
onVariantChange={jest.fn()}
{...props}
/>
);
}

+ 0
- 38
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/BitbucketServerForm-test.tsx View File

@@ -1,38 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockBitbucketServerBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
import BitbucketServerForm, { BitbucketServerFormProps } from '../BitbucketServerForm';

it('should render correctly', () => {
const wrapper = shallowRender();
expect(wrapper).toMatchSnapshot();
});

function shallowRender(props: Partial<BitbucketServerFormProps> = {}) {
return shallow<BitbucketServerFormProps>(
<BitbucketServerForm
onFieldChange={jest.fn()}
formData={mockBitbucketServerBindingDefinition()}
{...props}
/>
);
}

+ 0
- 43
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/CreationTooltip-test.tsx View File

@@ -1,43 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockAppState } from '../../../../../helpers/testMocks';
import { AlmKeys } from '../../../../../types/alm-settings';
import { EditionKey } from '../../../../../types/editions';
import { CreationTooltip, CreationTooltipProps } from '../CreationTooltip';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ preventCreation: false })).toMatchSnapshot();
});

function shallowRender(props: Partial<CreationTooltipProps> = {}) {
return shallow(
<CreationTooltip
alm={AlmKeys.Azure}
appState={mockAppState({ edition: EditionKey.community })}
preventCreation={true}
{...props}
>
<span>Child</span>
</CreationTooltip>
);
}

+ 0
- 33
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/DeleteModal-test.tsx View File

@@ -1,33 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 DeleteModal, { DeleteModalProps } from '../DeleteModal';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ projectCount: undefined })).toMatchSnapshot();
});

function shallowRender(props: Partial<DeleteModalProps> = {}) {
return shallow(
<DeleteModal id="1" onCancel={jest.fn()} onDelete={jest.fn()} projectCount={4} {...props} />
);
}

+ 0
- 46
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GithubForm-test.tsx View File

@@ -1,46 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { mockGithubBindingDefinition } from '../../../../../helpers/mocks/alm-settings';
import GithubForm, { GithubFormProps } from '../GithubForm';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ formData: mockGithubBindingDefinition() })).toMatchSnapshot();
});

function shallowRender(props: Partial<GithubFormProps> = {}) {
return shallow(
<GithubForm
formData={{
key: '',
appId: '',
clientId: '',
clientSecret: '',
privateKey: '',
url: '',
webhookSecret: '',
}}
onFieldChange={jest.fn()}
{...props}
/>
);
}

+ 0
- 38
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/GitlabForm-test.tsx View File

@@ -1,38 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 GitlabForm, { GitlabFormProps } from '../GitlabForm';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ formData: mockGitlabBindingDefinition() })).toMatchSnapshot();
});

function shallowRender(props: Partial<GitlabFormProps> = {}) {
return shallow(
<GitlabForm
formData={{ key: '', personalAccessToken: '' }}
onFieldChange={jest.fn()}
{...props}
/>
);
}

+ 0
- 679
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionBox-test.tsx.snap View File

@@ -1,679 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: Azure DevOps 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
>
<div
className="actions pull-right"
>
<Button
onClick={[Function]}
>
<EditIcon
className="spacer-right"
/>
edit
</Button>
<Button
className="button-red spacer-left"
onClick={[Function]}
>
<DeleteIcon
className="spacer-right"
/>
delete
</Button>
</div>
<div
className="big-spacer-bottom"
>
<h3>
key
</h3>
</div>
<i
className="spinner spacer-right"
/>
settings.almintegration.checking_configuration
</div>
`;

exports[`should render correctly: default 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
>
<div
className="actions pull-right"
>
<Button
onClick={[Function]}
>
<EditIcon
className="spacer-right"
/>
edit
</Button>
<Button
className="button-red spacer-left"
onClick={[Function]}
>
<DeleteIcon
className="spacer-right"
/>
delete
</Button>
</div>
<div
className="big-spacer-bottom"
>
<h3>
key
</h3>
<span>
http://github.enterprise.com
</span>
</div>
<i
className="spinner spacer-right"
/>
settings.almintegration.checking_configuration
</div>
`;

exports[`should render correctly: error 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
>
<div
className="actions pull-right"
>
<Button
onClick={[Function]}
>
<EditIcon
className="spacer-right"
/>
edit
</Button>
<Button
className="button-red spacer-left"
onClick={[Function]}
>
<DeleteIcon
className="spacer-right"
/>
delete
</Button>
</div>
<div
className="big-spacer-bottom"
>
<h3>
key
</h3>
<span>
http://github.enterprise.com
</span>
</div>
<div
className="display-flex-row spacer-bottom"
>
<div
className="huge-spacer-right"
>
<Tooltip
overlay="settings.almintegration.feature.status_reporting.description_pr_and_commits"
>
<span>
settings.almintegration.feature.status_reporting.title
</span>
</Tooltip>
<AlertErrorIcon
className="spacer-left"
/>
</div>
<div>
<Tooltip
overlay="settings.almintegration.feature.alm_repo_import.description"
>
<span>
settings.almintegration.feature.alm_repo_import.title
</span>
</Tooltip>
<AlertErrorIcon
className="spacer-left"
/>
</div>
</div>
<div
className="width-50"
>
<Alert
variant="error"
>
Oops, something went wrong
</Alert>
</div>
<Button
className="big-spacer-top"
onClick={[Function]}
>
settings.almintegration.check_configuration
</Button>
</div>
`;

exports[`should render correctly: success 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
>
<div
className="actions pull-right"
>
<Button
onClick={[Function]}
>
<EditIcon
className="spacer-right"
/>
edit
</Button>
<Button
className="button-red spacer-left"
onClick={[Function]}
>
<DeleteIcon
className="spacer-right"
/>
delete
</Button>
</div>
<div
className="big-spacer-bottom"
>
<h3>
key
</h3>
<span>
http://github.enterprise.com
</span>
</div>
<div
className="display-flex-row spacer-bottom"
>
<div
className="huge-spacer-right"
>
<Tooltip
overlay="settings.almintegration.feature.status_reporting.description_pr_and_commits"
>
<span>
settings.almintegration.feature.status_reporting.title
</span>
</Tooltip>
<AlertSuccessIcon
className="spacer-left"
/>
</div>
<div>
<Tooltip
overlay="settings.almintegration.feature.alm_repo_import.description"
>
<span>
settings.almintegration.feature.alm_repo_import.title
</span>
</Tooltip>
<AlertSuccessIcon
className="spacer-left"
/>
</div>
</div>
<div
className="width-50"
/>
<Button
className="big-spacer-top"
onClick={[Function]}
>
settings.almintegration.check_configuration
</Button>
</div>
`;

exports[`should render correctly: success for Bitbucket Cloud 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
>
<div
className="actions pull-right"
>
<Button
onClick={[Function]}
>
<EditIcon
className="spacer-right"
/>
edit
</Button>
<Button
className="button-red spacer-left"
onClick={[Function]}
>
<DeleteIcon
className="spacer-right"
/>
delete
</Button>
</div>
<div
className="big-spacer-bottom"
>
<h3>
key
</h3>
</div>
<div
className="display-flex-row spacer-bottom"
>
<div
className="huge-spacer-right"
>
<Tooltip
overlay="settings.almintegration.feature.status_reporting.description_pr"
>
<span>
settings.almintegration.feature.status_reporting.title
</span>
</Tooltip>
<AlertSuccessIcon
className="spacer-left"
/>
</div>
<div>
<Tooltip
overlay="settings.almintegration.feature.alm_repo_import.description"
>
<span>
settings.almintegration.feature.alm_repo_import.title
</span>
</Tooltip>
<AlertSuccessIcon
className="spacer-left"
/>
</div>
</div>
<div
className="width-50"
/>
<Button
className="big-spacer-top"
onClick={[Function]}
>
settings.almintegration.check_configuration
</Button>
</div>
`;

exports[`should render correctly: success for GitLab 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
>
<div
className="actions pull-right"
>
<Button
onClick={[Function]}
>
<EditIcon
className="spacer-right"
/>
edit
</Button>
<Button
className="button-red spacer-left"
onClick={[Function]}
>
<DeleteIcon
className="spacer-right"
/>
delete
</Button>
</div>
<div
className="big-spacer-bottom"
>
<h3>
foo
</h3>
</div>
<div
className="display-flex-row spacer-bottom"
>
<div
className="huge-spacer-right"
>
<Tooltip
overlay="settings.almintegration.feature.status_reporting.description_mr"
>
<span>
settings.almintegration.feature.status_reporting.title
</span>
</Tooltip>
<AlertSuccessIcon
className="spacer-left"
/>
</div>
<div>
<Tooltip
overlay="settings.almintegration.feature.alm_repo_import.description"
>
<span>
settings.almintegration.feature.alm_repo_import.title
</span>
</Tooltip>
<div
className="display-inline-flex-center"
>
<strong
className="spacer-left"
>
settings.almintegration.feature.alm_repo_import.disabled
</strong>
<HelpTooltip
className="little-spacer-left"
overlay="settings.almintegration.feature.alm_repo_import.disabled.no_url"
/>
</div>
</div>
</div>
<div
className="width-50"
/>
<Button
className="big-spacer-top"
onClick={[Function]}
>
settings.almintegration.check_configuration
</Button>
</div>
`;

exports[`should render correctly: success with alert 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
>
<div
className="actions pull-right"
>
<Button
onClick={[Function]}
>
<EditIcon
className="spacer-right"
/>
edit
</Button>
<Button
className="button-red spacer-left"
onClick={[Function]}
>
<DeleteIcon
className="spacer-right"
/>
delete
</Button>
</div>
<div
className="big-spacer-bottom"
>
<h3>
key
</h3>
<span>
http://github.enterprise.com
</span>
</div>
<div
className="display-flex-row spacer-bottom"
>
<div
className="huge-spacer-right"
>
<Tooltip
overlay="settings.almintegration.feature.status_reporting.description_pr_and_commits"
>
<span>
settings.almintegration.feature.status_reporting.title
</span>
</Tooltip>
<AlertSuccessIcon
className="spacer-left"
/>
</div>
<div>
<Tooltip
overlay="settings.almintegration.feature.alm_repo_import.description"
>
<span>
settings.almintegration.feature.alm_repo_import.title
</span>
</Tooltip>
<AlertSuccessIcon
className="spacer-left"
/>
</div>
</div>
<div
className="width-50"
>
<Alert
variant="success"
>
settings.almintegration.configuration_valid
</Alert>
<Alert
variant="warning"
>
<FormattedMessage
defaultMessage="settings.almintegration.github.additional_permission"
id="settings.almintegration.github.additional_permission"
values={
{
"link": <withAppStateContext(DocLink)
to="/devops-platform-integration/github-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
}
}
/>
</Alert>
</div>
<Button
className="big-spacer-top"
onClick={[Function]}
>
settings.almintegration.check_configuration
</Button>
</div>
`;

exports[`should render correctly: success with branches disabled 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
>
<div
className="actions pull-right"
>
<Button
onClick={[Function]}
>
<EditIcon
className="spacer-right"
/>
edit
</Button>
<Button
className="button-red spacer-left"
onClick={[Function]}
>
<DeleteIcon
className="spacer-right"
/>
delete
</Button>
</div>
<div
className="big-spacer-bottom"
>
<h3>
key
</h3>
<span>
http://github.enterprise.com
</span>
</div>
<div
className="display-flex-row spacer-bottom"
>
<div
className="huge-spacer-right"
>
<Tooltip
overlay="settings.almintegration.feature.status_reporting.description_pr_and_commits"
>
<span>
settings.almintegration.feature.status_reporting.title
</span>
</Tooltip>
<div
className="display-inline-flex-center"
>
<strong
className="spacer-left"
>
settings.almintegration.feature.pr_decoration.disabled
</strong>
<HelpTooltip
className="little-spacer-left"
overlay={
<FormattedMessage
defaultMessage="settings.almintegration.feature.pr_decoration.disabled.no_branches"
id="settings.almintegration.feature.pr_decoration.disabled.no_branches"
values={
{
"link": <a
href="https://www.sonarsource.com/plans-and-pricing/developer/?sourceEdition=community"
rel="noopener noreferrer"
target="_blank"
>
settings.almintegration.feature.pr_decoration.disabled.no_branches.link
</a>,
}
}
/>
}
/>
</div>
</div>
<div>
<Tooltip
overlay="settings.almintegration.feature.alm_repo_import.description"
>
<span>
settings.almintegration.feature.alm_repo_import.title
</span>
</Tooltip>
<AlertSuccessIcon
className="spacer-left"
/>
</div>
</div>
<div
className="width-50"
>
<Alert
variant="success"
>
settings.almintegration.configuration_valid
</Alert>
<Alert
variant="warning"
>
<FormattedMessage
defaultMessage="settings.almintegration.github.additional_permission"
id="settings.almintegration.github.additional_permission"
values={
{
"link": <withAppStateContext(DocLink)
to="/devops-platform-integration/github-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
}
}
/>
</Alert>
</div>
<Button
className="big-spacer-top"
onClick={[Function]}
>
settings.almintegration.check_configuration
</Button>
</div>
`;

exports[`should render correctly: warning 1`] = `
<div
className="boxed-group-inner bordered spacer-top spacer-bottom it__alm-binding-definition"
>
<div
className="actions pull-right"
>
<Button
onClick={[Function]}
>
<EditIcon
className="spacer-right"
/>
edit
</Button>
<Button
className="button-red spacer-left"
onClick={[Function]}
>
<DeleteIcon
className="spacer-right"
/>
delete
</Button>
</div>
<div
className="big-spacer-bottom"
>
<h3>
key
</h3>
<span>
http://github.enterprise.com
</span>
</div>
<div
className="width-50"
>
<Alert
variant="warning"
>
settings.almintegration.could_not_validate
</Alert>
</div>
<Button
className="big-spacer-top"
onClick={[Function]}
>
settings.almintegration.check_configuration
</Button>
</div>
`;

+ 0
- 49
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionForm-test.tsx.snap View File

@@ -1,49 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: create 1`] = `
<AlmBindingDefinitionFormRenderer
alm="github"
canSubmit={false}
formData={
{
"appId": "",
"clientId": "",
"clientSecret": "",
"key": "",
"privateKey": "",
"url": "",
"webhookSecret": "",
}
}
isUpdate={false}
onBitbucketVariantChange={[Function]}
onCancel={[Function]}
onFieldChange={[Function]}
onSubmit={[Function]}
submitting={false}
/>
`;

exports[`should render correctly: edit 1`] = `
<AlmBindingDefinitionFormRenderer
alm="github"
canSubmit={false}
formData={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
isUpdate={true}
onBitbucketVariantChange={[Function]}
onCancel={[Function]}
onFieldChange={[Function]}
onSubmit={[Function]}
submitting={false}
/>
`;

+ 0
- 277
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormField-test.tsx.snap View File

@@ -1,277 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: default 1`] = `
<div
className="settings-definition"
>
<div
className="settings-definition-left"
>
<label
className="h3"
htmlFor="key"
>
settings.almintegration.form.key
</label>
<MandatoryFieldMarker />
</div>
<div
className="settings-definition-right big-padded-top display-flex-column"
>
<ValidationInput
errorPlacement={1}
isInvalid={false}
isValid={false}
>
<input
className="width-100"
id="key"
maxLength={40}
name="key"
onChange={[Function]}
size={50}
type="text"
value="key"
/>
</ValidationInput>
</div>
</div>
`;

exports[`should render correctly: encryptable 1`] = `
<div
className="settings-definition"
>
<div
className="settings-definition-left"
>
<label
className="h3"
htmlFor="key"
>
settings.almintegration.form.key
</label>
<MandatoryFieldMarker />
</div>
<div
className="settings-definition-right big-padded-top display-flex-column"
>
<ValidationInput
errorPlacement={1}
isInvalid={false}
isValid={false}
>
<input
className="width-100"
id="key"
maxLength={40}
name="key"
onChange={[Function]}
size={50}
type="text"
value="key"
/>
</ValidationInput>
<Alert
className="spacer-top"
variant="info"
>
<FormattedMessage
defaultMessage="settings.almintegration.form.secret.can_encrypt"
id="settings.almintegration.form.secret.can_encrypt"
values={
{
"learn_more": <withAppStateContext(DocLink)
to="/instance-administration/security/#settings-encryption"
>
learn_more
</withAppStateContext(DocLink)>,
}
}
/>
</Alert>
</div>
</div>
`;

exports[`should render correctly: invalid with error 1`] = `
<div
className="settings-definition"
>
<div
className="settings-definition-left"
>
<label
className="h3"
htmlFor="key"
>
settings.almintegration.form.key
</label>
<MandatoryFieldMarker />
</div>
<div
className="settings-definition-right big-padded-top display-flex-column"
>
<ValidationInput
error="some error message"
errorPlacement={1}
isInvalid={true}
isValid={false}
>
<input
className="width-100"
id="key"
maxLength={40}
name="key"
onChange={[Function]}
size={50}
type="text"
value="key"
/>
</ValidationInput>
</div>
</div>
`;

exports[`should render correctly: optional 1`] = `
<div
className="settings-definition"
>
<div
className="settings-definition-left"
>
<label
className="h3"
htmlFor="key"
>
settings.almintegration.form.key
</label>
</div>
<div
className="settings-definition-right big-padded-top display-flex-column"
>
<ValidationInput
errorPlacement={1}
isInvalid={false}
isValid={false}
>
<input
className="width-100"
id="key"
maxLength={40}
name="key"
onChange={[Function]}
size={50}
type="text"
value="key"
/>
</ValidationInput>
</div>
</div>
`;

exports[`should render correctly: secret 1`] = `
<div
className="settings-definition"
>
<div
className="settings-definition-left"
>
<label
className="h3"
htmlFor="key"
>
settings.almintegration.form.key
</label>
<MandatoryFieldMarker />
</div>
<div
className="settings-definition-right big-padded-top display-flex-column"
>
<div>
<p>
settings.almintegration.form.secret.field
</p>
<ButtonLink
onClick={[Function]}
>
settings.almintegration.form.secret.update_field
</ButtonLink>
</div>
</div>
</div>
`;

exports[`should render correctly: textarea 1`] = `
<div
className="settings-definition"
>
<div
className="settings-definition-left"
>
<label
className="h3"
htmlFor="key"
>
settings.almintegration.form.key
</label>
<MandatoryFieldMarker />
</div>
<div
className="settings-definition-right big-padded-top display-flex-column"
>
<textarea
className="width-100"
id="key"
maxLength={40}
onChange={[Function]}
required={true}
rows={5}
value="key"
/>
</div>
</div>
`;

exports[`should render correctly: with help 1`] = `
<div
className="settings-definition"
>
<div
className="settings-definition-left"
>
<label
className="h3"
htmlFor="key"
>
settings.almintegration.form.key
</label>
<MandatoryFieldMarker />
<div
className="markdown small spacer-top"
>
help
</div>
</div>
<div
className="settings-definition-right big-padded-top display-flex-column"
>
<ValidationInput
errorPlacement={1}
isInvalid={false}
isValid={false}
>
<input
className="width-100"
id="key"
maxLength={40}
name="key"
onChange={[Function]}
size={50}
type="text"
value="key"
/>
</ValidationInput>
</div>
</div>
`;

+ 0
- 484
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmBindingDefinitionFormRenderer-test.tsx.snap View File

@@ -1,484 +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"
>
<GithubForm
formData={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
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={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
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={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
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={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
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={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
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={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
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={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
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>
`;

exports[`should render correctly: with validation error 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={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
onFieldChange={[MockFunction]}
/>
<Alert
variant="error"
>
<p
className="spacer-bottom"
>
settings.almintegration.configuration_invalid
</p>
<ul
className="list-styled"
>
<li>
this is a validation error
</li>
</ul>
</Alert>
</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>
`;

+ 0
- 27
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegration-test.tsx.snap View File

@@ -1,27 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<AlmIntegrationRenderer
branchesEnabled={true}
currentAlmTab="github"
definitionStatus={{}}
definitions={
{
"azure": [],
"bitbucket": [],
"bitbucketcloud": [],
"github": [],
"gitlab": [],
}
}
loadingAlmDefinitions={true}
loadingProjectCount={false}
multipleAlmEnabled={true}
onCancelDelete={[Function]}
onCheckConfiguration={[Function]}
onConfirmDelete={[Function]}
onDelete={[Function]}
onSelectAlmTab={[Function]}
onUpdateDefinitions={[Function]}
/>
`;

+ 0
- 528
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmIntegrationRenderer-test.tsx.snap View File

@@ -1,528 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: azure 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="azure"
tabs={
[
{
"key": "github",
"label": <React.Fragment>
<img
alt="github"
className="spacer-right"
height={16}
src="/images/alm/github.svg"
/>
GitHub
</React.Fragment>,
},
{
"key": "bitbucket",
"label": <React.Fragment>
<img
alt="bitbucket"
className="spacer-right"
height={16}
src="/images/alm/bitbucket.svg"
/>
Bitbucket
</React.Fragment>,
},
{
"key": "azure",
"label": <React.Fragment>
<img
alt="azure"
className="spacer-right"
height={16}
src="/images/alm/azure.svg"
/>
Azure DevOps
</React.Fragment>,
},
{
"key": "gitlab",
"label": <React.Fragment>
<img
alt="gitlab"
className="spacer-right"
height={16}
src="/images/alm/gitlab.svg"
/>
GitLab
</React.Fragment>,
},
]
}
/>
<AlmTab
almTab="azure"
branchesEnabled={true}
definitionStatus={{}}
definitions={[]}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onUpdateDefinitions={[MockFunction]}
/>
</Fragment>
`;

exports[`should render correctly: bitbucket 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="bitbucket"
tabs={
[
{
"key": "github",
"label": <React.Fragment>
<img
alt="github"
className="spacer-right"
height={16}
src="/images/alm/github.svg"
/>
GitHub
</React.Fragment>,
},
{
"key": "bitbucket",
"label": <React.Fragment>
<img
alt="bitbucket"
className="spacer-right"
height={16}
src="/images/alm/bitbucket.svg"
/>
Bitbucket
</React.Fragment>,
},
{
"key": "azure",
"label": <React.Fragment>
<img
alt="azure"
className="spacer-right"
height={16}
src="/images/alm/azure.svg"
/>
Azure DevOps
</React.Fragment>,
},
{
"key": "gitlab",
"label": <React.Fragment>
<img
alt="gitlab"
className="spacer-right"
height={16}
src="/images/alm/gitlab.svg"
/>
GitLab
</React.Fragment>,
},
]
}
/>
<AlmTab
almTab="bitbucket"
branchesEnabled={true}
definitionStatus={{}}
definitions={[]}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onUpdateDefinitions={[MockFunction]}
/>
</Fragment>
`;

exports[`should render correctly: default 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="github"
tabs={
[
{
"key": "github",
"label": <React.Fragment>
<img
alt="github"
className="spacer-right"
height={16}
src="/images/alm/github.svg"
/>
GitHub
</React.Fragment>,
},
{
"key": "bitbucket",
"label": <React.Fragment>
<img
alt="bitbucket"
className="spacer-right"
height={16}
src="/images/alm/bitbucket.svg"
/>
Bitbucket
</React.Fragment>,
},
{
"key": "azure",
"label": <React.Fragment>
<img
alt="azure"
className="spacer-right"
height={16}
src="/images/alm/azure.svg"
/>
Azure DevOps
</React.Fragment>,
},
{
"key": "gitlab",
"label": <React.Fragment>
<img
alt="gitlab"
className="spacer-right"
height={16}
src="/images/alm/gitlab.svg"
/>
GitLab
</React.Fragment>,
},
]
}
/>
<AlmTab
almTab="github"
branchesEnabled={true}
definitionStatus={{}}
definitions={[]}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onUpdateDefinitions={[MockFunction]}
/>
</Fragment>
`;

exports[`should render correctly: delete modal 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="github"
tabs={
[
{
"key": "github",
"label": <React.Fragment>
<img
alt="github"
className="spacer-right"
height={16}
src="/images/alm/github.svg"
/>
GitHub
</React.Fragment>,
},
{
"key": "bitbucket",
"label": <React.Fragment>
<img
alt="bitbucket"
className="spacer-right"
height={16}
src="/images/alm/bitbucket.svg"
/>
Bitbucket
</React.Fragment>,
},
{
"key": "azure",
"label": <React.Fragment>
<img
alt="azure"
className="spacer-right"
height={16}
src="/images/alm/azure.svg"
/>
Azure DevOps
</React.Fragment>,
},
{
"key": "gitlab",
"label": <React.Fragment>
<img
alt="gitlab"
className="spacer-right"
height={16}
src="/images/alm/gitlab.svg"
/>
GitLab
</React.Fragment>,
},
]
}
/>
<AlmTab
almTab="github"
branchesEnabled={true}
definitionStatus={{}}
definitions={[]}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onUpdateDefinitions={[MockFunction]}
/>
<DeleteModal
id="keyToDelete"
onCancel={[MockFunction]}
onDelete={[MockFunction]}
/>
</Fragment>
`;

exports[`should render correctly: gitlab 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="gitlab"
tabs={
[
{
"key": "github",
"label": <React.Fragment>
<img
alt="github"
className="spacer-right"
height={16}
src="/images/alm/github.svg"
/>
GitHub
</React.Fragment>,
},
{
"key": "bitbucket",
"label": <React.Fragment>
<img
alt="bitbucket"
className="spacer-right"
height={16}
src="/images/alm/bitbucket.svg"
/>
Bitbucket
</React.Fragment>,
},
{
"key": "azure",
"label": <React.Fragment>
<img
alt="azure"
className="spacer-right"
height={16}
src="/images/alm/azure.svg"
/>
Azure DevOps
</React.Fragment>,
},
{
"key": "gitlab",
"label": <React.Fragment>
<img
alt="gitlab"
className="spacer-right"
height={16}
src="/images/alm/gitlab.svg"
/>
GitLab
</React.Fragment>,
},
]
}
/>
<AlmTab
almTab="gitlab"
branchesEnabled={true}
definitionStatus={{}}
definitions={[]}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onUpdateDefinitions={[MockFunction]}
/>
</Fragment>
`;

exports[`should render correctly: loading 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="github"
tabs={
[
{
"key": "github",
"label": <React.Fragment>
<img
alt="github"
className="spacer-right"
height={16}
src="/images/alm/github.svg"
/>
GitHub
</React.Fragment>,
},
{
"key": "bitbucket",
"label": <React.Fragment>
<img
alt="bitbucket"
className="spacer-right"
height={16}
src="/images/alm/bitbucket.svg"
/>
Bitbucket
</React.Fragment>,
},
{
"key": "azure",
"label": <React.Fragment>
<img
alt="azure"
className="spacer-right"
height={16}
src="/images/alm/azure.svg"
/>
Azure DevOps
</React.Fragment>,
},
{
"key": "gitlab",
"label": <React.Fragment>
<img
alt="gitlab"
className="spacer-right"
height={16}
src="/images/alm/gitlab.svg"
/>
GitLab
</React.Fragment>,
},
]
}
/>
<AlmTab
almTab="github"
branchesEnabled={true}
definitionStatus={{}}
definitions={[]}
loadingAlmDefinitions={true}
loadingProjectCount={true}
multipleAlmEnabled={false}
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onUpdateDefinitions={[MockFunction]}
/>
</Fragment>
`;

+ 0
- 26
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTab-test.tsx.snap View File

@@ -1,26 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<AlmTabRenderer
afterSubmit={[Function]}
almTab="azure"
branchesEnabled={true}
definitionStatus={{}}
definitions={
[
{
"key": "key",
"personalAccessToken": "asdf1234",
},
]
}
loadingAlmDefinitions={false}
loadingProjectCount={false}
multipleAlmEnabled={true}
onCancel={[Function]}
onCheck={[MockFunction]}
onCreate={[Function]}
onDelete={[MockFunction]}
onEdit={[Function]}
/>
`;

+ 0
- 594
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AlmTabRenderer-test.tsx.snap View File

@@ -1,594 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly for multi-ALM binding: editing a definition 1`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={false}
>
<Button
data-test="settings__alm-create"
disabled={false}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="azure"
branchesEnabled={true}
definition={
{
"key": "key",
"personalAccessToken": "asdf1234",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly for multi-ALM binding: loaded 1`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={false}
>
<Button
data-test="settings__alm-create"
disabled={false}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="azure"
branchesEnabled={true}
definition={
{
"key": "key",
"personalAccessToken": "asdf1234",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly for multi-ALM binding: loading ALM definitions 1`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={true}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={false}
>
<Button
data-test="settings__alm-create"
disabled={false}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="azure"
branchesEnabled={true}
definition={
{
"key": "key",
"personalAccessToken": "asdf1234",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly for multi-ALM binding: loading project count 1`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={true}
>
<Button
data-test="settings__alm-create"
disabled={true}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="azure"
branchesEnabled={true}
definition={
{
"key": "key",
"personalAccessToken": "asdf1234",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly for single-ALM binding 1`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={true}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={true}
>
<Button
data-test="settings__alm-create"
disabled={true}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="azure"
branchesEnabled={true}
definition={
{
"key": "key",
"personalAccessToken": "asdf1234",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly for single-ALM binding 2`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={true}
>
<Button
data-test="settings__alm-create"
disabled={true}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="azure"
branchesEnabled={true}
definition={
{
"key": "key",
"personalAccessToken": "asdf1234",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly for single-ALM binding 3`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={true}
>
<Button
data-test="settings__alm-create"
disabled={true}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="azure"
branchesEnabled={true}
definition={
{
"key": "key",
"personalAccessToken": "asdf1234",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly with validation: create a first 1`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<p
className="spacer-top"
>
settings.almintegration.empty.azure
</p>
<div
className="big-spacer-top"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={false}
>
<Button
data-test="settings__alm-create"
disabled={false}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly with validation: create a second 1`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={false}
>
<Button
data-test="settings__alm-create"
disabled={false}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="azure"
branchesEnabled={true}
definition={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly with validation: default 1`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={false}
>
<Button
data-test="settings__alm-create"
disabled={false}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="azure"
branchesEnabled={true}
definition={
{
"appId": "123456",
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"privateKey": "asdf1234",
"url": "http://github.enterprise.com",
"webhookSecret": "verySecretText!!",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly with validation: empty 1`] = `
<div
aria-labelledby="tab-azure"
className="bordered"
id="tabpanel-azure"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<p
className="spacer-top"
>
settings.almintegration.empty.azure
</p>
<div
className="big-spacer-top"
>
<withAppStateContext(CreationTooltip)
alm="azure"
preventCreation={false}
>
<Button
data-test="settings__alm-create"
disabled={false}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
</DeferredSpinner>
</div>
</div>
`;

exports[`should render correctly with validation: pass the correct key for bitbucket cloud 1`] = `
<div
aria-labelledby="tab-bitbucket"
className="bordered"
id="tabpanel-bitbucket"
role="tabpanel"
>
<div
className="big-padded"
>
<DeferredSpinner
loading={false}
>
<div
className="spacer-bottom text-right"
>
<withAppStateContext(CreationTooltip)
alm="bitbucket"
preventCreation={false}
>
<Button
data-test="settings__alm-create"
disabled={false}
onClick={[MockFunction]}
>
settings.almintegration.create
</Button>
</withAppStateContext(CreationTooltip)>
</div>
<AlmBindingDefinitionBox
alm="bitbucketcloud"
branchesEnabled={true}
definition={
{
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"workspace": "workspace",
}
}
key="key"
onCheck={[MockFunction]}
onDelete={[MockFunction]}
onEdit={[MockFunction]}
/>
</DeferredSpinner>
</div>
<Alert
className="spacer"
variant="info"
>
<FormattedMessage
defaultMessage="settings.almintegration.tabs.authentication_moved"
id="settings.almintegration.tabs.authentication-moved"
values={
{
"link": <ForwardRef(Link)
to={
{
"pathname": "/admin/settings",
"search": "category=authentication&tab=bitbucket",
}
}
>
property.category.authentication
</ForwardRef(Link)>,
}
}
/>
</Alert>
</div>
`;

+ 0
- 143
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/AzureForm-test.tsx.snap View File

@@ -1,143 +0,0 @@
// 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"
maxLength={200}
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={
<FormattedMessage
defaultMessage="settings.almintegration.form.personal_access_token.azure.help"
id="settings.almintegration.form.personal_access_token.azure.help"
values={
{
"doc_link": <withAppStateContext(DocLink)
to="/devops-platform-integration/azure-devops-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
"pat": <ForwardRef(Link)
target="_blank"
to="https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate"
>
settings.almintegration.form.personal_access_token.azure.help.url
</ForwardRef(Link)>,
"permission": <strong>
Code &gt; Read & Write
</strong>,
}
}
/>
}
id="personal_access_token"
isSecret={true}
isTextArea={true}
maxLength={2000}
onFieldChange={[MockFunction]}
overwriteOnly={false}
propKey="personalAccessToken"
value=""
/>
</Fragment>
`;

exports[`should render correctly: edit 1`] = `
<Fragment>
<AlmBindingDefinitionFormField
autoFocus={true}
help="settings.almintegration.form.name.azure.help"
id="name.azure"
maxLength={200}
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={
<FormattedMessage
defaultMessage="settings.almintegration.form.personal_access_token.azure.help"
id="settings.almintegration.form.personal_access_token.azure.help"
values={
{
"doc_link": <withAppStateContext(DocLink)
to="/devops-platform-integration/azure-devops-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
"pat": <ForwardRef(Link)
target="_blank"
to="https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate"
>
settings.almintegration.form.personal_access_token.azure.help.url
</ForwardRef(Link)>,
"permission": <strong>
Code &gt; Read & Write
</strong>,
}
}
/>
}
id="personal_access_token"
isSecret={true}
isTextArea={true}
maxLength={2000}
onFieldChange={[MockFunction]}
overwriteOnly={true}
propKey="personalAccessToken"
value="asdf1234"
/>
</Fragment>
`;

+ 0
- 170
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketCloudForm-test.tsx.snap View File

@@ -1,170 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: default 1`] = `
<Fragment>
<AlmBindingDefinitionFormField
autoFocus={true}
help="settings.almintegration.form.name.bitbucketcloud.help"
id="name.bitbucket"
maxLength={200}
onFieldChange={[MockFunction]}
propKey="key"
value="key"
/>
<AlmBindingDefinitionFormField
help={
<FormattedMessage
defaultMessage="settings.almintegration.form.workspace.bitbucketcloud.help"
id="settings.almintegration.form.workspace.bitbucketcloud.help"
values={
{
"example": <React.Fragment>
https://bitbucket.org/
<strong>
{workspace}
</strong>
/{repository}
</React.Fragment>,
}
}
/>
}
id="workspace.bitbucketcloud"
isInvalid={false}
maxLength={80}
onFieldChange={[MockFunction]}
propKey="workspace"
value="workspace"
/>
<Alert
className="big-spacer-top"
variant="info"
>
<FormattedMessage
defaultMessage="settings.almintegration.bitbucketcloud.info"
id="settings.almintegration.bitbucketcloud.info"
values={
{
"doc_link": <withAppStateContext(DocLink)
to="/devops-platform-integration/bitbucket-integration/bitbucket-cloud-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
"oauth": <ForwardRef(Link)
target="_blank"
to="https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/"
>
settings.almintegration.bitbucketcloud.oauth
</ForwardRef(Link)>,
"permission": <strong>
Pull Requests: Read
</strong>,
}
}
/>
</Alert>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.oauth_key.bitbucketcloud.help"
id="client_id.bitbucketcloud"
maxLength={80}
onFieldChange={[MockFunction]}
propKey="clientId"
value="client1"
/>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.oauth_secret.bitbucketcloud.help"
id="client_secret.bitbucketcloud"
isSecret={true}
maxLength={160}
onFieldChange={[MockFunction]}
overwriteOnly={true}
propKey="clientSecret"
value="**clientsecret**"
/>
</Fragment>
`;

exports[`should render correctly: invalid workspace ID 1`] = `
<Fragment>
<AlmBindingDefinitionFormField
autoFocus={true}
help="settings.almintegration.form.name.bitbucketcloud.help"
id="name.bitbucket"
maxLength={200}
onFieldChange={[MockFunction]}
propKey="key"
value="key"
/>
<AlmBindingDefinitionFormField
error="settings.almintegration.form.workspace.bitbucketcloud.error"
help={
<FormattedMessage
defaultMessage="settings.almintegration.form.workspace.bitbucketcloud.help"
id="settings.almintegration.form.workspace.bitbucketcloud.help"
values={
{
"example": <React.Fragment>
https://bitbucket.org/
<strong>
{workspace}
</strong>
/{repository}
</React.Fragment>,
}
}
/>
}
id="workspace.bitbucketcloud"
isInvalid={true}
maxLength={80}
onFieldChange={[MockFunction]}
propKey="workspace"
value="my/workspace"
/>
<Alert
className="big-spacer-top"
variant="info"
>
<FormattedMessage
defaultMessage="settings.almintegration.bitbucketcloud.info"
id="settings.almintegration.bitbucketcloud.info"
values={
{
"doc_link": <withAppStateContext(DocLink)
to="/devops-platform-integration/bitbucket-integration/bitbucket-cloud-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
"oauth": <ForwardRef(Link)
target="_blank"
to="https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/"
>
settings.almintegration.bitbucketcloud.oauth
</ForwardRef(Link)>,
"permission": <strong>
Pull Requests: Read
</strong>,
}
}
/>
</Alert>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.oauth_key.bitbucketcloud.help"
id="client_id.bitbucketcloud"
maxLength={80}
onFieldChange={[MockFunction]}
propKey="clientId"
value="client1"
/>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.oauth_secret.bitbucketcloud.help"
id="client_secret.bitbucketcloud"
isSecret={true}
maxLength={160}
onFieldChange={[MockFunction]}
overwriteOnly={true}
propKey="clientSecret"
value="**clientsecret**"
/>
</Fragment>
`;

+ 0
- 119
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap View File

@@ -1,119 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: bbc 1`] = `
<Fragment>
<div
className="display-flex-column"
>
<strong>
settings.almintegration.form.choose_bitbucket_variant
</strong>
<div
className="little-spacer-top big-spacer-bottom"
>
<ButtonToggle
label="settings.almintegration.form.choose_bitbucket_variant"
onCheck={[MockFunction]}
options={
[
{
"label": "Bitbucket Server",
"value": "bitbucket",
},
{
"label": "Bitbucket Cloud",
"value": "bitbucketcloud",
},
]
}
value="bitbucketcloud"
/>
</div>
</div>
<BitbucketCloudForm
formData={
{
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"workspace": "workspace",
}
}
onFieldChange={[MockFunction]}
/>
</Fragment>
`;

exports[`should render correctly: bbs 1`] = `
<Fragment>
<div
className="display-flex-column"
>
<strong>
settings.almintegration.form.choose_bitbucket_variant
</strong>
<div
className="little-spacer-top big-spacer-bottom"
>
<ButtonToggle
label="settings.almintegration.form.choose_bitbucket_variant"
onCheck={[MockFunction]}
options={
[
{
"label": "Bitbucket Server",
"value": "bitbucket",
},
{
"label": "Bitbucket Cloud",
"value": "bitbucketcloud",
},
]
}
value="bitbucket"
/>
</div>
</div>
<BitbucketServerForm
formData={
{
"key": "key",
"personalAccessToken": "asdf1234",
"url": "http://bbs.enterprise.com",
}
}
onFieldChange={[MockFunction]}
/>
</Fragment>
`;

exports[`should render correctly: update bbc 1`] = `
<Fragment>
<BitbucketCloudForm
formData={
{
"clientId": "client1",
"clientSecret": "**clientsecret**",
"key": "key",
"workspace": "workspace",
}
}
onFieldChange={[MockFunction]}
/>
</Fragment>
`;

exports[`should render correctly: update bbs 1`] = `
<Fragment>
<BitbucketServerForm
formData={
{
"key": "key",
"personalAccessToken": "asdf1234",
"url": "http://bbs.enterprise.com",
}
}
onFieldChange={[MockFunction]}
/>
</Fragment>
`;

+ 0
- 67
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketServerForm-test.tsx.snap View File

@@ -1,67 +0,0 @@
// 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={200}
onFieldChange={[MockFunction]}
propKey="key"
value="key"
/>
<AlmBindingDefinitionFormField
help={
<FormattedMessage
defaultMessage="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={[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={
{
"doc_link": <withAppStateContext(DocLink)
to="/devops-platform-integration/bitbucket-integration/bitbucket-server-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
"pat": <ForwardRef(Link)
target="_blank"
to="https://confluence.atlassian.com/bitbucketserver0515/personal-access-tokens-961275199.html"
>
settings.almintegration.form.personal_access_token.bitbucket.help.url
</ForwardRef(Link)>,
"permission": <strong>
Read
</strong>,
}
}
/>
}
id="personal_access_token"
isSecret={true}
isTextArea={true}
maxLength={2000}
onFieldChange={[MockFunction]}
overwriteOnly={true}
propKey="personalAccessToken"
value="asdf1234"
/>
</Fragment>
`;

+ 0
- 40
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/CreationTooltip-test.tsx.snap View File

@@ -1,40 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<Tooltip
mouseLeaveDelay={0.25}
overlay={
<FormattedMessage
defaultMessage="settings.almintegration.create.tooltip"
id="settings.almintegration.create.tooltip"
values={
{
"alm": "alm.azure",
"link": <a
href="https://www.sonarsource.com/plans-and-pricing/enterprise/?sourceEdition=community"
rel="noopener noreferrer"
target="_blank"
>
settings.almintegration.create.tooltip.link
</a>,
}
}
/>
}
>
<span>
Child
</span>
</Tooltip>
`;

exports[`should render correctly 2`] = `
<Tooltip
mouseLeaveDelay={0.25}
overlay={null}
>
<span>
Child
</span>
</Tooltip>
`;

+ 0
- 62
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/DeleteModal-test.tsx.snap View File

@@ -1,62 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<ConfirmModal
confirmButtonText="delete"
confirmData="1"
header="settings.almintegration.delete.header"
isDestructive={true}
onClose={[MockFunction]}
onConfirm={[MockFunction]}
>
<p
className="spacer-bottom"
>
<FormattedMessage
defaultMessage="settings.almintegration.delete.message"
id="settings.almintegration.delete.message"
values={
{
"id": <b>
1
</b>,
}
}
/>
</p>
<p>
settings.almintegration.delete.info.4
</p>
</ConfirmModal>
`;

exports[`should render correctly 2`] = `
<ConfirmModal
confirmButtonText="delete"
confirmData="1"
header="settings.almintegration.delete.header"
isDestructive={true}
onClose={[MockFunction]}
onConfirm={[MockFunction]}
>
<p
className="spacer-bottom"
>
<FormattedMessage
defaultMessage="settings.almintegration.delete.message"
id="settings.almintegration.delete.message"
values={
{
"id": <b>
1
</b>,
}
}
/>
</p>
<p>
settings.almintegration.delete.no_info
</p>
</ConfirmModal>
`;

+ 0
- 207
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GithubForm-test.tsx.snap View File

@@ -1,207 +0,0 @@
// 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"
maxLength={200}
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=""
/>
<Alert
className="big-spacer-top"
variant="info"
>
<FormattedMessage
defaultMessage="settings.almintegration.github.info"
id="settings.almintegration.github.info"
values={
{
"link": <withAppStateContext(DocLink)
to="/devops-platform-integration/github-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
}
}
/>
</Alert>
<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"
isSecret={true}
maxLength={160}
onFieldChange={[MockFunction]}
overwriteOnly={false}
propKey="clientSecret"
value=""
/>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.private_key.github.help"
id="private_key"
isSecret={true}
isTextArea={true}
maxLength={2500}
onFieldChange={[MockFunction]}
overwriteOnly={false}
propKey="privateKey"
value=""
/>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.webhook_secret.github.help"
id="webhook_secret.github"
isSecret={true}
maxLength={160}
onFieldChange={[MockFunction]}
optional={true}
overwriteOnly={false}
propKey="webhookSecret"
value=""
/>
</Fragment>
`;

exports[`should render correctly 2`] = `
<Fragment>
<AlmBindingDefinitionFormField
autoFocus={true}
help="settings.almintegration.form.name.github.help"
id="name.github"
maxLength={200}
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"
/>
<Alert
className="big-spacer-top"
variant="info"
>
<FormattedMessage
defaultMessage="settings.almintegration.github.info"
id="settings.almintegration.github.info"
values={
{
"link": <withAppStateContext(DocLink)
to="/devops-platform-integration/github-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
}
}
/>
</Alert>
<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"
isSecret={true}
maxLength={160}
onFieldChange={[MockFunction]}
overwriteOnly={true}
propKey="clientSecret"
value="**clientsecret**"
/>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.private_key.github.help"
id="private_key"
isSecret={true}
isTextArea={true}
maxLength={2500}
onFieldChange={[MockFunction]}
overwriteOnly={true}
propKey="privateKey"
value="asdf1234"
/>
<AlmBindingDefinitionFormField
help="settings.almintegration.form.webhook_secret.github.help"
id="webhook_secret.github"
isSecret={true}
maxLength={160}
onFieldChange={[MockFunction]}
optional={true}
overwriteOnly={true}
propKey="webhookSecret"
value="verySecretText!!"
/>
</Fragment>
`;

+ 0
- 135
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/GitlabForm-test.tsx.snap View File

@@ -1,135 +0,0 @@
// 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"
maxLength={200}
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={
<FormattedMessage
defaultMessage="settings.almintegration.form.personal_access_token.gitlab.help"
id="settings.almintegration.form.personal_access_token.gitlab.help"
values={
{
"doc_link": <withAppStateContext(DocLink)
to="/devops-platform-integration/gitlab-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
"pat": <ForwardRef(Link)
target="_blank"
to="https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html"
>
settings.almintegration.form.personal_access_token.gitlab.help.url
</ForwardRef(Link)>,
"permission": <strong>
Reporter
</strong>,
"scope": <strong>
api
</strong>,
}
}
/>
}
id="personal_access_token"
isSecret={true}
isTextArea={true}
maxLength={2000}
onFieldChange={[MockFunction]}
overwriteOnly={false}
propKey="personalAccessToken"
value=""
/>
</Fragment>
`;

exports[`should render correctly 2`] = `
<Fragment>
<AlmBindingDefinitionFormField
autoFocus={true}
help="settings.almintegration.form.name.gitlab.help"
id="name.gitlab"
maxLength={200}
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={
<FormattedMessage
defaultMessage="settings.almintegration.form.personal_access_token.gitlab.help"
id="settings.almintegration.form.personal_access_token.gitlab.help"
values={
{
"doc_link": <withAppStateContext(DocLink)
to="/devops-platform-integration/gitlab-integration/"
>
learn_more
</withAppStateContext(DocLink)>,
"pat": <ForwardRef(Link)
target="_blank"
to="https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html"
>
settings.almintegration.form.personal_access_token.gitlab.help.url
</ForwardRef(Link)>,
"permission": <strong>
Reporter
</strong>,
"scope": <strong>
api
</strong>,
}
}
/>
}
id="personal_access_token"
isSecret={true}
isTextArea={true}
maxLength={2000}
onFieldChange={[MockFunction]}
overwriteOnly={true}
propKey="personalAccessToken"
value="foobar"
/>
</Fragment>
`;

+ 3
- 1
server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.tsx View File

@@ -107,7 +107,9 @@ export default class EncryptionForm extends React.PureComponent<Props, State> {

{encryptedValue && (
<div>
<span className="little-spacer-right">{translate('encryption.encrypted_value')}</span>
<label className="little-spacer-right" htmlFor="encrypted-value">
{translate('encryption.encrypted_value')}
</label>
<input
className="input-clear input-code input-super-large"
id="encrypted-value"

+ 4
- 1
server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx View File

@@ -66,8 +66,11 @@ export default class GenerateSecretKeyForm extends React.PureComponent<Props, St
{secretKey ? (
<>
<div className="big-spacer-bottom">
<h3 className="spacer-bottom">{translate('encryption.secret_key')}</h3>
<h3 className="spacer-bottom" id="secret-key-title">
{translate('encryption.secret_key')}
</h3>
<input
aria-labelledby="secret-key-title"
className="input-clear input-code input-large"
id="secret-key"
readOnly={true}

+ 73
- 0
server/sonar-web/src/main/js/apps/settings/encryption/__tests__/EncryptionApp-it.tsx View File

@@ -0,0 +1,73 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 userEvent from '@testing-library/user-event';
import React from 'react';
import { byRole } from 'testing-library-selector';
import SettingsServiceMock from '../../../../api/mocks/SettingsServiceMock';
import { renderComponent } from '../../../../helpers/testReactTestingUtils';
import EncryptionApp from '../EncryptionApp';

jest.mock('../../../../api/settings');

let settingsMock: SettingsServiceMock;

beforeAll(() => {
settingsMock = new SettingsServiceMock();
});

afterEach(() => {
settingsMock.reset();
});

const ui = {
appHeading: byRole('heading', { name: 'property.category.security.encryption' }),
generateSecretButton: byRole('button', { name: 'encryption.generate_secret_key' }),
secretKeyHeading: byRole('heading', { name: 'encryption.secret_key' }),
copyToClipboard: byRole('button', { name: 'copy_to_clipboard' }),
encryptTextarea: byRole('textbox'),
encryptButton: byRole('button', { name: 'encryption.encrypt' }),
generateNewSecretButton: byRole('button', { name: 'encryption.generate_new_secret_key' }),
};

it('should be able to generate new key', async () => {
renderEncryptionApp();

expect(await ui.appHeading.find()).toBeInTheDocument();
await userEvent.click(ui.generateSecretButton.get());
expect(ui.copyToClipboard.get()).toHaveAttribute('data-clipboard-text', 'secretKey');
});

it('should be able to encrypt property value when secret is registered', async () => {
settingsMock.setSecretKeyAvailable(true);
renderEncryptionApp();

expect(await ui.appHeading.find()).toBeInTheDocument();
await userEvent.type(ui.encryptTextarea.get(), 'sonar.announcement.message');
await userEvent.click(ui.encryptButton.get());
expect(ui.copyToClipboard.get()).toHaveAttribute('data-clipboard-text', 'encryptedValue');

// can generate new secret in view
await userEvent.click(ui.generateNewSecretButton.get());
expect(ui.copyToClipboard.get()).toHaveAttribute('data-clipboard-text', 'secretKey');
});

function renderEncryptionApp() {
return renderComponent(<EncryptionApp />);
}

+ 0
- 59
server/sonar-web/src/main/js/apps/settings/encryption/__tests__/EncryptionApp-test.tsx View File

@@ -1,59 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 { checkSecretKey, generateSecretKey } from '../../../../api/settings';
import { waitAndUpdate } from '../../../../helpers/testUtils';
import EncryptionApp from '../EncryptionApp';

jest.mock('../../../../api/settings', () => ({
checkSecretKey: jest.fn().mockResolvedValue({ secretKeyAvailable: true }),
generateSecretKey: jest.fn().mockResolvedValue({ secretKey: 'secret' }),
}));

it('should render correctly', () => {
const wrapper = shallowRender();
expect(wrapper).toMatchSnapshot('loading');
expect(wrapper.setState({ loading: false, secretKeyAvailable: false })).toMatchSnapshot(
'generate form'
);
expect(wrapper.setState({ secretKeyAvailable: true })).toMatchSnapshot('encryption form');
});

it('should correctly check a key', async () => {
const wrapper = shallowRender();
wrapper.instance().checkSecretKey();
await waitAndUpdate(wrapper);
expect(checkSecretKey).toHaveBeenCalled();
expect(wrapper.state().secretKeyAvailable).toBe(true);
});

it('should correctly generate a key', async () => {
const wrapper = shallowRender();
wrapper.instance().generateSecretKey();
await waitAndUpdate(wrapper);
expect(generateSecretKey).toHaveBeenCalled();
expect(wrapper.state().secretKey).toBe('secret');
expect(wrapper.state().secretKeyAvailable).toBe(false);
});

function shallowRender(props: Partial<EncryptionApp['props']> = {}) {
return shallow<EncryptionApp>(<EncryptionApp {...props} />);
}

+ 0
- 30
server/sonar-web/src/main/js/apps/settings/encryption/__tests__/EncryptionForm-test.tsx View File

@@ -1,30 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 EncryptionForm from '../EncryptionForm';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

function shallowRender() {
return shallow(<EncryptionForm generateSecretKey={jest.fn()} />);
}

+ 0
- 30
server/sonar-web/src/main/js/apps/settings/encryption/__tests__/GenerateSecretKeyForm-test.tsx View File

@@ -1,30 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2023 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 GenerateSecretKeyForm from '../GenerateSecretKeyForm';

it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
});

function shallowRender() {
return shallow(<GenerateSecretKeyForm generateSecretKey={jest.fn()} />);
}

+ 0
- 85
server/sonar-web/src/main/js/apps/settings/encryption/__tests__/__snapshots__/EncryptionApp-test.tsx.snap View File

@@ -1,85 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: encryption form 1`] = `
<div
className="page page-limited"
id="encryption-page"
>
<Helmet
defer={false}
encodeSpecialCharacters={true}
prioritizeSeoTags={false}
title="property.category.security.encryption"
/>
<header
className="page-header"
>
<h1
className="page-title"
>
property.category.security.encryption
</h1>
<DeferredSpinner
loading={false}
/>
</header>
<EncryptionForm
generateSecretKey={[Function]}
/>
</div>
`;

exports[`should render correctly: generate form 1`] = `
<div
className="page page-limited"
id="encryption-page"
>
<Helmet
defer={false}
encodeSpecialCharacters={true}
prioritizeSeoTags={false}
title="property.category.security.encryption"
/>
<header
className="page-header"
>
<h1
className="page-title"
>
property.category.security.encryption
</h1>
<DeferredSpinner
loading={false}
/>
</header>
<GenerateSecretKeyForm
generateSecretKey={[Function]}
/>
</div>
`;

exports[`should render correctly: loading 1`] = `
<div
className="page page-limited"
id="encryption-page"
>
<Helmet
defer={false}
encodeSpecialCharacters={true}
prioritizeSeoTags={false}
title="property.category.security.encryption"
/>
<header
className="page-header"
>
<h1
className="page-title"
>
property.category.security.encryption
</h1>
<DeferredSpinner
loading={true}
/>
</header>
</div>
`;

+ 0
- 74
server/sonar-web/src/main/js/apps/settings/encryption/__tests__/__snapshots__/EncryptionForm-test.tsx.snap View File

@@ -1,74 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div
id="encryption-form-container"
>
<div
className="spacer-bottom"
>
encryption.form_intro
</div>
<form
className="big-spacer-bottom"
id="encryption-form"
onSubmit={[Function]}
>
<textarea
autoFocus={true}
className="abs-width-600"
id="encryption-form-value"
onChange={[Function]}
required={true}
rows={5}
value=""
/>
<div
className="spacer-top"
>
<SubmitButton
disabled={false}
>
encryption.encrypt
</SubmitButton>
<DeferredSpinner
className="spacer-left"
loading={false}
/>
</div>
</form>
<form
className="huge-spacer-top bordered-top"
id="encryption-new-key-form"
onSubmit={[Function]}
>
<p
className="big-spacer-top spacer-bottom"
>
<FormattedMessage
defaultMessage="encryption.form_note"
id="encryption.form_note"
values={
{
"moreInformationLink": <withAppStateContext(DocLink)
to="/instance-administration/security/"
>
more_information
</withAppStateContext(DocLink)>,
}
}
/>
</p>
<SubmitButton
disabled={false}
>
encryption.generate_new_secret_key
</SubmitButton>
<DeferredSpinner
className="spacer-left"
loading={false}
/>
</form>
</div>
`;

+ 0
- 39
server/sonar-web/src/main/js/apps/settings/encryption/__tests__/__snapshots__/GenerateSecretKeyForm-test.tsx.snap View File

@@ -1,39 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly 1`] = `
<div
id="generate-secret-key-form-container"
>
<form
id="generate-secret-key-form"
onSubmit={[Function]}
>
<p
className="spacer-bottom"
>
<FormattedMessage
defaultMessage="encryption.secret_key_description"
id="encryption.secret_key_description"
values={
{
"moreInformationLink": <withAppStateContext(DocLink)
to="/instance-administration/security/"
>
more_information
</withAppStateContext(DocLink)>,
}
}
/>
</p>
<SubmitButton
disabled={false}
>
encryption.generate_secret_key
</SubmitButton>
<DeferredSpinner
className="spacer-left"
loading={false}
/>
</form>
</div>
`;

+ 8
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -1207,6 +1207,10 @@ settings.projects.change_visibility_form.submit=Change Default Visibility

settings.almintegration.title=DevOps Platform Integrations
settings.almintegration.description=DevOps Platform integrations allow SonarQube to interact with your DevOps Platform. This enables things like authentication, or providing analysis details and a Quality Gate to your Pull Requests directly in your DevOps Platform's interface.
settings.almintegration.tab.github=GitHub
settings.almintegration.tab.bitbucket=Bitbucket
settings.almintegration.tab.azure=Azure DevOps
settings.almintegration.tab.gitlab=GitLab
settings.almintegration.github.info=You need to install a GitHub App with specific settings and permissions to enable Pull Request Decoration on your Organization or Repository. {link}
settings.almintegration.github.additional_permission=If Quality Gate status reporting fails on private projects, you might need to add an additional permission to the GitHub App. {link}
settings.almintegration.bitbucketcloud.info=SonarQube needs you to create an {oauth} in your Bitbucket Cloud workspace settings to report the Quality Gate status on Pull Requests. It needs to be a private consumer with {permission} permission. An OAuth callback URL is required by Bitbucket Cloud but not used by SonarQube so any URL works. {doc_link}
@@ -1220,6 +1224,9 @@ settings.almintegration.create=Create configuration
settings.almintegration.create.tooltip=Upgrade to {link} to integrate with multiple {alm} instances.
settings.almintegration.create.tooltip.link=Enterprise Edition
settings.almintegration.check_configuration=Check configuration
settings.almintegration.check_configuration_x=Check configuration '{0}'
settings.almintegration.edit_configuration=Edit configuration '{0}'
settings.almintegration.delete_configuration=Delete configuration '{0}'
settings.almintegration.checking_configuration=Checking configuration
settings.almintegration.configuration_valid=Configuration valid
settings.almintegration.configuration_invalid=You have the following errors in your configuration:
@@ -1279,6 +1286,7 @@ settings.almintegration.form.save=Save configuration
settings.almintegration.form.cancel=Cancel
settings.almintegration.form.secret.field=This field is hidden for security reasons.
settings.almintegration.form.secret.update_field=Update field value
settings.almintegration.form.secret.update_field_x=Update {0} value
settings.almintegration.form.secret.can_encrypt=You can encrypt this value. {learn_more}
settings.almintegration.feature.status_reporting.title=Quality Gate status reporting
settings.almintegration.feature.status_reporting.description_pr=Add analysis and a Quality Gate to your Pull Requests directly in your DevOps Platform's interface.

Loading…
Cancel
Save