From 35f65c3c6204a1d3bbe5ed0670a716a61f06e126 Mon Sep 17 00:00:00 2001 From: stanislavh Date: Wed, 13 Nov 2024 11:50:50 +0100 Subject: [PATCH] SONAR-23536 Project badges page supports MQR mode --- .../main/js/api/mocks/WebApiServiceMock.ts | 39 ++++ .../__tests__/ProjectInformationApp-it.tsx | 3 + .../badges/ProjectBadges.tsx | 46 ++--- .../badges/__tests__/ProjectBadges-it.tsx | 185 ++++++++++++++++++ .../badges/__tests__/ProjectBadges-test.tsx | 177 ----------------- .../js/apps/web-api/__tests__/WebApi-it.tsx | 4 +- .../sonar-web/src/main/js/queries/badges.ts | 43 ++-- .../resources/org/sonar/l10n/core.properties | 1 - 8 files changed, 265 insertions(+), 233 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/projectInformation/badges/__tests__/ProjectBadges-it.tsx delete mode 100644 server/sonar-web/src/main/js/apps/projectInformation/badges/__tests__/ProjectBadges-test.tsx diff --git a/server/sonar-web/src/main/js/api/mocks/WebApiServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/WebApiServiceMock.ts index 11e32e2a0b9..b2ea2630e11 100644 --- a/server/sonar-web/src/main/js/api/mocks/WebApiServiceMock.ts +++ b/server/sonar-web/src/main/js/api/mocks/WebApiServiceMock.ts @@ -21,6 +21,7 @@ import { cloneDeep } from 'lodash'; import { OpenAPIV3 } from 'openapi-types'; import { mockAction } from '../../helpers/mocks/webapi'; +import { MetricKey } from '../../sonar-aligned/types/metrics'; import { fetchOpenAPI, fetchWebApi } from '../web-api'; import { openApiTestData } from './data/web-api'; @@ -49,6 +50,44 @@ const BASE_DOMAINS = [ path: 'internal/thing1', since: '1.3', }, + { + path: 'api/project_badges', + actions: [ + mockAction({ + key: 'measure', + params: [ + { + key: 'metric', + description: 'Badge Metric key', + required: true, + internal: false, + possibleValues: [ + MetricKey.bugs, + MetricKey.software_quality_reliability_issues, + MetricKey.code_smells, + MetricKey.software_quality_maintainability_issues, + MetricKey.vulnerabilities, + MetricKey.software_quality_security_issues, + MetricKey.sqale_rating, + MetricKey.software_quality_maintainability_rating, + MetricKey.security_rating, + MetricKey.software_quality_security_rating, + MetricKey.reliability_rating, + MetricKey.software_quality_reliability_rating, + MetricKey.coverage, + MetricKey.duplicated_lines_density, + MetricKey.alert_status, + MetricKey.security_hotspots, + MetricKey.ncloc, + ], + }, + ], + }), + ], + description: 'Badges API', + internal: false, + since: '1.3', + }, ]; export default class WebApiServiceMock { diff --git a/server/sonar-web/src/main/js/apps/projectInformation/__tests__/ProjectInformationApp-it.tsx b/server/sonar-web/src/main/js/apps/projectInformation/__tests__/ProjectInformationApp-it.tsx index 473923080d8..0d7ba65ab3a 100644 --- a/server/sonar-web/src/main/js/apps/projectInformation/__tests__/ProjectInformationApp-it.tsx +++ b/server/sonar-web/src/main/js/apps/projectInformation/__tests__/ProjectInformationApp-it.tsx @@ -30,6 +30,7 @@ import { MeasuresServiceMock } from '../../../api/mocks/MeasuresServiceMock'; import NotificationsMock from '../../../api/mocks/NotificationsMock'; import { ProjectBadgesServiceMock } from '../../../api/mocks/ProjectBadgesServiceMock'; import ProjectLinksServiceMock from '../../../api/mocks/ProjectLinksServiceMock'; +import SettingsServiceMock from '../../../api/mocks/SettingsServiceMock'; import { mockComponent } from '../../../helpers/mocks/component'; import { mockCurrentUser, mockLoggedInUser, mockMeasure } from '../../../helpers/testMocks'; import { @@ -56,6 +57,7 @@ const badgesHandler = new ProjectBadgesServiceMock(); const notificationsHandler = new NotificationsMock(); const branchesHandler = new BranchesServiceMock(); const aiCodeAssurance = new AiCodeAssuredServiceMock(); +const settingsHandler = new SettingsServiceMock(); const ui = { projectPageTitle: byRole('heading', { name: 'project.info.title' }), @@ -80,6 +82,7 @@ afterEach(() => { notificationsHandler.reset(); branchesHandler.reset(); aiCodeAssurance.reset(); + settingsHandler.reset(); }); it('should show fields for project', async () => { diff --git a/server/sonar-web/src/main/js/apps/projectInformation/badges/ProjectBadges.tsx b/server/sonar-web/src/main/js/apps/projectInformation/badges/ProjectBadges.tsx index 247e5e68d7b..28cdc20e5d8 100644 --- a/server/sonar-web/src/main/js/apps/projectInformation/badges/ProjectBadges.tsx +++ b/server/sonar-web/src/main/js/apps/projectInformation/badges/ProjectBadges.tsx @@ -36,11 +36,9 @@ import { Image } from '~sonar-aligned/components/common/Image'; import { getBranchLikeQuery } from '~sonar-aligned/helpers/branch-like'; import { MetricKey } from '~sonar-aligned/types/metrics'; import { useAvailableFeatures } from '../../../app/components/available-features/withAvailableFeatures'; -import { translate, translateWithParameters } from '../../../helpers/l10n'; -import { localizeMetric } from '../../../helpers/measures'; +import { translate } from '../../../helpers/l10n'; import { - DEPRECATED_METRIC_KEYS, - useBadgeMetricsQuery, + useBadgeMetrics, useBadgeTokenQuery, useRenewBagdeTokenMutation, } from '../../../queries/badges'; @@ -68,7 +66,7 @@ export default function ProjectBadges(props: ProjectBadgesProps) { isLoading: isLoadingToken, isFetching: isFetchingToken, } = useBadgeTokenQuery(project); - const { data: metricOptions, isLoading: isLoadingMetrics } = useBadgeMetricsQuery(); + const { data: metricOptions, isLoading: isLoadingMetrics } = useBadgeMetrics(); const { mutate: renewToken, isPending: isRenewing } = useRenewBagdeTokenMutation(); const { hasFeature } = useAvailableFeatures(); const isLoading = isLoadingMetrics || isLoadingToken || isRenewing; @@ -156,31 +154,19 @@ export default function ProjectBadges(props: ProjectBadgesProps) { {BadgeType.measure === selectedType && ( - <> - - { - if (option) { - setSelectedMetric(option.value); - } - }} - value={metricOptions.find((m) => m.value === selectedMetric)} - /> - - - {DEPRECATED_METRIC_KEYS.includes(selectedMetric) && ( - - {translateWithParameters( - 'overview.badges.deprecated_badge_x_y', - localizeMetric(selectedMetric), - translate('qualifier', qualifier), - )} - - )} - + + { + if (option) { + setSelectedMetric(option.value); + } + }} + value={metricOptions.find((m) => m.value === selectedMetric)} + /> + )} diff --git a/server/sonar-web/src/main/js/apps/projectInformation/badges/__tests__/ProjectBadges-it.tsx b/server/sonar-web/src/main/js/apps/projectInformation/badges/__tests__/ProjectBadges-it.tsx new file mode 100644 index 00000000000..c79d23a4496 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projectInformation/badges/__tests__/ProjectBadges-it.tsx @@ -0,0 +1,185 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { MetricKey } from '~sonar-aligned/types/metrics'; +import { ProjectBadgesServiceMock } from '../../../../api/mocks/ProjectBadgesServiceMock'; +import SettingsServiceMock from '../../../../api/mocks/SettingsServiceMock'; +import WebApiServiceMock from '../../../../api/mocks/WebApiServiceMock'; +import { getProjectBadgesToken } from '../../../../api/project-badges'; +import { mockBranch } from '../../../../helpers/mocks/branch-like'; +import { mockComponent } from '../../../../helpers/mocks/component'; +import { renderComponent } from '../../../../helpers/testReactTestingUtils'; +import { Location } from '../../../../helpers/urls'; +import { byLabelText, byRole, byText } from '../../../../sonar-aligned/helpers/testSelector'; +import { ComponentQualifier } from '../../../../sonar-aligned/types/component'; +import { SettingsKey } from '../../../../types/settings'; +import ProjectBadges, { ProjectBadgesProps } from '../ProjectBadges'; +import { BadgeType } from '../utils'; + +jest.mock('../../../../helpers/urls', () => ({ + getHostUrl: () => 'host', + getPathUrlAsString: (l: Location) => l.pathname, + getProjectUrl: () => ({ pathname: '/dashboard' }) as Location, +})); + +const badgesHandler = new ProjectBadgesServiceMock(); +const webApiHandler = new WebApiServiceMock(); +const settingsHandler = new SettingsServiceMock(); + +afterEach(() => { + badgesHandler.reset(); + webApiHandler.reset(); + settingsHandler.reset(); +}); + +it('should renew token', async () => { + const { user, ui } = getPageObjects(); + jest.mocked(getProjectBadgesToken).mockResolvedValueOnce('foo').mockResolvedValueOnce('bar'); + renderProjectBadges(); + await ui.appLoaded(); + + expect(screen.getByAltText(`overview.badges.${BadgeType.measure}.alt`)).toHaveAttribute( + 'src', + expect.stringContaining( + `host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=${MetricKey.alert_status}&token=foo`, + ), + ); + + await user.click(screen.getByText('overview.badges.renew')); + + expect( + await screen.findByAltText(`overview.badges.${BadgeType.qualityGate}.alt`), + ).toHaveAttribute( + 'src', + expect.stringContaining( + 'host/api/project_badges/quality_gate?branch=branch-6.7&project=my-project&token=bar', + ), + ); + + expect(screen.getByAltText(`overview.badges.${BadgeType.measure}.alt`)).toHaveAttribute( + 'src', + expect.stringContaining( + `host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=${MetricKey.alert_status}&token=bar`, + ), + ); +}); + +it('can select badges in Standard Experience Mode', async () => { + const { user, ui } = getPageObjects(); + settingsHandler.set(SettingsKey.MQRMode, 'false'); + + renderProjectBadges(); + await ui.appLoaded(); + + expect(ui.markdownCode(MetricKey.alert_status).get()).toBeInTheDocument(); + + await ui.selectMetric(MetricKey.code_smells); + expect(ui.markdownCode(MetricKey.code_smells).get()).toBeInTheDocument(); + + await ui.selectMetric(MetricKey.security_rating); + expect(ui.markdownCode(MetricKey.security_rating).get()).toBeInTheDocument(); + + await user.click(ui.imageUrlRadio.get()); + expect(ui.urlCode(MetricKey.security_rating).get()).toBeInTheDocument(); + + await user.click(ui.qualityGateBadge.get()); + expect(ui.urlCode().get()).toBeInTheDocument(); + + await user.click(ui.mardownRadio.get()); + expect(ui.markdownCode().get()).toBeInTheDocument(); +}); + +it('can select badges in MQR Mode', async () => { + const { user, ui } = getPageObjects(); + + renderProjectBadges(); + await ui.appLoaded(); + + expect(ui.markdownCode(MetricKey.alert_status).get()).toBeInTheDocument(); + + await ui.selectMetric(MetricKey.coverage); + expect(ui.markdownCode(MetricKey.coverage).get()).toBeInTheDocument(); + + await ui.selectMetric(MetricKey.software_quality_reliability_issues); + expect(ui.markdownCode(MetricKey.software_quality_reliability_issues).get()).toBeInTheDocument(); + + await ui.selectMetric(MetricKey.software_quality_maintainability_rating); + expect( + ui.markdownCode(MetricKey.software_quality_maintainability_rating).get(), + ).toBeInTheDocument(); + + await user.click(ui.imageUrlRadio.get()); + expect(ui.urlCode(MetricKey.software_quality_maintainability_rating).get()).toBeInTheDocument(); + + await user.click(ui.qualityGateBadge.get()); + expect(ui.urlCode().get()).toBeInTheDocument(); + + await user.click(ui.mardownRadio.get()); + expect(ui.markdownCode().get()).toBeInTheDocument(); +}); + +const getPageObjects = () => { + const user = userEvent.setup(); + + return { + user, + ui: { + qualityGateBadge: byRole('button', { + name: `overview.badges.${BadgeType.qualityGate}.alt overview.badges.${BadgeType.qualityGate}.description.${ComponentQualifier.Project}`, + }), + imageUrlRadio: byRole('radio', { name: 'overview.badges.options.formats.url' }), + mardownRadio: byRole('radio', { name: 'overview.badges.options.formats.md' }), + urlCode: (metric?: MetricKey) => + byText( + metric + ? `host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=${metric}&token=${badgesHandler.token}` + : `host/api/project_badges/quality_gate?branch=branch-6.7&project=my-project&token=${badgesHandler.token}`, + { exact: false }, + ), + markdownCode: (metric?: MetricKey) => + byText( + metric + ? `[![${metric}](host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=${metric}&token=${badgesHandler.token}` + : `[![Quality gate](host/api/project_badges/quality_gate?branch=branch-6.7&project=my-project&token=${badgesHandler.token}`, + { exact: false }, + ), + + async selectMetric(metric: MetricKey) { + await user.click(byLabelText('overview.badges.metric').get()); + await user.click(byText(`metric.${metric}.name`).get()); + }, + async appLoaded() { + await waitFor(() => expect(screen.queryByLabelText(`loading`)).not.toBeInTheDocument()); + }, + }, + }; +}; + +function renderProjectBadges(props: Partial = {}) { + return renderComponent( + , + ); +} diff --git a/server/sonar-web/src/main/js/apps/projectInformation/badges/__tests__/ProjectBadges-test.tsx b/server/sonar-web/src/main/js/apps/projectInformation/badges/__tests__/ProjectBadges-test.tsx deleted file mode 100644 index 294ff302f0c..00000000000 --- a/server/sonar-web/src/main/js/apps/projectInformation/badges/__tests__/ProjectBadges-test.tsx +++ /dev/null @@ -1,177 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -import { screen, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { ComponentQualifier } from '~sonar-aligned/types/component'; -import { MetricKey } from '~sonar-aligned/types/metrics'; -import { getProjectBadgesToken } from '../../../../api/project-badges'; -import { mockBranch } from '../../../../helpers/mocks/branch-like'; -import { mockComponent } from '../../../../helpers/mocks/component'; -import { renderComponent } from '../../../../helpers/testReactTestingUtils'; -import { Location } from '../../../../helpers/urls'; -import { byRole } from '../../../../sonar-aligned/helpers/testSelector'; -import ProjectBadges, { ProjectBadgesProps } from '../ProjectBadges'; -import { BadgeType } from '../utils'; - -jest.mock('../../../../helpers/urls', () => ({ - getHostUrl: () => 'host', - getPathUrlAsString: (l: Location) => l.pathname, - getProjectUrl: () => ({ pathname: '/dashboard' }) as Location, -})); - -jest.mock('../../../../api/project-badges', () => ({ - getProjectBadgesToken: jest.fn().mockResolvedValue('foo'), - renewProjectBadgesToken: jest.fn().mockResolvedValue({}), -})); - -jest.mock('../../../../api/web-api', () => ({ - fetchWebApi: jest.fn().mockResolvedValue([ - { - path: 'api/project_badges', - actions: [ - { - key: 'measure', - // eslint-disable-next-line local-rules/use-metrickey-enum - params: [{ key: 'metric', possibleValues: ['alert_status', 'coverage', 'bugs'] }], - }, - ], - }, - ]), -})); - -it('should renew token', async () => { - const user = userEvent.setup(); - jest.mocked(getProjectBadgesToken).mockResolvedValueOnce('foo').mockResolvedValueOnce('bar'); - renderProjectBadges(); - await appLoaded(); - - expect(screen.getByAltText(`overview.badges.${BadgeType.measure}.alt`)).toHaveAttribute( - 'src', - expect.stringContaining( - `host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=${MetricKey.alert_status}&token=foo`, - ), - ); - - await user.click(screen.getByText('overview.badges.renew')); - - expect( - await screen.findByAltText(`overview.badges.${BadgeType.qualityGate}.alt`), - ).toHaveAttribute( - 'src', - expect.stringContaining( - 'host/api/project_badges/quality_gate?branch=branch-6.7&project=my-project&token=bar', - ), - ); - - expect(screen.getByAltText(`overview.badges.${BadgeType.measure}.alt`)).toHaveAttribute( - 'src', - expect.stringContaining( - `host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=${MetricKey.alert_status}&token=bar`, - ), - ); -}); - -it('should update params', async () => { - const user = userEvent.setup(); - renderProjectBadges(); - await appLoaded(); - - expect( - screen.getByText( - `[![${MetricKey.alert_status}](host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=${MetricKey.alert_status}&token=foo`, - { exact: false }, - ), - ).toBeInTheDocument(); - - await user.click(byRole('radio', { name: 'overview.badges.options.formats.url' }).get()); - - expect( - screen.getByText( - 'host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=alert_status&token=foo', - { exact: false }, - ), - ).toBeInTheDocument(); - - await user.click(screen.getByLabelText('overview.badges.metric')); - await user.click(screen.getByText(`metric.${MetricKey.coverage}.name`)); - - expect( - screen.getByText( - 'host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=coverage&token=foo', - { exact: false }, - ), - ).toBeInTheDocument(); - - await user.click( - screen.getByRole('button', { - name: `overview.badges.${BadgeType.qualityGate}.alt overview.badges.${BadgeType.qualityGate}.description.${ComponentQualifier.Project}`, - }), - ); - - expect( - screen.getByText( - 'host/api/project_badges/quality_gate?branch=branch-6.7&project=my-project&token=foo', - { exact: false }, - ), - ).toBeInTheDocument(); - - await user.click( - screen.getByRole('button', { - name: `overview.badges.${BadgeType.measure}.alt overview.badges.${BadgeType.measure}.description.${ComponentQualifier.Project}`, - }), - ); - - expect( - screen.getByText( - 'host/api/project_badges/measure?branch=branch-6.7&project=my-project&metric=coverage&token=foo', - { exact: false }, - ), - ).toBeInTheDocument(); -}); - -it('should warn about deprecated metrics', async () => { - const user = userEvent.setup(); - renderProjectBadges(); - await appLoaded(); - - await user.click(screen.getByLabelText('overview.badges.metric')); - await user.click(screen.getByText(`metric.${MetricKey.bugs}.name (deprecated)`)); - - expect( - screen.getByText( - `overview.badges.deprecated_badge_x_y.metric.${MetricKey.bugs}.name.qualifier.${ComponentQualifier.Project}`, - ), - ).toBeInTheDocument(); -}); - -async function appLoaded() { - await waitFor(() => expect(screen.queryByLabelText(`loading`)).not.toBeInTheDocument()); -} - -function renderProjectBadges(props: Partial = {}) { - return renderComponent( - , - ); -} diff --git a/server/sonar-web/src/main/js/apps/web-api/__tests__/WebApi-it.tsx b/server/sonar-web/src/main/js/apps/web-api/__tests__/WebApi-it.tsx index 823d16aa4ae..ffe3ba5d54f 100644 --- a/server/sonar-web/src/main/js/apps/web-api/__tests__/WebApi-it.tsx +++ b/server/sonar-web/src/main/js/apps/web-api/__tests__/WebApi-it.tsx @@ -37,7 +37,7 @@ it('should allow to browse the api', async () => { renderWebApi(); expect(await ui.sidebarHeader.find()).toBeInTheDocument(); - expect(await ui.domainMenuItems.findAll()).toHaveLength(1); + expect(await ui.domainMenuItems.findAll()).toHaveLength(2); await user.click(ui.domainMenuItemLink('foo/bar').get()); @@ -63,7 +63,7 @@ it('should allow to browse the api', async () => { // Show internal await user.click(ui.showInternalCheckbox.get()); - expect(await ui.domainMenuItems.findAll()).toHaveLength(2); + expect(await ui.domainMenuItems.findAll()).toHaveLength(3); await user.click(ui.domainMenuItemLink('internal/thing1 internal').get()); expect(await byText('get internal memos').find()).toBeInTheDocument(); diff --git a/server/sonar-web/src/main/js/queries/badges.ts b/server/sonar-web/src/main/js/queries/badges.ts index e3e74ad28dd..981b2f651a3 100644 --- a/server/sonar-web/src/main/js/queries/badges.ts +++ b/server/sonar-web/src/main/js/queries/badges.ts @@ -19,10 +19,12 @@ */ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { uniq } from 'lodash'; import { MetricKey } from '~sonar-aligned/types/metrics'; import { getProjectBadgesToken, renewProjectBadgesToken } from '../api/project-badges'; -import { translate } from '../helpers/l10n'; +import { MQR_CONDITIONS_MAP, STANDARD_CONDITIONS_MAP } from '../apps/quality-gates/utils'; import { localizeMetric } from '../helpers/measures'; +import { useStandardExperienceMode } from './settings'; import { useWebApiQuery } from './web-api'; export function useRenewBagdeTokenMutation() { @@ -37,34 +39,29 @@ export function useRenewBagdeTokenMutation() { }); } -// The same list of deprecated metric keys is maintained on the backend at org.sonar.server.badge.ws.MeasureAction. -export const DEPRECATED_METRIC_KEYS = [ - MetricKey.bugs, - MetricKey.code_smells, - MetricKey.security_hotspots, - MetricKey.vulnerabilities, -]; - -export function useBadgeMetricsQuery() { - const { data: webservices = [], ...rest } = useWebApiQuery(); +export function useBadgeMetrics() { + const { data: webservices = [], isLoading: isLoadingWebApi } = useWebApiQuery(); + const { data: isStandardExperience, isLoading: isLoadingMode } = useStandardExperienceMode(); const domain = webservices.find((d) => d.path === 'api/project_badges'); const ws = domain?.actions.find((w) => w.key === 'measure'); const param = ws?.params?.find((p) => p.key === 'metric'); - if (param?.possibleValues) { + if (param?.possibleValues && !isLoadingMode) { return { - ...rest, - data: param.possibleValues.map((key: MetricKey) => { - const label = localizeMetric(key); - return { - value: key, - label: DEPRECATED_METRIC_KEYS.includes(key) - ? `${label} (${translate('deprecated')})` - : label, - }; - }), + isLoading: false, + data: uniq( + param.possibleValues.map((metric: MetricKey) => { + return ( + (isStandardExperience ? MQR_CONDITIONS_MAP[metric] : STANDARD_CONDITIONS_MAP[metric]) ?? + metric + ); + }), + ).map((metric) => ({ + value: metric, + label: localizeMetric(metric), + })), }; } - return { ...rest, data: [] }; + return { isLoading: isLoadingWebApi || isLoadingMode, data: [] }; } export function useBadgeTokenQuery(componentKey: string) { diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 36f8eb405eb..c382b9ff75f 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -4518,7 +4518,6 @@ overview.badges.ai_code_assurance.description.TRK=Displays the current status of overview.badges.leak_warning=Project badges can expose your security rating and other measures. Only use project badges in trusted environments. overview.badges.renew=Renew Token overview.badges.renew.description=If your project badge security token has leaked to an unsafe environment, you can renew it: -overview.badges.deprecated_badge_x_y=Badges displaying {0} are deprecated and will be removed in a future version. Please choose another badge for your {1}. overview.quality_profiles_update_after_sq_upgrade.message=Upgrade to {productName} {sqVersion} has updated your Quality Profiles. Issues on your project may have been affected. {link} overview.quality_profiles_update_after_sq_upgrade.link=See more details -- 2.39.5