]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7847 Add a way to see scanner context in the background page
authorStas Vilchik <vilchiks@gmail.com>
Mon, 22 Aug 2016 11:20:05 +0000 (13:20 +0200)
committerStas Vilchik <vilchiks@gmail.com>
Tue, 23 Aug 2016 09:42:54 +0000 (11:42 +0200)
it/it-tests/src/test/java/it/projectAdministration/BackgroundTasksTest.java
it/it-tests/src/test/java/pageobjects/BackgroundTaskItem.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/BackgroundTasksPage.java [new file with mode: 0644]
it/it-tests/src/test/java/pageobjects/Navigation.java
server/sonar-web/src/main/js/api/ce.js
server/sonar-web/src/main/js/apps/background-tasks/components/Task.js
server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.js [new file with mode: 0644]
server/sonar-web/src/main/js/apps/background-tasks/components/TaskCancelButton.js [deleted file]
server/sonar-web/src/main/js/apps/background-tasks/views/ScannerContextView.hbs [new file with mode: 0644]
server/sonar-web/src/main/js/apps/background-tasks/views/ScannerContextView.js [new file with mode: 0644]
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 9e895ff444a3f30b8fe7ec3a810765c383034e09..1a7f8795b055ad322c1f3fcbc7a880891e02ade9 100644 (file)
@@ -23,8 +23,12 @@ import com.sonar.orchestrator.Orchestrator;
 import com.sonar.orchestrator.build.SonarScanner;
 import com.sonar.orchestrator.selenium.Selenese;
 import it.Category1Suite;
+import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
+import pageobjects.BackgroundTaskItem;
+import pageobjects.BackgroundTasksPage;
+import pageobjects.Navigation;
 import util.selenium.SeleneseTest;
 
 import static util.ItUtils.projectDir;
