Browse Source

SONAR-7846 Display error of a failing CE task in the background page

tags/6.1-RC1
Stas Vilchik 7 years ago
parent
commit
4c2d7de346

+ 30
- 6
it/it-tests/src/test/java/it/projectAdministration/BackgroundTasksTest.java View File

@@ -25,6 +25,7 @@ import com.sonar.orchestrator.selenium.Selenese;
import it.Category1Suite;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import pageobjects.BackgroundTaskItem;
import pageobjects.BackgroundTasksPage;
@@ -36,7 +37,10 @@ import static util.ItUtils.projectDir;
public class BackgroundTasksTest {

@ClassRule
public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR;
public static Orchestrator ORCHESTRATOR = Category1Suite.ORCHESTRATOR;

@Rule
public Navigation nav = Navigation.get(ORCHESTRATOR);

@BeforeClass
public static void beforeClass() {
@@ -49,13 +53,12 @@ public class BackgroundTasksTest {
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);
new SeleneseTest(selenese).runOn(ORCHESTRATOR);
}

@Test
public void display_scanner_context() {
Navigation nav = Navigation.get(orchestrator);
nav.openHomepage().logIn().submitCredentials("admin", "admin");
nav.logIn().submitCredentials("admin", "admin");
BackgroundTasksPage page = nav.openBackgroundTasksPage();

BackgroundTaskItem task = page.getTasksAsItems().get(0);
@@ -65,11 +68,32 @@ public class BackgroundTasksTest {
.assertScannerContextContains("Global properties:");
}

@Test
public void display_error_message_and_stacktrace() {
executeBuild("test-project", "Test Project", "2010-01-01");

nav.logIn().submitCredentials("admin", "admin");
BackgroundTasksPage page = nav.openBackgroundTasksPage();

BackgroundTaskItem task = page.getTasksAsItems().get(0);
task.openActions()
.openErrorStacktrace()
.assertErrorMessageContains("Date of analysis cannot be older than the date of the last known analysis")
.assertErrorStacktraceContains("Date of analysis cannot be older than the date of the last known analysis");
}

private static void executeBuild(String projectKey, String projectName) {
orchestrator.executeBuild(
ORCHESTRATOR.executeBuild(
SonarScanner.create(projectDir("shared/xoo-sample"))
.setProjectKey(projectKey)
.setProjectName(projectName));
}

private static void executeBuild(String projectKey, String projectName, String date) {
ORCHESTRATOR.executeBuild(
SonarScanner.create(projectDir("shared/xoo-sample"))
.setProjectKey(projectKey)
.setProjectName(projectName)
);
.setProperty("sonar.projectDate", date));
}
}

+ 16
- 0
it/it-tests/src/test/java/pageobjects/BackgroundTaskItem.java View File

@@ -53,4 +53,20 @@ public class BackgroundTaskItem {
$(".js-task-scanner-context").should(hasText(text));
return this;
}

public BackgroundTaskItem openErrorStacktrace () {
elt.$(".js-task-show-stacktrace").click();
$(".js-task-error-message").shouldBe(visible);
return this;
}

public BackgroundTaskItem assertErrorMessageContains(String text) {
$(".js-task-error-message").should(hasText(text));
return this;
}

public BackgroundTaskItem assertErrorStacktraceContains(String text) {
$(".js-task-stacktrace").should(hasText(text));
return this;
}
}

+ 31
- 5
server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.js View File

@@ -20,8 +20,9 @@
import React from 'react';
import shallowCompare from 'react-addons-shallow-compare';
import ScannerContextView from '../views/ScannerContextView';
import StacktraceView from '../views/StacktraceView';
import { STATUSES } from './../constants';
import { translate } from '../../../helpers/l10n';
import { translate, translateWithParameters } from '../../../helpers/l10n';

