From: David Cho-Lerat Date: Wed, 15 Nov 2023 10:58:19 +0000 (+0100) Subject: SONAR-20473 Fix race condition on Measures page X-Git-Tag: 10.4.0.87286~464 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=907d47a213cfc48590048c3610592a82a2e9a5de;p=sonarqube.git SONAR-20473 Fix race condition on Measures page --- diff --git a/server/sonar-web/src/main/js/apps/component-measures/__tests__/ComponentMeasures-it.tsx b/server/sonar-web/src/main/js/apps/component-measures/__tests__/ComponentMeasures-it.tsx index c34b4c991b3..46eaaba121a 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/__tests__/ComponentMeasures-it.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/__tests__/ComponentMeasures-it.tsx @@ -392,14 +392,14 @@ describe('redirects', () => { it('should redirect old metric route', async () => { const { ui } = getPageObject(); - renderMeasuresApp('component_measures/metric/bugs'); + renderMeasuresApp('component_measures/metric/bugs?id=foo'); await ui.appLoaded(); expect(ui.measureBtn('Bugs 0').get()).toHaveAttribute('aria-current', 'true'); }); it('should redirect old domain route', async () => { const { ui } = getPageObject(); - renderMeasuresApp('component_measures/domain/bugs'); + renderMeasuresApp('component_measures/domain/bugs?id=foo'); await ui.appLoaded(); expect(ui.reliabilityDomainBtn.get()).toHaveAttribute('aria-expanded', 'true'); }); @@ -493,7 +493,7 @@ function getPageObject() { notShowingAllComponentsTxt: byText(/component_measures.hidden_best_score_metrics/), // Misc - loading: byLabelText('loading'), + loading: byText('loading'), breadcrumbLink: (name: string) => byRole('link', { name }), viewSelect: byLabelText('component_measures.view_as'), emptyText: byText('component_measures.empty'), @@ -542,7 +542,7 @@ function getPageObject() { function renderMeasuresApp(navigateTo?: string, componentContext?: Partial) { return renderAppWithComponentContext( - 'component_measures', + 'component_measures?id=foo', routes, { navigateTo, featureList: [Feature.BranchSupport] }, { component: mockComponent({ key: 'foo' }), ...componentContext }, diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/ComponentMeasuresApp.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/ComponentMeasuresApp.tsx index 9976a678389..e07f41aa4fc 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/ComponentMeasuresApp.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/components/ComponentMeasuresApp.tsx @@ -42,7 +42,7 @@ import { getBranchLikeQuery, isPullRequest, isSameBranchLike } from '../../../he import { translate } from '../../../helpers/l10n'; import { useBranchesQuery } from '../../../queries/branch'; import { BranchLike } from '../../../types/branch-like'; -import { ComponentQualifier } from '../../../types/component'; +import { ComponentQualifier, isPortfolioLike } from '../../../types/component'; import { MeasurePageView } from '../../../types/measures'; import { MetricKey } from '../../../types/metrics'; import { ComponentMeasure, Dict, MeasureEnhanced, Metric, Period } from '../../../types/types'; @@ -100,25 +100,31 @@ class ComponentMeasuresApp extends React.PureComponent { (metrics) => { const byKey = keyBy(metrics, 'key'); this.setState({ metrics: byKey }); - this.fetchMeasures(byKey); }, () => {}, ); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps: Props, prevState: State) { const prevQuery = parseQuery(prevProps.location.query); const query = parseQuery(this.props.location.query); + const hasSelectedQueryChanged = prevQuery.selected !== query.selected; + + const hasBranchChanged = !isSameBranchLike(prevProps.branchLike, this.props.branchLike); + + const isBranchReady = + isPortfolioLike(this.props.component.qualifier) || this.props.branchLike !== undefined; + + const haveMetricsChanged = + Object.keys(this.state.metrics).length !== Object.keys(prevState.metrics).length; + + const areMetricsReady = Object.keys(this.state.metrics).length > 0; + if ( - // If this update is triggered by the branch query resolving, and the metrics query started - // in componentDidMount is not done yet, we should not fetch measures just now, as it may - // throw a bug in ITs looking for a metric that isn't there yet. In this case the measures - // will be fetched once the state updates. - Object.keys(this.state.metrics).length > 0 && - (!isSameBranchLike(prevProps.branchLike, this.props.branchLike) || - prevProps.component.key !== this.props.component.key || - prevQuery.selected !== query.selected) + areMetricsReady && + isBranchReady && + (haveMetricsChanged || hasBranchChanged || hasSelectedQueryChanged) ) { this.fetchMeasures(this.state.metrics); }