From f740be3382c2bed29f688b7e3528de2b6a49d7f0 Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Tue, 5 May 2026 16:56:53 +0200 Subject: [PATCH] add unit tests --- .../src/clients/DependabotClient.test.ts | 21 ++++++++- .../DependabotMetricProvider.test.ts | 44 ++++++++++++++++--- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-dependabot/src/clients/DependabotClient.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-dependabot/src/clients/DependabotClient.test.ts index f00af2ec10..af564fb6f6 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-dependabot/src/clients/DependabotClient.test.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-dependabot/src/clients/DependabotClient.test.ts @@ -15,7 +15,10 @@ */ import { ConfigReader } from '@backstage/config'; -import { DefaultGithubCredentialsProvider } from '@backstage/integration'; +import { + DefaultGithubCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; import { DependabotClient } from './DependabotClient'; const mockPaginate = jest.fn(); @@ -112,6 +115,22 @@ describe('DependabotClient', () => { expect(mockPaginate).not.toHaveBeenCalled(); }); + it('throws when GitHub API base URL is missing', async () => { + jest.spyOn(ScmIntegrations, 'fromConfig').mockReturnValueOnce({ + github: { + byUrl: jest.fn().mockReturnValue({ + config: {}, + }), + }, + } as any); + const clientWithoutApiBaseUrl = new DependabotClient(config, logger); + + await expect( + clientWithoutApiBaseUrl.getAlerts(url, repo, 'critical'), + ).rejects.toThrow(`Missing GitHub API base URL for '${url}'`); + expect(mockPaginate).not.toHaveBeenCalled(); + }); + it('throws when Octokit paginate fails', async () => { mockPaginate.mockRejectedValueOnce(new Error('GitHub API error: 403')); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-dependabot/src/metricProviders/DependabotMetricProvider.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-dependabot/src/metricProviders/DependabotMetricProvider.test.ts index 35b38b1a56..a7a80d97e1 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-dependabot/src/metricProviders/DependabotMetricProvider.test.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-dependabot/src/metricProviders/DependabotMetricProvider.test.ts @@ -15,6 +15,7 @@ */ import { ConfigReader } from '@backstage/config'; +import { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client'; import type { Entity } from '@backstage/catalog-model'; import { DependabotMetricProvider } from './DependabotMetricProvider'; import { DEPENDABOT_SEVERITY_METRIC } from './DependabotConfig'; @@ -86,6 +87,8 @@ describe('DependabotMetricProvider', () => { expect(metric.description).toBe( DEPENDABOT_SEVERITY_METRIC[severity].description, ); + expect(metric.type).toBe('number'); + expect(metric.history).toBe(true); }, ); }); @@ -131,11 +134,10 @@ describe('DependabotMetricProvider', () => { mockLogger, 'critical', ); - const filter = provider.getCatalogFilter(); - expect( - filter['metadata.annotations.github.com/project-slug'], - ).toBeDefined(); - expect(filter['metadata.annotations.github.com/dependabot']).toBe('true'); + expect(provider.getCatalogFilter()).toEqual({ + 'metadata.annotations.github.com/project-slug': CATALOG_FILTER_EXISTS, + 'metadata.annotations.github.com/dependabot': 'true', + }); }); }); @@ -175,6 +177,20 @@ describe('DependabotMetricProvider', () => { "Invalid format of 'github.com/project-slug'", ); }); + + it.each(['/repo', 'owner/'])( + 'throws when project-slug has an empty owner or repo segment: %s', + projectSlug => { + const provider = new DependabotMetricProvider( + mockConfig, + mockLogger, + 'critical', + ); + expect(() => provider.getRepository(entity(projectSlug))).toThrow( + "Invalid format of 'github.com/project-slug'", + ); + }, + ); }); describe('calculateMetric', () => { @@ -214,5 +230,23 @@ describe('DependabotMetricProvider', () => { ); expect(await provider.calculateMetric(entity())).toBe(0); }); + + it('propagates errors when getAlerts fails', async () => { + mockGetAlerts.mockRejectedValueOnce(new Error('dependabot unavailable')); + const provider = new DependabotMetricProvider( + mockConfig, + mockLogger, + 'critical', + ); + + await expect(provider.calculateMetric(entity())).rejects.toThrow( + 'dependabot unavailable', + ); + expect(mockGetAlerts).toHaveBeenCalledWith( + 'https://github.com/owner/repo', + { owner: 'owner', repo: 'repo' }, + 'critical', + ); + }); }); });