From 3ac9340f013701017f8dbab5b0686d2682f1768f Mon Sep 17 00:00:00 2001
From: Stas Vilchik <stas.vilchik@sonarsource.com>
Date: Wed, 6 Sep 2017 17:53:37 +0200
Subject: SONAR-9181 bulk delete projects or bulk apply template in one go

---
 .../apps/projectsManagement/__tests__/App-test.tsx |  13 +-
 .../__tests__/BulkApplyTemplateModal-test.tsx      |  29 ++---
 .../__tests__/DeleteModal-test.tsx                 |  38 +++++-
 .../projectsManagement/__tests__/Header-test.tsx   |   2 +-
 .../__tests__/ProjectRow-test.tsx                  |   2 +-
 .../projectsManagement/__tests__/Projects-test.tsx |   2 +-
 .../projectsManagement/__tests__/Search-test.tsx   |   2 +-
 .../BulkApplyTemplateModal-test.tsx.snap           |  20 +++-
 .../__snapshots__/DeleteModal-test.tsx.snap        | 133 ++++++++++++++++++++-
 .../__tests__/__snapshots__/Search-test.tsx.snap   |  11 +-
 10 files changed, 208 insertions(+), 44 deletions(-)

(limited to 'server/sonar-web/src/main/js/apps/projectsManagement/__tests__')

diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx
index 07339957c4c..0fb6b1d21d0 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/App-test.tsx
@@ -30,17 +30,13 @@ jest.mock('rc-tooltip', () => ({
   }
 }));
 
-jest.mock('../../../api/components', () => ({
-  getComponents: jest.fn(),
-  getProvisioned: jest.fn(() => Promise.resolve({ paging: { total: 0 }, projects: [] }))
-}));
+jest.mock('../../../api/components', () => ({ getComponents: jest.fn() }));
 
 import * as React from 'react';
 import { mount } from 'enzyme';
 import App, { Props } from '../App';
 
 const getComponents = require('../../../api/components').getComponents as jest.Mock<any>;
-const getProvisioned = require('../../../api/components').getProvisioned as jest.Mock<any>;
 
 const organization = { key: 'org', name: 'org', projectVisibility: 'public' };
 
