]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10002 Add dismiss button to install error message on marketplace
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Thu, 19 Oct 2017 09:04:29 +0000 (11:04 +0200)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Mon, 23 Oct 2017 15:01:13 +0000 (08:01 -0700)
server/sonar-web/src/main/js/api/marketplace.ts
server/sonar-web/src/main/js/apps/marketplace/App.tsx
server/sonar-web/src/main/js/apps/marketplace/components/EditionsStatusNotif.tsx
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionsStatusNotif-test.tsx
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionsStatusNotif-test.tsx.snap

index 4eae2b77737b8bd3d9c78b971e94c03b4d970552..0574650e6033764fb9fd4322addd362ccc9137ab 100644 (file)
@@ -17,7 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import { checkStatus, corsRequest, getJSON, parseJSON, postJSON } from '../helpers/request';
+import { checkStatus, corsRequest, getJSON, parseJSON, post, postJSON } from '../helpers/request';
 import throwGlobalError from '../app/utils/throwGlobalError';
 
 export interface Edition {
@@ -75,5 +75,9 @@ export function applyLicense(data: { license: string }): Promise<EditionStatus>
 }
 
 export function uninstallEdition(): Promise<void | Response> {
-  return postJSON('/api/editions/uninstall').catch(throwGlobalError);
+  return post('/api/editions/uninstall').catch(throwGlobalError);
+}
+
+export function dismissErrorMessage(): Promise<void | Response> {
+  return post('/api/editions/clear_error_message').catch(throwGlobalError);
 }
index eaf510ac7073ee696b1ac168c07625f26c6120f1..37cc3b1d72a31e8caef371f69072d40240af6fb5 100644 (file)
@@ -177,7 +177,12 @@ export default class App extends React.PureComponent<Props, State> {
       <div className="page page-limited" id="marketplace-page">
         <Helmet title={translate('marketplace.page')} />
         <div className="marketplace-notifs">
-          {editionStatus && <EditionsStatusNotif editionStatus={editionStatus} />}
+          {editionStatus && (
+            <EditionsStatusNotif
+              editionStatus={editionStatus}
+              updateEditionStatus={this.updateEditionStatus}
+            />
+          )}
           <PendingActions refreshPending={this.fetchPendingPlugins} pending={pending} />
         </div>
         <Header />
index f1acfff516c44acde276a5038d1ba58ed6702d0c..1afc9931bf6136a694043ea8d16bc3296f032b6c 100644 (file)
  */
 import * as React from 'react';
 import RestartForm from '../../../components/common/RestartForm';
-import { EditionStatus } from '../../../api/marketplace';
+import CloseIcon from '../../../components/icons-components/CloseIcon';
+import { dismissErrorMessage, EditionStatus } from '../../../api/marketplace';
 import { translate } from '../../../helpers/l10n';
 
 interface Props {
   editionStatus: EditionStatus;
+  updateEditionStatus: (editionStatus: EditionStatus) => void;
 }
 
 interface State {
@@ -36,6 +38,15 @@ export default class EditionsStatusNotif extends React.PureComponent<Props, Stat
   handleOpenRestart = () => this.setState({ openRestart: true });
   hanleCloseRestart = () => this.setState({ openRestart: false });
 
+  handleDismissError = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
+    event.preventDefault();
+    dismissErrorMessage().then(
+      () =>
+        this.props.updateEditionStatus({ ...this.props.editionStatus, installError: undefined }),
+      () => {}
+    );
+  };
+
   renderStatusAlert() {
     const { installationStatus } = this.props.editionStatus;
     switch (installationStatus) {
@@ -74,7 +85,17 @@ export default class EditionsStatusNotif extends React.PureComponent<Props, Stat
     const { installError } = this.props.editionStatus;
     return (
       <div>
-        {installError && <div className="alert alert-danger">{installError}</div>}
+        {installError && (
+          <div className="alert alert-danger">
+            {installError}
+            <a
+              className="pull-right button-link text-danger"
+              href="#"
+              onClick={this.handleDismissError}>
+              <CloseIcon />
+            </a>
+          </div>
+        )}
         {this.renderStatusAlert}
       </div>
     );
index 378f57b3cbb1309a31d001492efb52200bcc0e6d..0a3ca4c9acdb05839e324be44c6f3cd1af298b23 100644 (file)
  */
 import * as React from 'react';
 import { shallow } from 'enzyme';
+import { click } from '../../../../helpers/testUtils';
 import EditionsStatusNotif from '../EditionsStatusNotif';
 
+jest.mock('../../../../api/marketplace', () => ({
+  dismissErrorMessage: jest.fn(() => Promise.resolve())
+}));
+
+const dismissMsg = require('../../../../api/marketplace').dismissErrorMessage as jest.Mock<any>;
+
+beforeEach(() => {
+  dismissMsg.mockClear();
+});
+
 it('should display an in progress notif', () => {
   const wrapper = shallow(
-    <EditionsStatusNotif editionStatus={{ installationStatus: 'AUTOMATIC_IN_PROGRESS' }} />
+    <EditionsStatusNotif
+      editionStatus={{ installationStatus: 'AUTOMATIC_IN_PROGRESS' }}
+      updateEditionStatus={jest.fn()}
+    />
   );
   expect(wrapper).toMatchSnapshot();
 });
 
 it('should display an error notification', () => {
   const wrapper = shallow(
-    <EditionsStatusNotif editionStatus={{ installationStatus: 'AUTOMATIC_FAILURE' }} />
+    <EditionsStatusNotif
+      editionStatus={{ installationStatus: 'AUTOMATIC_FAILURE' }}
+      updateEditionStatus={jest.fn()}
+    />
   );
   expect(wrapper).toMatchSnapshot();
 });
 
 it('should display a ready notification', () => {
   const wrapper = shallow(
-    <EditionsStatusNotif editionStatus={{ installationStatus: 'AUTOMATIC_READY' }} />
+    <EditionsStatusNotif
+      editionStatus={{ installationStatus: 'AUTOMATIC_READY' }}
+      updateEditionStatus={jest.fn()}
+    />
   );
   expect(wrapper).toMatchSnapshot();
 });
@@ -46,7 +66,25 @@ it('should display install errors', () => {
   const wrapper = shallow(
     <EditionsStatusNotif
       editionStatus={{ installationStatus: 'AUTOMATIC_IN_PROGRESS', installError: 'Foo error' }}
+      updateEditionStatus={jest.fn()}
     />
   );
   expect(wrapper).toMatchSnapshot();
 });
+
+it('should allow to dismiss install errors', async () => {
+  const updateEditionStatus = jest.fn();
+  const wrapper = shallow(
+    <EditionsStatusNotif
+      editionStatus={{ installationStatus: 'NONE', installError: 'Foo error' }}
+      updateEditionStatus={updateEditionStatus}
+    />
+  );
+  click(wrapper.find('a'));
+  expect(dismissMsg).toHaveBeenCalled();
+  await new Promise(setImmediate);
+  expect(updateEditionStatus).toHaveBeenCalledWith({
+    installationStatus: 'NONE',
+    installError: undefined
+  });
+});
index d136af03406880af9e5a5586794e19d716050f48..0f79649b873a66bee1c6567258d21d4aba59cf05 100644 (file)
@@ -12,6 +12,13 @@ exports[`should display install errors 1`] = `
     className="alert alert-danger"
   >
     Foo error
+    <a
+      className="pull-right button-link text-danger"
+      href="#"
+      onClick={[Function]}
+    >
+      <CloseIcon />
+    </a>
   </div>
 </div>
 `;