Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions frontend/config/health-breakdown-templates.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
Copyright (c) 2026 The Linux Foundation and each contributor.
SPDX-License-Identifier: MIT
*/

import { describe, test, expect } from 'vitest';
import type { HealthBreakdownResults } from '../types/overview/responses.types';
import { getOpenVulnRow } from './health-breakdown-templates';

describe('health-breakdown-templates', () => {
test('getOpenVulnRow returns no-data when openVulnScore is null', () => {
const signals = {
openVulnScore: null,
openVulnAvailable: null,
openCriticals: null,
openHighs: null,
openModerates: null,
isGerrit: null,
isExcluded: null,
} as HealthBreakdownResults;

const result = getOpenVulnRow(signals);

expect(result.status).toBe('no-data');
});

test('getOpenVulnRow returns no-data when the repo has never completed a vulnerability scan', () => {
const signals = {
openVulnScore: 10,
openVulnAvailable: false,
openCriticals: null,
openHighs: null,
openModerates: null,
isGerrit: false,
isExcluded: false,
} as HealthBreakdownResults;

const result = getOpenVulnRow(signals);

expect(result.status).toBe('no-data');
});

test('getOpenVulnRow returns positive when the repo has been scanned and is clean', () => {
const signals = {
openVulnScore: 10,
openVulnAvailable: true,
openCriticals: 0,
openHighs: 0,
openModerates: 0,
isGerrit: false,
isExcluded: false,
} as HealthBreakdownResults;

const result = getOpenVulnRow(signals);

expect(result.status).toBe('positive');
});
});
11 changes: 9 additions & 2 deletions frontend/config/health-breakdown-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,15 @@ const getCategoryUnavailableDescription = (
}
if (category === 'security') {
const availableSignals: string[] = [];
if (signals?.openVulnAvailable) availableSignals.push('open vulnerability data');
if (signals?.scorecardAvailable) availableSignals.push('OpenSSF Scorecard');
if (signals?.securityPracticesAvailable) availableSignals.push('security practices');
if (signals?.dependencyHealthAvailable) availableSignals.push('dependency health');
const reason = signals?.isGerrit ? 'Gerrit-hosted projects' : 'this repository type';
const namedAvailable =
availableSignals.length > 0
? `Only open vulnerability data and ${availableSignals.join(', ')} ${availableSignals.length === 1 ? 'is' : 'are'} available for ${reason}.`
: `Only open vulnerability data is available for ${reason}.`;
? `Only ${availableSignals.join(', ')} ${availableSignals.length === 1 ? 'is' : 'are'} available for ${reason}.`
: `No security signals are available for ${reason}.`;
return `${namedAvailable} The category has been dropped from the Health Score composite.`;
}
const availableSignals: string[] = [];
Expand Down Expand Up @@ -373,6 +374,12 @@ export const getOrgDiversityRow = (signals: HealthBreakdownResults): SignalRow =
// --- Security signals ---

export const getOpenVulnRow = (signals: HealthBreakdownResults): SignalRow => {
if (!signals.openVulnAvailable || signals.openVulnScore === null) {
return {
status: 'no-data',
description: blockedSignalDescription('Open vulnerabilities', signals),
};
}
const criticals = signals.openCriticals ?? 0;
const highs = signals.openHighs ?? 0;
const moderates = signals.openModerates ?? 0;
Expand Down
1 change: 1 addition & 0 deletions frontend/types/overview/responses.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export interface HealthBreakdownResults {

// Security
openVulnScore: number | null;
openVulnAvailable: boolean | null;
openCriticals: number | null;
openHighs: number | null;
openModerates: number | null;
Expand Down
Loading