export default class TaskActions extends React.Component {
shouldComponentUpdate (nextProps, nextState) {
@@ -43,9 +44,23 @@ export default class TaskActions extends React.Component {
new ScannerContextView({ task: this.props.task }).render();
}

handleShowStacktraceClick (e) {
e.preventDefault();
new StacktraceView({ task: this.props.task }).render();
}

render () {
const { component, task } = this.props;

const canFilter = component == null;
const canCancel = task.status === STATUSES.PENDING;
const canShowStacktrace = task.errorMessage != null;
const hasActions = canFilter || canCancel || task.hasScannerContext || canShowStacktrace;

if (!hasActions) {
return <td>&nbsp;</td>;
}

return (
<td className="thin nowrap">
<div className="dropdown js-task-action">
@@ -53,15 +68,15 @@ export default class TaskActions extends React.Component {
<i className="icon-dropdown"/>
</button>
<ul className="dropdown-menu dropdown-menu-right">
{!component && (
{canFilter && (
<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
<i className="spacer-right icon-filter icon-gray"/>
{translateWithParameters('background_tasks.filter_by_component_x', task.componentName)}
</a>
</li>
)}
{task.status === STATUSES.PENDING && (
{canCancel && (
<li>
<a className="js-task-cancel" href="#" onClick={this.handleCancelClick.bind(this)}>
<i className="spacer-right icon-delete"/>
@@ -74,10 +89,21 @@ export default class TaskActions extends React.Component {
<a className="js-task-show-scanner-context"
href="#"
onClick={this.handleShowScannerContextClick.bind(this)}>
<i className="spacer-right icon-list icon-gray"/>
{translate('background_tasks.show_scanner_context')}
</a>
</li>
)}
{canShowStacktrace && (
<li>
<a className="js-task-show-stacktrace"
href="#"
onClick={this.handleShowStacktraceClick.bind(this)}>
<i className="spacer-right icon-list icon-red"/>
{translate('background_tasks.show_stacktrace')}
</a>
</li>
)}
</ul>
</div>
</td>

+ 23
- 0
server/sonar-web/src/main/js/apps/background-tasks/views/StacktraceView.hbs View File

@@ -0,0 +1,23 @@
<form id="deactivate-user-form" autocomplete="off">
<div class="modal-head">
<h2>{{t 'background_tasks.error_stacktrace'}}: {{task.componentName}} [{{t 'background_task.type' task.type}}]</h2>
</div>
<div class="modal-body modal-container">
<div class="js-modal-messages"></div>

{{#if loaded}}
<h4 class="spacer-bottom">{{t 'background_tasks.error_message'}}</h4>
<pre class="js-task-error-message">{{task.errorMessage}}</pre>

{{#if stacktrace}}
<h4 class="huge-spacer-top spacer-bottom">{{t 'background_tasks.error_stacktrace'}}</h4>
<pre class="js-task-stacktrace">{{stacktrace}}</pre>
{{/if}}
{{else}}
<i class="spinner"></i>
{{/if}}
</div>
<div class="modal-foot">
<a href="#" class="js-modal-close">{{t 'close'}}</a>
</div>
</form>

+ 50
- 0
server/sonar-web/src/main/js/apps/background-tasks/views/StacktraceView.js View File

@@ -0,0 +1,50 @@
/*
* 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 './StacktraceView.hbs';
import { getTask } from '../../../api/ce';

export default Modal.extend({
template: Template,
className: 'modal modal-large',

initialize () {
this.loaded = false;
this.stacktrace = null;
this.loadStacktrace();
},

loadStacktrace() {
getTask(this.options.task.id, ['stacktrace']).then(task => {
this.loaded = true;
this.stacktrace = task.errorStacktrace;
this.render();
});
},

serializeData() {
return {
task: this.options.task,
stacktrace: this.stacktrace,
loaded: this.loaded
};
}
});


+ 2
- 0
server/sonar-web/src/main/less/init/icons.less View File

@@ -62,6 +62,8 @@ a[class^="icon-"], a[class*=" icon-"] {


.icon-black { color: @baseFontColor; }
.icon-gray { color: #999; }
.icon-gray path { fill: #999; }
.icon-red { color: @red; }
.icon-green { color: @green; }
.icon-color-link { color: @darkBlue; }

+ 4
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -2972,10 +2972,14 @@ background_tasks.table.finished=Finished
background_tasks.table.duration=Duration

background_tasks.logs=Logs
background_tasks.filter_by_component_x=Filter by Component "{0}"
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.show_stacktrace=Show Error Stacktrace
background_tasks.error_message=Error Message
background_tasks.error_stacktrace=Error Stacktrace
background_tasks.pending=pending
background_tasks.failures=still failing
background_tasks.in_progress_duration=Duration of the current task in progress.

Loading…
Cancel
Save