@@ -34,18 +38,34 @@ public class BackgroundTasksTest {
   @ClassRule
   public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR;
 
-  @Test
-  public void should_not_display_failing_and_search_and_filter_elements_on_project_level_page() throws Exception {
+  @BeforeClass
+  public static void beforeClass() {
     executeBuild("test-project", "Test Project");
     executeBuild("test-project-2", "Another Test Project");
+  }
 
+  @Test
+  public void should_not_display_failing_and_search_and_filter_elements_on_project_level_page() throws Exception {
     Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("should_not_display_failing_and_search_and_filter_elements_on_project_level_page",
       "/projectAdministration/BackgroundTasksTest/should_not_display_failing_and_search_and_filter_elements_on_project_level_page.html"
     ).build();
     new SeleneseTest(selenese).runOn(orchestrator);
   }
 
-  private void executeBuild(String projectKey, String projectName) {
+  @Test
+  public void display_scanner_context() {
+    Navigation nav = Navigation.get(orchestrator);
+    nav.openHomepage().logIn().submitCredentials("admin", "admin");
+    BackgroundTasksPage page = nav.openBackgroundTasksPage();
+
+    BackgroundTaskItem task = page.getTasksAsItems().get(0);
+    task.openActions()
+      .openScannerContext()
+      .assertScannerContextContains("SonarQube plugins:")
+      .assertScannerContextContains("Global properties:");
+  }
+
+  private static void executeBuild(String projectKey, String projectName) {
     orchestrator.executeBuild(
       SonarScanner.create(projectDir("shared/xoo-sample"))
         .setProjectKey(projectKey)
diff --git a/it/it-tests/src/test/java/pageobjects/BackgroundTaskItem.java b/it/it-tests/src/test/java/pageobjects/BackgroundTaskItem.java
new file mode 100644 (file)
index 0000000..e749c9c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package pageobjects;
+
+import com.codeborne.selenide.SelenideElement;
+
+import static com.codeborne.selenide.Condition.hasText;
+import static com.codeborne.selenide.Condition.visible;
+import static com.codeborne.selenide.Selenide.$;
+
+public class BackgroundTaskItem {
+
+  private final SelenideElement elt;
+
+  public BackgroundTaskItem(SelenideElement elt) {
+    this.elt = elt;
+  }
+
+  public SelenideElement getComponent() {
+    return elt.$("td:nth-child(2)");
+  }
+
+  public BackgroundTaskItem openActions() {
+    elt.$(".js-task-action > .dropdown-toggle").click();
+    elt.$(".js-task-action > .dropdown-menu").shouldBe(visible);
+    return this;
+  }
+
+  public BackgroundTaskItem openScannerContext () {
+    elt.$(".js-task-show-scanner-context").click();
+    $(".js-task-scanner-context").shouldBe(visible);
+    return this;
+  }
+
+  public BackgroundTaskItem assertScannerContextContains(String text) {
+    $(".js-task-scanner-context").should(hasText(text));
+    return this;
+  }
+}
diff --git a/it/it-tests/src/test/java/pageobjects/BackgroundTasksPage.java b/it/it-tests/src/test/java/pageobjects/BackgroundTasksPage.java
new file mode 100644 (file)
index 0000000..2793eed
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package pageobjects;
+
+import com.codeborne.selenide.ElementsCollection;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.openqa.selenium.By;
+
+import static com.codeborne.selenide.Condition.exist;
+import static com.codeborne.selenide.Selenide.$;
+import static com.codeborne.selenide.Selenide.$$;
+
+public class BackgroundTasksPage {
+
+  public BackgroundTasksPage() {
+    $(By.cssSelector(".background-tasks")).should(exist);
+  }
+
+  public ElementsCollection getTasks() {
+    return $$(".background-tasks > tbody > tr");
+  }
+
+  public List<BackgroundTaskItem> getTasksAsItems() {
+    return getTasks()
+      .stream()
+      .map(BackgroundTaskItem::new)
+      .collect(Collectors.toList());
+  }
+}
index 3dbde027d3be3ed932657ce873b8b5ccde535d4c..ecd9cc6bc67bac36acfa930c080b410e50bfaef4 100644 (file)
@@ -80,6 +80,10 @@ public class Navigation extends ExternalResource {
     return open(url, ProjectKeyPage.class);
   }
 
+  public BackgroundTasksPage openBackgroundTasksPage() {
+    return open("/background_tasks", BackgroundTasksPage.class);
+  }
+
   public void open(String relativeUrl) {
     Selenide.open(relativeUrl);
   }
index 9eb33301774eace90d91a5c9cbfacac9b99433fe..3143a1ec9e48df4997e1ac93fa9e4e57416dcbb4 100644 (file)
@@ -39,9 +39,9 @@ export function getStatus (componentId) {
   return getJSON(url, data);
 }
 
-export function getTask (id) {
+export function getTask (id, additionalFields) {
   const url = '/api/ce/task';
-  return getJSON(url, { id }).then(r => r.task);
+  return getJSON(url, { id, additionalFields }).then(r => r.task);
 }
 
 export function cancelTask (id) {
index a2084647461a326f098393234a141c72f6b19ee0..00e41c9b63e87e7987f23f7352f5dce4573d9486 100644 (file)
  */
 import React from 'react';
 import shallowCompare from 'react-addons-shallow-compare';
-
 import TaskStatus from './TaskStatus';
 import TaskComponent from './TaskComponent';
 import TaskId from './TaskId';
 import TaskDay from './TaskDay';
 import TaskDate from './TaskDate';
 import TaskExecutionTime from './TaskExecutionTime';
-import TaskCancelButton from './TaskCancelButton';
-import { STATUSES } from './../constants';
+import TaskActions from './TaskActions';
 
 export default class Task extends React.Component {
   static propTypes = {
@@ -44,13 +42,8 @@ export default class Task extends React.Component {
     return shallowCompare(this, nextProps, nextState);
   }
 
-  handleFilterTask (task, e) {
-    e.preventDefault();
-    this.props.onFilterTask(task);
-  }
-
   render () {
-    const { task, index, tasks, component, types, onCancelTask } = this.props;
+    const { task, index, tasks, component, types, onCancelTask, onFilterTask } = this.props;
 
     const prevTask = index > 0 ? tasks[index - 1] : null;
 
@@ -64,20 +57,11 @@ export default class Task extends React.Component {
           <TaskDate date={task.startedAt} baseDate={task.submittedAt} format="LTS"/>
           <TaskDate date={task.executedAt} baseDate={task.submittedAt} format="LTS"/>
           <TaskExecutionTime task={task}/>
-
-          <td className="thin nowrap">
-            {!component && (
-                <a
-                    onClick={this.handleFilterTask.bind(this, task)}
-                    className="icon-filter icon-half-transparent spacer-left"
-                    href="#"
-                    title={`Show only "${task.componentName}" tasks`}
-                    data-toggle="tooltip"/>
-            )}
-            {task.status === STATUSES.PENDING && (
-                <TaskCancelButton task={task} onCancelTask={onCancelTask}/>
-            )}
-          </td>
+          <TaskActions
+              component={component}
+              task={task}
+              onFilterTask={onFilterTask}
+              onCancelTask={onCancelTask}/>
         </tr>
     );
   }
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.js
new file mode 100644 (file)
index 0000000..82be5d2
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import React from 'react';
+import shallowCompare from 'react-addons-shallow-compare';
+import ScannerContextView from '../views/ScannerContextView';
+import { STATUSES } from './../constants';
+import { translate } from '../../../helpers/l10n';
+
+export default class TaskActions extends React.Component {
+  shouldComponentUpdate (nextProps, nextState) {
+    return shallowCompare(this, nextProps, nextState);
+  }
+
+  handleFilterClick (e) {
+    e.preventDefault();
+    this.props.onFilterTask(this.props.task);
+  }
+
+  handleCancelClick (e) {
+    e.preventDefault();
+    this.props.onCancelTask(this.props.task);
+  }
+
+  handleShowScannerContextClick (e) {
+    e.preventDefault();
+    new ScannerContextView({ task: this.props.task }).render();
+  }
+
+  render () {
+    const { component, task } = this.props;
+
+    return (
+        <td className="thin nowrap">
+          <div className="dropdown js-task-action">
+            <button className="dropdown-toggle" data-toggle="dropdown">
+              <i className="icon-dropdown"/>
+            </button>
+            <ul className="dropdown-menu dropdown-menu-right">
+              {!component && (
+                  <li>
+                    <a className="js-task-filter" href="#" onClick={this.handleFilterClick.bind(this)}>
+                      <i className="spacer-right icon-filter icon-half-transparent"/>
+                      Show only {task.componentName} tasks
+                    </a>
+                  </li>
+              )}
+              {task.status === STATUSES.PENDING && (
+                  <li>
+                    <a className="js-task-cancel" href="#" onClick={this.handleCancelClick.bind(this)}>
+                      <i className="spacer-right icon-delete"/>
+                      {translate('background_tasks.cancel_task')}
+                    </a>
+                  </li>
+              )}
+              {task.hasScannerContext && (
+                  <li>
+                    <a className="js-task-show-scanner-context"
+                       href="#"
+                       onClick={this.handleShowScannerContextClick.bind(this)}>
+                      {translate('background_tasks.show_scanner_context')}
+                    </a>
+                  </li>
+              )}
+            </ul>
+          </div>
+        </td>
+    );
+  }
+}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskCancelButton.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskCancelButton.js
deleted file mode 100644 (file)
index 4255f9f..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import { translate } from '../../../helpers/l10n';
-
-const TaskCancelButton = ({ task, onCancelTask }) => {
-  function handleClick (e) {
-    e.preventDefault();
-    onCancelTask(task);
-  }
-
-  return (
-      <a
-          onClick={handleClick}
-          className="spacer-left icon-delete"
-          title={translate('background_tasks.cancel_task')}
-          data-toggle="tooltip"
-          href="#"/>
-  );
-};
-
-export default TaskCancelButton;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/views/ScannerContextView.hbs b/server/sonar-web/src/main/js/apps/background-tasks/views/ScannerContextView.hbs
new file mode 100644 (file)
index 0000000..d1de3da
--- /dev/null
@@ -0,0 +1,17 @@
+<form id="deactivate-user-form" autocomplete="off">
+  <div class="modal-head">
+    <h2>{{t 'background_tasks.scanner_context'}}: {{task.componentName}} [{{t 'background_task.type' task.type}}]</h2>
+  </div>
+  <div class="modal-body modal-container">
+    <div class="js-modal-messages"></div>
+
+    {{#if scannerContext}}
+      <pre class="js-task-scanner-context">{{scannerContext}}</pre>
+    {{else}}
+      <i class="spinner"></i>
+    {{/if}}
+  </div>
+  <div class="modal-foot">
+    <a href="#" class="js-modal-close">{{t 'close'}}</a>
+  </div>
+</form>
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/views/ScannerContextView.js b/server/sonar-web/src/main/js/apps/background-tasks/views/ScannerContextView.js
new file mode 100644 (file)
index 0000000..21da975
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import Modal from '../../../components/common/modals';
+import Template from './ScannerContextView.hbs';
+import { getTask } from '../../../api/ce';
+
+export default Modal.extend({
+  template: Template,
+  className: 'modal modal-large',
+
+  initialize () {
+    this.scannerContext = null;
+    this.loadScannerContext();
+  },
+
+  loadScannerContext() {
+    getTask(this.options.task.id, ['scannerContext']).then(task => {
+      this.scannerContext = task.scannerContext;
+      this.render();
+    });
+  },
+
+  serializeData() {
+    return {
+      task: this.options.task,
+      scannerContext: this.scannerContext
+    };
+  }
+});
+
index c8ffe407419bfccb9eae18683efd4916a73fce0b..d68b0ad98d7d33314d7a5a553a58b4eeb0f82dc3 100644 (file)
@@ -2974,6 +2974,8 @@ background_tasks.table.duration=Duration
 background_tasks.logs=Logs
 background_tasks.cancel_task=Cancel Task
 background_tasks.cancel_all_tasks=Cancel All Pending Tasks
+background_tasks.scanner_context=Scanner Context
+background_tasks.show_scanner_context=Show Scanner Context
 background_tasks.pending=pending
 background_tasks.failures=still failing
 background_tasks.in_progress_duration=Duration of the current task in progress.