diff --git a/frontend/src/component/insights/componentsStat/CreationArchiveStats/CreationArchiveStats.tsx b/frontend/src/component/insights/componentsStat/CreationArchiveStats/CreationArchiveStats.tsx index a674165dfe..746b7c3172 100644 --- a/frontend/src/component/insights/componentsStat/CreationArchiveStats/CreationArchiveStats.tsx +++ b/frontend/src/component/insights/componentsStat/CreationArchiveStats/CreationArchiveStats.tsx @@ -7,36 +7,7 @@ import { StatsExplanation } from 'component/insights/InsightsCharts.styles'; import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends'; import type { InstanceInsightsSchema } from 'openapi'; import { Link } from 'react-router-dom'; -import { calculateRatio } from 'component/insights/calculate-ratio/calculate-ratio'; - -function getCurrentArchiveRatio( - groupedCreationArchiveData: GroupedDataByProject< - InstanceInsightsSchema['creationArchiveTrends'] - >, -) { - if (!groupedCreationArchiveData) { - return 0; - } - - let totalArchived = 0; - let totalCreated = 0; - - Object.values(groupedCreationArchiveData).forEach((projectData) => { - const latestData = projectData[0]; - if (latestData) { - totalArchived += latestData.archivedFlags || 0; - const createdSum = latestData.createdFlags - ? Object.values(latestData.createdFlags).reduce( - (sum: number, count: number) => sum + count, - 0, - ) - : 0; - totalCreated += createdSum; - } - }); - - return calculateRatio(totalArchived, totalCreated); -} +import { calculateArchiveRatio } from './calculateArchiveRatio.ts'; const StyledRatioContainer = styled(Box)(({ theme }) => ({ backgroundColor: theme.palette.background.elevation1, @@ -83,20 +54,20 @@ export const CreationArchiveStats: FC = ({ groupedCreationArchiveData, isLoading, }) => { - const currentRatio = getCurrentArchiveRatio(groupedCreationArchiveData); + const averageRatio = calculateArchiveRatio(groupedCreationArchiveData); return ( <> - {isLoading ? '...' : currentRatio} + {isLoading ? '...' : averageRatio} - + - Current ratio + Average ratio diff --git a/frontend/src/component/insights/componentsStat/CreationArchiveStats/calculateArchiveRatio.test.ts b/frontend/src/component/insights/componentsStat/CreationArchiveStats/calculateArchiveRatio.test.ts new file mode 100644 index 0000000000..0d31da89e1 --- /dev/null +++ b/frontend/src/component/insights/componentsStat/CreationArchiveStats/calculateArchiveRatio.test.ts @@ -0,0 +1,114 @@ +import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends.ts'; +import { calculateArchiveRatio } from './calculateArchiveRatio.ts'; +import type { InstanceInsightsSchema } from 'openapi/index.ts'; + +describe('calculateArchiveRatio', () => { + it('should return "N/A" when the data is empty', () => { + expect(calculateArchiveRatio({})).toBe('N/A'); + }); + + it('should return "N/A" when no flags have been created', () => { + const result = calculateArchiveRatio({ + a: [ + { + week: '2024-53', + date: '2025-01-05T01:00:00.000Z', + project: 'a', + createdFlags: { + release: 0, + }, + archivedFlags: 10, + }, + ], + }); + expect(result).toBe('N/A'); + }); + + it('should count missing `createdFlags` and `archivedFlags` properties as 0', () => { + const result = calculateArchiveRatio({ + project: [ + // @ts-expect-error: the type requires `createdFlags` to be present + { + week: '2024-53', + date: '2025-01-05T01:00:00.000Z', + project: 'a', + archivedFlags: 1, + }, + // @ts-expect-error: the type requires `archivedFlags` to be present + { + week: '2024-53', + date: '2025-01-05T01:00:00.000Z', + project: 'a', + createdFlags: { + release: 1, + }, + }, + ], + }); + expect(result).toBe('100%'); + }); + + it('should count all flag types listed under createdFlags', () => { + const input: GroupedDataByProject< + InstanceInsightsSchema['creationArchiveTrends'] + > = { + projectA: [ + { + week: '2025-40', + date: '2025-10-05T00:21:42.617Z', + project: 'projectA', + createdFlags: { + release: 1, + killswitch: 1, + experiment: 1, + operational: 1, + bogus: 1, + }, + archivedFlags: 5, + }, + ], + }; + + expect(calculateArchiveRatio(input)).toBe('100%'); + }); + + it('should take the average of all data points', () => { + const input: GroupedDataByProject< + InstanceInsightsSchema['creationArchiveTrends'] + > = { + projectA: [ + { + week: '2025-40', + date: '2025-10-05T00:21:42.617Z', + project: 'projectA', + createdFlags: { + release: 1, + }, + archivedFlags: 2, + }, + { + week: '2025-38', + date: '2025-09-22T10:36:58.612Z', + project: 'projectA', + createdFlags: { + killswitch: 6, + }, + archivedFlags: 7, + }, + ], + projectB: [ + { + week: '2025-03', + date: '2025-01-19T01:00:00.000Z', + project: 'projectB', + createdFlags: { + release: 0, + }, + archivedFlags: 5, + }, + ], + }; + + expect(calculateArchiveRatio(input)).toBe('200%'); + }); +}); diff --git a/frontend/src/component/insights/componentsStat/CreationArchiveStats/calculateArchiveRatio.ts b/frontend/src/component/insights/componentsStat/CreationArchiveStats/calculateArchiveRatio.ts new file mode 100644 index 0000000000..1d62b7a9d5 --- /dev/null +++ b/frontend/src/component/insights/componentsStat/CreationArchiveStats/calculateArchiveRatio.ts @@ -0,0 +1,37 @@ +import { calculateRatio } from 'component/insights/calculate-ratio/calculate-ratio'; +import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends'; +import type { InstanceInsightsSchema } from 'openapi'; + +export const calculateArchiveRatio = ( + groupedCreationArchiveData: GroupedDataByProject< + InstanceInsightsSchema['creationArchiveTrends'] + >, +): string => { + const { totalCreated, totalArchived } = Object.values( + groupedCreationArchiveData, + ).reduce( + (totalAcc, totalCurr) => { + const { created, archived } = totalCurr.reduce( + (acc, curr) => { + const createdSum = curr.createdFlags + ? Object.values(curr.createdFlags).reduce( + (sum, count) => sum + count, + 0, + ) + : 0; + return { + created: acc.created + createdSum, + archived: acc.archived + (curr.archivedFlags ?? 0), + }; + }, + { created: 0, archived: 0 }, + ); + return { + totalCreated: totalAcc.totalCreated + created, + totalArchived: totalAcc.totalArchived + archived, + }; + }, + { totalCreated: 0, totalArchived: 0 }, + ); + return calculateRatio(totalArchived, totalCreated); +};