]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20655 Redirect to the first branch being analysed when on tutorials page
authorMathieu Suen <mathieu.suen@sonarsource.com>
Tue, 3 Oct 2023 15:06:07 +0000 (17:06 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 4 Oct 2023 20:03:19 +0000 (20:03 +0000)
server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx
server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelection-it.tsx
server/sonar-web/src/main/js/queries/branch.tsx

index 2c78e3da34ddecc8063c12025f7d5dac30772a4f..0cd87ad6b9e4dee22f3775ef292e3472a1acc368 100644 (file)
@@ -28,13 +28,14 @@ import {
   Title,
 } from 'design-system';
 import * as React from 'react';
-import { isMainBranch } from '../../helpers/branch-like';
+import { useNavigate } from 'react-router-dom';
+import { getBranchLikeQuery, isMainBranch } from '../../helpers/branch-like';
 import { translate } from '../../helpers/l10n';
 import { getBaseUrl } from '../../helpers/system';
 import { getProjectTutorialLocation } from '../../helpers/urls';
 import { useBranchesQuery } from '../../queries/branch';
 import { AlmKeys, AlmSettingsInstance, ProjectAlmBindingResponse } from '../../types/alm-settings';
-import { MainBranch } from '../../types/branch-like';
+import { BranchLike, MainBranch } from '../../types/branch-like';
 import { Component } from '../../types/types';
 import { LoggedInUser } from '../../types/users';
 import { Alert } from '../ui/Alert';
@@ -81,6 +82,8 @@ function renderAlm(mode: TutorialModes, project: string, icon?: React.ReactNode)
   );
 }
 
+const CHECKING_NEW_BRANCH = 5_000;
+
 export default function TutorialSelectionRenderer(props: TutorialSelectionRendererProps) {
   const {
     almBinding,
@@ -94,7 +97,24 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender
     willRefreshAutomatically,
   } = props;
 
-  const { data: { branchLikes } = { branchLikes: [] } } = useBranchesQuery(component);
+  const { data: { branchLikes } = { branchLikes: [] as BranchLike[] } } = useBranchesQuery(
+    component,
+    CHECKING_NEW_BRANCH,
+  );
+
+  const navigate = useNavigate();
+
+  const firstAnalysedBranch = branchLikes.find((b) => b.analysisDate !== undefined);
+
+  if (firstAnalysedBranch) {
+    navigate({
+      pathname: '/dashboard',
+      search: new URLSearchParams({
+        id: component.key,
+        ...getBranchLikeQuery(firstAnalysedBranch),
+      }).toString(),
+    });
+  }
 
   const mainBranchName =
     (branchLikes.find((b) => isMainBranch(b)) as MainBranch | undefined)?.name ||
index c8a296e6bbb5a14f249f418e8cd1a361f2005632..636bce0f5def9e872a8924072d9d39c72ba8c98e 100644 (file)
@@ -23,6 +23,7 @@ import { UserEvent } from '@testing-library/user-event/dist/types/setup/setup';
 import * as React from 'react';
 import { getScannableProjects } from '../../../api/components';
 import AlmSettingsServiceMock from '../../../api/mocks/AlmSettingsServiceMock';
+import BranchesServiceMock from '../../../api/mocks/BranchesServiceMock';
 import SettingsServiceMock from '../../../api/mocks/SettingsServiceMock';
 import UserTokensMock from '../../../api/mocks/UserTokensMock';
 import { mockComponent } from '../../../helpers/mocks/component';
@@ -39,8 +40,6 @@ import { TutorialModes } from '../types';
 
 jest.mock('../../../api/user-tokens');
 
-jest.mock('../../../api/branches');
-
 jest.mock('../../../helpers/urls', () => ({
   ...jest.requireActual('../../../helpers/urls'),
   getHostUrl: jest.fn().mockReturnValue('http://host.url'),
@@ -53,20 +52,26 @@ jest.mock('../../../api/components', () => ({
 let settingsMock: SettingsServiceMock;
 let tokenMock: UserTokensMock;
 let almMock: AlmSettingsServiceMock;
+let branchesMock: BranchesServiceMock;
 
 beforeAll(() => {
   settingsMock = new SettingsServiceMock();
   tokenMock = new UserTokensMock();
   almMock = new AlmSettingsServiceMock();
+  branchesMock = new BranchesServiceMock();
 });
 
 afterEach(() => {
   tokenMock.reset();
   settingsMock.reset();
   almMock.reset();
+  branchesMock.reset();
 });
 
-beforeEach(jest.clearAllMocks);
+beforeEach(() => {
+  branchesMock.emptyBranchesAndPullRequest();
+  jest.clearAllMocks();
+});
 
 const ui = {
   loading: byLabelText('loading'),
index 5ccfcec40873c8beb786d1e0b3edd70ea0e1c3c6..4f3a95be6cff5dc36ca34d86902535126303cdc1 100644 (file)
@@ -104,7 +104,7 @@ function getContext(key: ReturnType<typeof useBranchesQueryKey>) {
   return { componentKey, query: {} };
 }
 
-export function useBranchesQuery(component?: Component) {
+export function useBranchesQuery(component?: Component, refetchInterval?: number) {
   const features = useContext(AvailableFeaturesContext);
   const key = useBranchesQueryKey(InnerState.Details);
   return useQuery({
@@ -132,7 +132,8 @@ export function useBranchesQuery(component?: Component) {
     },
     // The check of the key must desapear once component state is in react-query
     enabled: !!component && component.key === key[1],
-    staleTime: BRANCHES_STALE_TIME,
+    staleTime: refetchInterval ?? BRANCHES_STALE_TIME,
+    refetchInterval,
   });
 }