From 12cb1f15e4359a38c1047adf764c50633e23ed20 Mon Sep 17 00:00:00 2001 From: T0RAT0RA Date: Mon, 5 Dec 2022 14:54:09 -0500 Subject: [PATCH] Improve extensibility (#122) * Add ability to replace the % sign in chips * Add ability to specify reviewer entity ref * Add title prop to ScoreCardTable for extensibility * Add new prop scoreLabel to override chip labels on score tables Add podcast system scores as an example * Add changeset info * Remove unused import * Update plugins/score-card/src/components/ScoreCard/columns/areaColumn.tsx Signed-off-by: T0RAT0RA --- .changeset/tasty-seas-remember.md | 5 + .../app/cypress/integration/scoreboard.ts | 2 +- plugins/score-card/sample-data/all.json | 316 ++++++++++++++++++ plugins/score-card/sample-data/podcast.json | 316 ++++++++++++++++++ .../src/api/ScoringDataJsonClient.ts | 13 +- plugins/score-card/src/api/types.ts | 5 +- .../components/ScoreCard/ScoreCard.test.tsx | 25 +- .../src/components/ScoreCard/ScoreCard.tsx | 3 +- .../ScoreCard/columns/areaColumn.tsx | 2 +- .../ScoreCard/columns/scorePercentColumn.tsx | 3 +- .../ScoreCardTable/ScoreCardTable.test.tsx | 64 ++++ .../ScoreCardTable/ScoreCardTable.tsx | 18 +- 12 files changed, 757 insertions(+), 15 deletions(-) create mode 100644 .changeset/tasty-seas-remember.md create mode 100644 plugins/score-card/sample-data/podcast.json diff --git a/.changeset/tasty-seas-remember.md b/.changeset/tasty-seas-remember.md new file mode 100644 index 0000000000..0ebf4c69f1 --- /dev/null +++ b/.changeset/tasty-seas-remember.md @@ -0,0 +1,5 @@ +--- +'@oriflame/backstage-plugin-score-card': patch +--- + +Improve extensibility by adding `scoreLabel`, to override `scorePercent` and adding a `title` prop to ScoreCardTable component diff --git a/packages/app/cypress/integration/scoreboard.ts b/packages/app/cypress/integration/scoreboard.ts index 29eca73a7b..c9ed6fce98 100644 --- a/packages/app/cypress/integration/scoreboard.ts +++ b/packages/app/cypress/integration/scoreboard.ts @@ -27,7 +27,7 @@ describe('score-card', () => { cy.contains('System scores overview').should('be.visible'); cy.checkForErrors(); - cy.get('span:contains("1-2 of 2")').should('be.visible'); // beware, there is also a hidden

element + cy.get('span:contains("1-3 of 3")').should('be.visible'); // beware, there is also a hidden

element cy.contains('audio-playback').should('be.visible'); cy.contains('team-c').should('be.visible'); cy.contains('non-valid-system').should('be.visible'); diff --git a/plugins/score-card/sample-data/all.json b/plugins/score-card/sample-data/all.json index 0a58f83f0f..3dc247cff5 100644 --- a/plugins/score-card/sample-data/all.json +++ b/plugins/score-card/sample-data/all.json @@ -315,5 +315,321 @@ ] } ] + }, + { + "systemEntityName": "podcast", + "systemTier": "A", + "SystemDataConfidentiality": "Confidential", + "SystemDataSensitivity": ["PII", "Sensitive-PII"], + "generatedDateTimeUtc": "2021-07-22 10:00", + "scorePercent": 57, + "scoreLabel": "C", + "scoreSuccess": "partial", + "scoringReviewer": "Guest", + "scoringReviewDate": "2022-01-04T08:00:00Z", + "areaScores": [ + { + "id": 2199, + "title": "Code", + "scorePercent": 90, + "scoreLabel": "A", + "scoreSuccess": "success", + "scoreEntries": [ + { + "id": 2157, + "title": "GitFlow", + "scorePercent": 100, + "scoreLabel": "A", + "scoreSuccess": "success", + "scoreHints": "Gitflow: 100%", + "details": "..." + }, + { + "id": 2159, + "title": "Identity Management", + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2163, + "title": "Swagger", + "scoreSuccess": "unknown", + "isOptional": true, + "details": "..." + }, + { + "id": 2158, + "title": "Https", + "scoreSuccess": "unknown", + "isOptional": true, + "details": "..." + }, + { + "id": 2153, + "title": "Application Insights", + "scorePercent": 80, + "scoreLabel": "B", + "scoreSuccess": ["AppInsights configured", "Dashboard present"], + "details": "Lorem ipsum for **AppInsights** sit amet, consectetuer adipiscing elit. Aliquam erat volutpat. In laoreet, magna id viverra tincidunt, sem odio bibendum justo, vel imperdiet sapien wisi sed libero. Nullam at arcu a est sollicitudin euismod. Aliquam id dolor. Fusce nibh. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor. Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Mauris elementum mauris vitae tortor. Maecenas libero. Duis pulvinar. Pellentesque pretium lectus id turpis. Duis ante orci, molestie vitae vehicula venenatis, tincidunt ac pede. Etiam commodo dui eget wisi. Nunc dapibus tortor vel mi dapibus sollicitudin. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Duis risus." + } + ] + }, + { + "id": 3937, + "title": "Documentation", + "scorePercent": 75, + "scoreLabel": "B+", + "scoreSuccess": "almost-success", + "scoreEntries": [ + { + "id": 3938, + "title": "Project introduction", + "scorePercent": 100, + "scoreSuccess": "success", + "scoreHints": "Well structured/documented/linked with the wiki: 100%", + "details": "Project home page is linked to **devops wiki**." + }, + { + "id": 3940, + "title": "Project wiki", + "isOptional": false, + "scorePercent": 50, + "scoreSuccess": "partial", + "scoreHints": "Somewhat usefull: 50%", + "details": "Project wiki contains basic information however it is not well structured. It contains brief introduction and few pages about the technology used, but it is missing business context, processes description etc." + }, + { + "id": 2207, + "title": "README", + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2170, + "title": "RFP", + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2164, + "title": "Architecture Diagrams", + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2205, + "title": "SLA", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2165, + "title": "Business Documentation", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2171, + "title": "Road Map", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + } + ] + }, + { + "id": 2208, + "title": "Operations", + "scorePercent": 50, + "scoreLabel": "D", + "scoreSuccess": "partial", + "scoreEntries": [ + { + "id": 2210, + "title": "Health Checks", + "scorePercent": 0, + "scoreSuccess": "failure", + "details": "Completelly missing healthchecks." + }, + { + "id": 2185, + "title": "Semantic Versioning", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2176, + "title": "CI Pipelines", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2175, + "title": "CD Pipelines", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2181, + "title": "Insights Dashboard", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2173, + "title": "Alerts", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2184, + "title": "Release-Notes", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2183, + "title": "Release-Annotations-to-App-Insights", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2178, + "title": "DNS Record", + "isOptional": true, + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2180, + "title": "GitOps", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2177, + "title": "Canary-Checks", + "isOptional": true, + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "...depends on tier/SLA..." + }, + { + "id": 2172, + "title": "AB Testing", + "isOptional": true, + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 3941, + "title": "Disaster Recovery Plan", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2179, + "title": "Data Refresh For Testing Environments", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2174, + "title": "Basic Ops Handed Over to L2", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + } + ] + }, + { + "id": 4333, + "title": "Quality", + "scorePercent": 25, + "scoreLabel": "F", + "scoreSuccess": "almost-failure", + "scoreEntries": [ + { + "id": 2187, + "title": "Code Reviews", + "scorePercent": 100, + "scoreSuccess": "success", + "scoreHints": [ + "PR requires reviewer", + "No override possible", + "PRs are well described", + "PRs are small", + "PRs has comments" + ], + "details": "Development policy is defined. Code review process is done during the pull request with minimum of 2 reviewers." + }, + { + "id": 2191, + "title": "Unit Tests", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2189, + "title": "Integration Tests", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2190, + "title": "Performance Tests", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2186, + "title": "Automation Tests", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2188, + "title": "Design Reviews", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + } + ] + }, + { + "id": 4328, + "title": "Security", + "scorePercent": 10, + "scoreLabel": "F", + "scoreSuccess": "failure", + "scoreEntries": [ + { + "id": 2158, + "title": "Https", + "scorePercent": 0, + "scoreSuccess": "failure", + "details": "At least one endpoint accessible without SSL protection" + } + ] + } + ] } ] diff --git a/plugins/score-card/sample-data/podcast.json b/plugins/score-card/sample-data/podcast.json new file mode 100644 index 0000000000..e5200d500e --- /dev/null +++ b/plugins/score-card/sample-data/podcast.json @@ -0,0 +1,316 @@ +{ + "systemEntityName": "podcast", + "systemTier": "A", + "SystemDataConfidentiality": "Confidential", + "SystemDataSensitivity": ["PII", "Sensitive-PII"], + "generatedDateTimeUtc": "2021-07-22 10:00", + "scorePercent": 57, + "scoreLabel": "C", + "scoreSuccess": "partial", + "scoringReviewer": "Guest", + "scoringReviewDate": "2022-01-04T08:00:00Z", + "areaScores": [ + { + "id": 2199, + "title": "Code", + "scorePercent": 90, + "scoreLabel": "A", + "scoreSuccess": "success", + "scoreEntries": [ + { + "id": 2157, + "title": "GitFlow", + "scorePercent": 100, + "scoreLabel": "A", + "scoreSuccess": "success", + "scoreHints": "Gitflow: 100%", + "details": "..." + }, + { + "id": 2159, + "title": "Identity Management", + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2163, + "title": "Swagger", + "scoreSuccess": "unknown", + "isOptional": true, + "details": "..." + }, + { + "id": 2158, + "title": "Https", + "scoreSuccess": "unknown", + "isOptional": true, + "details": "..." + }, + { + "id": 2153, + "title": "Application Insights", + "scorePercent": 80, + "scoreLabel": "B", + "scoreSuccess": ["AppInsights configured", "Dashboard present"], + "details": "Lorem ipsum for **AppInsights** sit amet, consectetuer adipiscing elit. Aliquam erat volutpat. In laoreet, magna id viverra tincidunt, sem odio bibendum justo, vel imperdiet sapien wisi sed libero. Nullam at arcu a est sollicitudin euismod. Aliquam id dolor. Fusce nibh. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor. Etiam sapien elit, consequat eget, tristique non, venenatis quis, ante. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Mauris elementum mauris vitae tortor. Maecenas libero. Duis pulvinar. Pellentesque pretium lectus id turpis. Duis ante orci, molestie vitae vehicula venenatis, tincidunt ac pede. Etiam commodo dui eget wisi. Nunc dapibus tortor vel mi dapibus sollicitudin. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Duis risus." + } + ] + }, + { + "id": 3937, + "title": "Documentation", + "scorePercent": 75, + "scoreLabel": "B+", + "scoreSuccess": "almost-success", + "scoreEntries": [ + { + "id": 3938, + "title": "Project introduction", + "scorePercent": 100, + "scoreSuccess": "success", + "scoreHints": "Well structured/documented/linked with the wiki: 100%", + "details": "Project home page is linked to **devops wiki**." + }, + { + "id": 3940, + "title": "Project wiki", + "isOptional": false, + "scorePercent": 50, + "scoreSuccess": "partial", + "scoreHints": "Somewhat usefull: 50%", + "details": "Project wiki contains basic information however it is not well structured. It contains brief introduction and few pages about the technology used, but it is missing business context, processes description etc." + }, + { + "id": 2207, + "title": "README", + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2170, + "title": "RFP", + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2164, + "title": "Architecture Diagrams", + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2205, + "title": "SLA", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2165, + "title": "Business Documentation", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2171, + "title": "Road Map", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + } + ] + }, + { + "id": 2208, + "title": "Operations", + "scorePercent": 50, + "scoreLabel": "D", + "scoreSuccess": "partial", + "scoreEntries": [ + { + "id": 2210, + "title": "Health Checks", + "scorePercent": 0, + "scoreSuccess": "failure", + "details": "Completelly missing healthchecks." + }, + { + "id": 2185, + "title": "Semantic Versioning", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2176, + "title": "CI Pipelines", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2175, + "title": "CD Pipelines", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2181, + "title": "Insights Dashboard", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2173, + "title": "Alerts", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2184, + "title": "Release-Notes", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2183, + "title": "Release-Annotations-to-App-Insights", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2178, + "title": "DNS Record", + "isOptional": true, + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2180, + "title": "GitOps", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2177, + "title": "Canary-Checks", + "isOptional": true, + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "...depends on tier/SLA..." + }, + { + "id": 2172, + "title": "AB Testing", + "isOptional": true, + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 3941, + "title": "Disaster Recovery Plan", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2179, + "title": "Data Refresh For Testing Environments", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2174, + "title": "Basic Ops Handed Over to L2", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + } + ] + }, + { + "id": 4333, + "title": "Quality", + "scorePercent": 25, + "scoreLabel": "F", + "scoreSuccess": "almost-failure", + "scoreEntries": [ + { + "id": 2187, + "title": "Code Reviews", + "scorePercent": 100, + "scoreSuccess": "success", + "scoreHints": [ + "PR requires reviewer", + "No override possible", + "PRs are well described", + "PRs are small", + "PRs has comments" + ], + "details": "Development policy is defined. Code review process is done during the pull request with minimum of 2 reviewers." + }, + { + "id": 2191, + "title": "Unit Tests", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2189, + "title": "Integration Tests", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2190, + "title": "Performance Tests", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2186, + "title": "Automation Tests", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + }, + { + "id": 2188, + "title": "Design Reviews", + "scorePercent": 0, + "scoreSuccess": "unknown", + "details": "..." + } + ] + }, + { + "id": 4328, + "title": "Security", + "scorePercent": 10, + "scoreLabel": "F", + "scoreSuccess": "failure", + "scoreEntries": [ + { + "id": 2158, + "title": "Https", + "scorePercent": 0, + "scoreSuccess": "failure", + "details": "At least one endpoint accessible without SSL protection" + } + ] + } + ] +} diff --git a/plugins/score-card/src/api/ScoringDataJsonClient.ts b/plugins/score-card/src/api/ScoringDataJsonClient.ts index 70d37c2a62..dbc1168663 100644 --- a/plugins/score-card/src/api/ScoringDataJsonClient.ts +++ b/plugins/score-card/src/api/ScoringDataJsonClient.ts @@ -19,6 +19,7 @@ import { SystemScore, SystemScoreExtended } from './types'; import { CatalogApi } from '@backstage/plugin-catalog-react'; import { Entity, + CompoundEntityRef, getCompoundEntityRef, parseEntityRef, RELATION_OWNED_BY, @@ -122,9 +123,15 @@ export class ScoringDataJsonClient implements ScoringDataApi { const owner = catalogEntity?.relations?.find( r => r.type === RELATION_OWNED_BY, )?.targetRef; - const reviewer = score.scoringReviewer - ? { name: score.scoringReviewer, kind: 'User', namespace: 'default' } - : undefined; + + let reviewer = undefined; + if (score.scoringReviewer && !(score.scoringReviewer as CompoundEntityRef)?.name) { + reviewer = { name: score.scoringReviewer as string, kind: 'User', namespace: 'default' }; + } else if ((score.scoringReviewer as CompoundEntityRef)?.name) { + const scoringReviewer = score.scoringReviewer as CompoundEntityRef + reviewer = { name: scoringReviewer.name, kind: scoringReviewer?.kind ?? "User", namespace: scoringReviewer?.namespace ?? 'default' }; + } + const reviewDate = score.scoringReviewDate ? new Date(score.scoringReviewDate) : undefined; diff --git a/plugins/score-card/src/api/types.ts b/plugins/score-card/src/api/types.ts index 32b76a1611..d2d04572ec 100644 --- a/plugins/score-card/src/api/types.ts +++ b/plugins/score-card/src/api/types.ts @@ -19,8 +19,9 @@ export interface SystemScore { systemEntityName: string; generatedDateTimeUtc: Date | string; scorePercent: number; + scoreLabel?: string; scoreSuccess: ScoreSuccessEnum; - scoringReviewer: string | undefined | null; + scoringReviewer: string | CompoundEntityRef | undefined | null; scoringReviewDate: Date | string | undefined | null; areaScores: SystemScoreArea[]; } @@ -29,6 +30,7 @@ export interface SystemScoreArea { id: number; title: string; scorePercent: number; + scoreLabel?: string; scoreSuccess: ScoreSuccessEnum; scoreEntries: SystemScoreEntry[]; } @@ -38,6 +40,7 @@ export interface SystemScoreEntry { title: string; isOptional: boolean; scorePercent: number; + scoreLabel?: string; scoreSuccess: ScoreSuccessEnum; scoreHints: string | string[]; details: string; diff --git a/plugins/score-card/src/components/ScoreCard/ScoreCard.test.tsx b/plugins/score-card/src/components/ScoreCard/ScoreCard.test.tsx index 2b17af7b1b..7b6004de12 100644 --- a/plugins/score-card/src/components/ScoreCard/ScoreCard.test.tsx +++ b/plugins/score-card/src/components/ScoreCard/ScoreCard.test.tsx @@ -92,7 +92,7 @@ describe('ScoreCard-TestWithData', () => { ): Promise { return new Promise( (resolve, _reject) => { - const sampleData = require('../../../sample-data/audio-playback.json'); + const sampleData = require('../../../sample-data/podcast.json'); resolve(sampleData); }, ); @@ -139,4 +139,27 @@ describe('ScoreCard-TestWithData', () => { await findByTestId('score-card'); jest.useRealTimers(); }); + + it('should render the score label when provided', async () => { + const { findByText } = render( + + + + + + + , + ); + + await findByText('Total score: C'); + + const codeScore = await findByText('Code'); + expect(codeScore.querySelector('div')).toHaveTextContent('A'); + }); }); diff --git a/plugins/score-card/src/components/ScoreCard/ScoreCard.tsx b/plugins/score-card/src/components/ScoreCard/ScoreCard.tsx index 4ca065d1aa..ae6ec88204 100644 --- a/plugins/score-card/src/components/ScoreCard/ScoreCard.tsx +++ b/plugins/score-card/src/components/ScoreCard/ScoreCard.tsx @@ -107,7 +107,8 @@ export const ScoreCard = ({ backgroundColor: scoreToColorConverter(data?.scoreSuccess), }; if (data?.scorePercent || data?.scorePercent === 0) { - gateLabel = `Total score: ${data?.scorePercent} %`; + const label = data?.scoreLabel ?? `${data.scorePercent} %`; + gateLabel = `Total score: ${label}`; } const qualityBadge = !loading && ; diff --git a/plugins/score-card/src/components/ScoreCard/columns/areaColumn.tsx b/plugins/score-card/src/components/ScoreCard/columns/areaColumn.tsx index 70fc7456b2..6e09b29606 100644 --- a/plugins/score-card/src/components/ScoreCard/columns/areaColumn.tsx +++ b/plugins/score-card/src/components/ScoreCard/columns/areaColumn.tsx @@ -42,7 +42,7 @@ export function areaColumn( float: 'right', minWidth: '4rem', }; - const areaGateLabel = `${area?.scorePercent} %`; + const areaGateLabel = area?.scoreLabel ?? `${area?.scorePercent} %`; return ( <> diff --git a/plugins/score-card/src/components/ScoreCard/columns/scorePercentColumn.tsx b/plugins/score-card/src/components/ScoreCard/columns/scorePercentColumn.tsx index 82c85c5c89..511d48bdac 100644 --- a/plugins/score-card/src/components/ScoreCard/columns/scorePercentColumn.tsx +++ b/plugins/score-card/src/components/ScoreCard/columns/scorePercentColumn.tsx @@ -32,8 +32,9 @@ export const scorePercentColumn: TableColumn = { backgroundColor: scoreToColorConverter(systemScoreEntry?.scoreSuccess), minWidth: '4rem', }; + const label = systemScoreEntry?.scoreLabel ?? `${systemScoreEntry.scorePercent} %`; return typeof systemScoreEntry.scorePercent !== 'undefined' ? ( - + ) : null; }, }; diff --git a/plugins/score-card/src/components/ScoreCardTable/ScoreCardTable.test.tsx b/plugins/score-card/src/components/ScoreCardTable/ScoreCardTable.test.tsx index aac12d2c96..db49ea185a 100644 --- a/plugins/score-card/src/components/ScoreCardTable/ScoreCardTable.test.tsx +++ b/plugins/score-card/src/components/ScoreCardTable/ScoreCardTable.test.tsx @@ -68,3 +68,67 @@ describe('ScoreBoardPage-EmptyData', () => { jest.useRealTimers(); }); }); + + +describe('ScoreCard-TestWithData', () => { + class MockClient implements ScoringDataApi { + getScore( + _entity?: Entity | undefined, + ): Promise { + throw new Error('Method not implemented.'); + } + getAllScores(): Promise { + return new Promise( + (resolve, _reject) => { + const sampleData = require('../../../sample-data/all.json'); + resolve(sampleData); + }, + ); + } + } + + const mockClient = new MockClient(); + + // TODO: find how to stop render the progress bar and display the ScoreCardTable + // it('should render title', async () => { + // jest.useFakeTimers(); + + // const errorApi = { post: () => {} }; + // const { container } = render( + // + // + // + // + // , + // ); + + // expect(container).toHaveTextContent('Custom title'); + // }); + + it('should render scoreLabel', async () => { + const errorApi = { post: () => {} }; + const { getByText, findByTestId } = render( + + + + + , + ); + + await findByTestId('score-board-table'); + + const podcastColumn = await getByText('podcast'); + const podcastRow = podcastColumn.closest("tr"); + expect(podcastRow).toHaveTextContent('AB+DFFC'); + }); +}); diff --git a/plugins/score-card/src/components/ScoreCardTable/ScoreCardTable.tsx b/plugins/score-card/src/components/ScoreCardTable/ScoreCardTable.tsx index 9146f60816..da3d2f115c 100644 --- a/plugins/score-card/src/components/ScoreCardTable/ScoreCardTable.tsx +++ b/plugins/score-card/src/components/ScoreCardTable/ScoreCardTable.tsx @@ -43,10 +43,11 @@ const useScoringAllDataLoader = () => { }; type ScoreTableProps = { + title?: string; scores: SystemScoreExtended[]; }; -export const ScoreTable = ({ scores }: ScoreTableProps) => { +export const ScoreTable = ({ title, scores }: ScoreTableProps) => { const columns: TableColumn[] = [ { title: 'Name', @@ -129,9 +130,10 @@ export const ScoreTable = ({ scores }: ScoreTableProps) => { ), minWidth: '4rem', }; + const label = currentScoreEntry?.scoreLabel ?? `${currentScoreEntry?.scorePercent} %`; return typeof currentScoreEntry?.scorePercent !== 'undefined' ? ( ) : null; @@ -151,8 +153,9 @@ export const ScoreTable = ({ scores }: ScoreTableProps) => { float: 'right', minWidth: '4rem', }; + const label = systemScoreEntry?.scoreLabel ?? `${systemScoreEntry?.scorePercent} %`; return typeof systemScoreEntry.scorePercent !== 'undefined' ? ( - + ) : null; }, }); @@ -178,7 +181,7 @@ export const ScoreTable = ({ scores }: ScoreTableProps) => { return (

- title="System scores overview" + title={title ?? "System scores overview"} options={{ search: true, paging: true, @@ -193,7 +196,10 @@ export const ScoreTable = ({ scores }: ScoreTableProps) => { ); }; -export const ScoreCardTable = () => { +type ScoreCardTableProps = { + title?: string; +}; +export const ScoreCardTable = ({title}: ScoreCardTableProps) => { const { loading, error, value: data } = useScoringAllDataLoader(); if (loading) { @@ -202,5 +208,5 @@ export const ScoreCardTable = () => { return getWarningPanel(error); } - return ; + return ; };