@@ -0,0 +1,51 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import * as React from 'react'; | |||
import AlmSettingsInstanceSelector from '../../../components/devops-platform/AlmSettingsInstanceSelector'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { AlmSettingsInstance } from '../../../types/alm-settings'; | |||
export interface AlmSettingsInstanceDropdownProps { | |||
almInstances?: AlmSettingsInstance[]; | |||
selectedAlmInstance?: AlmSettingsInstance; | |||
onChangeConfig: (instance: AlmSettingsInstance) => void; | |||
} | |||
export default function AlmSettingsInstanceDropdown(props: AlmSettingsInstanceDropdownProps) { | |||
const { almInstances, selectedAlmInstance } = props; | |||
return ( | |||
<> | |||
{almInstances && almInstances.length > 1 ? ( | |||
<div className="display-flex-column huge-spacer-bottom"> | |||
<label htmlFor="alm-config-selector" className="spacer-bottom"> | |||
{translate('alm.configuration.selector.label')} | |||
</label> | |||
<AlmSettingsInstanceSelector | |||
instances={almInstances} | |||
onChange={props.onChangeConfig} | |||
initialValue={selectedAlmInstance ? selectedAlmInstance.key : undefined} | |||
classNames="abs-width-400" | |||
inputId="alm-config-selector" | |||
/> | |||
</div> | |||
) : null} | |||
</> | |||
); | |||
} |
@@ -36,7 +36,7 @@ interface Props { | |||
canAdmin: boolean; | |||
loadingBindings: boolean; | |||
onProjectCreate: (projectKey: string) => void; | |||
settings: AlmSettingsInstance[]; | |||
almInstances: AlmSettingsInstance[]; | |||
location: Location; | |||
router: Router; | |||
} | |||
@@ -52,7 +52,7 @@ interface State { | |||
searchResults?: AzureRepository[]; | |||
searchQuery?: string; | |||
selectedRepository?: AzureRepository; | |||
settings?: AlmSettingsInstance; | |||
selectedAlmInstance?: AlmSettingsInstance; | |||
submittingToken?: boolean; | |||
tokenValidationFailed: boolean; | |||
} | |||
@@ -65,7 +65,7 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
this.state = { | |||
// For now, we only handle a single instance. So we always use the first | |||
// one from the list. | |||
settings: props.settings[0], | |||
selectedAlmInstance: props.almInstances[0], | |||
importing: false, | |||
loading: false, | |||
loadingRepositories: {}, | |||
@@ -76,15 +76,12 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
componentDidMount() { | |||
this.mounted = true; | |||
this.fetchInitialData(); | |||
this.fetchData(); | |||
} | |||
componentDidUpdate(prevProps: Props) { | |||
if (prevProps.settings.length === 0 && this.props.settings.length > 0) { | |||
this.setState( | |||
{ settings: this.props.settings.length === 1 ? this.props.settings[0] : undefined }, | |||
() => this.fetchInitialData() | |||
); | |||
if (prevProps.almInstances.length === 0 && this.props.almInstances.length > 0) { | |||
this.setState({ selectedAlmInstance: this.props.almInstances[0] }, () => this.fetchData()); | |||
} | |||
} | |||
@@ -92,7 +89,7 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
this.mounted = false; | |||
} | |||
fetchInitialData = async () => { | |||
fetchData = async () => { | |||
this.setState({ loading: true }); | |||
const patIsValid = await this.checkPersonalAccessToken().catch(() => false); | |||
@@ -135,23 +132,23 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
}; | |||
fetchAzureProjects = (): Promise<AzureProject[] | undefined> => { | |||
const { settings } = this.state; | |||
const { selectedAlmInstance } = this.state; | |||
if (!settings) { | |||
if (!selectedAlmInstance) { | |||
return Promise.resolve(undefined); | |||
} | |||
return getAzureProjects(settings.key).then(({ projects }) => projects); | |||
return getAzureProjects(selectedAlmInstance.key).then(({ projects }) => projects); | |||
}; | |||
fetchAzureRepositories = (projectName: string): Promise<AzureRepository[]> => { | |||
const { settings } = this.state; | |||
const { selectedAlmInstance } = this.state; | |||
if (!settings) { | |||
if (!selectedAlmInstance) { | |||
return Promise.resolve([]); | |||
} | |||
return getAzureRepositories(settings.key, projectName) | |||
return getAzureRepositories(selectedAlmInstance.key, projectName) | |||
.then(({ repositories }) => repositories) | |||
.catch(() => []); | |||
}; | |||
@@ -180,9 +177,9 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
}; | |||
handleSearchRepositories = async (searchQuery: string) => { | |||
const { settings } = this.state; | |||
const { selectedAlmInstance } = this.state; | |||
if (!settings) { | |||
if (!selectedAlmInstance) { | |||
return; | |||
} | |||
@@ -194,7 +191,7 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
this.setState({ searching: true }); | |||
const searchResults: AzureRepository[] = await searchAzureRepositories( | |||
settings.key, | |||
selectedAlmInstance.key, | |||
searchQuery | |||
) | |||
.then(({ repositories }) => repositories) | |||
@@ -210,16 +207,16 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
}; | |||
handleImportRepository = async () => { | |||
const { selectedRepository, settings } = this.state; | |||
const { selectedRepository, selectedAlmInstance } = this.state; | |||
if (!settings || !selectedRepository) { | |||
if (!selectedAlmInstance || !selectedRepository) { | |||
return; | |||
} | |||
this.setState({ importing: true }); | |||
const createdProject = await importAzureRepository( | |||
settings.key, | |||
selectedAlmInstance.key, | |||
selectedRepository.projectName, | |||
selectedRepository.name | |||
) | |||
@@ -239,26 +236,26 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
}; | |||
checkPersonalAccessToken = () => { | |||
const { settings } = this.state; | |||
const { selectedAlmInstance } = this.state; | |||
if (!settings) { | |||
if (!selectedAlmInstance) { | |||
return Promise.resolve(false); | |||
} | |||
return checkPersonalAccessTokenIsValid(settings.key).then(({ status }) => status); | |||
return checkPersonalAccessTokenIsValid(selectedAlmInstance.key).then(({ status }) => status); | |||
}; | |||
handlePersonalAccessTokenCreate = async (token: string) => { | |||
const { settings } = this.state; | |||
const { selectedAlmInstance } = this.state; | |||
if (!settings || token.length < 1) { | |||
if (!selectedAlmInstance || token.length < 1) { | |||
return; | |||
} | |||
this.setState({ submittingToken: true, tokenValidationFailed: false }); | |||
try { | |||
await setAlmPersonalAccessToken(settings.key, token); | |||
await setAlmPersonalAccessToken(selectedAlmInstance.key, token); | |||
const patIsValid = await this.checkPersonalAccessToken(); | |||
if (this.mounted) { | |||
@@ -266,7 +263,7 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
if (patIsValid) { | |||
this.cleanUrl(); | |||
this.fetchInitialData(); | |||
this.fetchData(); | |||
} | |||
} | |||
} catch (e) { | |||
@@ -276,8 +273,12 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
} | |||
}; | |||
onChangeConfig = (instance: AlmSettingsInstance) => { | |||
this.setState({ selectedAlmInstance: instance }, () => this.fetchData()); | |||
}; | |||
render() { | |||
const { canAdmin, loadingBindings, location } = this.props; | |||
const { canAdmin, loadingBindings, location, almInstances } = this.props; | |||
const { | |||
importing, | |||
loading, | |||
@@ -289,7 +290,7 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
searchResults, | |||
searchQuery, | |||
selectedRepository, | |||
settings, | |||
selectedAlmInstance, | |||
submittingToken, | |||
tokenValidationFailed, | |||
} = this.state; | |||
@@ -311,10 +312,12 @@ export default class AzureProjectCreate extends React.PureComponent<Props, State | |||
searchResults={searchResults} | |||
searchQuery={searchQuery} | |||
selectedRepository={selectedRepository} | |||
settings={settings} | |||
almInstances={almInstances} | |||
selectedAlmInstance={selectedAlmInstance} | |||
showPersonalAccessTokenForm={!patIsValid || Boolean(location.query.resetPat)} | |||
submittingToken={submittingToken} | |||
tokenValidationFailed={tokenValidationFailed} | |||
onChangeConfig={this.onChangeConfig} | |||
/> | |||
); | |||
} |
@@ -31,6 +31,7 @@ import { AzureProject, AzureRepository } from '../../../types/alm-integration'; | |||
import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings'; | |||
import { Dict } from '../../../types/types'; | |||
import { ALM_INTEGRATION_CATEGORY } from '../../settings/constants'; | |||
import AlmSettingsInstanceDropdown from './AlmSettingsInstanceDropdown'; | |||
import AzurePersonalAccessTokenForm from './AzurePersonalAccessTokenForm'; | |||
import AzureProjectsList from './AzureProjectsList'; | |||
import CreateProjectPageHeader from './CreateProjectPageHeader'; | |||
@@ -52,10 +53,12 @@ export interface AzureProjectCreateRendererProps { | |||
searchResults?: AzureRepository[]; | |||
searchQuery?: string; | |||
selectedRepository?: AzureRepository; | |||
settings?: AlmSettingsInstance; | |||
almInstances?: AlmSettingsInstance[]; | |||
selectedAlmInstance?: AlmSettingsInstance; | |||
showPersonalAccessTokenForm?: boolean; | |||
submittingToken?: boolean; | |||
tokenValidationFailed: boolean; | |||
onChangeConfig: (instance: AlmSettingsInstance) => void; | |||
} | |||
export default function AzureProjectCreateRenderer(props: AzureProjectCreateRendererProps) { | |||
@@ -70,15 +73,16 @@ export default function AzureProjectCreateRenderer(props: AzureProjectCreateRend | |||
searchResults, | |||
searchQuery, | |||
selectedRepository, | |||
settings, | |||
almInstances, | |||
showPersonalAccessTokenForm, | |||
submittingToken, | |||
tokenValidationFailed, | |||
selectedAlmInstance, | |||
} = props; | |||
const settingIsValid = settings && settings.url; | |||
const showCountError = !loading && !settings; | |||
const showUrlError = !loading && settings && !settings.url; | |||
const showCountError = !loading && (!almInstances || almInstances?.length === 0); | |||
const settingIsValid = selectedAlmInstance && selectedAlmInstance.url; | |||
const showUrlError = !loading && selectedAlmInstance && !selectedAlmInstance.url; | |||
return ( | |||
<> | |||
@@ -111,6 +115,12 @@ export default function AzureProjectCreateRenderer(props: AzureProjectCreateRend | |||
} | |||
/> | |||
<AlmSettingsInstanceDropdown | |||
almInstances={almInstances} | |||
selectedAlmInstance={selectedAlmInstance} | |||
onChangeConfig={props.onChangeConfig} | |||
/> | |||
{loading && <i className="spinner" />} | |||
{showUrlError && ( | |||
@@ -137,12 +147,12 @@ export default function AzureProjectCreateRenderer(props: AzureProjectCreateRend | |||
{showCountError && <WrongBindingCountAlert alm={AlmKeys.Azure} canAdmin={!!canAdmin} />} | |||
{!loading && | |||
settings && | |||
settings.url && | |||
selectedAlmInstance && | |||
selectedAlmInstance.url && | |||
(showPersonalAccessTokenForm ? ( | |||
<div className="display-flex-justify-center"> | |||
<div> | |||
<AzurePersonalAccessTokenForm | |||
almSetting={settings} | |||
almSetting={selectedAlmInstance} | |||
onPersonalAccessTokenCreate={props.onPersonalAccessTokenCreate} | |||
submitting={submittingToken} | |||
validationFailed={tokenValidationFailed} |
@@ -171,7 +171,7 @@ export class CreateProjectPage extends React.PureComponent<Props, State> { | |||
location={location} | |||
onProjectCreate={this.handleProjectCreate} | |||
router={router} | |||
settings={azureSettings} | |||
almInstances={azureSettings} | |||
/> | |||
); | |||
} |
@@ -18,12 +18,12 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import * as React from 'react'; | |||
import AlmSettingsInstanceSelector from '../../../components/devops-platform/AlmSettingsInstanceSelector'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import { getBaseUrl } from '../../../helpers/system'; | |||
import { GitlabProject } from '../../../types/alm-integration'; | |||
import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings'; | |||
import { Paging } from '../../../types/types'; | |||
import AlmSettingsInstanceDropdown from './AlmSettingsInstanceDropdown'; | |||
import CreateProjectPageHeader from './CreateProjectPageHeader'; | |||
import GitlabProjectSelectionForm from './GitlabProjectSelectionForm'; | |||
import PersonalAccessTokenForm from './PersonalAccessTokenForm'; | |||
@@ -81,20 +81,11 @@ export default function GitlabProjectCreateRenderer(props: GitlabProjectCreateRe | |||
} | |||
/> | |||
{almInstances && almInstances.length > 1 && ( | |||
<div className="display-flex-column huge-spacer-bottom"> | |||
<label htmlFor="alm-config-selector" className="spacer-bottom"> | |||
{translate('alm.configuration.selector.label')} | |||
</label> | |||
<AlmSettingsInstanceSelector | |||
instances={almInstances} | |||
onChange={props.onChangeConfig} | |||
initialValue={selectedAlmInstance ? selectedAlmInstance.key : undefined} | |||
classNames="abs-width-400" | |||
inputId="alm-config-selector" | |||
/> | |||
</div> | |||
)} | |||
<AlmSettingsInstanceDropdown | |||
almInstances={almInstances} | |||
selectedAlmInstance={selectedAlmInstance} | |||
onChangeConfig={props.onChangeConfig} | |||
/> | |||
{loading && <i className="spinner" />} | |||
@@ -195,8 +195,8 @@ it('should select and import a repository', async () => { | |||
expect(wrapper.state().importing).toBe(false); | |||
}); | |||
it('should handle no settings', () => { | |||
const wrapper = shallowRender({ settings: [] }); | |||
it('should handle no almInstances', () => { | |||
const wrapper = shallowRender({ almInstances: [] }); | |||
wrapper.instance().fetchAzureProjects(); | |||
wrapper.instance().fetchAzureRepositories('whatever'); | |||
@@ -221,7 +221,7 @@ function shallowRender(overrides: Partial<AzureProjectCreate['props']> = {}) { | |||
location={mockLocation()} | |||
onProjectCreate={jest.fn()} | |||
router={mockRouter()} | |||
settings={[mockAlmSettingsInstance({ alm: AlmKeys.Azure, key: 'foo' })]} | |||
almInstances={[mockAlmSettingsInstance({ alm: AlmKeys.Azure, key: 'foo' })]} | |||
{...overrides} | |||
/> | |||
); |
@@ -28,19 +28,35 @@ import AzureProjectCreateRenderer, { | |||
it('should render correctly', () => { | |||
expect(shallowRender({ loading: true })).toMatchSnapshot('loading'); | |||
expect(shallowRender({ settings: undefined })).toMatchSnapshot('no settings'); | |||
expect(shallowRender({ almInstances: undefined })).toMatchSnapshot('no settings'); | |||
expect(shallowRender({ showPersonalAccessTokenForm: true })).toMatchSnapshot('token form'); | |||
expect(shallowRender()).toMatchSnapshot('project list'); | |||
expect( | |||
shallowRender({ | |||
settings: mockAlmSettingsInstance({ alm: AlmKeys.Azure }), | |||
almInstances: [ | |||
mockAlmSettingsInstance({ alm: AlmKeys.Azure, url: 'https://azure.company.com' }), | |||
mockAlmSettingsInstance({ | |||
alm: AlmKeys.Azure, | |||
url: 'https://azure.company.com', | |||
key: 'key2', | |||
}), | |||
], | |||
selectedAlmInstance: mockAlmSettingsInstance({ | |||
alm: AlmKeys.Azure, | |||
url: 'https://azure.company.com', | |||
}), | |||
}) | |||
).toMatchSnapshot('project list'); | |||
expect( | |||
shallowRender({ | |||
almInstances: [mockAlmSettingsInstance({ alm: AlmKeys.Azure })], | |||
showPersonalAccessTokenForm: true, | |||
}) | |||
).toMatchSnapshot('setting missing url, admin'); | |||
expect( | |||
shallowRender({ | |||
canAdmin: false, | |||
settings: mockAlmSettingsInstance({ alm: AlmKeys.Azure }), | |||
almInstances: [mockAlmSettingsInstance({ alm: AlmKeys.Azure })], | |||
}) | |||
).toMatchSnapshot('setting missing url, not admin'); | |||
}); | |||
@@ -62,9 +78,12 @@ function shallowRender(overrides: Partial<AzureProjectCreateRendererProps> = {}) | |||
projects={[project]} | |||
repositories={{ [project.name]: [mockAzureRepository()] }} | |||
tokenValidationFailed={false} | |||
settings={mockAlmSettingsInstance({ alm: AlmKeys.Azure, url: 'https://azure.company.com' })} | |||
almInstances={[ | |||
mockAlmSettingsInstance({ alm: AlmKeys.Azure, url: 'https://azure.company.com' }), | |||
]} | |||
showPersonalAccessTokenForm={false} | |||
submittingToken={false} | |||
onChangeConfig={jest.fn()} | |||
{...overrides} | |||
/> | |||
); |
@@ -102,7 +102,7 @@ it('should call the proper click handler', () => { | |||
const onSelectMode = jest.fn(); | |||
const onConfigMode = jest.fn(); | |||
let wrapper = shallowRender({ onSelectMode, onConfigMode }, { [AlmKeys.Azure]: 2 }); | |||
let wrapper = shallowRender({ onSelectMode, onConfigMode }, { [AlmKeys.Azure]: 0 }); | |||
click(wrapper.find(almButton).at(0)); | |||
expect(onConfigMode).not.toHaveBeenCalled(); |
@@ -2,17 +2,26 @@ | |||
exports[`should render correctly 1`] = ` | |||
<AzureProjectCreateRenderer | |||
almInstances={ | |||
Array [ | |||
Object { | |||
"alm": "azure", | |||
"key": "foo", | |||
}, | |||
] | |||
} | |||
canAdmin={true} | |||
importing={false} | |||
loading={true} | |||
loadingRepositories={Object {}} | |||
onChangeConfig={[Function]} | |||
onImportRepository={[Function]} | |||
onOpenProject={[Function]} | |||
onPersonalAccessTokenCreate={[Function]} | |||
onSearch={[Function]} | |||
onSelectRepository={[Function]} | |||
repositories={Object {}} | |||
settings={ | |||
selectedAlmInstance={ | |||
Object { | |||
"alm": "azure", | |||
"key": "foo", |
@@ -3,23 +3,6 @@ | |||
exports[`should render correctly: loading 1`] = ` | |||
<Fragment> | |||
<CreateProjectPageHeader | |||
additionalActions={ | |||
<div | |||
className="display-flex-center pull-right" | |||
> | |||
<DeferredSpinner | |||
className="spacer-right" | |||
loading={false} | |||
/> | |||
<Button | |||
className="button-large button-primary" | |||
disabled={true} | |||
onClick={[MockFunction]} | |||
> | |||
onboarding.create_project.import_selected_repo | |||
</Button> | |||
</div> | |||
} | |||
title={ | |||
<span | |||
className="text-middle" | |||
@@ -34,6 +17,18 @@ exports[`should render correctly: loading 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<AlmSettingsInstanceDropdown | |||
almInstances={ | |||
Array [ | |||
Object { | |||
"alm": "azure", | |||
"key": "key", | |||
"url": "https://azure.company.com", | |||
}, | |||
] | |||
} | |||
onChangeConfig={[MockFunction]} | |||
/> | |||
<i | |||
className="spinner" | |||
/> | |||
@@ -57,6 +52,9 @@ exports[`should render correctly: no settings 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<AlmSettingsInstanceDropdown | |||
onChangeConfig={[MockFunction]} | |||
/> | |||
<WrongBindingCountAlert | |||
alm="azure" | |||
canAdmin={true} | |||
@@ -98,6 +96,30 @@ exports[`should render correctly: project list 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<AlmSettingsInstanceDropdown | |||
almInstances={ | |||
Array [ | |||
Object { | |||
"alm": "azure", | |||
"key": "key", | |||
"url": "https://azure.company.com", | |||
}, | |||
Object { | |||
"alm": "azure", | |||
"key": "key2", | |||
"url": "https://azure.company.com", | |||
}, | |||
] | |||
} | |||
onChangeConfig={[MockFunction]} | |||
selectedAlmInstance={ | |||
Object { | |||
"alm": "azure", | |||
"key": "key", | |||
"url": "https://azure.company.com", | |||
} | |||
} | |||
/> | |||
<div | |||
className="huge-spacer-bottom" | |||
> | |||
@@ -155,29 +177,17 @@ exports[`should render correctly: setting missing url, admin 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<Alert | |||
variant="error" | |||
> | |||
<FormattedMessage | |||
defaultMessage="onboarding.create_project.azure.no_url.admin" | |||
id="onboarding.create_project.azure.no_url.admin" | |||
values={ | |||
<AlmSettingsInstanceDropdown | |||
almInstances={ | |||
Array [ | |||
Object { | |||
"alm": "onboarding.alm.azure", | |||
"url": <ForwardRef(Link) | |||
to={ | |||
Object { | |||
"pathname": "/admin/settings", | |||
"search": "?category=almintegration", | |||
} | |||
} | |||
> | |||
settings.page | |||
</ForwardRef(Link)>, | |||
} | |||
} | |||
/> | |||
</Alert> | |||
"alm": "azure", | |||
"key": "key", | |||
}, | |||
] | |||
} | |||
onChangeConfig={[MockFunction]} | |||
/> | |||
</Fragment> | |||
`; | |||
@@ -198,11 +208,17 @@ exports[`should render correctly: setting missing url, not admin 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<Alert | |||
variant="error" | |||
> | |||
onboarding.create_project.azure.no_url | |||
</Alert> | |||
<AlmSettingsInstanceDropdown | |||
almInstances={ | |||
Array [ | |||
Object { | |||
"alm": "azure", | |||
"key": "key", | |||
}, | |||
] | |||
} | |||
onChangeConfig={[MockFunction]} | |||
/> | |||
</Fragment> | |||
`; | |||
@@ -224,21 +240,17 @@ exports[`should render correctly: token form 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<div | |||
className="display-flex-justify-center" | |||
> | |||
<AzurePersonalAccessTokenForm | |||
almSetting={ | |||
<AlmSettingsInstanceDropdown | |||
almInstances={ | |||
Array [ | |||
Object { | |||
"alm": "azure", | |||
"key": "key", | |||
"url": "https://azure.company.com", | |||
} | |||
} | |||
onPersonalAccessTokenCreate={[MockFunction]} | |||
submitting={false} | |||
validationFailed={false} | |||
/> | |||
</div> | |||
}, | |||
] | |||
} | |||
onChangeConfig={[MockFunction]} | |||
/> | |||
</Fragment> | |||
`; |
@@ -92,6 +92,7 @@ exports[`should render correctly for azure mode 1`] = ` | |||
id="create-project" | |||
> | |||
<AzureProjectCreate | |||
almInstances={Array []} | |||
canAdmin={false} | |||
loadingBindings={true} | |||
location={ | |||
@@ -120,7 +121,6 @@ exports[`should render correctly for azure mode 1`] = ` | |||
"setRouteLeaveHook": [MockFunction], | |||
} | |||
} | |||
settings={Array []} | |||
/> | |||
</div> | |||
</Fragment> |
@@ -17,6 +17,15 @@ exports[`should render correctly: invalid settings 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<AlmSettingsInstanceDropdown | |||
onChangeConfig={[MockFunction]} | |||
selectedAlmInstance={ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
} | |||
} | |||
/> | |||
<PersonalAccessTokenForm | |||
almSetting={ | |||
Object { | |||
@@ -47,6 +56,15 @@ exports[`should render correctly: invalid settings, admin user 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<AlmSettingsInstanceDropdown | |||
onChangeConfig={[MockFunction]} | |||
selectedAlmInstance={ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
} | |||
} | |||
/> | |||
<PersonalAccessTokenForm | |||
almSetting={ | |||
Object { | |||
@@ -77,38 +95,31 @@ exports[`should render correctly: loading 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<div | |||
className="display-flex-column huge-spacer-bottom" | |||
> | |||
<label | |||
className="spacer-bottom" | |||
htmlFor="alm-config-selector" | |||
> | |||
alm.configuration.selector.label | |||
</label> | |||
<AlmSettingsInstanceSelector | |||
classNames="abs-width-400" | |||
initialValue="key" | |||
inputId="alm-config-selector" | |||
instances={ | |||
Array [ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "github", | |||
"key": "key", | |||
}, | |||
] | |||
<AlmSettingsInstanceDropdown | |||
almInstances={ | |||
Array [ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "github", | |||
"key": "key", | |||
}, | |||
] | |||
} | |||
onChangeConfig={[MockFunction]} | |||
selectedAlmInstance={ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
} | |||
onChange={[MockFunction]} | |||
/> | |||
</div> | |||
} | |||
/> | |||
<i | |||
className="spinner" | |||
/> | |||
@@ -132,38 +143,31 @@ exports[`should render correctly: pat form 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<div | |||
className="display-flex-column huge-spacer-bottom" | |||
> | |||
<label | |||
className="spacer-bottom" | |||
htmlFor="alm-config-selector" | |||
> | |||
alm.configuration.selector.label | |||
</label> | |||
<AlmSettingsInstanceSelector | |||
classNames="abs-width-400" | |||
initialValue="key" | |||
inputId="alm-config-selector" | |||
instances={ | |||
Array [ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "github", | |||
"key": "key", | |||
}, | |||
] | |||
<AlmSettingsInstanceDropdown | |||
almInstances={ | |||
Array [ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "github", | |||
"key": "key", | |||
}, | |||
] | |||
} | |||
onChangeConfig={[MockFunction]} | |||
selectedAlmInstance={ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
} | |||
onChange={[MockFunction]} | |||
/> | |||
</div> | |||
} | |||
/> | |||
<PersonalAccessTokenForm | |||
almSetting={ | |||
Object { | |||
@@ -194,38 +198,31 @@ exports[`should render correctly: project selection form 1`] = ` | |||
</span> | |||
} | |||
/> | |||
<div | |||
className="display-flex-column huge-spacer-bottom" | |||
> | |||
<label | |||
className="spacer-bottom" | |||
htmlFor="alm-config-selector" | |||
> | |||
alm.configuration.selector.label | |||
</label> | |||
<AlmSettingsInstanceSelector | |||
classNames="abs-width-400" | |||
initialValue="key" | |||
inputId="alm-config-selector" | |||
instances={ | |||
Array [ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "github", | |||
"key": "key", | |||
}, | |||
] | |||
<AlmSettingsInstanceDropdown | |||
almInstances={ | |||
Array [ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
}, | |||
Object { | |||
"alm": "github", | |||
"key": "key", | |||
}, | |||
] | |||
} | |||
onChangeConfig={[MockFunction]} | |||
selectedAlmInstance={ | |||
Object { | |||
"alm": "gitlab", | |||
"key": "key", | |||
} | |||
onChange={[MockFunction]} | |||
/> | |||
</div> | |||
} | |||
/> | |||
<GitlabProjectSelectionForm | |||
loadingMore={false} | |||
onImport={[MockFunction]} |
@@ -23,4 +23,4 @@ export const PROJECT_NAME_MAX_LEN = 255; | |||
export const DEFAULT_BBS_PAGE_SIZE = 25; | |||
export const ALLOWED_MULTIPLE_CONFIGS = [AlmKeys.GitLab]; | |||
export const ALLOWED_MULTIPLE_CONFIGS = [AlmKeys.GitLab, AlmKeys.Azure]; |
@@ -121,7 +121,7 @@ it('should filter alm bindings appropriately', async () => { | |||
wrapper = shallowRender(); | |||
await waitAndUpdate(wrapper); | |||
expect(wrapper.state().boundAlms).toEqual([AlmKeys.GitLab]); | |||
expect(wrapper.state().boundAlms).toEqual([AlmKeys.Azure, AlmKeys.GitLab]); | |||
}); | |||
function shallowRender(overrides: Partial<ProjectCreationMenu['props']> = {}) { |
@@ -3583,7 +3583,7 @@ onboarding.create_project.see_on_github=See project on GitHub | |||
onboarding.create_project.search_prompt=Search for projects | |||
onboarding.create_project.set_up=Set up | |||
onboarding.create_project.azure.title=Which Azure DevOps repository do you want to set up? | |||
onboarding.create_project.azure.title=Azure project onboarding | |||
onboarding.create_project.azure.no_projects=No projects could be fetched from Azure DevOps. Contact your system administrator, or {link}. | |||
onboarding.create_project.azure.search_results_for_project_X=Search results for "{0}" | |||
onboarding.create_project.azure.no_repositories=Could not fetch repositories for this project. Contact your system administrator, or {link}. |