@@ -26,6 +26,7 @@ import { | |||
AzureProjectAlmBindingParams, | |||
BitbucketBindingDefinition, | |||
BitbucketCloudBindingDefinition, | |||
BitbucketCloudProjectAlmBindingParams, | |||
BitbucketProjectAlmBindingParams, | |||
GithubBindingDefinition, | |||
GithubProjectAlmBindingParams, | |||
@@ -132,6 +133,10 @@ export function setProjectBitbucketBinding(data: BitbucketProjectAlmBindingParam | |||
return post('/api/alm_settings/set_bitbucket_binding', data).catch(throwGlobalError); | |||
} | |||
export function setProjectBitbucketCloudBinding(data: BitbucketCloudProjectAlmBindingParams) { | |||
return post('/api/alm_settings/set_bitbucketcloud_binding', data).catch(throwGlobalError); | |||
} | |||
export function setProjectGithubBinding(data: GithubProjectAlmBindingParams) { | |||
return post('/api/alm_settings/set_github_binding', data).catch(throwGlobalError); | |||
} |
@@ -53,19 +53,48 @@ it('should not fetch alm bindings if user cannot create projects', async () => { | |||
}); | |||
it('should filter alm bindings appropriately', async () => { | |||
(getAlmSettings as jest.Mock).mockResolvedValueOnce([ | |||
{ alm: AlmKeys.Azure }, | |||
{ alm: AlmKeys.BitbucketServer, url: 'b1' }, | |||
{ alm: AlmKeys.BitbucketServer, url: 'b2' }, | |||
{ alm: AlmKeys.GitHub }, | |||
{ alm: AlmKeys.GitLab, url: 'gitlab.com' } | |||
]); | |||
(getAlmSettings as jest.Mock) | |||
.mockResolvedValueOnce([ | |||
// Only faulty configs. | |||
{ alm: AlmKeys.Azure }, // Missing some configuration; will be ignored. | |||
{ alm: AlmKeys.BitbucketCloud }, // Bitbucket Cloud isn't supported. | |||
{ alm: AlmKeys.GitLab } // Missing some configuration; will be ignored. | |||
]) | |||
.mockResolvedValueOnce([ | |||
// All correct configs. | |||
{ alm: AlmKeys.Azure, url: 'http://ado.example.com' }, | |||
{ alm: AlmKeys.BitbucketServer, url: 'b1' }, | |||
{ alm: AlmKeys.GitHub }, | |||
{ alm: AlmKeys.GitLab, url: 'gitlab.com' } | |||
]) | |||
.mockResolvedValueOnce([ | |||
// Only duplicate ALMs; should all be ignored. | |||
{ alm: AlmKeys.Azure, url: 'http://ado.example.com' }, | |||
{ alm: AlmKeys.Azure, url: 'http://ado.example.com' }, | |||
{ alm: AlmKeys.BitbucketServer, url: 'b1' }, | |||
{ alm: AlmKeys.BitbucketServer, url: 'b1' }, | |||
{ alm: AlmKeys.GitHub }, | |||
{ alm: AlmKeys.GitHub }, | |||
{ alm: AlmKeys.GitLab, url: 'gitlab.com' }, | |||
{ alm: AlmKeys.GitLab, url: 'gitlab.com' } | |||
]); | |||
const wrapper = shallowRender(); | |||
let wrapper = shallowRender(); | |||
await waitAndUpdate(wrapper); | |||
expect(wrapper.state().boundAlms).toEqual([]); | |||
wrapper = shallowRender(); | |||
await waitAndUpdate(wrapper); | |||
expect(wrapper.state().boundAlms).toEqual([ | |||
AlmKeys.Azure, | |||
AlmKeys.BitbucketServer, | |||
AlmKeys.GitHub, | |||
AlmKeys.GitLab | |||
]); | |||
expect(wrapper.state().boundAlms).toEqual([AlmKeys.GitHub, AlmKeys.GitLab]); | |||
wrapper = shallowRender(); | |||
await waitAndUpdate(wrapper); | |||
expect(wrapper.state().boundAlms).toEqual([]); | |||
}); | |||
function shallowRender(overrides: Partial<ProjectCreationMenu['props']> = {}) { |
@@ -217,7 +217,27 @@ export default function AlmSpecificForm(props: AlmSpecificFormProps) { | |||
propKey: 'slug', | |||
value: slug || '' | |||
})} | |||
{renderMonoRepoFieldWithDocLink(ALM_DOCUMENTATION_PATHS[AlmKeys.Bitbucket])} | |||
{renderMonoRepoFieldWithDocLink(ALM_DOCUMENTATION_PATHS[AlmKeys.BitbucketServer])} | |||
</> | |||
); | |||
case AlmKeys.BitbucketCloud: | |||
return ( | |||
<> | |||
{renderField({ | |||
help: true, | |||
helpParams: { | |||
example: ( | |||
<> | |||
{'https://bitbucket.org/{workspace}/'} | |||
<strong>{'{repository}'}</strong> | |||
</> | |||
) | |||
}, | |||
id: 'bitbucketcloud.repository', | |||
onFieldChange: props.onFieldChange, | |||
propKey: 'repository', | |||
value: repository || '' | |||
})} | |||
</> | |||
); | |||
case AlmKeys.GitHub: |
@@ -26,6 +26,7 @@ import { | |||
getProjectAlmBinding, | |||
setProjectAzureBinding, | |||
setProjectBitbucketBinding, | |||
setProjectBitbucketCloudBinding, | |||
setProjectGithubBinding, | |||
setProjectGitlabBinding | |||
} from '../../../../api/alm-settings'; | |||
@@ -193,6 +194,16 @@ export class PRDecorationBinding extends React.PureComponent<Props & StateProps, | |||
monorepo | |||
}); | |||
} | |||
case AlmKeys.BitbucketCloud: { | |||
if (!repository) { | |||
return Promise.reject(); | |||
} | |||
return setProjectBitbucketCloudBinding({ | |||
almSetting, | |||
project, | |||
repository | |||
}); | |||
} | |||
case AlmKeys.GitHub: { | |||
// By default it must remain true. | |||
const summaryCommentEnabled = |
@@ -27,6 +27,7 @@ it.each([ | |||
[AlmKeys.Azure, true], | |||
[AlmKeys.BitbucketServer, false], | |||
[AlmKeys.BitbucketServer, true], | |||
[AlmKeys.BitbucketCloud, false], | |||
[AlmKeys.GitHub, false], | |||
[AlmKeys.GitHub, true], | |||
[AlmKeys.GitLab, false], |
@@ -26,6 +26,7 @@ import { | |||
getProjectAlmBinding, | |||
setProjectAzureBinding, | |||
setProjectBitbucketBinding, | |||
setProjectBitbucketCloudBinding, | |||
setProjectGithubBinding, | |||
setProjectGitlabBinding | |||
} from '../../../../../api/alm-settings'; | |||
@@ -40,6 +41,7 @@ jest.mock('../../../../../api/alm-settings', () => ({ | |||
setProjectBitbucketBinding: jest.fn().mockResolvedValue(undefined), | |||
setProjectGithubBinding: jest.fn().mockResolvedValue(undefined), | |||
setProjectGitlabBinding: jest.fn().mockResolvedValue(undefined), | |||
setProjectBitbucketCloudBinding: jest.fn().mockResolvedValue(undefined), | |||
deleteProjectAlmBinding: jest.fn().mockResolvedValue(undefined) | |||
})); | |||
@@ -94,7 +96,8 @@ describe('handleSubmit', () => { | |||
{ key: 'github', alm: AlmKeys.GitHub }, | |||
{ key: 'azure', alm: AlmKeys.Azure }, | |||
{ key: 'bitbucket', alm: AlmKeys.BitbucketServer }, | |||
{ key: 'gitlab', alm: AlmKeys.GitLab } | |||
{ key: 'gitlab', alm: AlmKeys.GitLab }, | |||
{ key: 'bitbucketcloud', alm: AlmKeys.BitbucketCloud } | |||
]; | |||
it('should work for github', async () => { | |||
@@ -187,6 +190,28 @@ describe('handleSubmit', () => { | |||
}); | |||
expect(wrapper.state().success).toBe(true); | |||
}); | |||
it('should work for bitbucket cloud', async () => { | |||
const wrapper = shallowRender(); | |||
await waitAndUpdate(wrapper); | |||
const bitbucketKey = 'bitbucketcloud'; | |||
const repository = 'repoKey'; | |||
wrapper.setState({ formData: { key: bitbucketKey, repository }, instances: [] }); | |||
wrapper.instance().handleSubmit(); | |||
await waitAndUpdate(wrapper); | |||
expect(setProjectBitbucketCloudBinding).not.toBeCalled(); | |||
wrapper.setState({ formData: { key: bitbucketKey, repository }, instances }); | |||
wrapper.instance().handleSubmit(); | |||
await waitAndUpdate(wrapper); | |||
expect(setProjectBitbucketCloudBinding).toBeCalledWith({ | |||
almSetting: bitbucketKey, | |||
project: PROJECT_KEY, | |||
repository | |||
}); | |||
expect(wrapper.state().success).toBe(true); | |||
}); | |||
}); | |||
describe.each([[500], [404]])('For status %i', status => { | |||
@@ -266,6 +291,7 @@ it.each([ | |||
[AlmKeys.BitbucketServer, {}], | |||
[AlmKeys.BitbucketServer, { slug: 'test' }], | |||
[AlmKeys.BitbucketServer, { repository: 'test' }], | |||
[AlmKeys.BitbucketCloud, {}], | |||
[AlmKeys.GitHub, {}], | |||
[AlmKeys.GitLab, {}] | |||
])('should properly reject promise for %s & %s', async (almKey: AlmKeys, params: {}) => { | |||
@@ -290,6 +316,7 @@ it('should validate form', async () => { | |||
instances: [ | |||
{ key: 'azure', alm: AlmKeys.Azure }, | |||
{ key: 'bitbucket', alm: AlmKeys.BitbucketServer }, | |||
{ key: 'bitbucketcloud', alm: AlmKeys.BitbucketCloud }, | |||
{ key: 'github', alm: AlmKeys.GitHub }, | |||
{ key: 'gitlab', alm: AlmKeys.GitLab } | |||
] | |||
@@ -303,6 +330,8 @@ it('should validate form', async () => { | |||
{ values: { key: 'github', repository: 'asdf' }, result: true }, | |||
{ values: { key: 'bitbucket', repository: 'key' }, result: false }, | |||
{ values: { key: 'bitbucket', repository: 'key', slug: 'slug' }, result: true }, | |||
{ values: { key: 'bitbucketcloud', repository: '' }, result: false }, | |||
{ values: { key: 'bitbucketcloud', repository: 'key' }, result: true }, | |||
{ values: { key: 'gitlab' }, result: false }, | |||
{ values: { key: 'gitlab', repository: 'key' }, result: true } | |||
].forEach(({ values, result }) => { |
@@ -424,6 +424,55 @@ exports[`it should render correctly for bitbucket and monorepo=true 1`] = ` | |||
</Fragment> | |||
`; | |||
exports[`it should render correctly for bitbucketcloud and monorepo=false 1`] = ` | |||
<Fragment> | |||
<div | |||
className="form-field" | |||
> | |||
<label | |||
className="display-flex-center" | |||
htmlFor="bitbucketcloud.repository" | |||
> | |||
settings.pr_decoration.binding.form.bitbucketcloud.repository | |||
<em | |||
className="mandatory" | |||
> | |||
* | |||
</em> | |||
<HelpTooltip | |||
className="spacer-left" | |||
overlay={ | |||
<FormattedMessage | |||
defaultMessage="settings.pr_decoration.binding.form.bitbucketcloud.repository.help" | |||
id="settings.pr_decoration.binding.form.bitbucketcloud.repository.help" | |||
values={ | |||
Object { | |||
"example": <React.Fragment> | |||
https://bitbucket.org/{workspace}/ | |||
<strong> | |||
{repository} | |||
</strong> | |||
</React.Fragment>, | |||
} | |||
} | |||
/> | |||
} | |||
placement="right" | |||
/> | |||
</label> | |||
<input | |||
className="input-super-large" | |||
id="bitbucketcloud.repository" | |||
maxLength={256} | |||
name="bitbucketcloud.repository" | |||
onChange={[Function]} | |||
type="text" | |||
value="" | |||
/> | |||
</div> | |||
</Fragment> | |||
`; | |||
exports[`it should render correctly for github and monorepo=false 1`] = ` | |||
<Fragment> | |||
<div |
@@ -113,6 +113,10 @@ export interface BitbucketProjectAlmBindingParams extends ProjectAlmBindingParam | |||
monorepo: boolean; | |||
} | |||
export interface BitbucketCloudProjectAlmBindingParams extends ProjectAlmBindingParams { | |||
repository: string; | |||
} | |||
export interface GithubProjectAlmBindingParams extends ProjectAlmBindingParams { | |||
repository: string; | |||
summaryCommentEnabled: boolean; |
@@ -1165,6 +1165,9 @@ settings.pr_decoration.binding.form.bitbucket.repository=Project Key | |||
settings.pr_decoration.binding.form.bitbucket.repository.help=The project key is part of your Bitbucket Server repository URL. Example: ({example}) | |||
settings.pr_decoration.binding.form.bitbucket.slug=Repository SLUG | |||
settings.pr_decoration.binding.form.bitbucket.slug.help=The Repository Slug is part of your Bitbucket Server repository URL. Example: ({example}) | |||
settings.pr_decoration.binding.form.bitbucketcloud.repository=Repository SLUG | |||
settings.pr_decoration.binding.form.bitbucketcloud.repository.help=The Repository SLUG is part of your Bitbucket Cloud URL. Example: {example} | |||
settings.pr_decoration.binding.form.gitlab.repository=Project ID | |||
property.category.general=General |