diff --git a/plugins/azure-devops/src/components/EntityPageAzurePipelines/EntityPageAzurePipelines.tsx b/plugins/azure-devops/src/components/EntityPageAzurePipelines/EntityPageAzurePipelines.tsx index 02a61a9a9a..95d1a365b9 100644 --- a/plugins/azure-devops/src/components/EntityPageAzurePipelines/EntityPageAzurePipelines.tsx +++ b/plugins/azure-devops/src/components/EntityPageAzurePipelines/EntityPageAzurePipelines.tsx @@ -16,21 +16,13 @@ import { BuildTable } from '../BuildTable/BuildTable'; import React from 'react'; -import { getAnnotationValuesFromEntity } from '../../utils/getAnnotationValuesFromEntity'; import { useBuildRuns } from '../../hooks/useBuildRuns'; import { useEntity } from '@backstage/plugin-catalog-react'; export const EntityPageAzurePipelines = (props: { defaultLimit?: number }) => { const { entity } = useEntity(); - const { project, repo, definition } = getAnnotationValuesFromEntity(entity); - - const { items, loading, error } = useBuildRuns( - project, - props.defaultLimit, - repo, - definition, - ); + const { items, loading, error } = useBuildRuns(entity, props.defaultLimit); return ; }; diff --git a/plugins/azure-devops/src/hooks/useBuildRuns.test.tsx b/plugins/azure-devops/src/hooks/useBuildRuns.test.tsx new file mode 100644 index 0000000000..409602eec4 --- /dev/null +++ b/plugins/azure-devops/src/hooks/useBuildRuns.test.tsx @@ -0,0 +1,126 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { renderHook, waitFor } from '@testing-library/react'; +import { Entity } from '@backstage/catalog-model'; +import { BuildRun } from '@backstage/plugin-azure-devops-common'; +import { TestApiProvider } from '@backstage/test-utils'; +import { AzureDevOpsApi, azureDevOpsApiRef } from '../api'; +import { useBuildRuns } from './useBuildRuns'; + +describe('useBuildRuns', () => { + const azureDevOpsApiMock = { + getBuildRuns: jest.fn(), + }; + const azureDevOpsApi = + azureDevOpsApiMock as Partial as AzureDevOpsApi; + + const Wrapper = (props: { children?: React.ReactNode }) => ( + + {props.children} + + ); + + it('should provide an array of BuildRun', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'projectName/repoName', + }, + }, + }; + const buildRuns: BuildRun[] = [ + { + id: 1, + title: 'title-1', + source: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + }, + { + id: 2, + title: 'title-2', + source: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + }, + { + id: 3, + title: 'title-3', + source: 'awanlin', + link: 'https://dev.azure.com/org/project/repo', + }, + ]; + azureDevOpsApiMock.getBuildRuns.mockResolvedValue({ + items: buildRuns, + }); + const { result } = renderHook(() => useBuildRuns(entity), { + wrapper: Wrapper, + }); + + expect(result.current.loading).toEqual(true); + + await waitFor(() => { + expect(result.current).toEqual({ + error: undefined, + items: buildRuns, + loading: false, + }); + }); + }); + + it('should return throw when annotation missing', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + }, + }; + + expect(() => + renderHook(() => useBuildRuns(entity), { + wrapper: Wrapper, + }), + ).toThrow('Value for annotation "dev.azure.com/project" was not found'); + }); + + it('should return throw when annotation invalid', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + namespace: 'default', + name: 'project-repo', + annotations: { + 'dev.azure.com/project-repo': 'fake', + }, + }, + }; + + expect(() => + renderHook(() => useBuildRuns(entity), { + wrapper: Wrapper, + }), + ).toThrow( + 'Invalid value for annotation "dev.azure.com/project-repo"; expected format is: /, found: "fake"', + ); + }); +}); diff --git a/plugins/azure-devops/src/hooks/useBuildRuns.ts b/plugins/azure-devops/src/hooks/useBuildRuns.ts index ae0273de44..2b70ea63a5 100644 --- a/plugins/azure-devops/src/hooks/useBuildRuns.ts +++ b/plugins/azure-devops/src/hooks/useBuildRuns.ts @@ -23,12 +23,12 @@ import { AZURE_DEVOPS_DEFAULT_TOP } from '../constants'; import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; +import { getAnnotationValuesFromEntity } from '../utils'; +import { Entity } from '@backstage/catalog-model'; export function useBuildRuns( - projectName: string, + entity: Entity, defaultLimit?: number, - repoName?: string, - definitionName?: string, ): { items?: BuildRun[]; loading: boolean; @@ -42,8 +42,9 @@ export function useBuildRuns( const api = useApi(azureDevOpsApiRef); const { value, loading, error } = useAsync(() => { - return api.getBuildRuns(projectName, repoName, definitionName, options); - }, [api, projectName, repoName, definitionName]); + const { project, repo, definition } = getAnnotationValuesFromEntity(entity); + return api.getBuildRuns(project, repo, definition, options); + }, [api]); return { items: value?.items, diff --git a/plugins/azure-devops/src/hooks/useGitTags.ts b/plugins/azure-devops/src/hooks/useGitTags.ts index 13c7118934..8a2fb2825d 100644 --- a/plugins/azure-devops/src/hooks/useGitTags.ts +++ b/plugins/azure-devops/src/hooks/useGitTags.ts @@ -28,11 +28,11 @@ export function useGitTags(entity: Entity): { error?: Error; } { const api = useApi(azureDevOpsApiRef); - const { project, repo } = getAnnotationValuesFromEntity(entity); - const { value, loading, error } = useAsync(async () => { - return await api.getGitTags(project, repo as string); - }, [api, project, repo]); + const { value, loading, error } = useAsync(() => { + const { project, repo } = getAnnotationValuesFromEntity(entity); + return api.getGitTags(project, repo as string); + }, [api]); return { items: value?.items, diff --git a/plugins/azure-devops/src/hooks/usePullRequests.ts b/plugins/azure-devops/src/hooks/usePullRequests.ts index c4223871f2..de886919eb 100644 --- a/plugins/azure-devops/src/hooks/usePullRequests.ts +++ b/plugins/azure-devops/src/hooks/usePullRequests.ts @@ -44,11 +44,11 @@ export function usePullRequests( }; const api = useApi(azureDevOpsApiRef); - const { project, repo } = getAnnotationValuesFromEntity(entity); - const { value, loading, error } = useAsync(async () => { - return await api.getPullRequests(project, repo as string, options); - }, [api, project, repo, top, status]); + const { value, loading, error } = useAsync(() => { + const { project, repo } = getAnnotationValuesFromEntity(entity); + return api.getPullRequests(project, repo as string, options); + }, [api, top, status]); return { items: value?.items, diff --git a/plugins/azure-devops/src/hooks/useReadme.ts b/plugins/azure-devops/src/hooks/useReadme.ts index 60b2e21990..67d3c5dfd0 100644 --- a/plugins/azure-devops/src/hooks/useReadme.ts +++ b/plugins/azure-devops/src/hooks/useReadme.ts @@ -28,11 +28,11 @@ export function useReadme(entity: Entity): { error?: Error; } { const api = useApi(azureDevOpsApiRef); - const { project, repo } = getAnnotationValuesFromEntity(entity); - const { value, loading, error } = useAsync(async () => { - return await api.getReadme({ project, repo: repo as string }); - }, [api, project, repo]); + const { value, loading, error } = useAsync(() => { + const { project, repo } = getAnnotationValuesFromEntity(entity); + return api.getReadme({ project, repo: repo as string }); + }, [api]); return { item: value, diff --git a/plugins/azure-devops/src/hooks/useRepoBuilds.ts b/plugins/azure-devops/src/hooks/useRepoBuilds.ts index 9292a6e035..17fc6bbfe5 100644 --- a/plugins/azure-devops/src/hooks/useRepoBuilds.ts +++ b/plugins/azure-devops/src/hooks/useRepoBuilds.ts @@ -26,6 +26,9 @@ import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; import { getAnnotationValuesFromEntity } from '../utils'; +/** + * @deprecated Use `useBuildRuns` instead + */ export function useRepoBuilds( entity: Entity, defaultLimit?: number, @@ -40,11 +43,11 @@ export function useRepoBuilds( }; const api = useApi(azureDevOpsApiRef); - const { project, repo } = getAnnotationValuesFromEntity(entity); - const { value, loading, error } = useAsync(async () => { - return await api.getRepoBuilds(project, repo as string, options); - }, [api, project, repo, entity]); + const { value, loading, error } = useAsync(() => { + const { project, repo } = getAnnotationValuesFromEntity(entity); + return api.getRepoBuilds(project, repo as string, options); + }, [api, entity]); return { items: value?.items,