@@ -55,7 +51,6 @@ beforeEach(() => {
   getComponents
     .mockImplementation(() => Promise.resolve({ paging: { total: 0 }, components: [] }))
     .mockClear();
-  getProvisioned.mockClear();
 });
 
 it('fetches all projects on mount', () => {
@@ -66,7 +61,11 @@ it('fetches all projects on mount', () => {
 it('selects provisioned', () => {
   const wrapper = mountRender();
   wrapper.find('Search').prop<Function>('onProvisionedChanged')(true);
-  expect(getProvisioned).lastCalledWith(defaultSearchParameters);
+  expect(getComponents).lastCalledWith({
+    ...defaultSearchParameters,
+    onProvisionedOnly: true,
+    qualifiers: 'TRK'
+  });
 });
 
 it('changes qualifier and resets provisioned', () => {
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/BulkApplyTemplateModal-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/BulkApplyTemplateModal-test.tsx
index 6f11a5d48da..cdb33cf7f33 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/BulkApplyTemplateModal-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/BulkApplyTemplateModal-test.tsx
@@ -18,9 +18,8 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 jest.mock('../../../api/permissions', () => ({
-  applyTemplateToProject: jest.fn(),
-  bulkApplyTemplate: jest.fn(),
-  getPermissionTemplates: jest.fn()
+  bulkApplyTemplate: jest.fn(() => Promise.resolve()),
+  getPermissionTemplates: jest.fn(() => Promise.resolve({ permissionTemplates: [] }))
 }));
 
 import * as React from 'react';
@@ -28,18 +27,13 @@ import { mount, shallow } from 'enzyme';
 import BulkApplyTemplateModal, { Props } from '../BulkApplyTemplateModal';
 import { click } from '../../../helpers/testUtils';
 
-const applyTemplateToProject = require('../../../api/permissions')
-  .applyTemplateToProject as jest.Mock<any>;
 const bulkApplyTemplate = require('../../../api/permissions').bulkApplyTemplate as jest.Mock<any>;
 const getPermissionTemplates = require('../../../api/permissions')
   .getPermissionTemplates as jest.Mock<any>;
 
 beforeEach(() => {
-  applyTemplateToProject.mockImplementation(() => Promise.resolve()).mockClear();
-  bulkApplyTemplate.mockImplementation(() => Promise.resolve()).mockClear();
-  getPermissionTemplates
-    .mockImplementation(() => Promise.resolve({ permissionTemplates: [] }))
-    .mockClear();
+  bulkApplyTemplate.mockClear();
+  getPermissionTemplates.mockClear();
 });
 
 it('fetches permission templates on mount', () => {
@@ -61,9 +55,11 @@ it('bulk applies template to all results', async () => {
 
   click(wrapper.find('button'));
   expect(bulkApplyTemplate).toBeCalledWith({
+    analyzedBefore: '2017-04-08T00:00:00.000Z',
+    onProvisionedOnly: true,
     organization: 'org',
     q: 'bla',
-    qualifier: 'TRK',
+    qualifiers: 'TRK',
     templateId: 'foo'
   });
   expect(wrapper).toMatchSnapshot();
@@ -88,15 +84,9 @@ it('bulk applies template to selected results', async () => {
   click(wrapper.find('button'));
   expect(wrapper).toMatchSnapshot();
   await new Promise(setImmediate);
-  expect(applyTemplateToProject.mock.calls).toHaveLength(2);
-  expect(applyTemplateToProject).toBeCalledWith({
-    organization: 'org',
-    projectKey: 'proj1',
-    templateId: 'foo'
-  });
-  expect(applyTemplateToProject).toBeCalledWith({
+  expect(bulkApplyTemplate).toBeCalledWith({
     organization: 'org',
-    projectKey: 'proj2',
+    projects: 'proj1,proj2',
     templateId: 'foo'
   });
 
@@ -114,6 +104,7 @@ it('closes', () => {
 function render(props?: { [P in keyof Props]?: Props[P] }) {
   return (
     <BulkApplyTemplateModal
+      analyzedBefore="2017-04-08T00:00:00.000Z"
       onClose={jest.fn()}
       organization="org"
       provisioned={true}
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/DeleteModal-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/DeleteModal-test.tsx
index d24f30e9cdf..976be4403a8 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/DeleteModal-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/DeleteModal-test.tsx
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 jest.mock('../../../api/components', () => ({
-  deleteComponents: jest.fn(() => Promise.resolve())
+  bulkDeleteProjects: jest.fn(() => Promise.resolve())
 }));
 
 import * as React from 'react';
@@ -26,9 +26,13 @@ import { shallow } from 'enzyme';
 import DeleteModal, { Props } from '../DeleteModal';
 import { click } from '../../../helpers/testUtils';
 
-const deleteComponents = require('../../../api/components').deleteComponents as jest.Mock<any>;
+const bulkDeleteProjects = require('../../../api/components').bulkDeleteProjects as jest.Mock<any>;
 
-it('deletes projects', async () => {
+beforeEach(() => {
+  bulkDeleteProjects.mockClear();
+});
+
+it('deletes all projects', async () => {
   const onConfirm = jest.fn();
   const wrapper = shallowRender({ onConfirm });
   (wrapper.instance() as DeleteModal).mounted = true;
@@ -36,7 +40,27 @@ it('deletes projects', async () => {
 
   click(wrapper.find('button'));
   expect(wrapper).toMatchSnapshot();
-  expect(deleteComponents).toBeCalledWith(['foo', 'bar'], 'org');
+  expect(bulkDeleteProjects).toBeCalledWith({
+    analyzedBefore: '2017-04-08T00:00:00.000Z',
+    onProvisionedOnly: undefined,
+    organization: 'org',
+    q: 'bla',
+    qualifiers: 'TRK'
+  });
+
+  await new Promise(setImmediate);
+  expect(onConfirm).toBeCalled();
+});
+
+it('deletes selected projects', async () => {
+  const onConfirm = jest.fn();
+  const wrapper = shallowRender({ onConfirm, selection: ['proj1', 'proj2'] });
+  (wrapper.instance() as DeleteModal).mounted = true;
+  expect(wrapper).toMatchSnapshot();
+
+  click(wrapper.find('button'));
+  expect(wrapper).toMatchSnapshot();
+  expect(bulkDeleteProjects).toBeCalledWith({ organization: 'org', projects: 'proj1,proj2' });
 
   await new Promise(setImmediate);
   expect(onConfirm).toBeCalled();
@@ -52,11 +76,15 @@ it('closes', () => {
 function shallowRender(props?: { [P in keyof Props]?: Props[P] }) {
   return shallow(
     <DeleteModal
+      analyzedBefore="2017-04-08T00:00:00.000Z"
       onClose={jest.fn()}
       onConfirm={jest.fn()}
       organization="org"
+      provisioned={false}
       qualifier="TRK"
-      selection={['foo', 'bar']}
+      query="bla"
+      selection={[]}
+      total={17}
       {...props}
     />
   );
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx
index 726c6b186cb..64b7d42366b 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx
@@ -20,7 +20,7 @@
 import * as React from 'react';
 import { shallow } from 'enzyme';
 import Header, { Props } from '../Header';
-import { Visibility } from '../utils';
+import { Visibility } from '../../../app/types';
 import { click } from '../../../helpers/testUtils';
 
 const organization = { key: 'org', name: 'org', projectVisibility: 'public' };
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRow-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRow-test.tsx
index 982ef5ce35a..b1d052dbb86 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRow-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRow-test.tsx
@@ -20,7 +20,7 @@
 import * as React from 'react';
 import { shallow } from 'enzyme';
 import ProjectRow from '../ProjectRow';
-import { Visibility } from '../utils';
+import { Visibility } from '../../../app/types';
 import { click } from '../../../helpers/testUtils';
 
 const project = {
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Projects-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Projects-test.tsx
index b1f165cde7a..2cc0ec841ef 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Projects-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Projects-test.tsx
@@ -22,8 +22,8 @@ jest.mock('../../permissions/project/views/ApplyTemplateView');
 import * as React from 'react';
 import { shallow } from 'enzyme';
 import Projects from '../Projects';
-import { Visibility } from '../utils';
 import ApplyTemplateView from '../../permissions/project/views/ApplyTemplateView';
+import { Visibility } from '../../../app/types';
 
 const organization = { key: 'org', name: 'org', projectVisibility: 'public' };
 const projects = [
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx
index 66e0439de3f..e7ec8d71e94 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Search-test.tsx
@@ -118,7 +118,7 @@ function shallowRender(props?: { [P in keyof Props]?: Props[P] }) {
       ready={true}
       selection={[]}
       topLevelQualifiers={['TRK']}
-      total={0}
+      total={17}
       {...props}
     />
   );
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap
index bc3e39d7f64..4cadeebb4a0 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/BulkApplyTemplateModal-test.tsx.snap
@@ -67,8 +67,11 @@ exports[`bulk applies template to all results 2`] = `
     className="modal-body"
   >
     <div
-      className="alert alert-warning"
+      className="alert alert-warning modal-alert"
     >
+      <AlertWarnIcon
+        className="spacer-right"
+      />
       permission_templates.bulk_apply_permission_template.apply_to_all.17
     </div>
     <div
@@ -183,8 +186,11 @@ exports[`bulk applies template to all results 3`] = `
     className="modal-body"
   >
     <div
-      className="alert alert-warning"
+      className="alert alert-warning modal-alert"
     >
+      <AlertWarnIcon
+        className="spacer-right"
+      />
       permission_templates.bulk_apply_permission_template.apply_to_all.17
     </div>
     <div
@@ -388,8 +394,11 @@ exports[`bulk applies template to selected results 2`] = `
     className="modal-body"
   >
     <div
-      className="alert alert-info"
+      className="alert alert-warning modal-alert"
     >
+      <AlertWarnIcon
+        className="spacer-right"
+      />
       permission_templates.bulk_apply_permission_template.apply_to_selected.2
     </div>
     <div
@@ -504,8 +513,11 @@ exports[`bulk applies template to selected results 3`] = `
     className="modal-body"
   >
     <div
-      className="alert alert-info"
+      className="alert alert-warning modal-alert"
     >
+      <AlertWarnIcon
+        className="spacer-right"
+      />
       permission_templates.bulk_apply_permission_template.apply_to_selected.2
     </div>
     <div
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/DeleteModal-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/DeleteModal-test.tsx.snap
index e57788fbc92..12d6e222a77 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/DeleteModal-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/DeleteModal-test.tsx.snap
@@ -1,6 +1,6 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`deletes projects 1`] = `
+exports[`deletes all projects 1`] = `
 <Modal
   ariaHideApp={true}
   bodyOpenClassName="ReactModal__Body--open"
@@ -24,6 +24,14 @@ exports[`deletes projects 1`] = `
   <div
     className="modal-body"
   >
+    <div
+      className="alert alert-warning modal-alert"
+    >
+      <AlertWarnIcon
+        className="spacer-right"
+      />
+      projects_management.delete_all_warning.17
+    </div>
     qualifiers.delete_confirm.TRK
   </div>
   <footer
@@ -47,7 +55,7 @@ exports[`deletes projects 1`] = `
 </Modal>
 `;
 
-exports[`deletes projects 2`] = `
+exports[`deletes all projects 2`] = `
 <Modal
   ariaHideApp={true}
   bodyOpenClassName="ReactModal__Body--open"
@@ -71,6 +79,127 @@ exports[`deletes projects 2`] = `
   <div
     className="modal-body"
   >
+    <div
+      className="alert alert-warning modal-alert"
+    >
+      <AlertWarnIcon
+        className="spacer-right"
+      />
+      projects_management.delete_all_warning.17
+    </div>
+    qualifiers.delete_confirm.TRK
+  </div>
+  <footer
+    className="modal-foot"
+  >
+    <i
+      className="spinner spacer-right"
+    />
+    <button
+      className="button-red"
+      disabled={true}
+      onClick={[Function]}
+    >
+      delete
+    </button>
+    <a
+      className="js-modal-close"
+      href="#"
+      onClick={[Function]}
+    >
+      cancel
+    </a>
+  </footer>
+</Modal>
+`;
+
+exports[`deletes selected projects 1`] = `
+<Modal
+  ariaHideApp={true}
+  bodyOpenClassName="ReactModal__Body--open"
+  className="modal"
+  closeTimeoutMS={0}
+  contentLabel="qualifiers.delete.TRK"
+  isOpen={true}
+  onRequestClose={[Function]}
+  overlayClassName="modal-overlay"
+  parentSelector={[Function]}
+  portalClassName="ReactModalPortal"
+  shouldCloseOnOverlayClick={true}
+>
+  <header
+    className="modal-head"
+  >
+    <h2>
+      qualifiers.delete.TRK
+    </h2>
+  </header>
+  <div
+    className="modal-body"
+  >
+    <div
+      className="alert alert-warning modal-alert"
+    >
+      <AlertWarnIcon
+        className="spacer-right"
+      />
+      projects_management.delete_selected_warning.2
+    </div>
+    qualifiers.delete_confirm.TRK
+  </div>
+  <footer
+    className="modal-foot"
+  >
+    <button
+      className="button-red"
+      disabled={false}
+      onClick={[Function]}
+    >
+      delete
+    </button>
+    <a
+      className="js-modal-close"
+      href="#"
+      onClick={[Function]}
+    >
+      cancel
+    </a>
+  </footer>
+</Modal>
+`;
+
+exports[`deletes selected projects 2`] = `
+<Modal
+  ariaHideApp={true}
+  bodyOpenClassName="ReactModal__Body--open"
+  className="modal"
+  closeTimeoutMS={0}
+  contentLabel="qualifiers.delete.TRK"
+  isOpen={true}
+  onRequestClose={[Function]}
+  overlayClassName="modal-overlay"
+  parentSelector={[Function]}
+  portalClassName="ReactModalPortal"
+  shouldCloseOnOverlayClick={true}
+>
+  <header
+    className="modal-head"
+  >
+    <h2>
+      qualifiers.delete.TRK
+    </h2>
+  </header>
+  <div
+    className="modal-body"
+  >
+    <div
+      className="alert alert-warning modal-alert"
+    >
+      <AlertWarnIcon
+        className="spacer-right"
+      />
+      projects_management.delete_selected_warning.2
+    </div>
     qualifiers.delete_confirm.TRK
   </div>
   <footer
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/Search-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/Search-test.tsx.snap
index 89a31381713..9e0a31ce941 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/Search-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/Search-test.tsx.snap
@@ -8,7 +8,7 @@ exports[`bulk applies permission template 1`] = `
   qualifier="TRK"
   query=""
   selection={Array []}
-  total={0}
+  total={17}
 />
 `;
 
@@ -17,13 +17,16 @@ exports[`deletes projects 1`] = `
   onClose={[Function]}
   onConfirm={[Function]}
   organization="org"
+  provisioned={false}
   qualifier="TRK"
+  query=""
   selection={
     Array [
       "foo",
       "bar",
     ]
   }
+  total={17}
 />
 `;
 
@@ -176,13 +179,14 @@ exports[`render qualifiers filter 1`] = `
         >
           <button
             className="spacer-right js-bulk-apply-permission-template"
+            disabled={false}
             onClick={[Function]}
           >
             permission_templates.bulk_apply_permission_template
           </button>
           <button
             className="js-delete button-red"
-            disabled={true}
+            disabled={false}
             onClick={[Function]}
           >
             delete
@@ -277,13 +281,14 @@ exports[`renders 1`] = `
         >
           <button
             className="spacer-right js-bulk-apply-permission-template"
+            disabled={false}
             onClick={[Function]}
           >
             permission_templates.bulk_apply_permission_template
           </button>
           <button
             className="js-delete button-red"
-            disabled={true}
+            disabled={false}
             onClick={[Function]}
           >
             delete
-- 
cgit v1.2.3