From 68451681fec346eab3b237f0c95da9cb98a22b76 Mon Sep 17 00:00:00 2001 From: Ihor Mykhno Date: Mon, 25 May 2026 16:39:05 +0200 Subject: [PATCH 1/4] refactor(tests): streamline scorecard test structure and add utility functions Signed-off-by: Ihor Mykhno --- .../app-legacy/e2e-tests/scorecard.test.ts | 220 +++++++----------- .../e2e-tests/utils/homepageWidgetUtils.ts | 40 ++++ 2 files changed, 118 insertions(+), 142 deletions(-) create mode 100644 workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts index eefc4742f4..e96ea83516 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test, expect, Page } from '@playwright/test'; +import { test, expect, Page, Locator, TestInfo } from '@playwright/test'; import { mockJiraAggregationResponse, mockScorecardEntitiesDrillDown, @@ -65,6 +65,10 @@ import { mockAllDefaultHomepageAggregationsSuccess, mockHomepageAggregationsPermissionDenied, } from './utils/mockHomepageAggregations'; +import { + addAggregatedScorecardWidgets, + addWidgets, +} from './utils/homepageWidgetUtils'; import { expectAverageCardCenterPercent, verifyAverageDonutCenterTooltip, @@ -78,28 +82,6 @@ import { } from './constants/homepageWidgetTitles'; import { installWebpackDevOverlayGuards } from './utils/devOverlays'; -async function addWidgets(homePage: HomePage, widgetTitle: string) { - await homePage.navigateToHome(); - await homePage.enterEditMode(); - await homePage.clearAllCards(); - await homePage.addCard(widgetTitle); - await homePage.saveChanges(); -} - -async function addAggregatedScorecardWidgets(homePage: HomePage) { - await homePage.navigateToHome(); - await homePage.enterEditMode(); - await homePage.clearAllCards(); - - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withDeprecatedMetricId); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withDefaultAggregation); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withGithubOpenPrs); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withJiraOpenIssuesKpi); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi); - - await homePage.saveChanges(); -} - test.describe('Scorecard Plugin Tests', () => { let page: Page; let catalogPage: CatalogPage; @@ -129,11 +111,6 @@ test.describe('Scorecard Plugin Tests', () => { await page?.context()?.close(); }); - test.afterEach(async () => { - await page.unroute('**/api/scorecard/metrics/**'); - await page.unroute('**/api/scorecard/aggregations/**'); - }); - test.describe('Entity Scorecards', () => { test('Verify permission required state', async ({ browser }, testInfo) => { await mockApiResponse( @@ -1069,8 +1046,8 @@ test.describe('Scorecard Plugin Tests', () => { }); }); - test.describe('Average aggregation KPI (openPrsWeightedKpi)', () => { - test('Verify title and description from API metadata', async () => { + test.describe('Aggregation homepage widget - "average" type', () => { + test.beforeAll(async () => { await mockApiResponse( page, ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, @@ -1081,50 +1058,83 @@ test.describe('Scorecard Plugin Tests', () => { homePage, AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi, ); + await page.reload(); + }); - const card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, - ); - await expect(card).toBeVisible(); - await expect(card).toContainText( - openPrsWeightedKpiMetadataResponse.title, - ); - await expect(card).toContainText( - openPrsWeightedKpiMetadataResponse.description, - ); + test.afterAll(async () => { + await page.unroute('**/api/scorecard/aggregations/**'); }); - test('Verify center score and average tooltips', async () => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, - openPrsWeightedAggregatedResponse, - ); + test.describe('Validate "average" type card content', () => { + let card: Locator; - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi, - ); - await page.reload(); + test.beforeAll(async () => { + await homePage.navigateToHome(); + card = homePage.getCard( + AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, + ); + }); - const card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, - ); - await expectAverageCardCenterPercent(card, '51.5%'); - await verifyAverageDonutCenterTooltip( - page, - card, - translations, - 515, - 1000, - ); - await verifyAverageCenterTooltipBreakdownRows( - page, - card, - translations, - currentLocale, - ); + test('Verify provided title', async () => { + await expect(card).toBeVisible(); + await expect(card).toContainText( + openPrsWeightedKpiMetadataResponse.title, + ); + }); + + test('Verify provided description', async () => { + await expect(card).toBeVisible(); + await expect(card).toContainText( + openPrsWeightedKpiMetadataResponse.description, + ); + }); + + test('Verify last updated date', async () => { + const lastUpdatedFormatted = formatLastUpdatedDate( + openPrsWeightedAggregatedResponse.result.timestamp, + currentLocale, + ); + await expect(card).toBeVisible(); + await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); + }); + + test('Verify center score percentage', async () => { + await expect(card).toBeVisible(); + await expectAverageCardCenterPercent(card, '51.5%'); + }); + + test('Verify center tooltip', async () => { + await expect(card).toBeVisible(); + await verifyAverageDonutCenterTooltip( + page, + card, + translations, + openPrsWeightedAggregatedResponse.result.averageWeightedSum, + openPrsWeightedAggregatedResponse.result.averageMaxPossible, + ); + await verifyAverageCenterTooltipBreakdownRows( + page, + card, + translations, + currentLocale, + ); + }); + + test('Verify accessibility on weighted average card', async ({ + browser: _browser, + }, testInfo) => { + await expect(card).toBeVisible(); + await runAccessibilityTests(page, testInfo); + }); + + test('Verify open drill-down link', async () => { + await expect(card).toBeVisible(); + await homePage.clickDrillDownLink(); + await scorecardDrillDownPage.expectOnPage('github.open_prs', { + aggregationId: AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, + }); + }); }); test('Verify empty aggregated response shows no data', async () => { @@ -1144,80 +1154,6 @@ test.describe('Scorecard Plugin Tests', () => { AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, ); }); - - test('Accessibility on weighted average card', async ({ - browser: _browser, - }, testInfo) => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, - openPrsWeightedAggregatedResponse, - ); - - await homePage.navigateToHome(); - await homePage.enterEditMode(); - await homePage.clearAllCards(); - await homePage.addCard( - AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi, - ); - await homePage.saveChanges(); - await page.reload(); - - await runAccessibilityTests(page, testInfo); - }); - - test('GitHub weighted KPI: drill-down, average card, and table', async () => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, - openPrsWeightedAggregatedResponse, - ); - await mockScorecardEntitiesDrillDownWithSort( - page, - githubEntitiesDrillDownResponse, - 'github.open_prs', - ); - - await homePage.navigateToHome(); - await page.reload(); - await homePage.enterEditMode(); - await homePage.clearAllCards(); - await homePage.addCard( - AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi, - ); - await homePage.saveChanges(); - - const weightedEntityTotal = String( - openPrsWeightedAggregatedResponse.result.total, - ); - await homePage.clickDrillDownLink({ - healthy: weightedEntityTotal, - total: weightedEntityTotal, - }); - await scorecardDrillDownPage.expectOnPage('github.open_prs', { - aggregationId: AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, - }); - await scorecardDrillDownPage.expectPageTitle( - 'github.open_prs', - openPrsWeightedKpiMetadataResponse.title, - ); - - const drillCard = scorecardDrillDownPage.getDrillDownCard( - 'github.open_prs', - { - aggregationId: AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, - }, - ); - await expectAverageCardCenterPercent(drillCard, '51.5%'); - await scorecardDrillDownPage.expectTableHeadersVisible(); - await scorecardDrillDownPage.expectEntityNamesVisible([ - 'all-scorecards-service', - 'red-hat-developer-hub', - 'github-scorecard-only-service', - 'all-scorecards-service-different-owner', - 'backend-api', - ]); - }); }); test.describe('Unsupported aggregation type', () => { diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts new file mode 100644 index 0000000000..1a09dc5842 --- /dev/null +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts @@ -0,0 +1,40 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { HomePage } from '../pages/HomePage'; +import { AGGREGATED_CARDS_WIDGET_TITLES } from '../constants/homepageWidgetTitles'; + +export async function addWidgets(homePage: HomePage, widgetTitle: string) { + await homePage.navigateToHome(); + await homePage.enterEditMode(); + await homePage.clearAllCards(); + await homePage.addCard(widgetTitle); + await homePage.saveChanges(); +} + +export async function addAggregatedScorecardWidgets(homePage: HomePage) { + await homePage.navigateToHome(); + await homePage.enterEditMode(); + await homePage.clearAllCards(); + + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withDeprecatedMetricId); + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withDefaultAggregation); + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withGithubOpenPrs); + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withJiraOpenIssuesKpi); + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi); + + await homePage.saveChanges(); +} From 5283834100e20f7da9bd5a4cc012a4a649bc78c7 Mon Sep 17 00:00:00 2001 From: Ihor Mykhno Date: Tue, 26 May 2026 18:43:11 +0200 Subject: [PATCH 2/4] refactor(tests): update scorecard tests to use new aggregation constants and improve widget handling Signed-off-by: Ihor Mykhno --- .../e2e-tests/constants/aggregations.ts | 60 ++ .../constants/homepageWidgetTitles.ts | 32 - .../app-legacy/e2e-tests/pages/HomePage.ts | 6 +- .../app-legacy/e2e-tests/scorecard.test.ts | 640 ++++++------------ .../app-legacy/e2e-tests/utils/apiUtils.ts | 65 ++ .../e2e-tests/utils/homepageWidgetUtils.ts | 55 +- .../utils/mockHomepageAggregations.ts | 47 ++ 7 files changed, 440 insertions(+), 465 deletions(-) create mode 100644 workspaces/scorecard/packages/app-legacy/e2e-tests/constants/aggregations.ts delete mode 100644 workspaces/scorecard/packages/app-legacy/e2e-tests/constants/homepageWidgetTitles.ts diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/constants/aggregations.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/constants/aggregations.ts new file mode 100644 index 0000000000..4fa01b08fc --- /dev/null +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/constants/aggregations.ts @@ -0,0 +1,60 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const AGGREGATED_CARDS_METRIC_IDS = { + jiraMetricId: 'jira.open_issues', + githubMetricId: 'github.open_prs', + githubOpenPrsKpi: 'openPrsKpi', + jiraOpenIssuesKpi: 'openIssuesKpi', + openPrsWeightedKpi: 'openPrsWeightedKpi', +} as const; + +/** Must match `title` in App.tsx homepage widget config (Add widget picker). */ +export const AGGREGATED_CARDS_WIDGET_TITLES = { + jiraMetricId: 'Scorecard: With deprecated metricId property (Jira)', + githubMetricId: 'Scorecard: With default aggregation config (GitHub)', + githubOpenPrsKpi: 'Scorecard: GitHub open PRs', + jiraOpenIssuesKpi: 'Scorecard: Jira open blocking tickets', + openPrsWeightedKpi: 'Scorecard: GitHub open PRs (weighted health)', +} as const; + +export const AGGREGATED_CARDS_METADATA = { + deprecatedMetricId: { + id: AGGREGATED_CARDS_METRIC_IDS.jiraMetricId, + title: 'Scorecard: With deprecated metricId property (Jira)', + metricId: 'jira.open_issues', + }, + defaultAggregation: { + id: AGGREGATED_CARDS_METRIC_IDS.githubMetricId, + title: 'Scorecard: With default aggregation config (GitHub)', + metricId: 'github.open_prs', + }, + jiraOpenIssuesKpi: { + id: AGGREGATED_CARDS_METRIC_IDS.jiraOpenIssuesKpi, + title: 'Scorecard: Jira open blocking tickets', + metricId: 'jira.open_issues', + }, + githubOpenPrsKpi: { + id: AGGREGATED_CARDS_METRIC_IDS.githubOpenPrsKpi, + title: 'Scorecard: GitHub open PRs', + metricId: 'github.open_prs', + }, + openPrsWeightedKpi: { + id: AGGREGATED_CARDS_METRIC_IDS.openPrsWeightedKpi, + title: 'Scorecard: GitHub open PRs (weighted health)', + metricId: 'github.open_prs', + }, +} as const; diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/constants/homepageWidgetTitles.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/constants/homepageWidgetTitles.ts deleted file mode 100644 index fd4cf72a53..0000000000 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/constants/homepageWidgetTitles.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export const AGGREGATED_CARDS_METRIC_IDS = { - withDeprecatedMetricId: 'jira.open_issues', - withDefaultAggregation: 'github.open_prs', - withGithubOpenPrs: 'openPrsKpi', - withJiraOpenIssuesKpi: 'openIssuesKpi', - withOpenPrsWeightedKpi: 'openPrsWeightedKpi', -} as const; - -export const AGGREGATED_CARDS_WIDGET_TITLES = { - /** Must match `title` in App.tsx homepage widget config (Add widget picker). */ - withDeprecatedMetricId: 'Scorecard: With deprecated metricId property (Jira)', - withDefaultAggregation: 'Scorecard: With default aggregation config (GitHub)', - withGithubOpenPrs: 'Scorecard: GitHub open PRs', - withJiraOpenIssuesKpi: 'Scorecard: Jira open blocking tickets', - withOpenPrsWeightedKpi: 'Scorecard: GitHub open PRs (weighted health)', -} as const; 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 b8045e001c..591917caa6 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/HomePage.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/pages/HomePage.ts @@ -15,7 +15,7 @@ */ import { Locator, Page, expect } from '@playwright/test'; -import { AGGREGATED_CARDS_WIDGET_TITLES } from '../constants/homepageWidgetTitles'; +import { AGGREGATED_CARDS_WIDGET_TITLES } from '../constants/aggregations'; import { ScorecardMessages, getEntityCount, @@ -63,9 +63,7 @@ export class HomePage { cardPattern = /Scorecard:\s*GitHub open PRs|ScorecardGithubHomepage/i; } else if (cardName === 'Scorecard: Jira open blocking') { cardPattern = /Scorecard:\s*Jira open blocking|ScorecardJiraHomepage/i; - } else if ( - cardName === AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi - ) { + } else if (cardName === AGGREGATED_CARDS_WIDGET_TITLES.openPrsWeightedKpi) { cardPattern = /Scorecard:\s*GitHub open PRs \(weighted health\)|ScorecardOpenPrsWeightedKpi/i; } else { diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts index e96ea83516..d3278bf673 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { test, expect, Page, Locator, TestInfo } from '@playwright/test'; +import { test, expect, Page, Locator } from '@playwright/test'; import { mockJiraAggregationResponse, mockScorecardEntitiesDrillDown, @@ -35,7 +35,6 @@ import { invalidThresholdResponse, githubAggregatedResponse, jiraAggregatedResponse, - emptyGithubAggregatedResponse, emptyJiraAggregatedResponse, openPrsKpiMetadataResponse, openPrsWeightedAggregatedResponse, @@ -61,13 +60,11 @@ import { getTableFooterSnapshot, getEntitiesTableFooterRowsLabel, } from './utils/translationUtils'; -import { - mockAllDefaultHomepageAggregationsSuccess, - mockHomepageAggregationsPermissionDenied, -} from './utils/mockHomepageAggregations'; +import { mockHomepageAggregationsPermissionDenied } from './utils/mockHomepageAggregations'; import { addAggregatedScorecardWidgets, - addWidgets, + setupHomepageAggregationCard, + setupHomepageAllCardsNoData, } from './utils/homepageWidgetUtils'; import { expectAverageCardCenterPercent, @@ -77,9 +74,9 @@ import { import { runAccessibilityTests } from './utils/accessibility'; import { ScorecardRoutes } from './constants/routes'; import { + AGGREGATED_CARDS_METADATA, AGGREGATED_CARDS_METRIC_IDS, - AGGREGATED_CARDS_WIDGET_TITLES, -} from './constants/homepageWidgetTitles'; +} from './constants/aggregations'; import { installWebpackDevOverlayGuards } from './utils/devOverlays'; test.describe('Scorecard Plugin Tests', () => { @@ -439,7 +436,20 @@ test.describe('Scorecard Plugin Tests', () => { } }); + test('Verify empty aggregated response shows no data on all default homepage scorecard widgets', async () => { + await setupHomepageAllCardsNoData(page, homePage); + + for (const instanceId of Object.values(AGGREGATED_CARDS_METRIC_IDS)) { + await homePage.expectCardHasNoDataFound(instanceId); + } + }); + test('Manage scorecards on Home page', async () => { + const aggregationGithubMetadata = + AGGREGATED_CARDS_METADATA.defaultAggregation; + const aggregationJiraMetadata = + AGGREGATED_CARDS_METADATA.jiraOpenIssuesKpi; + await homePage.navigateToHome(); await homePage.enterEditMode(); @@ -447,263 +457,137 @@ test.describe('Scorecard Plugin Tests', () => { await homePage.addCard('Onboarding section'); await homePage.saveChanges(); - await homePage.expectCardNotVisible( - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation, - ); - await homePage.expectCardNotVisible( - AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, - ); + await homePage.expectCardNotVisible(aggregationGithubMetadata.id); + await homePage.expectCardNotVisible(aggregationJiraMetadata.id); await homePage.enterEditMode(); - await homePage.addCard( - AGGREGATED_CARDS_WIDGET_TITLES.withDefaultAggregation, - ); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withGithubOpenPrs); + await homePage.addCard(aggregationGithubMetadata.title); + await homePage.addCard(aggregationJiraMetadata.title); await homePage.saveChanges(); - await homePage.expectCardVisible( - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation, - ); - await homePage.expectCardVisible( - AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, - ); + await homePage.expectCardVisible(aggregationGithubMetadata.id); + await homePage.expectCardVisible(aggregationJiraMetadata.id); }); test.describe('Deprecated homepage card (metricId only)', () => { - test('Verify translated title and description', async () => { - await mockApiResponse( - page, - ScorecardRoutes.JIRA_OPEN_ISSUES_METRIC_AGGREGATION_ROUTE, - jiraAggregatedResponse, - ); + const aggregationMetadata = AGGREGATED_CARDS_METADATA.deprecatedMetricId; - await homePage.navigateToHome(); - await homePage.enterEditMode(); - await homePage.clearAllCards(); - await homePage.addCard( - AGGREGATED_CARDS_WIDGET_TITLES.withDeprecatedMetricId, - ); - await homePage.saveChanges(); + test.beforeAll(async () => { + await setupHomepageAggregationCard(page, homePage, { + aggregationMetadata, + route: ScorecardRoutes.JIRA_OPEN_ISSUES_METRIC_AGGREGATION_ROUTE, + response: jiraAggregatedResponse, + }); + }); - const card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withDeprecatedMetricId, - ); - const metadata = - translations.metric[ - AGGREGATED_CARDS_METRIC_IDS.withDeprecatedMetricId - ]; + test('Verify translated title and description', async () => { + const card = homePage.getCard(aggregationMetadata.id); + const translationMetadata = translations.metric[aggregationMetadata.id]; await expect(card).toBeVisible(); - await expect(card).toContainText(metadata.title); - await expect(card).toContainText(metadata.description); + await expect(card).toContainText(translationMetadata.title); + await expect(card).toContainText(translationMetadata.description); }); - test('Verify entity counts with mocked API response', async ({ - browser, - }, testInfo) => { - await mockAllDefaultHomepageAggregationsSuccess(page); - await addAggregatedScorecardWidgets(homePage); - await page.reload(); - - const card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withDeprecatedMetricId, - ); - const metadata = - translations.metric[ - AGGREGATED_CARDS_METRIC_IDS.withDeprecatedMetricId - ]; + test('Verify entity counts with mocked API response', async ({}, testInfo) => { + const card = homePage.getCard(aggregationMetadata.id); + const translationMetadata = translations.metric[aggregationMetadata.id]; await expect(card).toBeVisible(); await expect(card).toMatchAriaSnapshot( getThresholdsSnapshot(translations, { - drillDownMetricId: - AGGREGATED_CARDS_METRIC_IDS.withDeprecatedMetricId, - cardTitle: metadata.title, - cardDescription: metadata.description, + drillDownMetricId: aggregationMetadata.metricId, + cardTitle: translationMetadata.title, + cardDescription: translationMetadata.description, }), ); await runAccessibilityTests(page, testInfo); }); - test('Verify empty aggregated response shows no data', async () => { - await mockApiResponse( - page, - ScorecardRoutes.JIRA_OPEN_ISSUES_METRIC_AGGREGATION_ROUTE, - emptyJiraAggregatedResponse, - ); - - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withDeprecatedMetricId, - ); - await page.reload(); - - await homePage.expectCardHasNoDataFound( - AGGREGATED_CARDS_METRIC_IDS.withDeprecatedMetricId, - ); - }); - test('Verify threshold and last updated tooltips', async () => { const lastUpdatedFormatted = formatLastUpdatedDate( '2026-01-24T14:10:32.776Z', currentLocale, ); + const card = homePage.getCard(aggregationMetadata.id); - await mockApiResponse( - page, - ScorecardRoutes.JIRA_OPEN_ISSUES_METRIC_AGGREGATION_ROUTE, - jiraAggregatedResponse, - ); - - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withDeprecatedMetricId, - ); - await page.reload(); - - const jiraCard = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withDeprecatedMetricId, - ); - await homePage.verifyThresholdTooltip(jiraCard, 'success', '6', '60%'); - await homePage.verifyThresholdTooltip(jiraCard, 'warning', '3', '30%'); - await homePage.verifyThresholdTooltip(jiraCard, 'error', '1', '10%'); - await homePage.verifyLastUpdatedTooltip(jiraCard, lastUpdatedFormatted); + await homePage.verifyThresholdTooltip(card, 'success', '6', '60%'); + await homePage.verifyThresholdTooltip(card, 'warning', '3', '30%'); + await homePage.verifyThresholdTooltip(card, 'error', '1', '10%'); + await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); }); }); test.describe('Default aggregation (aggregationId equals metric id)', () => { - // Backend: no KPI entry → aggregationId is treated as metric id (aggregation.md). - test('Verify translated title and description', async () => { - await mockApiResponse( - page, - ScorecardRoutes.GITHUB_OPEN_PRS_METRIC_AGGREGATION_ROUTE, - githubAggregatedResponse, - ); + const aggregationMetadata = AGGREGATED_CARDS_METADATA.defaultAggregation; - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withDefaultAggregation, - ); - await page.reload(); + test.beforeAll(async () => { + await setupHomepageAggregationCard(page, homePage, { + aggregationMetadata, + route: ScorecardRoutes.GITHUB_OPEN_PRS_METRIC_AGGREGATION_ROUTE, + response: githubAggregatedResponse, + }); + }); - const card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation, - ); - const metadata = - translations.metric[ - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation - ]; + // Backend: no KPI entry → aggregationId is treated as metric id (aggregation.md). + test('Verify translated title and description', async () => { + const card = homePage.getCard(aggregationMetadata.id); + const translationMetadata = translations.metric[aggregationMetadata.id]; await expect(card).toBeVisible(); - await expect(card).toContainText(metadata.title); - await expect(card).toContainText(metadata.description); + await expect(card).toContainText(translationMetadata.title); + await expect(card).toContainText(translationMetadata.description); }); - test('Verify entity counts with mocked API response', async ({ - browser, - }, testInfo) => { - await mockAllDefaultHomepageAggregationsSuccess(page); - await addAggregatedScorecardWidgets(homePage); - await page.reload(); - - const metadata = - translations.metric[ - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation - ]; - const card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation, - ); + test('Verify entity counts with mocked API response', async ({}, testInfo) => { + const translationMetadata = translations.metric[aggregationMetadata.id]; + const card = homePage.getCard(aggregationMetadata.id); await expect(card).toBeVisible(); await expect(card).toMatchAriaSnapshot( getThresholdsSnapshot(translations, { - drillDownMetricId: - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation, - cardTitle: metadata.title, - cardDescription: metadata.description, + drillDownMetricId: aggregationMetadata.metricId, + cardTitle: translationMetadata.title, + cardDescription: translationMetadata.description, }), ); await runAccessibilityTests(page, testInfo); }); - test('Verify empty aggregated response shows no data', async () => { - await mockApiResponse( - page, - ScorecardRoutes.GITHUB_OPEN_PRS_METRIC_AGGREGATION_ROUTE, - emptyGithubAggregatedResponse, - ); - - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withDefaultAggregation, - ); - await page.reload(); - - await homePage.expectCardHasNoDataFound( - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation, - ); - }); - test('Verify threshold and last updated tooltips', async () => { const lastUpdatedFormatted = formatLastUpdatedDate( '2026-01-24T14:10:32.858Z', currentLocale, ); - await mockApiResponse( - page, - ScorecardRoutes.GITHUB_OPEN_PRS_METRIC_AGGREGATION_ROUTE, - githubAggregatedResponse, - ); + const card = homePage.getCard(aggregationMetadata.id); - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withDefaultAggregation, - ); - await page.reload(); - - const githubCard = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation, - ); - await homePage.verifyThresholdTooltip( - githubCard, - 'success', - '3', - '30%', - ); - await homePage.verifyThresholdTooltip( - githubCard, - 'warning', - '5', - '50%', - ); - await homePage.verifyThresholdTooltip(githubCard, 'error', '2', '20%'); - await homePage.verifyLastUpdatedTooltip( - githubCard, - lastUpdatedFormatted, - ); + await homePage.verifyThresholdTooltip(card, 'success', '3', '30%'); + await homePage.verifyThresholdTooltip(card, 'warning', '5', '50%'); + await homePage.verifyThresholdTooltip(card, 'error', '2', '20%'); + await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); }); }); - test.describe('Configured aggregation KPI (metadata labels, no metric id translation keys)', () => { - test('Verify provided title and description from API metadata', async () => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_KPI_AGGREGATION_ROUTE, - githubAggregatedResponse, - ); + test.describe('Configured aggregation KPI - "statusGrouped" type', () => { + const aggregationMetadata = AGGREGATED_CARDS_METADATA.githubOpenPrsKpi; - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withGithubOpenPrs, - ); - await page.reload(); + test.beforeAll(async () => { + await setupHomepageAggregationCard(page, homePage, { + aggregationMetadata, + route: ScorecardRoutes.OPEN_PRS_KPI_AGGREGATION_ROUTE, + response: githubAggregatedResponse, + }); + }); - const card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, - ); + test.afterAll(async () => { + await page.unroute('**/api/scorecard/aggregations/**'); + }); + + test('Verify title and description', async () => { + const card = homePage.getCard(aggregationMetadata.id); await expect(card).toBeVisible(); await expect(card).toContainText(openPrsKpiMetadataResponse.title); @@ -713,27 +597,14 @@ test.describe('Scorecard Plugin Tests', () => { ); }); - test('Verify entity counts with mocked API response', async ({ - browser, - }, testInfo) => { - await mockAllDefaultHomepageAggregationsSuccess(page); - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withGithubOpenPrs, - ); - await page.reload(); - - const card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, - ); + test('Verify entity counts with mocked API response', async ({}, testInfo) => { + const card = homePage.getCard(aggregationMetadata.id); await expect(card).toBeVisible(); await expect(card).toMatchAriaSnapshot( getThresholdsSnapshot(translations, { - drillDownMetricId: - AGGREGATED_CARDS_METRIC_IDS.withDefaultAggregation, - drillDownAggregationId: - AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, + drillDownMetricId: aggregationMetadata.metricId, + drillDownAggregationId: aggregationMetadata.id, cardTitle: githubAggregatedResponse.metadata.title, cardDescription: githubAggregatedResponse.metadata.description, }), @@ -742,81 +613,126 @@ test.describe('Scorecard Plugin Tests', () => { await runAccessibilityTests(page, testInfo); }); - test('Verify empty aggregated response shows no data', async () => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_KPI_AGGREGATION_ROUTE, - emptyGithubAggregatedResponse, + test('Verify threshold and last updated tooltips', async () => { + const lastUpdatedFormatted = formatLastUpdatedDate( + '2026-01-24T14:10:32.858Z', + currentLocale, ); - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withGithubOpenPrs, - ); - await page.reload(); + const card = homePage.getCard(aggregationMetadata.id); + await homePage.verifyThresholdTooltip(card, 'success', '3', '30%'); + await homePage.verifyThresholdTooltip(card, 'warning', '5', '50%'); + await homePage.verifyThresholdTooltip(card, 'error', '2', '20%'); + await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); + }); + }); - await homePage.expectCardHasNoDataFound( - AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, - ); + test.describe('Configured aggregation KPI - "average" type', () => { + const aggregationMetadata = AGGREGATED_CARDS_METADATA.openPrsWeightedKpi; + + test.beforeAll(async () => { + await setupHomepageAggregationCard(page, homePage, { + aggregationMetadata, + route: ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, + response: openPrsWeightedAggregatedResponse, + }); }); - test('Verify threshold and last updated tooltips', async () => { - const githubLastUpdated = formatLastUpdatedDate( - '2026-01-24T14:10:32.858Z', - currentLocale, - ); + test.afterAll(async () => { + await page.unroute('**/api/scorecard/aggregations/**'); + }); - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_KPI_AGGREGATION_ROUTE, - githubAggregatedResponse, - ); + test.describe('Validate "average" type card content', () => { + let card: Locator; - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withGithubOpenPrs, - ); - await page.reload(); + test.beforeAll(async () => { + await homePage.navigateToHome(); + card = homePage.getCard(aggregationMetadata.id); + }); - const githubCard = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, - ); - await homePage.verifyThresholdTooltip( - githubCard, - 'success', - '3', - '30%', - ); - await homePage.verifyThresholdTooltip( - githubCard, - 'warning', - '5', - '50%', - ); - await homePage.verifyThresholdTooltip(githubCard, 'error', '2', '20%'); - await homePage.verifyLastUpdatedTooltip(githubCard, githubLastUpdated); + test('Verify title and description', async () => { + await expect(card).toBeVisible(); + await expect(card).toContainText( + openPrsWeightedKpiMetadataResponse.title, + ); + await expect(card).toContainText( + openPrsWeightedKpiMetadataResponse.description, + ); + }); + + test('Verify last updated date', async () => { + const lastUpdatedFormatted = formatLastUpdatedDate( + openPrsWeightedAggregatedResponse.result.timestamp, + currentLocale, + ); + await expect(card).toBeVisible(); + await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); + }); + + test('Verify center score percentage', async () => { + await expect(card).toBeVisible(); + await expectAverageCardCenterPercent(card, '51.5%'); + }); + + test('Verify center tooltip', async () => { + await expect(card).toBeVisible(); + await verifyAverageDonutCenterTooltip( + page, + card, + translations, + openPrsWeightedAggregatedResponse.result.averageWeightedSum, + openPrsWeightedAggregatedResponse.result.averageMaxPossible, + ); + await verifyAverageCenterTooltipBreakdownRows( + page, + card, + translations, + currentLocale, + ); + }); + + test('Verify accessibility on weighted average card', async ({ + browser: _browser, + }, testInfo) => { + await expect(card).toBeVisible(); + await runAccessibilityTests(page, testInfo); + }); + + test('Verify open drill-down link', async () => { + await expect(card).toBeVisible(); + await homePage.clickDrillDownLink(); + await scorecardDrillDownPage.expectOnPage('github.open_prs', { + aggregationId: aggregationMetadata.id, + }); + }); }); + test('Verify empty aggregated response shows no data', async () => { + await setupHomepageAggregationCard(page, homePage, { + aggregationMetadata, + route: ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, + response: emptyOpenPrsWeightedAggregatedResponse, + }); + + await homePage.expectCardHasNoDataFound(aggregationMetadata.id); + }); + }); + + test.describe('Drill down logic', () => { test('GitHub scorecard: tooltips, entity drill-down, and metric sort', async () => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_KPI_AGGREGATION_ROUTE, - githubAggregatedResponse, - ); + const aggregationMetadata = AGGREGATED_CARDS_METADATA.githubOpenPrsKpi; + await mockScorecardEntitiesDrillDownWithSort( page, githubEntitiesDrillDownResponse, 'github.open_prs', ); - await homePage.navigateToHome(); - await page.reload(); - await homePage.enterEditMode(); - await homePage.clearAllCards(); - await homePage.addCard( - AGGREGATED_CARDS_WIDGET_TITLES.withGithubOpenPrs, - ); - await homePage.saveChanges(); + await setupHomepageAggregationCard(page, homePage, { + aggregationMetadata, + route: ScorecardRoutes.OPEN_PRS_KPI_AGGREGATION_ROUTE, + response: githubAggregatedResponse, + }); const lastUpdatedFormatted = formatLastUpdatedDate( '2026-01-24T14:10:32.858Z', @@ -824,9 +740,7 @@ test.describe('Scorecard Plugin Tests', () => { ); await test.step('Verify threshold and last updated tooltips', async () => { - const githubCard = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, - ); + const githubCard = homePage.getCard(aggregationMetadata.id); await homePage.verifyThresholdTooltip( githubCard, 'success', @@ -854,7 +768,7 @@ test.describe('Scorecard Plugin Tests', () => { await test.step('Entity drill-down', async () => { await homePage.clickDrillDownLink(); await scorecardDrillDownPage.expectOnPage('github.open_prs', { - aggregationId: AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, + aggregationId: aggregationMetadata.id, }); await scorecardDrillDownPage.expectPageTitle( 'github.open_prs', @@ -863,7 +777,7 @@ test.describe('Scorecard Plugin Tests', () => { await scorecardDrillDownPage.expectDrillDownCardSnapshot( 'github.open_prs', { - aggregationId: AGGREGATED_CARDS_METRIC_IDS.withGithubOpenPrs, + aggregationId: aggregationMetadata.id, cardTitle: githubAggregatedResponse.metadata.title, cardDescription: githubAggregatedResponse.metadata.description, }, @@ -922,23 +836,19 @@ test.describe('Scorecard Plugin Tests', () => { }); test('Jira scorecard: tooltips, entity drill-down, and metric sort', async () => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_ISSUES_KPI_AGGREGATION_ROUTE, - jiraAggregatedResponse, - ); + const aggregationMetadata = AGGREGATED_CARDS_METADATA.jiraOpenIssuesKpi; + await mockScorecardEntitiesDrillDownWithSort( page, jiraEntitiesDrillDownResponse, 'jira.open_issues', ); - await homePage.navigateToHome(); - await page.reload(); - await homePage.enterEditMode(); - await homePage.clearAllCards(); - await homePage.addCard('Scorecard: Jira open blocking'); - await homePage.saveChanges(); + await setupHomepageAggregationCard(page, homePage, { + aggregationMetadata, + route: ScorecardRoutes.OPEN_ISSUES_KPI_AGGREGATION_ROUTE, + response: jiraAggregatedResponse, + }); const lastUpdatedFormatted = formatLastUpdatedDate( '2026-01-24T14:10:32.776Z', @@ -946,9 +856,7 @@ test.describe('Scorecard Plugin Tests', () => { ); await test.step('Verify threshold and last updated tooltips', async () => { - const jiraCard = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withJiraOpenIssuesKpi, - ); + const jiraCard = homePage.getCard(aggregationMetadata.id); await homePage.verifyThresholdTooltip( jiraCard, 'success', @@ -971,7 +879,7 @@ test.describe('Scorecard Plugin Tests', () => { await test.step('Entity drill-down', async () => { await homePage.clickDrillDownLink(); await scorecardDrillDownPage.expectOnPage('jira.open_issues', { - aggregationId: AGGREGATED_CARDS_METRIC_IDS.withJiraOpenIssuesKpi, + aggregationId: aggregationMetadata.id, }); await scorecardDrillDownPage.expectPageTitle( 'jira.open_issues', @@ -980,7 +888,7 @@ test.describe('Scorecard Plugin Tests', () => { await scorecardDrillDownPage.expectDrillDownCardSnapshot( 'jira.open_issues', { - aggregationId: AGGREGATED_CARDS_METRIC_IDS.withJiraOpenIssuesKpi, + aggregationId: aggregationMetadata.id, cardTitle: jiraAggregatedResponse.metadata.title, cardDescription: jiraAggregatedResponse.metadata.description, }, @@ -1046,133 +954,19 @@ test.describe('Scorecard Plugin Tests', () => { }); }); - test.describe('Aggregation homepage widget - "average" type', () => { - test.beforeAll(async () => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, - openPrsWeightedAggregatedResponse, - ); - - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi, - ); - - await page.reload(); - }); - - test.afterAll(async () => { - await page.unroute('**/api/scorecard/aggregations/**'); - }); - - test.describe('Validate "average" type card content', () => { - let card: Locator; - - test.beforeAll(async () => { - await homePage.navigateToHome(); - card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, - ); - }); - - test('Verify provided title', async () => { - await expect(card).toBeVisible(); - await expect(card).toContainText( - openPrsWeightedKpiMetadataResponse.title, - ); - }); - - test('Verify provided description', async () => { - await expect(card).toBeVisible(); - await expect(card).toContainText( - openPrsWeightedKpiMetadataResponse.description, - ); - }); - - test('Verify last updated date', async () => { - const lastUpdatedFormatted = formatLastUpdatedDate( - openPrsWeightedAggregatedResponse.result.timestamp, - currentLocale, - ); - await expect(card).toBeVisible(); - await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); - }); - - test('Verify center score percentage', async () => { - await expect(card).toBeVisible(); - await expectAverageCardCenterPercent(card, '51.5%'); - }); - - test('Verify center tooltip', async () => { - await expect(card).toBeVisible(); - await verifyAverageDonutCenterTooltip( - page, - card, - translations, - openPrsWeightedAggregatedResponse.result.averageWeightedSum, - openPrsWeightedAggregatedResponse.result.averageMaxPossible, - ); - await verifyAverageCenterTooltipBreakdownRows( - page, - card, - translations, - currentLocale, - ); - }); - - test('Verify accessibility on weighted average card', async ({ - browser: _browser, - }, testInfo) => { - await expect(card).toBeVisible(); - await runAccessibilityTests(page, testInfo); - }); + test.describe('Unsupported aggregation type', () => { + const aggregationMetadata = AGGREGATED_CARDS_METADATA.openPrsWeightedKpi; - test('Verify open drill-down link', async () => { - await expect(card).toBeVisible(); - await homePage.clickDrillDownLink(); - await scorecardDrillDownPage.expectOnPage('github.open_prs', { - aggregationId: AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, - }); + test.beforeAll(async () => { + await setupHomepageAggregationCard(page, homePage, { + aggregationMetadata, + route: ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, + response: openPrsWeightedUnsupportedAggregationResponse, }); }); - test('Verify empty aggregated response shows no data', async () => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, - emptyOpenPrsWeightedAggregatedResponse, - ); - - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi, - ); - await page.reload(); - - await homePage.expectCardHasNoDataFound( - AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, - ); - }); - }); - - test.describe('Unsupported aggregation type', () => { test('Shows unsupported message when aggregationType is unknown', async () => { - await mockApiResponse( - page, - ScorecardRoutes.OPEN_PRS_WEIGHTED_KPI_AGGREGATION_ROUTE, - openPrsWeightedUnsupportedAggregationResponse, - ); - - await addWidgets( - homePage, - AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi, - ); - await page.reload(); - - const card = homePage.getCard( - AGGREGATED_CARDS_METRIC_IDS.withOpenPrsWeightedKpi, - ); + const card = homePage.getCard(aggregationMetadata.id); await expect(card).toContainText( translations.errors.unsupportedAggregationType, ); diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/apiUtils.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/apiUtils.ts index 17335d133d..a199337479 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/apiUtils.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/apiUtils.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import type { Response } from '@playwright/test'; import { Page, expect } from '@playwright/test'; import { ScorecardRoutes } from '../constants/routes'; @@ -21,6 +22,15 @@ const GITHUB_AGGREGATION_ROUTE = const JIRA_AGGREGATION_ROUTE = ScorecardRoutes.JIRA_OPEN_ISSUES_METRIC_AGGREGATION_ROUTE; +export type WaitForAggregationResponseOptions = { + status?: number; + timeout?: number; + expectedResult?: { + averageScore?: number; + total?: number; + }; +}; + export async function waitUntilApiCallSucceeds( page: Page, urlPart: string = '/api/scorecard/metrics/catalog/Component/default/red-hat-developer-hub', @@ -37,6 +47,61 @@ export async function waitUntilApiCallSucceeds( expect(response.status()).toBe(200); } +function isAggregationDataUrl(url: string, aggregationId: string): boolean { + return ( + url.includes(`/api/scorecard/aggregations/${aggregationId}`) && + !url.includes('/metadata') + ); +} + +/** + * Waits for GET /api/scorecard/aggregations/{aggregationId} (not /metadata). + * Start the returned promise before the action that triggers the fetch (e.g. page.reload). + */ +export function waitForAggregationResponse( + page: Page, + aggregationId: string, + options?: WaitForAggregationResponseOptions, +): Promise { + const status = options?.status ?? 200; + const timeout = options?.timeout ?? 60_000; + + return page.waitForResponse( + async res => { + const isStatusValid = res.status() === status; + + if (!isAggregationDataUrl(res.url(), aggregationId) || !isStatusValid) { + return false; + } + + const expected = options?.expectedResult; + if (!expected) { + return true; + } + + try { + const json = await res.json(); + const result = json?.result; + + const isAverageScoreValid = + expected.averageScore !== undefined && + result?.averageScore !== expected.averageScore; + const isTotalValid = + expected.total !== undefined && result?.total !== expected.total; + + if (!isAverageScoreValid || !isTotalValid) { + return false; + } + + return true; + } catch { + return false; + } + }, + { timeout }, + ); +} + export async function mockApiResponse( page: Page, route: string, diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts index 1a09dc5842..2a84658e73 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts @@ -14,8 +14,21 @@ * limitations under the License. */ +import type { Page } from '@playwright/test'; import type { HomePage } from '../pages/HomePage'; -import { AGGREGATED_CARDS_WIDGET_TITLES } from '../constants/homepageWidgetTitles'; +import { + AGGREGATED_CARDS_WIDGET_TITLES, + AGGREGATED_CARDS_METRIC_IDS, +} from '../constants/aggregations'; +import { mockApiResponse, waitForAggregationResponse } from './apiUtils'; +import { mockAggregationNoDataFound } from './mockHomepageAggregations'; + +type SetupHomepageAggregationCardOptions = { + aggregationMetadata: { id: string; title: string }; + route: string; + response: object; + status?: number; +}; export async function addWidgets(homePage: HomePage, widgetTitle: string) { await homePage.navigateToHome(); @@ -30,11 +43,41 @@ export async function addAggregatedScorecardWidgets(homePage: HomePage) { await homePage.enterEditMode(); await homePage.clearAllCards(); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withDeprecatedMetricId); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withDefaultAggregation); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withGithubOpenPrs); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withJiraOpenIssuesKpi); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.withOpenPrsWeightedKpi); + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.jiraMetricId); + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.githubMetricId); + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.githubOpenPrsKpi); + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.jiraOpenIssuesKpi); + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.openPrsWeightedKpi); await homePage.saveChanges(); } + +export async function setupHomepageAggregationCard( + page: Page, + homePage: HomePage, + options: SetupHomepageAggregationCardOptions, +): Promise { + const { aggregationMetadata, route, response, status } = options; + + await mockApiResponse(page, route, response, status ?? 200); + + await addWidgets(homePage, aggregationMetadata.title); + + // Reload clears the singleton React Query cache + await page.reload(); +} + +export async function setupHomepageAllCardsNoData( + page: Page, + homePage: HomePage, +): Promise { + await mockAggregationNoDataFound(page); + + const responseWaits = Object.values(AGGREGATED_CARDS_METRIC_IDS).map(id => + waitForAggregationResponse(page, id), + ); + + await addAggregatedScorecardWidgets(homePage); + await page.reload(); + await Promise.all(responseWaits); +} diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/mockHomepageAggregations.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/mockHomepageAggregations.ts index 4c041411ca..de2599a5ef 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/mockHomepageAggregations.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/mockHomepageAggregations.ts @@ -18,6 +18,9 @@ import type { Page } from '@playwright/test'; import { mockApiResponse } from './apiUtils'; import { ScorecardRoutes } from '../constants/routes'; import { + emptyGithubAggregatedResponse, + emptyJiraAggregatedResponse, + emptyOpenPrsWeightedAggregatedResponse, githubAggregatedResponse, jiraAggregatedResponse, notAllowedAggregationErrorBody, @@ -71,6 +74,50 @@ export async function mockHomepageAggregationsPermissionDenied( }); } +export async function mockAggregationNoDataFound(page: Page): Promise { + await page.route('**/api/scorecard/aggregations/**', async route => { + const url = route.request().url(); + const id = url.split('/').pop(); + + if (id === 'openPrsWeightedKpi') { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify(emptyOpenPrsWeightedAggregatedResponse), + }); + return; + } + + const githubAggregations = ['openPrsKpi', 'github.open_prs']; + if (id && githubAggregations.includes(id)) { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify(emptyGithubAggregatedResponse), + }); + + return; + } + + const jiraAggregations = ['openIssuesKpi', 'jira.open_issues']; + if (id && jiraAggregations.includes(id)) { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify(emptyJiraAggregatedResponse), + }); + + return; + } + + await route.fulfill({ + status: 404, + contentType: 'application/json', + body: JSON.stringify(notAllowedAggregationErrorBody), + }); + }); +} + /** * Mocks all default homepage scorecard aggregation KPI endpoints used by * `addAggregatedScorecardWidgets` so the grid can load without hitting the real backend. From 1d79f52a2136dbe5056bad6b5f642fc1410f01f8 Mon Sep 17 00:00:00 2001 From: Ihor Mykhno Date: Wed, 27 May 2026 11:13:16 +0200 Subject: [PATCH 3/4] fix(scorecard): issues found in test utils Signed-off-by: Ihor Mykhno --- .../app-legacy/e2e-tests/utils/apiUtils.ts | 16 ++++++---------- .../e2e-tests/utils/homepageWidgetUtils.ts | 6 +++--- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/apiUtils.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/apiUtils.ts index a199337479..94915d7f11 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/apiUtils.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/apiUtils.ts @@ -83,17 +83,13 @@ export function waitForAggregationResponse( const json = await res.json(); const result = json?.result; - const isAverageScoreValid = - expected.averageScore !== undefined && - result?.averageScore !== expected.averageScore; - const isTotalValid = - expected.total !== undefined && result?.total !== expected.total; + const isAverageOk = + expected.averageScore === undefined || + result?.averageScore === expected.averageScore; + const isTotalOk = + expected.total === undefined || result?.total === expected.total; - if (!isAverageScoreValid || !isTotalValid) { - return false; - } - - return true; + return isAverageOk && isTotalOk; } catch { return false; } diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts index 2a84658e73..9cce20593e 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts @@ -73,11 +73,11 @@ export async function setupHomepageAllCardsNoData( ): Promise { await mockAggregationNoDataFound(page); + await addAggregatedScorecardWidgets(homePage); + const responseWaits = Object.values(AGGREGATED_CARDS_METRIC_IDS).map(id => waitForAggregationResponse(page, id), ); - await addAggregatedScorecardWidgets(homePage); - await page.reload(); - await Promise.all(responseWaits); + await Promise.all([page.reload(), ...responseWaits]); } From 1cdddb3b39fa34591879749c336302526ebe9a4c Mon Sep 17 00:00:00 2001 From: Ihor Mykhno Date: Thu, 4 Jun 2026 16:00:47 +0200 Subject: [PATCH 4/4] refactor(scorecard): enhance scorecard test structure and improve widget handling Signed-off-by: Ihor Mykhno --- .../app-legacy/e2e-tests/scorecard.test.ts | 140 ++++++++++++------ .../e2e-tests/utils/homepageWidgetUtils.ts | 12 +- .../utils/mockHomepageAggregations.ts | 35 ++++- 3 files changed, 126 insertions(+), 61 deletions(-) diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts index d3278bf673..e1da9907b7 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/scorecard.test.ts @@ -60,7 +60,10 @@ import { getTableFooterSnapshot, getEntitiesTableFooterRowsLabel, } from './utils/translationUtils'; -import { mockHomepageAggregationsPermissionDenied } from './utils/mockHomepageAggregations'; +import { + mockAllDefaultHomepageAggregationsSuccess, + mockHomepageAggregationsPermissionDenied, +} from './utils/mockHomepageAggregations'; import { addAggregatedScorecardWidgets, setupHomepageAggregationCard, @@ -445,31 +448,28 @@ test.describe('Scorecard Plugin Tests', () => { }); test('Manage scorecards on Home page', async () => { - const aggregationGithubMetadata = - AGGREGATED_CARDS_METADATA.defaultAggregation; - const aggregationJiraMetadata = - AGGREGATED_CARDS_METADATA.jiraOpenIssuesKpi; + await mockAllDefaultHomepageAggregationsSuccess(page); + await page.reload(); await homePage.navigateToHome(); - await homePage.enterEditMode(); await homePage.clearAllCards(); await homePage.addCard('Onboarding section'); await homePage.saveChanges(); - await homePage.expectCardNotVisible(aggregationGithubMetadata.id); - await homePage.expectCardNotVisible(aggregationJiraMetadata.id); + for (const instanceId of Object.values(AGGREGATED_CARDS_METRIC_IDS)) { + await homePage.expectCardNotVisible(instanceId); + } - await homePage.enterEditMode(); - await homePage.addCard(aggregationGithubMetadata.title); - await homePage.addCard(aggregationJiraMetadata.title); - await homePage.saveChanges(); + await addAggregatedScorecardWidgets(homePage); - await homePage.expectCardVisible(aggregationGithubMetadata.id); - await homePage.expectCardVisible(aggregationJiraMetadata.id); + for (const instanceId of Object.values(AGGREGATED_CARDS_METRIC_IDS)) { + await homePage.expectCardVisible(instanceId); + } }); test.describe('Deprecated homepage card (metricId only)', () => { + let card: Locator; const aggregationMetadata = AGGREGATED_CARDS_METADATA.deprecatedMetricId; test.beforeAll(async () => { @@ -478,10 +478,10 @@ test.describe('Scorecard Plugin Tests', () => { route: ScorecardRoutes.JIRA_OPEN_ISSUES_METRIC_AGGREGATION_ROUTE, response: jiraAggregatedResponse, }); + card = homePage.getCard(aggregationMetadata.id); }); test('Verify translated title and description', async () => { - const card = homePage.getCard(aggregationMetadata.id); const translationMetadata = translations.metric[aggregationMetadata.id]; await expect(card).toBeVisible(); @@ -490,7 +490,6 @@ test.describe('Scorecard Plugin Tests', () => { }); test('Verify entity counts with mocked API response', async ({}, testInfo) => { - const card = homePage.getCard(aggregationMetadata.id); const translationMetadata = translations.metric[aggregationMetadata.id]; await expect(card).toBeVisible(); @@ -505,21 +504,43 @@ test.describe('Scorecard Plugin Tests', () => { await runAccessibilityTests(page, testInfo); }); - test('Verify threshold and last updated tooltips', async () => { + test('Verify last updated date', async () => { const lastUpdatedFormatted = formatLastUpdatedDate( - '2026-01-24T14:10:32.776Z', + jiraAggregatedResponse.result.timestamp, currentLocale, ); - const card = homePage.getCard(aggregationMetadata.id); + await expect(card).toBeVisible(); + await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); + }); + + test('Verify threshold', async () => { await homePage.verifyThresholdTooltip(card, 'success', '6', '60%'); await homePage.verifyThresholdTooltip(card, 'warning', '3', '30%'); await homePage.verifyThresholdTooltip(card, 'error', '1', '10%'); - await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); + }); + + test('Verify status grouped drill-down link', async () => { + await expect(card).toBeVisible(); + await homePage.clickDrillDownLink(); + + await scorecardDrillDownPage.expectOnPage('jira.open_issues', { + aggregationId: aggregationMetadata.id, + }); + + const githubOpenPrsTitle = evaluateMessage( + translations.metric['jira.open_issues'].title, + 'jira.open_issues', + ); + await scorecardDrillDownPage.expectPageTitle( + 'jira.open_issues', + githubOpenPrsTitle, + ); }); }); test.describe('Default aggregation (aggregationId equals metric id)', () => { + let card: Locator; const aggregationMetadata = AGGREGATED_CARDS_METADATA.defaultAggregation; test.beforeAll(async () => { @@ -528,11 +549,11 @@ test.describe('Scorecard Plugin Tests', () => { route: ScorecardRoutes.GITHUB_OPEN_PRS_METRIC_AGGREGATION_ROUTE, response: githubAggregatedResponse, }); + card = homePage.getCard(aggregationMetadata.id); }); // Backend: no KPI entry → aggregationId is treated as metric id (aggregation.md). test('Verify translated title and description', async () => { - const card = homePage.getCard(aggregationMetadata.id); const translationMetadata = translations.metric[aggregationMetadata.id]; await expect(card).toBeVisible(); @@ -542,7 +563,6 @@ test.describe('Scorecard Plugin Tests', () => { test('Verify entity counts with mocked API response', async ({}, testInfo) => { const translationMetadata = translations.metric[aggregationMetadata.id]; - const card = homePage.getCard(aggregationMetadata.id); await expect(card).toBeVisible(); await expect(card).toMatchAriaSnapshot( @@ -556,22 +576,43 @@ test.describe('Scorecard Plugin Tests', () => { await runAccessibilityTests(page, testInfo); }); - test('Verify threshold and last updated tooltips', async () => { + test('Verify last updated date', async () => { const lastUpdatedFormatted = formatLastUpdatedDate( - '2026-01-24T14:10:32.858Z', + githubAggregatedResponse.result.timestamp, currentLocale, ); - const card = homePage.getCard(aggregationMetadata.id); + await expect(card).toBeVisible(); + await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); + }); + test('Verify threshold', async () => { await homePage.verifyThresholdTooltip(card, 'success', '3', '30%'); await homePage.verifyThresholdTooltip(card, 'warning', '5', '50%'); await homePage.verifyThresholdTooltip(card, 'error', '2', '20%'); - await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); + }); + + test('Verify open drill-down link', async () => { + await expect(card).toBeVisible(); + await homePage.clickDrillDownLink(); + + await scorecardDrillDownPage.expectOnPage('github.open_prs', { + aggregationId: aggregationMetadata.id, + }); + + const githubOpenPrsTitle = evaluateMessage( + translations.metric['github.open_prs'].title, + 'github.open_prs', + ); + await scorecardDrillDownPage.expectPageTitle( + 'github.open_prs', + githubOpenPrsTitle, + ); }); }); test.describe('Configured aggregation KPI - "statusGrouped" type', () => { + let card: Locator; const aggregationMetadata = AGGREGATED_CARDS_METADATA.githubOpenPrsKpi; test.beforeAll(async () => { @@ -580,15 +621,11 @@ test.describe('Scorecard Plugin Tests', () => { route: ScorecardRoutes.OPEN_PRS_KPI_AGGREGATION_ROUTE, response: githubAggregatedResponse, }); - }); - test.afterAll(async () => { - await page.unroute('**/api/scorecard/aggregations/**'); + card = homePage.getCard(aggregationMetadata.id); }); test('Verify title and description', async () => { - const card = homePage.getCard(aggregationMetadata.id); - await expect(card).toBeVisible(); await expect(card).toContainText(openPrsKpiMetadataResponse.title); await expect(card).toContainText( @@ -598,8 +635,6 @@ test.describe('Scorecard Plugin Tests', () => { }); test('Verify entity counts with mocked API response', async ({}, testInfo) => { - const card = homePage.getCard(aggregationMetadata.id); - await expect(card).toBeVisible(); await expect(card).toMatchAriaSnapshot( getThresholdsSnapshot(translations, { @@ -613,17 +648,32 @@ test.describe('Scorecard Plugin Tests', () => { await runAccessibilityTests(page, testInfo); }); - test('Verify threshold and last updated tooltips', async () => { + test('Verify last updated date', async () => { const lastUpdatedFormatted = formatLastUpdatedDate( - '2026-01-24T14:10:32.858Z', + githubAggregatedResponse.result.timestamp, currentLocale, ); + await expect(card).toBeVisible(); + await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); + }); - const card = homePage.getCard(aggregationMetadata.id); + test('Verify threshold', async () => { await homePage.verifyThresholdTooltip(card, 'success', '3', '30%'); await homePage.verifyThresholdTooltip(card, 'warning', '5', '50%'); await homePage.verifyThresholdTooltip(card, 'error', '2', '20%'); - await homePage.verifyLastUpdatedTooltip(card, lastUpdatedFormatted); + }); + + test('Verify status grouped drill-down link', async () => { + await expect(card).toBeVisible(); + await homePage.clickDrillDownLink(); + + await scorecardDrillDownPage.expectOnPage('github.open_prs', { + aggregationId: aggregationMetadata.id, + }); + await scorecardDrillDownPage.expectPageTitle( + 'github.open_prs', + githubAggregatedResponse.metadata.title, + ); }); }); @@ -638,10 +688,6 @@ test.describe('Scorecard Plugin Tests', () => { }); }); - test.afterAll(async () => { - await page.unroute('**/api/scorecard/aggregations/**'); - }); - test.describe('Validate "average" type card content', () => { let card: Locator; @@ -691,19 +737,17 @@ test.describe('Scorecard Plugin Tests', () => { ); }); - test('Verify accessibility on weighted average card', async ({ - browser: _browser, - }, testInfo) => { - await expect(card).toBeVisible(); - await runAccessibilityTests(page, testInfo); - }); - test('Verify open drill-down link', async () => { await expect(card).toBeVisible(); await homePage.clickDrillDownLink(); + await scorecardDrillDownPage.expectOnPage('github.open_prs', { aggregationId: aggregationMetadata.id, }); + await scorecardDrillDownPage.expectPageTitle( + 'github.open_prs', + openPrsWeightedAggregatedResponse.metadata.title, + ); }); }); diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts index 9cce20593e..5f73d07089 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/homepageWidgetUtils.ts @@ -30,7 +30,7 @@ type SetupHomepageAggregationCardOptions = { status?: number; }; -export async function addWidgets(homePage: HomePage, widgetTitle: string) { +async function addWidget(homePage: HomePage, widgetTitle: string) { await homePage.navigateToHome(); await homePage.enterEditMode(); await homePage.clearAllCards(); @@ -43,11 +43,9 @@ export async function addAggregatedScorecardWidgets(homePage: HomePage) { await homePage.enterEditMode(); await homePage.clearAllCards(); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.jiraMetricId); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.githubMetricId); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.githubOpenPrsKpi); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.jiraOpenIssuesKpi); - await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES.openPrsWeightedKpi); + for (const instanceId of Object.keys(AGGREGATED_CARDS_METRIC_IDS)) { + await homePage.addCard(AGGREGATED_CARDS_WIDGET_TITLES[instanceId]); + } await homePage.saveChanges(); } @@ -61,7 +59,7 @@ export async function setupHomepageAggregationCard( await mockApiResponse(page, route, response, status ?? 200); - await addWidgets(homePage, aggregationMetadata.title); + await addWidget(homePage, aggregationMetadata.title); // Reload clears the singleton React Query cache await page.reload(); diff --git a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/mockHomepageAggregations.ts b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/mockHomepageAggregations.ts index de2599a5ef..78f5928b42 100644 --- a/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/mockHomepageAggregations.ts +++ b/workspaces/scorecard/packages/app-legacy/e2e-tests/utils/mockHomepageAggregations.ts @@ -29,6 +29,7 @@ import { openPrsWeightedAggregatedResponse, openPrsWeightedKpiMetadataResponse, } from './scorecardResponseUtils'; +import { AGGREGATED_CARDS_METRIC_IDS } from '../constants/aggregations'; function aggregationMetadataForRequestUrl(url: string): object { if (url.includes('openIssuesKpi')) { @@ -77,9 +78,17 @@ export async function mockHomepageAggregationsPermissionDenied( export async function mockAggregationNoDataFound(page: Page): Promise { await page.route('**/api/scorecard/aggregations/**', async route => { const url = route.request().url(); - const id = url.split('/').pop(); - if (id === 'openPrsWeightedKpi') { + if (url.includes('metadata')) { + await route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify(aggregationMetadataForRequestUrl(url)), + }); + return; + } + + if (url.includes(AGGREGATED_CARDS_METRIC_IDS.openPrsWeightedKpi)) { await route.fulfill({ status: 200, contentType: 'application/json', @@ -88,8 +97,15 @@ export async function mockAggregationNoDataFound(page: Page): Promise { return; } - const githubAggregations = ['openPrsKpi', 'github.open_prs']; - if (id && githubAggregations.includes(id)) { + const githubAggregations = [ + AGGREGATED_CARDS_METRIC_IDS.githubOpenPrsKpi, + AGGREGATED_CARDS_METRIC_IDS.githubMetricId, + ]; + const isGithubAggregation = githubAggregations.some(aggregation => + url.includes(aggregation), + ); + + if (isGithubAggregation) { await route.fulfill({ status: 200, contentType: 'application/json', @@ -99,8 +115,15 @@ export async function mockAggregationNoDataFound(page: Page): Promise { return; } - const jiraAggregations = ['openIssuesKpi', 'jira.open_issues']; - if (id && jiraAggregations.includes(id)) { + const jiraAggregations = [ + AGGREGATED_CARDS_METRIC_IDS.jiraOpenIssuesKpi, + AGGREGATED_CARDS_METRIC_IDS.jiraMetricId, + ]; + const isJiraAggregation = jiraAggregations.some(aggregation => + url.includes(aggregation), + ); + + if (isJiraAggregation) { await route.fulfill({ status: 200, contentType: 'application/json',