}
export function getProjectAlmBinding(project: string): Promise<T.ProjectAlmBinding> {
- return getJSON('/api/alm_settings/get_github_binding', { project });
+ return getJSON('/api/alm_settings/get_binding', { project });
}
export function deleteProjectAlmBinding(project: string): Promise<void> {
return post('/api/alm_settings/delete_binding', { project }).catch(throwGlobalError);
}
-export function setProjectAlmBinding(data: T.GithubProjectAlmBinding) {
+export function setProjectAzureBinding(data: T.AzureProjectAlmBinding) {
+ return post('/api/alm_settings/set_azure_binding', data).catch(throwGlobalError);
+}
+
+export function setProjectGithubBinding(data: T.GithubProjectAlmBinding) {
return post('/api/alm_settings/set_github_binding', data).catch(throwGlobalError);
}
deleteProjectAlmBinding,
getAlmSettings,
getProjectAlmBinding,
- setProjectAlmBinding
+ setProjectAzureBinding,
+ setProjectGithubBinding
} from '../../../../api/almSettings';
import throwGlobalError from '../../../../app/utils/throwGlobalError';
+import { ALM_KEYS } from '../../utils';
import PRDecorationBindingRenderer from './PRDecorationBindingRenderer';
interface Props {
}
interface State {
- formData: T.GithubBinding;
+ formData: T.ProjectAlmBinding;
hasBinding: boolean;
instances: T.AlmSettingsInstance[];
isValid: boolean;
success: boolean;
}
+const FIELDS_BY_ALM: { [almKey: string]: Array<'repository'> } = {
+ [ALM_KEYS.AZURE]: [],
+ [ALM_KEYS.GITHUB]: ['repository']
+};
+
export default class PRDecorationBinding extends React.PureComponent<Props, State> {
mounted = false;
state: State = {
return Promise.all([getAlmSettings(project), this.getProjectBinding(project)])
.then(([instances, data]) => {
if (this.mounted) {
- this.setState(({ formData }) => ({
- formData: data || formData,
- hasBinding: Boolean(data),
- instances,
- isValid: this.validateForm(),
- loading: false
- }));
+ this.setState(({ formData }) => {
+ const newFormData = data || formData;
+ return {
+ formData: newFormData,
+ hasBinding: Boolean(data),
+ instances,
+ isValid: this.validateForm(newFormData),
+ loading: false
+ };
+ });
if (!data && instances.length === 1) {
this.handleFieldChange('key', instances[0].key);
.catch(this.catchError);
};
+ submitProjectAlmBinding(
+ alm: ALM_KEYS,
+ key: string,
+ almSpecificFields?: { repository?: string }
+ ): Promise<void> {
+ const almSetting = key;
+ const project = this.props.component.key;
+
+ switch (alm) {
+ case ALM_KEYS.AZURE:
+ return setProjectAzureBinding({
+ almSetting,
+ project
+ });
+ case ALM_KEYS.GITHUB: {
+ const repository = almSpecificFields && almSpecificFields.repository;
+ if (!repository) {
+ return Promise.reject();
+ }
+ return setProjectGithubBinding({
+ almSetting,
+ project,
+ repository
+ });
+ }
+ default:
+ return Promise.reject();
+ }
+ }
+
handleSubmit = () => {
this.setState({ saving: true });
const {
- formData: { key, repository }
+ formData: { key, ...additionalFields },
+ instances
} = this.state;
- if (key && repository) {
- setProjectAlmBinding({
- almSetting: key,
- project: this.props.component.key,
- repository
- })
+ const selected = instances.find(i => i.key === key);
+ if (!key || !selected) {
+ return;
+ }
+
+ if (key) {
+ this.submitProjectAlmBinding(selected.alm as ALM_KEYS, key, additionalFields)
.then(() => {
if (this.mounted) {
this.setState({
}
};
- handleFieldChange = (id: keyof T.GithubBinding, value: string) => {
- this.setState(({ formData: formdata }) => ({
- formData: {
- ...formdata,
+ handleFieldChange = (id: keyof T.ProjectAlmBinding, value: string) => {
+ this.setState(({ formData }) => {
+ const newFormData = {
+ ...formData,
[id]: value
- },
- isValid: this.validateForm(),
- success: false
- }));
+ };
+ return {
+ formData: newFormData,
+ isValid: this.validateForm(newFormData),
+ success: false
+ };
+ });
};
- validateForm = () => {
- const { formData } = this.state;
- return Object.values(formData).reduce(
- (result: boolean, value) => result && Boolean(value),
+ validateForm = ({ key, ...additionalFields }: State['formData']) => {
+ const { instances } = this.state;
+ const selected = instances.find(i => i.key === key);
+ if (!key || !selected) {
+ return false;
+ }
+ return FIELDS_BY_ALM[selected.alm as ALM_KEYS].reduce(
+ (result: boolean, field) => result && Boolean(additionalFields[field]),
true
);
};
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import { translate } from 'sonar-ui-common/helpers/l10n';
+import { ALM_KEYS } from '../../utils';
export interface PRDecorationBindingRendererProps {
- formData: T.GithubBinding;
+ formData: T.ProjectAlmBinding;
hasBinding: boolean;
instances: T.AlmSettingsInstance[];
isValid: boolean;
loading: boolean;
- onFieldChange: (id: keyof T.GithubBinding, value: string) => void;
+ onFieldChange: (id: keyof T.ProjectAlmBinding, value: string) => void;
onReset: () => void;
onSubmit: () => void;
saving: boolean;
);
}
+ const selected = key && instances.find(i => i.key === key);
+ const alm = selected && (selected.alm as ALM_KEYS);
+
return (
<div>
<header className="page-header">
/>
</div>
- {key && (
+ {alm === ALM_KEYS.GITHUB && (
<div className="form-field">
<label htmlFor="repository">
{translate('settings.pr_decoration.binding.form.repository')}
deleteProjectAlmBinding,
getAlmSettings,
getProjectAlmBinding,
- setProjectAlmBinding
+ setProjectAzureBinding,
+ setProjectGithubBinding
} from '../../../../../api/almSettings';
import { mockComponent } from '../../../../../helpers/testMocks';
+import { ALM_KEYS } from '../../../utils';
import PRDecorationBinding from '../PRDecorationBinding';
jest.mock('../../../../../api/almSettings', () => ({
getAlmSettings: jest.fn().mockResolvedValue([]),
getProjectAlmBinding: jest.fn().mockResolvedValue(undefined),
- setProjectAlmBinding: jest.fn().mockResolvedValue(undefined),
+ setProjectAzureBinding: jest.fn().mockResolvedValue(undefined),
+ setProjectGithubBinding: jest.fn().mockResolvedValue(undefined),
deleteProjectAlmBinding: jest.fn().mockResolvedValue(undefined)
}));
it('should fill selects and fill formdata', async () => {
const url = 'github.com';
- const instances = [{ key: 'instance1', url, alm: 'github' }];
+ const instances = [{ key: 'instance1', url, alm: ALM_KEYS.GITHUB }];
const formdata = {
key: 'instance1',
repository: 'account/repo'
expect(wrapper.state().hasBinding).toBe(false);
});
-it('should handle submit', async () => {
+it('should handle submit to github or azure', async () => {
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
- wrapper.setState({ formData });
+ const instances = [
+ { key: 'github', alm: ALM_KEYS.GITHUB },
+ { key: 'azure', alm: ALM_KEYS.AZURE }
+ ];
+ // Github
+ const githubKey = 'github';
+ const repository = 'repo/path';
+ wrapper.setState({ formData: { key: githubKey, repository }, instances });
wrapper.instance().handleSubmit();
await waitAndUpdate(wrapper);
- expect(setProjectAlmBinding).toBeCalledWith({
- almSetting: formData.key,
+ expect(setProjectGithubBinding).toBeCalledWith({
+ almSetting: githubKey,
project: PROJECT_KEY,
- repository: formData.repository
+ repository
+ });
+ expect(wrapper.state().hasBinding).toBe(true);
+ expect(wrapper.state().success).toBe(true);
+
+ // azure
+ const azureKey = 'azure';
+ wrapper.setState({ formData: { key: azureKey } });
+ wrapper.instance().handleSubmit();
+ await waitAndUpdate(wrapper);
+
+ expect(setProjectAzureBinding).toBeCalledWith({
+ almSetting: azureKey,
+ project: PROJECT_KEY
});
expect(wrapper.state().hasBinding).toBe(true);
expect(wrapper.state().success).toBe(true);
it('should handle failures gracefully', async () => {
(getProjectAlmBinding as jest.Mock).mockRejectedValueOnce({ status: 500 });
- (setProjectAlmBinding as jest.Mock).mockRejectedValueOnce({ status: 500 });
+ (setProjectGithubBinding as jest.Mock).mockRejectedValueOnce({ status: 500 });
(deleteProjectAlmBinding as jest.Mock).mockRejectedValueOnce({ status: 500 });
const wrapper = shallowRender();
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
- expect(wrapper.instance().validateForm()).toBe(false);
-
- wrapper.setState({ formData: { key: '', repository: 'c' } });
- expect(wrapper.instance().validateForm()).toBe(false);
+ expect(wrapper.instance().validateForm({ key: '', repository: '' })).toBe(false);
+ expect(wrapper.instance().validateForm({ key: '', repository: 'c' })).toBe(false);
- wrapper.setState({ formData: { key: 'a', repository: 'c' } });
- expect(wrapper.instance().validateForm()).toBe(true);
+ wrapper.setState({
+ instances: [{ key: 'azure', alm: ALM_KEYS.AZURE }, { key: 'github', alm: ALM_KEYS.GITHUB }]
+ });
+ expect(wrapper.instance().validateForm({ key: 'azure' })).toBe(true);
+ expect(wrapper.instance().validateForm({ key: 'github', repository: '' })).toBe(false);
+ expect(wrapper.instance().validateForm({ key: 'github', repository: 'asdf' })).toBe(true);
});
function shallowRender(props: Partial<PRDecorationBinding['props']> = {}) {
expect(
shallowRender({
formData: {
- key: 'Github - main instance',
+ key: 'i1',
repository: 'account/repo'
},
hasBinding: true,
]
}
searchable={false}
- value="Github - main instance"
+ value="i1"
/>
</div>
<div
export interface ProjectAlmBinding {
key: string;
- alm: string;
- url: string;
- repository: string;
+ repository?: string;
}
- export interface GithubProjectAlmBinding {
+ export interface AzureProjectAlmBinding {
almSetting: string;
project: string;
- repository: string;
}
- export interface GithubBinding {
- key: string;
- repository?: string;
+ export interface GithubProjectAlmBinding {
+ almSetting: string;
+ project: string;
+ repository: string;
}
}