]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19870 Github sync warning message
authorViktor Vorona <viktor.vorona@sonarsource.com>
Mon, 14 Aug 2023 11:07:45 +0000 (13:07 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 15 Aug 2023 20:02:41 +0000 (20:02 +0000)
server/sonar-web/src/main/js/api/mocks/AuthenticationServiceMock.ts
server/sonar-web/src/main/js/app/components/GitHubSynchronisationWarning.tsx
server/sonar-web/src/main/js/apps/settings/components/authentication/__tests__/Authentication-it.tsx
server/sonar-web/src/main/js/apps/users/__tests__/UsersApp-it.tsx
server/sonar-web/src/main/js/types/provisioning.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index a274646fa14c56e6b8c2a46b3df3d9e35baa4166..800cd0ef8a00ddfbe6047b621d28c26aecb7dd4e 100644 (file)
@@ -129,11 +129,11 @@ export default class AuthenticationServiceMock {
       return Promise.resolve({ enabled: false });
     }
 
-    const nextSync = this.tasks.find((t: any) =>
+    const nextSync = this.tasks.find((t: Task) =>
       [TaskStatuses.InProgress, TaskStatuses.Pending].includes(t.status)
     );
     const lastSync = this.tasks.find(
-      (t: any) => ![TaskStatuses.InProgress, TaskStatuses.Pending].includes(t.status)
+      (t: Task) => ![TaskStatuses.InProgress, TaskStatuses.Pending].includes(t.status)
     );
 
     return Promise.resolve({
@@ -147,6 +147,7 @@ export default class AuthenticationServiceMock {
             executionTimeMs: lastSync.executionTimeMs,
             summary: lastSync.status === TaskStatuses.Success ? 'Test summary' : undefined,
             errorMessage: lastSync.errorMessage,
+            warningMessage: lastSync.warnings?.join() ?? undefined,
           }
         : undefined,
     });
index 5b637c729df75e8e0d8e3e4045d0be55232ef562..0fafaea3e734bc7664ba7f9f14f17f8cd8e9cffa 100644 (file)
@@ -22,6 +22,7 @@ import * as React from 'react';
 import { FormattedMessage } from 'react-intl';
 import Link from '../../components/common/Link';
 import CheckIcon from '../../components/icons/CheckIcon';
+import WarningIcon from '../../components/icons/WarningIcon';
 import { Alert } from '../../components/ui/Alert';
 import { translate, translateWithParameters } from '../../helpers/l10n';
 import { useGitHubSyncStatusQuery } from '../../queries/identity-provider';
@@ -42,7 +43,7 @@ function LastSyncAlert({ info, short }: LastSyncProps) {
   if (info === undefined) {
     return null;
   }
-  const { finishedAt, errorMessage, status, summary } = info;
+  const { finishedAt, errorMessage, status, summary, warningMessage } = info;
 
   const formattedDate = finishedAt ? formatDistance(new Date(finishedAt), new Date()) : '';
 
@@ -50,12 +51,33 @@ function LastSyncAlert({ info, short }: LastSyncProps) {
     return status === TaskStatuses.Success ? (
       <div>
         <span className="authentication-enabled spacer-left">
-          <CheckIcon className="spacer-right" />
+          {warningMessage ? (
+            <WarningIcon className="spacer-right" />
+          ) : (
+            <CheckIcon className="spacer-right" />
+          )}
         </span>
         <i>
-          {translateWithParameters(
-            'settings.authentication.github.synchronization_successful',
-            formattedDate
+          {warningMessage ? (
+            <FormattedMessage
+              id="settings.authentication.github.synchronization_successful.with_warning"
+              defaultMessage={translate(
+                'settings.authentication.github.synchronization_successful.with_warning'
+              )}
+              values={{
+                date: formattedDate,
+                details: (
+                  <Link to="../settings?category=authentication&tab=github">
+                    {translate('settings.authentication.github.synchronization_details_link')}
+                  </Link>
+                ),
+              }}
+            />
+          ) : (
+            translateWithParameters(
+              'settings.authentication.github.synchronization_successful',
+              formattedDate
+            )
           )}
         </i>
       </div>
@@ -67,7 +89,7 @@ function LastSyncAlert({ info, short }: LastSyncProps) {
           values={{
             details: (
               <Link to="../settings?category=authentication&tab=github">
-                {translate('settings.authentication.github.synchronization_failed_link')}
+                {translate('settings.authentication.github.synchronization_details_link')}
               </Link>
             ),
           }}
@@ -77,33 +99,38 @@ function LastSyncAlert({ info, short }: LastSyncProps) {
   }
 
   return (
-    <Alert
-      variant={status === TaskStatuses.Success ? 'success' : 'error'}
-      role="alert"
-      aria-live="assertive"
-    >
-      {status === TaskStatuses.Success ? (
-        <>
-          {translateWithParameters(
-            'settings.authentication.github.synchronization_successful',
-            formattedDate
-          )}
-          <br />
-          {summary ?? ''}
-        </>
-      ) : (
-        <React.Fragment key={`synch-alert-${finishedAt}`}>
-          <div>
+    <>
+      <Alert
+        variant={status === TaskStatuses.Success ? 'success' : 'error'}
+        role="alert"
+        aria-live="assertive"
+      >
+        {status === TaskStatuses.Success ? (
+          <>
             {translateWithParameters(
-              'settings.authentication.github.synchronization_failed',
+              'settings.authentication.github.synchronization_successful',
               formattedDate
             )}
-          </div>
-          <br />
-          {errorMessage ?? ''}
-        </React.Fragment>
-      )}
-    </Alert>
+            <br />
+            {summary ?? ''}
+          </>
+        ) : (
+          <React.Fragment key={`synch-alert-${finishedAt}`}>
+            <div>
+              {translateWithParameters(
+                'settings.authentication.github.synchronization_failed',
+                formattedDate
+              )}
+            </div>
+            <br />
+            {errorMessage ?? ''}
+          </React.Fragment>
+        )}
+      </Alert>
+      <Alert variant="warning" role="alert" aria-live="assertive">
+        {warningMessage}
+      </Alert>
+    </>
   );
 }
 
index d5a119ebbc1064c62d6ed56b742f6fb2f76c867f..b61e05b3f8693b04380cfb3cf18e62444c3222d4 100644 (file)
@@ -172,6 +172,8 @@ const ui = {
     configurationValidityError: byRole('status', {
       name: /github.configuration.validation.invalid/,
     }),
+    syncWarning: byText(/Warning/),
+    syncSummary: byText(/Test summary/),
     configurationValidityWarning: byRole('status', {
       name: /github.configuration.validation.valid.short/,
     }),
@@ -473,7 +475,7 @@ describe('Github tab', () => {
       renderAuthentication([Feature.GithubProvisioning]);
       await github.enableProvisioning(user);
       expect(github.githubProvisioningSuccess.get()).toBeInTheDocument();
-      expect(github.githubProvisioningButton.get()).toHaveTextContent('Test summary');
+      expect(github.syncSummary.get()).toBeInTheDocument();
     });
 
     it('should display a success status even when another task is pending', async () => {
@@ -777,6 +779,18 @@ describe('Github tab', () => {
       expect(github.configurationValiditySuccess.get()).toBeInTheDocument();
       expect(github.configurationValidityError.query()).not.toBeInTheDocument();
     });
+
+    it('should show warning', async () => {
+      handler.addProvisioningTask({
+        status: TaskStatuses.Success,
+        warnings: ['Warning'],
+      });
+      renderAuthentication([Feature.GithubProvisioning]);
+      await github.enableProvisioning(user);
+
+      expect(await github.syncWarning.find()).toBeInTheDocument();
+      expect(github.syncSummary.get()).toBeInTheDocument();
+    });
   });
 });
 
index 702e348f7c40dd5f38dd8ee0354c748756dd2bce..d7a0eda66dee57a6cd78f79011aafea73b3a3cda 100644 (file)
@@ -128,6 +128,7 @@ const ui = {
   githubProvisioningPending: byText(/synchronization_pending/),
   githubProvisioningInProgress: byText(/synchronization_in_progress/),
   githubProvisioningSuccess: byText(/synchronization_successful/),
+  githubProvisioningWarning: byText(/synchronization_successful.with_warning/),
   githubProvisioningAlert: byText(/synchronization_failed_short/),
 };
 
@@ -607,6 +608,19 @@ describe('in manage mode', () => {
       expect(ui.githubProvisioningSuccess.query()).not.toBeInTheDocument();
       expect(ui.githubProvisioningInProgress.query()).not.toBeInTheDocument();
     });
+
+    it('should display an warning alert', async () => {
+      const warningMessage = 'Very long warning about something that user is not interested in';
+      authenticationHandler.addProvisioningTask({
+        status: TaskStatuses.Success,
+        warnings: [warningMessage],
+      });
+      renderUsersApp([Feature.GithubProvisioning]);
+      await act(async () => expect(await ui.githubProvisioningWarning.find()).toBeInTheDocument());
+      // We don't want to display the full warning message.
+      expect(screen.queryByText(warningMessage)).not.toBeInTheDocument();
+      expect(ui.githubProvisioningWarning.byRole('link').get()).toBeInTheDocument();
+    });
   });
 });
 
index 521fdb8de442d07bc9955344b02204e8a2abf651..81ff4c6d1c977113f40cb42aeba38dbe98fb40b8 100644 (file)
@@ -32,6 +32,7 @@ export type GithubStatusEnabled = {
     executionTimeMs: number;
     finishedAt: number;
     startedAt: number;
+    warningMessage?: string;
   } & (
     | {
         status: TaskStatuses.Success;
index cd7c7f23d0d79ab4f6b54a860e76517d1872e6ed..eda63d5a5996da05dd7a95999a6c30255cd86e78 100644 (file)
@@ -1425,9 +1425,10 @@ settings.authentication.github.synchronization_in_progress=Synchronization is in
 settings.authentication.github.synchronization_pending=Synchronization is scheduled.
 settings.authentication.github.synchronization_finish=Synchronization is done.
 settings.authentication.github.synchronization_successful=Last synchronization was done {0} ago.
+settings.authentication.github.synchronization_successful.with_warning=Last synchronization was done {date} ago with warnings. {details}
 settings.authentication.github.synchronization_failed=Last synchronization failed {0} ago.
 settings.authentication.github.synchronization_failed_short=Last synchronization failed. {details}
-settings.authentication.github.synchronization_failed_link=More details
+settings.authentication.github.synchronization_details_link=More details
 settings.authentication.github.configuration.validation.details=View details
 settings.authentication.github.configuration.validation.test=Test configuration
 settings.authentication.github.configuration.validation.loading=Checking the configuration