diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/autocomplete/autocomplete.test.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/autocomplete/autocomplete.test.ts index 1729593d2b..10b277963b 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/autocomplete/autocomplete.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/autocomplete/autocomplete.test.ts @@ -26,7 +26,6 @@ describe('handleAutocompleteRequest', () => { values: [ { slug: 'workspace1', - uuid: '486F4F29-9B88-4BE8-9092-24BEB8A5F3B3', }, ], }, @@ -35,9 +34,7 @@ describe('handleAutocompleteRequest', () => { listProjectsByWorkspace: jest.fn().mockReturnValue({ iteratePages: jest.fn().mockReturnValue([ { - values: [ - { key: 'project1', uuid: '70F065E3-CE7C-487A-99B6-D81EB84E5A21' }, - ], + values: [{ key: 'project1' }], }, ]), }), @@ -47,7 +44,6 @@ describe('handleAutocompleteRequest', () => { values: [ { slug: 'repository1', - uuid: 'F2F0DAF7-B4D6-4694-A131-C2478A200AC5', }, ], }, @@ -85,9 +81,7 @@ describe('handleAutocompleteRequest', () => { }); expect(result).toEqual({ - results: [ - { title: 'workspace1', id: '486F4F29-9B88-4BE8-9092-24BEB8A5F3B3' }, - ], + results: [{ id: 'workspace1' }], }); }); @@ -101,9 +95,7 @@ describe('handleAutocompleteRequest', () => { }); expect(result).toEqual({ - results: [ - { title: 'project1', id: '70F065E3-CE7C-487A-99B6-D81EB84E5A21' }, - ], + results: [{ id: 'project1' }], }); }); @@ -118,9 +110,7 @@ describe('handleAutocompleteRequest', () => { }); expect(result).toEqual({ - results: [ - { title: 'repository1', id: 'F2F0DAF7-B4D6-4694-A131-C2478A200AC5' }, - ], + results: [{ id: 'repository1' }], }); }); @@ -134,7 +124,7 @@ describe('handleAutocompleteRequest', () => { }, }); - expect(result).toEqual({ results: [{ title: 'branch1', id: 'branch1' }] }); + expect(result).toEqual({ results: [{ id: 'branch1' }] }); }); it('should throw an error when passing an invalid resource', async () => { diff --git a/plugins/scaffolder-backend-module-bitbucket-cloud/src/autocomplete/autocomplete.ts b/plugins/scaffolder-backend-module-bitbucket-cloud/src/autocomplete/autocomplete.ts index 3439ca616a..3d1cdd5748 100644 --- a/plugins/scaffolder-backend-module-bitbucket-cloud/src/autocomplete/autocomplete.ts +++ b/plugins/scaffolder-backend-module-bitbucket-cloud/src/autocomplete/autocomplete.ts @@ -34,12 +34,11 @@ export async function handleAutocompleteRequest({ switch (resource) { case 'workspaces': { - const results: { title: string; id: string }[] = []; + const results: { title?: string; id: string }[] = []; for await (const page of client.listWorkspaces().iteratePages()) { const slugs = [...page.values!].map(p => ({ - title: p.slug!, - id: p.uuid!, + id: p.slug!, })); results.push(...slugs); } @@ -50,14 +49,13 @@ export async function handleAutocompleteRequest({ if (!context.workspace) throw new InputError('Missing workspace context parameter'); - const results: { title: string; id: string }[] = []; + const results: { title?: string; id: string }[] = []; for await (const page of client .listProjectsByWorkspace(context.workspace) .iteratePages()) { const keys = [...page.values!].map(p => ({ - title: p.key!, - id: p.uuid!, + id: p.key!, })); results.push(...keys); } @@ -70,7 +68,7 @@ export async function handleAutocompleteRequest({ 'Missing workspace and/or project context parameter', ); - const results: { title: string; id: string }[] = []; + const results: { title?: string; id: string }[] = []; for await (const page of client .listRepositoriesByWorkspace(context.workspace, { @@ -78,8 +76,7 @@ export async function handleAutocompleteRequest({ }) .iteratePages()) { const slugs = [...page.values!].map(p => ({ - title: p.slug!, - id: p.uuid!, + id: p.slug!, })); results.push(...slugs); } @@ -92,13 +89,12 @@ export async function handleAutocompleteRequest({ 'Missing workspace and/or repository context parameter', ); - const results: { title: string; id: string }[] = []; + const results: { title?: string; id: string }[] = []; for await (const page of client .listBranchesByRepository(context.repository, context.workspace) .iteratePages()) { const names = [...page.values!].map(p => ({ - title: p.name!, id: p.name!, })); results.push(...names); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx index 05d04886e4..af3952ff51 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx @@ -14,22 +14,22 @@ * limitations under the License. */ -import React from 'react'; -import { BitbucketRepoPicker } from './BitbucketRepoPicker'; -import { fireEvent, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { ScaffolderApi, scaffolderApiRef, } from '@backstage/plugin-scaffolder-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { fireEvent, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; import { act } from 'react-dom/test-utils'; +import { BitbucketRepoPicker } from './BitbucketRepoPicker'; describe('BitbucketRepoPicker', () => { const scaffolderApiMock: Partial = { autocomplete: jest.fn().mockImplementation(opts => Promise.resolve({ - results: [{ title: `${opts.resource}_example` }], + results: [{ id: `${opts.resource}_example` }], }), ), }; @@ -266,7 +266,7 @@ describe('BitbucketRepoPicker', () => { // Verify that the available repos are updated await waitFor(() => expect(onChange).toHaveBeenCalledWith({ - availableRepos: ['repositories_example'], + availableRepos: [{ name: 'repositories_example' }], }), ); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx index c9fccb40be..45a6439a63 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx @@ -89,7 +89,7 @@ export const BitbucketRepoPicker = ( provider: 'bitbucket-cloud', }) .then(({ results }) => { - setAvailableWorkspaces(results.map(r => r.title!)); + setAvailableWorkspaces(results.map(r => r.id)); }) .catch(() => { setAvailableWorkspaces([]); @@ -118,7 +118,7 @@ export const BitbucketRepoPicker = ( provider: 'bitbucket-cloud', }) .then(({ results }) => { - setAvailableProjects(results.map(r => r.title!)); + setAvailableProjects(results.map(r => r.id)); }) .catch(() => { setAvailableProjects([]); @@ -148,7 +148,11 @@ export const BitbucketRepoPicker = ( provider: 'bitbucket-cloud', }) .then(({ results }) => { - onChange({ availableRepos: results.map(r => r.title!) }); + onChange({ + availableRepos: results.map(r => { + return { name: r.id }; + }), + }); }) .catch(() => { onChange({ availableRepos: [] }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.tsx index d190c7b10c..d97c9431ee 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.tsx @@ -96,7 +96,11 @@ export const GitlabRepoPicker = ( provider: 'gitlab', }) .then(({ results }) => { - onChange({ availableRepos: results.map(r => r.title!) }); + onChange({ + availableRepos: results.map(r => { + return { name: r.title!, id: r.id }; + }), + }); }) .catch(() => { onChange({ availableRepos: [] }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index c0e52e1826..18da234012 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -242,7 +242,11 @@ export const RepoUrlPicker = ( repoName={state.repoName} allowedRepos={allowedRepos} onChange={repo => - setState(prevState => ({ ...prevState, repoName: repo })) + setState(prevState => ({ + ...prevState, + repoName: repo.name, + id: repo.id || '', + })) } rawErrors={rawErrors} availableRepos={state.availableRepos} diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx index ec4853c714..f78abc2dfb 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.test.tsx @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { RepoUrlPickerRepoName } from './RepoUrlPickerRepoName'; +import { renderInTestApp } from '@backstage/test-utils'; import { fireEvent } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import React from 'react'; import { act } from 'react-dom/test-utils'; -import { renderInTestApp } from '@backstage/test-utils'; +import { RepoUrlPickerRepoName } from './RepoUrlPickerRepoName'; describe('RepoUrlPickerRepoName', () => { it('should call onChange with the first allowed repo if there is none set already', async () => { @@ -32,7 +32,7 @@ describe('RepoUrlPickerRepoName', () => { />, ); - expect(onChange).toHaveBeenCalledWith('foo'); + expect(onChange).toHaveBeenCalledWith({ name: 'foo' }); }); it('should render a dropdown of all the options', async () => { @@ -78,11 +78,11 @@ describe('RepoUrlPickerRepoName', () => { textArea.blur(); }); - expect(onChange).toHaveBeenCalledWith('foo'); + expect(onChange).toHaveBeenCalledWith({ name: 'foo' }); }); it('should autocomplete with provided availableRepos', async () => { - const availableRepos = ['foo', 'bar']; + const availableRepos = [{ name: 'foo' }, { name: 'bar' }]; const onChange = jest.fn(); @@ -100,11 +100,11 @@ describe('RepoUrlPickerRepoName', () => { // Verify that available repos are shown for (const repo of availableRepos) { - expect(getByText(repo)).toBeInTheDocument(); + expect(getByText(repo.name)).toBeInTheDocument(); } // Verify that selecting an option calls onChange - await userEvent.click(getByText(availableRepos[0])); + await userEvent.click(getByText(availableRepos[0].name)); expect(onChange).toHaveBeenCalledWith(availableRepos[0]); }); }); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx index b1152d3c1f..d23a4bcd86 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx @@ -13,21 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useEffect } from 'react'; import { Select, SelectItem } from '@backstage/core-components'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; import FormControl from '@material-ui/core/FormControl'; import FormHelperText from '@material-ui/core/FormHelperText'; -import Autocomplete from '@material-ui/lab/Autocomplete'; import TextField from '@material-ui/core/TextField'; -import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import Autocomplete from '@material-ui/lab/Autocomplete'; +import React, { useEffect } from 'react'; import { scaffolderTranslationRef } from '../../../translation'; +import { AvailableRepositories } from './types'; export const RepoUrlPickerRepoName = (props: { repoName?: string; allowedRepos?: string[]; - onChange: (host: string) => void; + onChange: (chosenRepo: AvailableRepositories) => void; rawErrors: string[]; - availableRepos?: string[]; + availableRepos?: AvailableRepositories[]; }) => { const { repoName, allowedRepos, onChange, rawErrors, availableRepos } = props; const { t } = useTranslationRef(scaffolderTranslationRef); @@ -37,7 +38,7 @@ export const RepoUrlPickerRepoName = (props: { if (!repoName) { // Set the first of the allowedRepos option if that available if (allowedRepos?.length) { - onChange(allowedRepos[0]); + onChange({ name: allowedRepos[0] }); } } }, [allowedRepos, repoName, onChange]); @@ -58,7 +59,9 @@ export const RepoUrlPickerRepoName = (props: { native label={t('fields.repoUrlPicker.repository.title')} onChange={selected => - onChange(String(Array.isArray(selected) ? selected[0] : selected)) + onChange({ + name: String(Array.isArray(selected) ? selected[0] : selected), + }) } disabled={allowedRepos.length === 1} selected={repoName} @@ -68,9 +71,12 @@ export const RepoUrlPickerRepoName = (props: { { - onChange(newValue || ''); + const selectedRepo = availableRepos?.find( + r => r.name === newValue, + ); + onChange(selectedRepo || { name: newValue || '' }); }} - options={availableRepos || []} + options={(availableRepos || []).map(r => r.name)} renderInput={params => ( = T & {