From 5c2f1aca5ad26820519eec10083ee5afcffa58e3 Mon Sep 17 00:00:00 2001 From: Philipp Martens Date: Wed, 26 Feb 2025 15:08:24 +0100 Subject: [PATCH 1/7] feat: delete critical license table --- .../CriticalLicensesTable.tsx | 168 ------------------ .../ProjectStatisticsPopup.tsx | 8 - src/shared/text.ts | 1 - 3 files changed, 177 deletions(-) delete mode 100644 src/Frontend/Components/CriticalLicensesTable/CriticalLicensesTable.tsx diff --git a/src/Frontend/Components/CriticalLicensesTable/CriticalLicensesTable.tsx b/src/Frontend/Components/CriticalLicensesTable/CriticalLicensesTable.tsx deleted file mode 100644 index 43c6f5ee4..000000000 --- a/src/Frontend/Components/CriticalLicensesTable/CriticalLicensesTable.tsx +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-FileCopyrightText: Meta Platforms, Inc. and its affiliates -// SPDX-FileCopyrightText: TNG Technology Consulting GmbH -// -// SPDX-License-Identifier: Apache-2.0 -import { sortBy } from 'lodash'; - -import { Criticality } from '../../../shared/shared-types'; -import { text } from '../../../shared/text'; -import { clickableIcon } from '../../shared-styles'; -import { LicenseNamesWithCriticality } from '../../types/types'; -import { ProjectLicensesTable } from '../ProjectLicensesTable/ProjectLicensesTable'; - -const LICENSE_COLUMN_NAME_IN_TABLE = 'License name'; -const FOOTER_TITLE = 'Total'; -const TABLE_COLUMN_NAMES = [ - LICENSE_COLUMN_NAME_IN_TABLE, - text.projectStatisticsPopup.criticalLicensesSignalCountColumnName, -]; - -const classes = { - container: { - maxHeight: '400px', - maxWidth: '500px', - marginBottom: '3px', - }, - clickableIcon, - iconButton: { - marginLeft: '8px', - }, -}; - -interface CriticalLicensesTableProps { - totalAttributionsPerLicense: { [licenseName: string]: number }; - licenseNamesWithCriticality: LicenseNamesWithCriticality; - title: string; -} - -interface LicenseNameAndTotalNumberOfAttributions { - licenseName: string; - totalNumberOfAttributions: number; -} - -export const CriticalLicensesTable: React.FC = ( - props, -) => { - const allLicensesWithCriticality = Object.entries( - props.licenseNamesWithCriticality, - ).map((licenseNameAndCriticality) => { - return { - licenseName: licenseNameAndCriticality[0], - criticality: licenseNameAndCriticality[1], - }; - }); - const highCriticalityLicenseNames = getLicenseNamesByCriticality( - allLicensesWithCriticality, - Criticality.High, - ); - const mediumCriticalityLicenseNames = getLicenseNamesByCriticality( - allLicensesWithCriticality, - Criticality.Medium, - ); - const highCriticalityLicensesTotalAttributions: Array = - getCriticalLicenseNamesWithTheirTotalAttributions( - props.totalAttributionsPerLicense, - highCriticalityLicenseNames, - ); - const mediumCriticalityLicensesTotalAttributions: Array = - getCriticalLicenseNamesWithTheirTotalAttributions( - props.totalAttributionsPerLicense, - mediumCriticalityLicenseNames, - ); - const sortedCriticalLicensesTotalAttributions: Array = - sortLicenseNamesWithTotalAttributions( - highCriticalityLicensesTotalAttributions, - ).concat( - sortLicenseNamesWithTotalAttributions( - mediumCriticalityLicensesTotalAttributions, - ), - ); - - return ( - attribution.licenseName, - )} - tableContent={Object.fromEntries( - sortedCriticalLicensesTotalAttributions.map( - ({ licenseName, totalNumberOfAttributions }) => [ - licenseName, - { - [text.projectStatisticsPopup - .criticalLicensesSignalCountColumnName]: - totalNumberOfAttributions, - }, - ], - ), - )} - tableFooter={[FOOTER_TITLE].concat( - getTotalNumberOfAttributions( - sortedCriticalLicensesTotalAttributions, - ).toString(), - )} - licenseNamesWithCriticality={props.licenseNamesWithCriticality} - /> - ); -}; - -function getLicenseNamesByCriticality( - allLicensesWithCriticality: Array<{ - licenseName: string; - criticality: Criticality | undefined; - }>, - criticality: Criticality, -): Array { - return allLicensesWithCriticality - .map((licenseNameAndCriticality) => - licenseNameAndCriticality.criticality === criticality - ? licenseNameAndCriticality.licenseName - : '', - ) - .filter((licenseName) => licenseName !== ''); -} - -function getCriticalLicenseNamesWithTheirTotalAttributions( - totalAttributionsPerLicense: { [licenseName: string]: number }, - criticalLicenseNames: Array, -): Array { - const licenseNamesAndTheirTotalAttributions = criticalLicenseNames.map( - (criticalLicenseName) => { - return { - licenseName: criticalLicenseName, - totalNumberOfAttributions: - totalAttributionsPerLicense[criticalLicenseName], - }; - }, - ); - return licenseNamesAndTheirTotalAttributions.sort(); -} - -function getTotalNumberOfAttributions( - licenseNamesAndTheirTotalAttributions: Array<{ - licenseName: string; - totalNumberOfAttributions: number; - }>, -): number { - return licenseNamesAndTheirTotalAttributions - .map( - (licenseNameAndTotalAttributions) => - licenseNameAndTotalAttributions.totalNumberOfAttributions, - ) - .reduce((total, value) => total + value, 0); -} - -function sortLicenseNamesWithTotalAttributions( - licenseNamesWithTotalAttributions: Array<{ - licenseName: string; - totalNumberOfAttributions: number; - }>, -): Array<{ licenseName: string; totalNumberOfAttributions: number }> { - return sortBy( - licenseNamesWithTotalAttributions, - ({ licenseName }) => licenseName, - ); -} diff --git a/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx b/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx index 9478d5fe4..53984a514 100644 --- a/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx +++ b/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx @@ -21,7 +21,6 @@ import { AccordionWithPieChart } from '../AccordionWithPieChart/AccordionWithPie import { AttributionCountPerSourcePerLicenseTable } from '../AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable'; import { AttributionPropertyCountTable } from '../AttributionPropertyCountTable/AttributionPropertyCountTable'; import { Checkbox } from '../Checkbox/Checkbox'; -import { CriticalLicensesTable } from '../CriticalLicensesTable/CriticalLicensesTable'; import { NotificationPopup } from '../NotificationPopup/NotificationPopup'; import { aggregateAttributionPropertiesFromAttributions, @@ -117,13 +116,6 @@ export const ProjectStatisticsPopup: React.FC = () => { .attributionPropertyCountTable } /> - diff --git a/src/shared/text.ts b/src/shared/text.ts index 984e0af91..002d72864 100644 --- a/src/shared/text.ts +++ b/src/shared/text.ts @@ -170,7 +170,6 @@ export const text = { charts: { licenseCountsTable: 'Signals per Sources', attributionPropertyCountTable: 'Attributions Overview', - criticalLicensesTable: 'Critical Licenses', pieChartsSectionHeader: 'Pie Charts', mostFrequentLicenseCountPieChart: 'Most Frequent Licenses', criticalSignalsCountPieChart: 'Signals by Criticality', From 57314542528b6c3dc470385b84794eb32d02863b Mon Sep 17 00:00:00 2001 From: Philipp Martens Date: Wed, 26 Feb 2025 15:14:01 +0100 Subject: [PATCH 2/7] refactor: delete ProjectLicensesTable component * as there was only one remaining component it, move its functionality there --- ...tributionCountPerSourcePerLicenseTable.tsx | 115 ++++++++++++++++-- .../ProjectLicensesTable.tsx | 107 ---------------- .../ProjectStatisticsPopup.tsx | 1 + 3 files changed, 103 insertions(+), 120 deletions(-) delete mode 100644 src/Frontend/Components/ProjectLicensesTable/ProjectLicensesTable.tsx diff --git a/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx b/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx index a01816c4e..564189abb 100644 --- a/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx +++ b/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx @@ -2,10 +2,22 @@ // SPDX-FileCopyrightText: TNG Technology Consulting GmbH // // SPDX-License-Identifier: Apache-2.0 -import { sortBy } from 'lodash'; +import MuiBox from '@mui/material/Box'; +import MuiTable from '@mui/material/Table'; +import MuiTableBody from '@mui/material/TableBody'; +import MuiTableCell from '@mui/material/TableCell'; +import MuiTableContainer from '@mui/material/TableContainer'; +import MuiTableFooter from '@mui/material/TableFooter'; +import MuiTableHead from '@mui/material/TableHead'; +import MuiTableRow from '@mui/material/TableRow'; +import MuiTypography from '@mui/material/Typography'; -import { LicenseCounts, LicenseNamesWithCriticality } from '../../types/types'; -import { ProjectLicensesTable } from '../ProjectLicensesTable/ProjectLicensesTable'; +import { tableClasses } from '../../shared-styles'; +import { + LicenseCounts, + LicenseNamesWithClassification, + LicenseNamesWithCriticality, +} from '../../types/types'; const classes = { container: { @@ -21,6 +33,7 @@ const TOTAL_SOURCES_TITLE = 'Total'; interface AttributionCountPerSourcePerLicenseTableProps { licenseCounts: LicenseCounts; licenseNamesWithCriticality: LicenseNamesWithCriticality; + licenseNamesWithClassification: LicenseNamesWithClassification; title: string; } @@ -58,16 +71,92 @@ export const AttributionCountPerSourcePerLicenseTable: React.FC< props.licenseCounts.totalAttributionsPerLicense[licenseName]), ); + const tableHead = ( + + + {headerRow.map((columnHeader, columnIndex) => ( + + {columnHeader} + + ))} + + + ); + + const buildTableRow = (licenseName: string, rowIndex: number) => { + const licenseNameCell = ( + + {licenseName} + + ); + + const countBySourceCells = sourceNames + .concat(TOTAL_SOURCES_TITLE) + .map((sourceName, sourceIdx) => { + const columnIndex = 1 + sourceIdx; + + return ( + + {props.licenseCounts.attributionCountPerSourcePerLicense[ + licenseName + ][sourceName] || '-'} + + ); + }); + + return ( + + {[licenseNameCell, ...countBySourceCells]} + + ); + }; + + const tableFooter = ( + + + {footerRow.map((total, columnIndex) => ( + + {total} + + ))} + + + ); + return ( - + + {props.title} + + + {tableHead} + + {Object.keys(props.licenseNamesWithCriticality) + .toSorted() + .map(buildTableRow)} + + {tableFooter} + + + ); }; diff --git a/src/Frontend/Components/ProjectLicensesTable/ProjectLicensesTable.tsx b/src/Frontend/Components/ProjectLicensesTable/ProjectLicensesTable.tsx deleted file mode 100644 index d3a30c8a7..000000000 --- a/src/Frontend/Components/ProjectLicensesTable/ProjectLicensesTable.tsx +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-FileCopyrightText: Meta Platforms, Inc. and its affiliates -// SPDX-FileCopyrightText: TNG Technology Consulting GmbH -// -// SPDX-License-Identifier: Apache-2.0 -import MuiBox from '@mui/material/Box'; -import MuiTable from '@mui/material/Table'; -import MuiTableBody from '@mui/material/TableBody'; -import MuiTableCell from '@mui/material/TableCell'; -import MuiTableContainer from '@mui/material/TableContainer'; -import MuiTableFooter from '@mui/material/TableFooter'; -import MuiTableHead from '@mui/material/TableHead'; -import MuiTableRow from '@mui/material/TableRow'; -import MuiTypography from '@mui/material/Typography'; - -import { Criticality } from '../../../shared/shared-types'; -import { OpossumColors, tableClasses } from '../../shared-styles'; -import { LicenseNamesWithCriticality } from '../../types/types'; - -const PLACEHOLDER_ATTRIBUTION_COUNT = '-'; - -interface TableContent { - [rowName: string]: { [columnName: string]: number }; -} - -interface ProjectLicensesTableProps { - title: string; - containerStyle: { [key: string]: string | number }; - columnHeaders: Array; - columnNames: Array; - rowNames: Array; - tableContent: TableContent; - tableFooter?: Array; - licenseNamesWithCriticality: LicenseNamesWithCriticality; -} - -export const ProjectLicensesTable: React.FC = ( - props, -) => { - return ( - - {props.title} - - - - - {props.columnHeaders.map((columnHeader, columnIndex) => ( - - {columnHeader} - - ))} - - - - {props.rowNames.map((rowName, rowIndex) => ( - - {props.columnNames.map((columnName, columnIndex) => ( - - {columnIndex === 0 ? ( - {rowName} - ) : ( - props.tableContent[rowName][columnName] || - PLACEHOLDER_ATTRIBUTION_COUNT - )} - - ))} - - ))} - - {props.tableFooter && ( - - - {props.tableFooter.map((total, columnIndex) => ( - - {total} - - ))} - - - )} - - - - ); -}; diff --git a/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx b/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx index 53984a514..93830f147 100644 --- a/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx +++ b/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx @@ -158,6 +158,7 @@ export const ProjectStatisticsPopup: React.FC = () => { From c9a9df5834441bbd478e904fea27b9b3843ab9ab Mon Sep 17 00:00:00 2001 From: Philipp Martens Date: Wed, 26 Feb 2025 16:00:41 +0100 Subject: [PATCH 3/7] feat: add criticality column to SignalsPerSources table --- ...tributionCountPerSourcePerLicenseTable.tsx | 51 ++++++++++++++----- .../ProjectStatisticsPopup.tsx | 1 - 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx b/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx index 564189abb..2a634c6d8 100644 --- a/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx +++ b/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx @@ -12,12 +12,9 @@ import MuiTableHead from '@mui/material/TableHead'; import MuiTableRow from '@mui/material/TableRow'; import MuiTypography from '@mui/material/Typography'; -import { tableClasses } from '../../shared-styles'; -import { - LicenseCounts, - LicenseNamesWithClassification, - LicenseNamesWithCriticality, -} from '../../types/types'; +import { Criticality } from '../../../shared/shared-types'; +import { OpossumColors, tableClasses } from '../../shared-styles'; +import { LicenseCounts, LicenseNamesWithCriticality } from '../../types/types'; const classes = { container: { @@ -27,13 +24,13 @@ const classes = { }; const LICENSE_COLUMN_NAME_IN_TABLE = 'License name'; +const CRITICALITY_COLUMN_NAME_IN_TABLE = 'Criticality'; const FOOTER_TITLE = 'Total'; const TOTAL_SOURCES_TITLE = 'Total'; interface AttributionCountPerSourcePerLicenseTableProps { licenseCounts: LicenseCounts; licenseNamesWithCriticality: LicenseNamesWithCriticality; - licenseNamesWithClassification: LicenseNamesWithClassification; title: string; } @@ -54,9 +51,11 @@ export const AttributionCountPerSourcePerLicenseTable: React.FC< .toString(); const footerRow = [FOOTER_TITLE] + .concat('') .concat(totalNumberOfAttributionsPerSource) .concat(totalNumberOfAttributions); const headerRow = [LICENSE_COLUMN_NAME_IN_TABLE] + .concat(CRITICALITY_COLUMN_NAME_IN_TABLE) .concat(sourceNames) .concat(TOTAL_SOURCES_TITLE) .map( @@ -100,10 +99,30 @@ export const AttributionCountPerSourcePerLicenseTable: React.FC< ); - const countBySourceCells = sourceNames - .concat(TOTAL_SOURCES_TITLE) - .map((sourceName, sourceIdx) => { - const columnIndex = 1 + sourceIdx; + const licenseCriticality = props.licenseNamesWithCriticality[licenseName]; + const criticalityColor = + licenseCriticality === Criticality.High + ? OpossumColors.orange + : licenseCriticality === Criticality.Medium + ? OpossumColors.mediumOrange + : undefined; + + const criticalityCell = ( + + {licenseCriticality ?? '-'} + + ); + + const buildCountBySourceCell = + (columnOffset: number) => (sourceName: string, sourceIdx: number) => { + const columnIndex = columnOffset + sourceIdx; return ( ); - }); + }; + + const singleCells = [licenseNameCell, criticalityCell]; return ( - {[licenseNameCell, ...countBySourceCells]} + {singleCells.concat( + sourceNames + .concat(TOTAL_SOURCES_TITLE) + .map(buildCountBySourceCell(singleCells.length)), + )} ); }; diff --git a/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx b/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx index 93830f147..53984a514 100644 --- a/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx +++ b/src/Frontend/Components/ProjectStatisticsPopup/ProjectStatisticsPopup.tsx @@ -158,7 +158,6 @@ export const ProjectStatisticsPopup: React.FC = () => { From 68dd61e6afabbeb2cef7f1e06f2bc8e9d7bb3cbe Mon Sep 17 00:00:00 2001 From: Philipp Martens Date: Wed, 26 Feb 2025 16:03:21 +0100 Subject: [PATCH 4/7] test: update test for ProjectStatisticsPopup --- .../__tests__/ProjectStatisticsPopup.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Frontend/Components/ProjectStatisticsPopup/__tests__/ProjectStatisticsPopup.test.tsx b/src/Frontend/Components/ProjectStatisticsPopup/__tests__/ProjectStatisticsPopup.test.tsx index f9408d023..df5841359 100644 --- a/src/Frontend/Components/ProjectStatisticsPopup/__tests__/ProjectStatisticsPopup.test.tsx +++ b/src/Frontend/Components/ProjectStatisticsPopup/__tests__/ProjectStatisticsPopup.test.tsx @@ -218,8 +218,8 @@ describe('The ProjectStatisticsPopup', () => { ), ], }); - expect(screen.getAllByText('License name')).toHaveLength(2); - expect(screen.getAllByText('Total')).toHaveLength(3); + expect(screen.getAllByText('License name')).toHaveLength(1); + expect(screen.getAllByText('Total')).toHaveLength(2); expect(screen.getByText('Follow up')).toBeInTheDocument(); expect(screen.getByText('First party')).toBeInTheDocument(); }); From 1e648da800ea5ee331253985273cb0a2262b49ba Mon Sep 17 00:00:00 2001 From: Philipp Martens Date: Wed, 26 Feb 2025 16:35:20 +0100 Subject: [PATCH 5/7] test: fix e2e test for project statistics popup --- .../__tests__/project-statistics.test.ts | 4 ++-- .../page-objects/ProjectStatisticsPopup.ts | 17 +++++------------ 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/e2e-tests/__tests__/project-statistics.test.ts b/src/e2e-tests/__tests__/project-statistics.test.ts index d1f91b578..2aa0cd82d 100644 --- a/src/e2e-tests/__tests__/project-statistics.test.ts +++ b/src/e2e-tests/__tests__/project-statistics.test.ts @@ -54,7 +54,7 @@ test('hidden signals are ignored for project statistics', async ({ await menuBar.openProjectStatistics(); await projectStatisticsPopup.assert.titleIsVisible(); - await projectStatisticsPopup.assert.criticalLicenseCount(2); + await projectStatisticsPopup.assert.totalSignalCount(2); await projectStatisticsPopup.closeButton.click(); await resourcesTree.goto(resourceName1); @@ -67,5 +67,5 @@ test('hidden signals are ignored for project statistics', async ({ await signalsPanel.packageCard.assert.isHidden(packageInfo3); await menuBar.openProjectStatistics(); - await projectStatisticsPopup.assert.criticalLicenseCount(1); + await projectStatisticsPopup.assert.totalSignalCount(1); }); diff --git a/src/e2e-tests/page-objects/ProjectStatisticsPopup.ts b/src/e2e-tests/page-objects/ProjectStatisticsPopup.ts index 624bdfbc7..a1d903a05 100644 --- a/src/e2e-tests/page-objects/ProjectStatisticsPopup.ts +++ b/src/e2e-tests/page-objects/ProjectStatisticsPopup.ts @@ -4,24 +4,19 @@ // SPDX-License-Identifier: Apache-2.0 import { expect, type Locator, type Page } from '@playwright/test'; -import { text } from '../../shared/text'; - export class ProjectStatisticsPopup { private readonly node: Locator; readonly title: Locator; readonly closeButton: Locator; - readonly totalCriticalLicensesCount: Locator; + readonly totalSignalCount: Locator; constructor(window: Page) { this.node = window.getByLabel('project statistics'); this.title = this.node.getByRole('heading').getByText('Project Statistics'); this.closeButton = this.node.getByRole('button', { name: 'Close' }); - const signalsCount = window.getByText( - text.projectStatisticsPopup.criticalLicensesSignalCountColumnName, - ); - this.totalCriticalLicensesCount = this.node + this.totalSignalCount = this.node .getByRole('table') - .filter({ has: signalsCount }) + .filter({ hasText: 'License name' }) .getByRole('row') .last() .getByRole('cell') @@ -35,10 +30,8 @@ export class ProjectStatisticsPopup { titleIsHidden: async (): Promise => { await expect(this.title).toBeHidden(); }, - criticalLicenseCount: async (count: number): Promise => { - await expect(this.totalCriticalLicensesCount).toContainText( - count.toString(), - ); + totalSignalCount: async (count: number): Promise => { + await expect(this.totalSignalCount).toContainText(count.toString()); }, }; } From 271f0bba502de0feb3d73092996d583a53c765ac Mon Sep 17 00:00:00 2001 From: Philipp Martens Date: Wed, 26 Feb 2025 16:51:57 +0100 Subject: [PATCH 6/7] refactor: move user-facing text from signal by source table text.ts --- ...tributionCountPerSourcePerLicenseTable.tsx | 36 ++++++++++--------- .../page-objects/ProjectStatisticsPopup.ts | 7 +++- src/shared/text.ts | 8 +++++ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx b/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx index 2a634c6d8..e26569823 100644 --- a/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx +++ b/src/Frontend/Components/AttributionCountPerSourcePerLicenseTable/AttributionCountPerSourcePerLicenseTable.tsx @@ -13,6 +13,7 @@ import MuiTableRow from '@mui/material/TableRow'; import MuiTypography from '@mui/material/Typography'; import { Criticality } from '../../../shared/shared-types'; +import { text } from '../../../shared/text'; import { OpossumColors, tableClasses } from '../../shared-styles'; import { LicenseCounts, LicenseNamesWithCriticality } from '../../types/types'; @@ -23,10 +24,7 @@ const classes = { }, }; -const LICENSE_COLUMN_NAME_IN_TABLE = 'License name'; -const CRITICALITY_COLUMN_NAME_IN_TABLE = 'Criticality'; -const FOOTER_TITLE = 'Total'; -const TOTAL_SOURCES_TITLE = 'Total'; +const TOTAL_SOURCE_NAME = 'Total'; interface AttributionCountPerSourcePerLicenseTableProps { licenseCounts: LicenseCounts; @@ -50,23 +48,27 @@ export const AttributionCountPerSourcePerLicenseTable: React.FC< .reduce((partialSum, num) => partialSum + num, 0) .toString(); - const footerRow = [FOOTER_TITLE] - .concat('') - .concat(totalNumberOfAttributionsPerSource) - .concat(totalNumberOfAttributions); - const headerRow = [LICENSE_COLUMN_NAME_IN_TABLE] - .concat(CRITICALITY_COLUMN_NAME_IN_TABLE) - .concat(sourceNames) - .concat(TOTAL_SOURCES_TITLE) - .map( - (sourceName) => sourceName.charAt(0).toUpperCase() + sourceName.slice(1), - ); + const footerRow = [ + text.attributionCountPerSourcePerLicenseTable.footerTitle, + '', + ...totalNumberOfAttributionsPerSource, + totalNumberOfAttributions, + ]; + + const headerRow = [ + text.attributionCountPerSourcePerLicenseTable.columnNames.licenseName, + text.attributionCountPerSourcePerLicenseTable.columnNames.criticality, + ...sourceNames, + text.attributionCountPerSourcePerLicenseTable.columnNames.totalSources, + ].map( + (sourceName) => sourceName.charAt(0).toUpperCase() + sourceName.slice(1), + ); Object.entries( props.licenseCounts.attributionCountPerSourcePerLicense, ).forEach( ([licenseName, value]) => - (value[TOTAL_SOURCES_TITLE] = + (value[TOTAL_SOURCE_NAME] = props.licenseCounts.totalAttributionsPerLicense[licenseName]), ); @@ -145,7 +147,7 @@ export const AttributionCountPerSourcePerLicenseTable: React.FC< {singleCells.concat( sourceNames - .concat(TOTAL_SOURCES_TITLE) + .concat(TOTAL_SOURCE_NAME) .map(buildCountBySourceCell(singleCells.length)), )} diff --git a/src/e2e-tests/page-objects/ProjectStatisticsPopup.ts b/src/e2e-tests/page-objects/ProjectStatisticsPopup.ts index a1d903a05..847d68ef5 100644 --- a/src/e2e-tests/page-objects/ProjectStatisticsPopup.ts +++ b/src/e2e-tests/page-objects/ProjectStatisticsPopup.ts @@ -4,6 +4,8 @@ // SPDX-License-Identifier: Apache-2.0 import { expect, type Locator, type Page } from '@playwright/test'; +import { text } from '../../shared/text'; + export class ProjectStatisticsPopup { private readonly node: Locator; readonly title: Locator; @@ -16,7 +18,10 @@ export class ProjectStatisticsPopup { this.closeButton = this.node.getByRole('button', { name: 'Close' }); this.totalSignalCount = this.node .getByRole('table') - .filter({ hasText: 'License name' }) + .filter({ + hasText: + text.attributionCountPerSourcePerLicenseTable.columnNames.licenseName, + }) .getByRole('row') .last() .getByRole('cell') diff --git a/src/shared/text.ts b/src/shared/text.ts index 002d72864..a9d2ddfb9 100644 --- a/src/shared/text.ts +++ b/src/shared/text.ts @@ -177,6 +177,14 @@ export const text = { incompleteAttributionsPieChart: 'Incomplete Attributions', }, }, + attributionCountPerSourcePerLicenseTable: { + footerTitle: 'Total', + columnNames: { + licenseName: 'License Name', + criticality: 'Criticality', + totalSources: 'Total', + }, + }, unsavedChangesPopup: { title: 'Unsaved Changes', message: 'You have unsaved changes. What would you like to do?', From 2c65cf4f005b35144d97c0485400cad1f9d55d75 Mon Sep 17 00:00:00 2001 From: Philipp Martens Date: Wed, 26 Feb 2025 16:56:51 +0100 Subject: [PATCH 7/7] test: fix failing unit test for project statistics popup --- .../__tests__/ProjectStatisticsPopup.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Frontend/Components/ProjectStatisticsPopup/__tests__/ProjectStatisticsPopup.test.tsx b/src/Frontend/Components/ProjectStatisticsPopup/__tests__/ProjectStatisticsPopup.test.tsx index df5841359..7e27820c6 100644 --- a/src/Frontend/Components/ProjectStatisticsPopup/__tests__/ProjectStatisticsPopup.test.tsx +++ b/src/Frontend/Components/ProjectStatisticsPopup/__tests__/ProjectStatisticsPopup.test.tsx @@ -218,7 +218,7 @@ describe('The ProjectStatisticsPopup', () => { ), ], }); - expect(screen.getAllByText('License name')).toHaveLength(1); + expect(screen.getAllByText('License Name')).toHaveLength(1); expect(screen.getAllByText('Total')).toHaveLength(2); expect(screen.getByText('Follow up')).toBeInTheDocument(); expect(screen.getByText('First party')).toBeInTheDocument();