From 9ccaa8efc2bb059a996fbb013c7f6f5ce5ac0f65 Mon Sep 17 00:00:00 2001 From: Patrick Knight Date: Tue, 21 Apr 2026 20:58:55 -0400 Subject: [PATCH 1/8] fix(scorecard): entity calculation health on aggregation and drill-down APIs Signed-off-by: Patrick Knight --- .../.changeset/rhidp-13128-entity-health.md | 7 + workspaces/scorecard/app-config.yaml | 3 +- .../app-legacy/e2e-tests/pages/CatalogPage.ts | 26 +- .../app-legacy/e2e-tests/pages/HomePage.ts | 32 ++- .../e2e-tests/pages/ScorecardDrillDownPage.ts | 32 ++- .../app-legacy/e2e-tests/scorecard.test.ts | 39 +-- .../e2e-tests/utils/scorecardResponseUtils.ts | 23 ++ .../e2e-tests/utils/translationUtils.ts | 52 ++-- .../scorecard-backend/docs/aggregation.md | 6 +- .../scorecard-backend/docs/drill-down.md | 6 + .../src/database/DatabaseMetricValues.test.ts | 48 ++++ .../src/database/DatabaseMetricValues.ts | 74 ++++-- .../scorecard-backend/src/database/types.ts | 7 + .../src/service/CatalogMetricService.test.ts | 94 +++++++- .../src/service/CatalogMetricService.ts | 77 +++++- .../src/service/mappers.test.ts | 12 + .../scorecard-backend/src/service/mappers.ts | 2 + .../src/service/router.test.ts | 28 ++- .../src/utils/metricCalculationError.ts | 28 +++ .../plugins/scorecard-common/report.api.md | 10 + .../scorecard-common/src/types/Metric.ts | 15 ++ .../scorecard-common/src/types/aggregation.ts | 10 + .../aggregatedScorecardEntitiesData.ts | 5 + .../scorecard/__fixtures__/scorecardData.ts | 2 + .../plugins/scorecard/report-alpha.api.md | 2 +- .../src/api/ScorecardApiClient.test.ts | 2 + .../ScorecardHomepageCard.tsx | 8 +- .../ScorecardHomepageCardComponent.tsx | 226 ++++++++++++++++++ .../__tests__/ScorecardHomepageCard.test.tsx | 12 +- .../ScorecardHomepageSection.test.tsx | 4 + .../EntitiesTable/EntitiesTable.tsx | 7 +- .../EntitiesTable/EntitiesTableWrapper.tsx | 9 +- .../__tests__/EntitiesTable.test.tsx | 39 ++- .../__tests__/EntitiesTableWrapper.test.tsx | 29 ++- .../__tests__/useAggregatedScorecard.test.tsx | 2 + .../plugins/scorecard/src/translations/de.ts | 4 + .../plugins/scorecard/src/translations/es.ts | 4 + .../plugins/scorecard/src/translations/fr.ts | 4 + .../plugins/scorecard/src/translations/it.ts | 4 + .../plugins/scorecard/src/translations/ja.ts | 4 + .../plugins/scorecard/src/translations/ref.ts | 6 +- 41 files changed, 861 insertions(+), 143 deletions(-) create mode 100644 workspaces/scorecard/.changeset/rhidp-13128-entity-health.md create mode 100644 workspaces/scorecard/plugins/scorecard-backend/src/utils/metricCalculationError.ts create mode 100644 workspaces/scorecard/plugins/scorecard/src/components/ScorecardHomepageSection/ScorecardHomepageCardComponent.tsx diff --git a/workspaces/scorecard/.changeset/rhidp-13128-entity-health.md b/workspaces/scorecard/.changeset/rhidp-13128-entity-health.md new file mode 100644 index 00000000000..180f26e102b --- /dev/null +++ b/workspaces/scorecard/.changeset/rhidp-13128-entity-health.md @@ -0,0 +1,7 @@ +--- +'@red-hat-developer-hub/backstage-plugin-scorecard-common': patch +'@red-hat-developer-hub/backstage-plugin-scorecard-backend': patch +'@red-hat-developer-hub/backstage-plugin-scorecard': patch +--- + +Expose scorecard entity calculation health on drill-down and aggregation APIs, and align the drill-down warning plus homepage subheader with those counts. diff --git a/workspaces/scorecard/app-config.yaml b/workspaces/scorecard/app-config.yaml index c1c31480b5c..f3f72a01467 100644 --- a/workspaces/scorecard/app-config.yaml +++ b/workspaces/scorecard/app-config.yaml @@ -162,7 +162,8 @@ auth: # see https://backstage.io/docs/auth/ to learn about auth providers providers: # See https://backstage.io/docs/auth/guest/provider - guest: {} + guest: + userEntityRef: user:development/guest scaffolder: # see https://backstage.io/docs/features/software-templates/configuration for software template options diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/CatalogPage.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/CatalogPage.ts index d4471030217..64eab91d479 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/CatalogPage.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/CatalogPage.ts @@ -39,24 +39,22 @@ export class CatalogPage { async loginAndSetLocale(locale: string) { await this.page.goto('/'); const enterButton = this.page.getByRole('button', { name: 'Enter' }); - await expect(enterButton).toBeVisible(); + await expect(enterButton).toBeVisible({ timeout: 30000 }); await enterButton.click(); - await expect(this.page.getByText('Welcome back!')).toBeVisible(); + // Guest flow copy varies by Backstage / branding; wait for shell instead of "Welcome back!". + await expect( + this.page.getByRole('link', { name: 'Home' }).first(), + ).toBeVisible({ + timeout: 30000, + }); await this.switchToLocale(locale); } - async openCatalog() { - await this.page.goto('/catalog'); // Resolves the issue when "My Groups" sidebar covers the catalog toolbar - await this.page.getByTestId('user-picker-all').getByText('All').click(); - } - - async openComponent(componentName: string) { - const link = this.page.getByRole('link', { name: componentName }); - await this.page - .getByRole('textbox', { name: 'Search' }) - .fill(componentName); - await expect(link).toBeVisible({ timeout: 10000 }); - await link.click(); + /** Opens a Component in `default` by `metadata.name` (avoids catalog index / filter flakiness). */ + async openComponent(name: string) { + await this.page.goto( + `/catalog/default/component/${encodeURIComponent(name)}`, + ); } async switchToLocale(locale: string): Promise { diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/HomePage.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/HomePage.ts index 27c4ec68e65..a5dd1abe2be 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/HomePage.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/HomePage.ts @@ -18,8 +18,8 @@ import { Locator, Page, expect } from '@playwright/test'; import { AGGREGATED_CARDS_WIDGET_TITLES } from '../constants/homepageWidgetTitles'; import { ScorecardMessages, - getEntitiesLabel, getEntityCount, + getHomepageEntityCalculationHealthText, getLastUpdatedLabel, } from '../utils/translationUtils'; @@ -130,22 +130,18 @@ export class HomePage { await expect(this.page.getByText(label)).toBeVisible(); } - async clickDrillDownLink() { - // CardSubheader renders the count as a Link (e.g. "10 entities"). The card - // description can also contain the word "entities" (see API metadata), so - // getByText(entitiesLabel) is ambiguous. MUI Tooltip also sets the link’s - // accessible name to the long tooltip, so getByRole('link', { name }) is - // locale‑fragile. Match only links whose *visible* text is "{{count}}