]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-21368 Update component container to avoid infinite loop on tutorial page
authorstanislavh <stanislav.honcharov@sonarsource.com>
Wed, 17 Jan 2024 08:11:50 +0000 (09:11 +0100)
committersonartech <sonartech@sonarsource.com>
Wed, 17 Jan 2024 20:02:45 +0000 (20:02 +0000)
server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx

index 886f1389ddef942e019356f64bdd26ae2f0ac7dd..d21f6d24ce934a11db0d9e8a006b14b48a0e9934 100644 (file)
@@ -30,7 +30,7 @@ import { getComponentNavigation } from '../../api/navigation';
 import { useLocation, useRouter } from '../../components/hoc/withRouter';
 import { translateWithParameters } from '../../helpers/l10n';
 import { HttpStatus } from '../../helpers/request';
-import { getPortfolioUrl, getProjectUrl } from '../../helpers/urls';
+import { getPortfolioUrl } from '../../helpers/urls';
 import { useBranchesQuery } from '../../queries/branch';
 import { ProjectAlmBindingConfigurationErrors } from '../../types/alm-settings';
 import { Branch } from '../../types/branch-like';
@@ -98,22 +98,25 @@ function ComponentContainer({ hasFeature }: Readonly<WithAvailableFeaturesProps>
     [key, branch, pullRequest],
   );
 
-  const fetchStatus = React.useCallback(async (componentKey: string) => {
-    try {
-      const { current, queue } = await getTasksForComponent(componentKey);
-      const newCurrentTask = getCurrentTask(current);
-      const pendingTasks = getPendingTasksForBranchLike(queue);
-      const newTasksInProgress = getInProgressTasks(pendingTasks);
-
-      const isPending = pendingTasks.some((task) => task.status === TaskStatuses.Pending);
-
-      setPending(isPending);
-      setCurrentTask(newCurrentTask);
-      setTasksInProgress(newTasksInProgress);
-    } catch {
-      // noop
-    }
-  }, []);
+  const fetchStatus = React.useCallback(
+    async (componentKey: string) => {
+      try {
+        const { current, queue } = await getTasksForComponent(componentKey);
+        const newCurrentTask = getCurrentTask(current, branch, pullRequest);
+        const pendingTasks = getPendingTasksForBranchLike(queue, branch, pullRequest);
+        const newTasksInProgress = getInProgressTasks(pendingTasks);
+
+        const isPending = pendingTasks.some((task) => task.status === TaskStatuses.Pending);
+
+        setPending(isPending);
+        setCurrentTask(newCurrentTask);
+        setTasksInProgress(newTasksInProgress);
+      } catch {
+        // noop
+      }
+    },
+    [branch, pullRequest],
+  );
 
   const fetchProjectBindingErrors = React.useCallback(
     async (component: Component) => {
@@ -189,8 +192,14 @@ function ComponentContainer({ hasFeature }: Readonly<WithAvailableFeaturesProps>
 
     oldCurrentTask.current = currentTask;
     oldTasksInProgress.current = tasks;
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [tasksInProgress, currentTask]);
+  }, [tasksInProgress, currentTask, component, fetchComponent, fetchStatus]);
+
+  // Refetch component when a new branch is analyzed
+  React.useEffect(() => {
+    if (branchLike?.analysisDate && !component?.analysisDate) {
+      fetchComponent();
+    }
+  }, [branchLike, component, fetchComponent]);
 
   // Refetch component when target branch for fixing pull request is fetched
   React.useEffect(() => {
@@ -210,11 +219,6 @@ function ComponentContainer({ hasFeature }: Readonly<WithAvailableFeaturesProps>
      */
     if (pathname.includes('dashboard') && component && isPortfolioLike(component.qualifier)) {
       router.replace(getPortfolioUrl(component.key));
-      return;
-    }
-    // Redirect from tutorials to to dashboard
-    if (component && !component.analysisDate && pathname.includes('tutorials')) {
-      router.replace(getProjectUrl(key));
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [component]);
@@ -313,16 +317,20 @@ export function isSameBranch(
   return branch === task.branch;
 }
 
-function getCurrentTask(current?: Task) {
+function getCurrentTask(current?: Task, branch?: string, pullRequest?: string) {
   if (!current || !isReportRelatedTask(current)) {
     return undefined;
   }
 
-  return current.status === TaskStatuses.Failed || isSameBranch(current) ? current : undefined;
+  return current.status === TaskStatuses.Failed || isSameBranch(current, branch, pullRequest)
+    ? current
+    : undefined;
 }
 
-function getPendingTasksForBranchLike(pendingTasks: Task[]) {
-  return pendingTasks.filter((task) => isReportRelatedTask(task) && isSameBranch(task));
+function getPendingTasksForBranchLike(pendingTasks: Task[], branch?: string, pullRequest?: string) {
+  return pendingTasks.filter(
+    (task) => isReportRelatedTask(task) && isSameBranch(task, branch, pullRequest),
+  );
 }
 
 function getInProgressTasks(pendingTasks: Task[]) {
index d277bdd6709bb80f73ff96e2597eecf80807425f..8f1d7bf92817dc3166cc60526b3b16f33f8fea0b 100644 (file)
@@ -391,31 +391,6 @@ describe('redirects', () => {
 
     expect(await ui.portfolioText.find()).toBeInTheDocument();
   });
-
-  it('should redirect to project from tutorial when component is loaded', async () => {
-    const component = mockComponent({
-      breadcrumbs: [{ key: 'project', name: 'Project', qualifier: ComponentQualifier.Project }],
-      key: 'project-key',
-    });
-
-    jest
-      .mocked(getComponentNavigation)
-      .mockResolvedValueOnce({} as unknown as Awaited<ReturnType<typeof getComponentNavigation>>);
-
-    jest
-      .mocked(getComponentData)
-      .mockResolvedValueOnce({ component } as unknown as Awaited<
-        ReturnType<typeof getComponentData>
-      >);
-
-    renderComponentContainer(
-      { hasFeature: jest.fn().mockReturnValue(true) },
-      'tutorials?id=project-key',
-      '/tutorials',
-    );
-
-    expect(await ui.projectText.find()).toBeInTheDocument();
-  });
 });
 
 it.each([