summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2017-09-01 11:18:10 +0200
committerJanos Gyerik <janos.gyerik@sonarsource.com>2017-09-12 11:34:56 +0200
commitc01264d91bd4d05e405d4e93e2accd5fefb81136 (patch)
tree47c1769b2616ec7719d5e03b60703dc3969b9562 /server
parent53430982c1c63b764be3f25177cefaeed4db38df (diff)
downloadsonarqube-c01264d91bd4d05e405d4e93e2accd5fefb81136.tar.gz
sonarqube-c01264d91bd4d05e405d4e93e2accd5fefb81136.zip
SONAR-9702 rewrite some background tasks components
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.js)33
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.js)36
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/Task.js64
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx62
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.js)56
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js)37
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.tsx12
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.tsx11
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js)16
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/TaskId.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/TaskId.js)14
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js)16
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.js)19
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js2
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/ScannerContext-test.tsx60
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/Stacktrace-test.tsx60
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/Task-test.tsx40
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskActions-test.tsx65
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskComponent-test.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskComponent-test.js)5
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskDate-test.tsx29
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskDay-test.tsx32
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskExecutionTime-test.tsx27
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskId-test.tsx26
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskStatus-test.tsx30
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskType-test.tsx (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskType-test.js)7
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/ScannerContext-test.tsx.snap50
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/Stacktrace-test.tsx.snap57
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/Task-test.tsx.snap49
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskActions-test.tsx.snap272
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskComponent-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskComponent-test.js.snap)22
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskDate-test.tsx.snap45
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskDay-test.tsx.snap18
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskExecutionTime-test.tsx.snap15
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskId-test.tsx.snap13
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskStatus-test.tsx.snap55
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskType-test.tsx.snap (renamed from server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskType-test.js.snap)4
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/types.ts15
36 files changed, 1153 insertions, 221 deletions
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.js b/server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.tsx
index f5286bccfd8..c15d38eda16 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/ScannerContext.tsx
@@ -17,31 +17,24 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import Modal from 'react-modal';
import { getTask } from '../../../api/ce';
import { translate } from '../../../helpers/l10n';
+import { Task } from '../types';
-/*::
-type Props = {
- onClose: () => void,
- task: { componentName: string, id: string, type: string }
-};
-*/
+interface Props {
+ onClose: () => void;
+ task: Task;
+}
-/*::
-type State = {
- scannerContext: ?string
-};
-*/
+interface State {
+ scannerContext?: string;
+}
-export default class ScannerContext extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = {
- scannerContext: null
- };
+export default class ScannerContext extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = {};
componentDidMount() {
this.mounted = true;
@@ -60,7 +53,7 @@ export default class ScannerContext extends React.PureComponent {
});
}
- handleCloseClick = (event /*: Event */) => {
+ handleCloseClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
event.preventDefault();
this.props.onClose();
};
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.tsx
index 9f00597e2b7..1397e58ac6a 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Stacktrace.tsx
@@ -17,33 +17,25 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import Modal from 'react-modal';
import { getTask } from '../../../api/ce';
import { translate } from '../../../helpers/l10n';
+import { Task } from '../types';
-/*::
-type Props = {
- onClose: () => void,
- task: { componentName: string, errorMessage: string, id: string, type: string }
-};
-*/
+interface Props {
+ onClose: () => void;
+ task: Task;
+}
-/*::
-type State = {
- loading: boolean,
- stacktrace: ?string
-};
-*/
+interface State {
+ loading: boolean;
+ stacktrace?: string;
+}
-export default class Stacktrace extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = {
- loading: true,
- stacktrace: null
- };
+export default class Stacktrace extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = { loading: true };
componentDidMount() {
this.mounted = true;
@@ -62,7 +54,7 @@ export default class Stacktrace extends React.PureComponent {
});
}
- handleCloseClick = (event /*: Event */) => {
+ handleCloseClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
event.preventDefault();
this.props.onClose();
};
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js
deleted file mode 100644
index 3c93857dadb..00000000000
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info 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 PropTypes from 'prop-types';
-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 TaskActions from './TaskActions';
-
-export default class Task extends React.PureComponent {
- static propTypes = {
- task: PropTypes.object.isRequired,
- index: PropTypes.number.isRequired,
- tasks: PropTypes.array.isRequired,
- component: PropTypes.object,
- onCancelTask: PropTypes.func.isRequired,
- onFilterTask: PropTypes.func.isRequired
- };
-
- render() {
- const { task, index, tasks, component, onCancelTask, onFilterTask } = this.props;
-
- const prevTask = index > 0 ? tasks[index - 1] : null;
-
- return (
- <tr>
- <TaskStatus task={task} />
- <TaskComponent task={task} />
- <TaskId task={task} />
- <TaskDay task={task} prevTask={prevTask} />
- <TaskDate date={task.submittedAt} baseDate={task.submittedAt} />
- <TaskDate date={task.startedAt} baseDate={task.submittedAt} />
- <TaskDate date={task.executedAt} baseDate={task.submittedAt} />
- <TaskExecutionTime task={task} />
- <TaskActions
- component={component}
- task={task}
- onFilterTask={onFilterTask}
- onCancelTask={onCancelTask}
- />
- </tr>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx
new file mode 100644
index 00000000000..701fffd7ced
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx
@@ -0,0 +1,62 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info 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 * as React from 'react';
+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 TaskActions from './TaskActions';
+import { Task as ITask } from '../types';
+
+interface Props {
+ component?: {};
+ onCancelTask: (task: ITask) => void;
+ onFilterTask: (task: ITask) => void;
+ task: ITask;
+ previousTask?: ITask;
+}
+
+export default function Task(props: Props) {
+ const { task, component, onCancelTask, onFilterTask, previousTask } = props;
+
+ return (
+ <tr>
+ <TaskStatus status={task.status} />
+ <TaskComponent task={task} />
+ <TaskId id={task.id} />
+ <TaskDay
+ submittedAt={task.submittedAt}
+ prevSubmittedAt={previousTask && previousTask.submittedAt}
+ />
+ <TaskDate date={task.submittedAt} />
+ <TaskDate date={task.startedAt} baseDate={task.submittedAt} />
+ <TaskDate date={task.executedAt} baseDate={task.submittedAt} />
+ <TaskExecutionTime ms={task.executionTimeMs} />
+ <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.tsx
index 03b8be8455d..e75801aa4f8 100644
--- 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.tsx
@@ -17,48 +17,61 @@
* 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 * as React from 'react';
import ScannerContext from './ScannerContext';
import Stacktrace from './Stacktrace';
import { STATUSES } from './../constants';
import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { Task } from '../types';
-export default class TaskActions extends React.PureComponent {
- state = {
+interface Props {
+ component?: {};
+ onCancelTask: (task: Task) => void;
+ onFilterTask: (task: Task) => void;
+ task: Task;
+}
+
+interface State {
+ scannerContextOpen: boolean;
+ stacktraceOpen: boolean;
+}
+
+export default class TaskActions extends React.PureComponent<Props, State> {
+ state: State = {
scannerContextOpen: false,
stacktraceOpen: false
};
- handleFilterClick(e) {
- e.preventDefault();
+ handleFilterClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
this.props.onFilterTask(this.props.task);
- }
+ };
- handleCancelClick(e) {
- e.preventDefault();
+ handleCancelClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
this.props.onCancelTask(this.props.task);
- }
+ };
- handleShowScannerContextClick(e) {
- e.preventDefault();
+ handleShowScannerContextClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
this.setState({ scannerContextOpen: true });
- }
+ };
closeScannerContext = () => this.setState({ scannerContextOpen: false });
- handleShowStacktraceClick(e) {
- e.preventDefault();
+ handleShowStacktraceClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
this.setState({ stacktraceOpen: true });
- }
+ };
closeStacktrace = () => this.setState({ stacktraceOpen: false });
render() {
const { component, task } = this.props;
- const canFilter = component == null;
+ const canFilter = component == undefined;
const canCancel = task.status === STATUSES.PENDING;
- const canShowStacktrace = task.errorMessage != null;
+ const canShowStacktrace = task.errorMessage != undefined;
const hasActions = canFilter || canCancel || task.hasScannerContext || canShowStacktrace;
if (!hasActions) {
@@ -73,8 +86,9 @@ export default class TaskActions extends React.PureComponent {
</button>
<ul className="dropdown-menu dropdown-menu-right">
{canFilter &&
+ task.componentName &&
<li>
- <a className="js-task-filter" href="#" onClick={this.handleFilterClick.bind(this)}>
+ <a className="js-task-filter" href="#" onClick={this.handleFilterClick}>
<i className="spacer-right icon-filter icon-gray" />
{translateWithParameters(
'background_tasks.filter_by_component_x',
@@ -84,7 +98,7 @@ export default class TaskActions extends React.PureComponent {
</li>}
{canCancel &&
<li>
- <a className="js-task-cancel" href="#" onClick={this.handleCancelClick.bind(this)}>
+ <a className="js-task-cancel" href="#" onClick={this.handleCancelClick}>
<i className="spacer-right icon-delete" />
{translate('background_tasks.cancel_task')}
</a>
@@ -94,7 +108,7 @@ export default class TaskActions extends React.PureComponent {
<a
className="js-task-show-scanner-context"
href="#"
- onClick={this.handleShowScannerContextClick.bind(this)}>
+ onClick={this.handleShowScannerContextClick}>
<i className="spacer-right icon-list icon-gray" />
{translate('background_tasks.show_scanner_context')}
</a>
@@ -104,7 +118,7 @@ export default class TaskActions extends React.PureComponent {
<a
className="js-task-show-stacktrace"
href="#"
- onClick={this.handleShowStacktraceClick.bind(this)}>
+ onClick={this.handleShowStacktraceClick}>
<i className="spacer-right icon-list icon-red" />
{translate('background_tasks.show_stacktrace')}
</a>
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.tsx
index 1123a8de956..07bb92df540 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.tsx
@@ -17,47 +17,44 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/* @flow */
-import React from 'react';
+import * as React from 'react';
import { Link } from 'react-router';
import TaskType from './TaskType';
import QualifierIcon from '../../../components/shared/QualifierIcon';
import Organization from '../../../components/shared/Organization';
-/*:: import type { Task } from '../types'; */
+import { Task } from '../types';
-/*::
-type Props = {
- task: Task
-};
-*/
-
-export default function TaskComponent(props /*: Props */) {
- const { task } = props;
+interface Props {
+ task: Task;
+}
+export default function TaskComponent({ task }: Props) {
if (!task.componentKey) {
return (
<td>
<span className="note">
{task.id}
</span>
- <TaskType task={task} />
+ <TaskType incremental={task.incremental} type={task.type} />
</td>
);
}
return (
<td>
- <span className="little-spacer-right">
- <QualifierIcon qualifier={task.componentQualifier} />
- </span>
+ {task.componentQualifier &&
+ <span className="little-spacer-right">
+ <QualifierIcon qualifier={task.componentQualifier} />
+ </span>}
- {task.organization != null && <Organization organizationKey={task.organization} />}
+ {task.organization && <Organization organizationKey={task.organization} />}
- <Link to={{ pathname: '/dashboard', query: { id: task.componentKey } }}>
- {task.componentName}
- </Link>
+ {task.componentName &&
+ <Link to={{ pathname: '/dashboard', query: { id: task.componentKey } }}>
+ {task.componentName}
+ </Link>}
- <TaskType task={task} />
+ <TaskType incremental={task.incremental} type={task.type} />
</td>
);
}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.tsx
index 525d8bbc420..6cebb2f9af6 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.tsx
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.tsx
@@ -22,15 +22,15 @@ import TimeFormatter from '../../../components/intl/TimeFormatter';
import { differenceInDays, isValidDate, parseDate } from '../../../helpers/dates';
interface Props {
- date: string;
- baseDate: string;
+ date?: string;
+ baseDate?: string;
}
export default function TaskDate({ date, baseDate }: Props) {
- const parsedDate = parseDate(date);
- const parsedBaseDate = parseDate(baseDate);
+ const parsedDate = date && parseDate(date);
+ const parsedBaseDate = baseDate && parseDate(baseDate);
const diff =
- date && baseDate && isValidDate(parsedDate) && isValidDate(parsedBaseDate)
+ parsedDate && parsedBaseDate && isValidDate(parsedDate) && isValidDate(parsedBaseDate)
? differenceInDays(parsedDate, parsedBaseDate)
: 0;
@@ -38,7 +38,7 @@ export default function TaskDate({ date, baseDate }: Props) {
<td className="thin nowrap text-right">
{diff > 0 && <span className="text-warning little-spacer-right">{`(+${diff}d)`}</span>}
- {date && isValidDate(parsedDate) ? <TimeFormatter date={parsedDate} long={true} /> : ''}
+ {parsedDate && isValidDate(parsedDate) ? <TimeFormatter date={parsedDate} long={true} /> : ''}
</td>
);
}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.tsx
index c2d8911358b..46bb3879a6a 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.tsx
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.tsx
@@ -20,20 +20,19 @@
import * as React from 'react';
import DateFormatter from '../../../components/intl/DateFormatter';
import { isSameDay, parseDate } from '../../../helpers/dates';
-import { ITask } from '../types';
interface Props {
- task: ITask;
- prevTask?: ITask;
+ submittedAt: string;
+ prevSubmittedAt?: string;
}
-export default function TaskDay({ task, prevTask }: Props) {
+export default function TaskDay({ submittedAt, prevSubmittedAt }: Props) {
const shouldDisplay =
- !prevTask || !isSameDay(parseDate(task.submittedAt), parseDate(prevTask.submittedAt));
+ !prevSubmittedAt || !isSameDay(parseDate(submittedAt), parseDate(prevSubmittedAt));
return (
<td className="thin nowrap text-right">
- {shouldDisplay ? <DateFormatter date={task.submittedAt} long={true} /> : ''}
+ {shouldDisplay ? <DateFormatter date={submittedAt} long={true} /> : ''}
</td>
);
}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.tsx
index ee2eedb43e5..55baca3f360 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.tsx
@@ -17,17 +17,17 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/* @flow */
-import React from 'react';
+import * as React from 'react';
import { formatDuration } from '../utils';
-/*:: import type { Task } from '../types'; */
-const TaskExecutionTime = ({ task } /*: { task: Task } */) => {
+interface Props {
+ ms?: number;
+}
+
+export default function TaskExecutionTime({ ms }: Props) {
return (
<td className="thin nowrap text-right">
- {formatDuration(task.executionTimeMs)}
+ {ms && formatDuration(ms)}
</td>
);
-};
-
-export default TaskExecutionTime;
+}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskId.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskId.tsx
index b4e705d4f54..cd2215d40e6 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskId.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskId.tsx
@@ -17,16 +17,18 @@
* 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 * as React from 'react';
-const TaskId = ({ task }) => {
+interface Props {
+ id: string;
+}
+
+export default function TaskId({ id }: Props) {
return (
<td className="thin nowrap">
<div className="note">
- {task.id}
+ {id}
</div>
</td>
);
-};
-
-export default TaskId;
+}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.tsx
index b2ef518c558..87b2a7d7338 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.tsx
@@ -17,17 +17,19 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/* @flow */
-import React from 'react';
+import * as React from 'react';
import { STATUSES } from './../constants';
import PendingIcon from '../../../components/icons-components/PendingIcon';
import { translate } from '../../../helpers/l10n';
-/*:: import type { Task } from '../types'; */
-const TaskStatus = ({ task } /*: { task: Task } */) => {
+interface Props {
+ status: string;
+}
+
+export default function TaskStatus({ status }: Props) {
let inner;
- switch (task.status) {
+ switch (status) {
case STATUSES.PENDING:
inner = <PendingIcon />;
break;
@@ -64,6 +66,4 @@ const TaskStatus = ({ task } /*: { task: Task } */) => {
{inner}
</td>
);
-};
-
-export default TaskStatus;
+}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.tsx
index da9f6c36f41..5769bdb868a 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskType.tsx
@@ -17,20 +17,21 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/* @flow */
-import React from 'react';
-/*:: import type { Task } from '../types'; */
+import * as React from 'react';
import { translate } from '../../../helpers/l10n';
-const TaskType = ({ task } /*: { task: Task } */) => {
+interface Props {
+ incremental?: boolean;
+ type: string;
+}
+
+export default function TaskType({ incremental, type }: Props) {
return (
<span className="note nowrap spacer-left">
{'['}
- {translate('background_task.type', task.type)}
- {task.incremental && ` - ${translate('incremental')}`}
+ {translate('background_task.type', type)}
+ {incremental && ` - ${translate('incremental')}`}
{']'}
</span>
);
-};
-
-export default TaskType;
+}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js
index fef3f83eea7..ebbfb3f253e 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js
@@ -82,11 +82,11 @@ export default class Tasks extends React.PureComponent {
<Task
key={task.id}
task={task}
- index={index}
tasks={tasks}
component={component}
onCancelTask={onCancelTask}
onFilterTask={onFilterTask}
+ previousTask={index > 0 ? tasks[index - 1] : undefined}
/>
)}
</tbody>
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/ScannerContext-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/ScannerContext-test.tsx
new file mode 100644
index 00000000000..af7194151d6
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/ScannerContext-test.tsx
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+jest.mock('../../../../api/ce', () => ({
+ getTask: jest.fn()
+}));
+
+import * as React from 'react';
+import { mount, shallow } from 'enzyme';
+import ScannerContext from '../ScannerContext';
+import { click, doAsync } from '../../../../helpers/testUtils';
+
+const getTask = require('../../../../api/ce').getTask as jest.Mock<any>;
+
+const task = {
+ componentName: 'foo',
+ status: 'PENDING',
+ id: '123',
+ submittedAt: '2017-01-01',
+ type: 'REPORT'
+};
+
+it('renders', () => {
+ const wrapper = shallow(<ScannerContext onClose={jest.fn()} task={task} />);
+ wrapper.setState({ scannerContext: 'context' });
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('closes', () => {
+ const onClose = jest.fn();
+ const wrapper = shallow(<ScannerContext onClose={onClose} task={task} />);
+ click(wrapper.find('.js-modal-close'));
+ expect(onClose).toBeCalled();
+});
+
+it('fetches scanner context on mount', () => {
+ getTask.mockImplementation(() => Promise.resolve({ scannerContext: 'context' }));
+ const wrapper = mount(<ScannerContext onClose={jest.fn()} task={task} />);
+ expect(wrapper.state()).toEqual({});
+ expect(getTask).toBeCalledWith('123', ['scannerContext']);
+ return doAsync().then(() => {
+ expect(wrapper.state()).toEqual({ scannerContext: 'context' });
+ });
+});
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/Stacktrace-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/Stacktrace-test.tsx
new file mode 100644
index 00000000000..979af8df09e
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/Stacktrace-test.tsx
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+jest.mock('../../../../api/ce', () => ({
+ getTask: jest.fn()
+}));
+
+import * as React from 'react';
+import { mount, shallow } from 'enzyme';
+import Stacktrace from '../Stacktrace';
+import { click, doAsync } from '../../../../helpers/testUtils';
+
+const getTask = require('../../../../api/ce').getTask as jest.Mock<any>;
+
+const task = {
+ componentName: 'foo',
+ status: 'PENDING',
+ id: '123',
+ submittedAt: '2017-01-01',
+ type: 'REPORT'
+};
+
+it('renders', () => {
+ const wrapper = shallow(<Stacktrace onClose={jest.fn()} task={task} />);
+ wrapper.setState({ loading: false, stacktrace: 'stacktrace' });
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('closes', () => {
+ const onClose = jest.fn();
+ const wrapper = shallow(<Stacktrace onClose={onClose} task={task} />);
+ click(wrapper.find('.js-modal-close'));
+ expect(onClose).toBeCalled();
+});
+
+it('fetches scanner context on mount', () => {
+ getTask.mockImplementation(() => Promise.resolve({ errorStacktrace: 'stacktrace' }));
+ const wrapper = mount(<Stacktrace onClose={jest.fn()} task={task} />);
+ expect(wrapper.state()).toEqual({ loading: true });
+ expect(getTask).toBeCalledWith('123', ['stacktrace']);
+ return doAsync().then(() => {
+ expect(wrapper.state()).toEqual({ loading: false, stacktrace: 'stacktrace' });
+ });
+});
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/Task-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/Task-test.tsx
new file mode 100644
index 00000000000..a928e53ae78
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/Task-test.tsx
@@ -0,0 +1,40 @@
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import Task from '../Task';
+
+it('renders', () => {
+ expect(
+ shallow(
+ <Task
+ onCancelTask={jest.fn()}
+ onFilterTask={jest.fn()}
+ task={{
+ componentName: 'foo',
+ status: 'PENDING',
+ id: '123',
+ submittedAt: '2017-01-01',
+ type: 'REPORT'
+ }}
+ />
+ )
+ ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskActions-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskActions-test.tsx
new file mode 100644
index 00000000000..940fe3341da
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskActions-test.tsx
@@ -0,0 +1,65 @@
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import TaskActions from '../TaskActions';
+import { click } from '../../../../helpers/testUtils';
+
+it('renders', () => {
+ expect(shallowRender()).toMatchSnapshot();
+ expect(shallowRender({ status: 'SUCCESS' })).toMatchSnapshot();
+ expect(shallowRender({ hasScannerContext: true })).toMatchSnapshot();
+ expect(shallowRender({ errorMessage: 'error!' })).toMatchSnapshot();
+ expect(shallowRender({}, { component: { key: 'foo' } })).toMatchSnapshot();
+});
+
+it('shows stack trace', () => {
+ const wrapper = shallowRender({ errorMessage: 'error!' });
+ click(wrapper.find('.js-task-show-stacktrace'));
+ expect(wrapper.find('Stacktrace')).toMatchSnapshot();
+ wrapper.find('Stacktrace').prop<Function>('onClose')();
+ expect(wrapper.find('Stacktrace')).toMatchSnapshot();
+});
+
+it('shows scanner context', () => {
+ const wrapper = shallowRender({ hasScannerContext: true });
+ click(wrapper.find('.js-task-show-scanner-context'));
+ expect(wrapper.find('ScannerContext')).toMatchSnapshot();
+ wrapper.find('ScannerContext').prop<Function>('onClose')();
+ expect(wrapper.find('ScannerContext')).toMatchSnapshot();
+});
+
+function shallowRender(fields?: any, props?: any) {
+ return shallow(
+ <TaskActions
+ onCancelTask={jest.fn()}
+ onFilterTask={jest.fn()}
+ task={{
+ componentName: 'foo',
+ status: 'PENDING',
+ id: '123',
+ submittedAt: '2017-01-01',
+ type: 'REPORT',
+ ...fields
+ }}
+ {...props}
+ />
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskComponent-test.js b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskComponent-test.tsx
index b1c54c7f158..5f12acf8f48 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskComponent-test.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskComponent-test.tsx
@@ -17,8 +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.
*/
-/* @flow */
-import React from 'react';
+import * as React from 'react';
import { shallow } from 'enzyme';
import TaskComponent from '../TaskComponent';
@@ -29,6 +28,8 @@ it('renders', () => {
componentQualifier: 'TRK',
id: 'bar',
organization: 'org',
+ status: 'PENDING',
+ submittedAt: '2017-01-01',
type: 'REPORT'
};
expect(shallow(<TaskComponent task={task} />)).toMatchSnapshot();
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskDate-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskDate-test.tsx
new file mode 100644
index 00000000000..7e37c8dbfa6
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskDate-test.tsx
@@ -0,0 +1,29 @@
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import TaskDate from '../TaskDate';
+
+it('renders', () => {
+ expect(shallow(<TaskDate />)).toMatchSnapshot();
+ expect(shallow(<TaskDate date="2017-01-01" />)).toMatchSnapshot();
+ expect(shallow(<TaskDate date="2017-01-01" baseDate="2017-01-01" />)).toMatchSnapshot();
+ expect(shallow(<TaskDate date="2017-01-05" baseDate="2017-01-01" />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskDay-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskDay-test.tsx
new file mode 100644
index 00000000000..2413a5689a0
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskDay-test.tsx
@@ -0,0 +1,32 @@
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import TaskDay from '../TaskDay';
+
+it('renders', () => {
+ expect(
+ shallow(<TaskDay submittedAt="2017-01-02" prevSubmittedAt="2017-01-01" />)
+ ).toMatchSnapshot();
+
+ expect(
+ shallow(<TaskDay submittedAt="2017-01-01" prevSubmittedAt="2017-01-01" />)
+ ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskExecutionTime-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskExecutionTime-test.tsx
new file mode 100644
index 00000000000..77bd3e73e70
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskExecutionTime-test.tsx
@@ -0,0 +1,27 @@
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import TaskExecutionTime from '../TaskExecutionTime';
+
+it('renders', () => {
+ expect(shallow(<TaskExecutionTime />)).toMatchSnapshot();
+ expect(shallow(<TaskExecutionTime ms={12345} />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskId-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskId-test.tsx
new file mode 100644
index 00000000000..63cca20adb9
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskId-test.tsx
@@ -0,0 +1,26 @@
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import TaskId from '../TaskId';
+
+it('renders', () => {
+ expect(shallow(<TaskId id="173" />)).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskStatus-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskStatus-test.tsx
new file mode 100644
index 00000000000..e404108db57
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskStatus-test.tsx
@@ -0,0 +1,30 @@
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import TaskStatus from '../TaskStatus';
+
+it('renders', () => {
+ expect.assertions(5);
+ const statuses = ['PENDING', 'IN_PROGRESS', 'SUCCESS', 'FAILED', 'CANCELED'];
+ statuses.forEach(status => {
+ expect(shallow(<TaskStatus status={status} />)).toMatchSnapshot();
+ });
+});
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskType-test.js b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskType-test.tsx
index ed32df32523..1c0e961622f 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskType-test.js
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/TaskType-test.tsx
@@ -17,12 +17,11 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/* @flow */
-import React from 'react';
+import * as React from 'react';
import { shallow } from 'enzyme';
import TaskType from '../TaskType';
it('renders', () => {
- expect(shallow(<TaskType task={{ id: 'foo' }} />)).toMatchSnapshot();
- expect(shallow(<TaskType task={{ incremental: true, id: 'foo' }} />)).toMatchSnapshot();
+ expect(shallow(<TaskType type="REPORT" />)).toMatchSnapshot();
+ expect(shallow(<TaskType incremental={true} type="REPORT" />)).toMatchSnapshot();
});
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/ScannerContext-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/ScannerContext-test.tsx.snap
new file mode 100644
index 00000000000..8b3ce1ea4b6
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/ScannerContext-test.tsx.snap
@@ -0,0 +1,50 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<Modal
+ ariaHideApp={true}
+ bodyOpenClassName="ReactModal__Body--open"
+ className="modal modal-large"
+ closeTimeoutMS={0}
+ contentLabel="scanner context"
+ isOpen={true}
+ onRequestClose={[Function]}
+ overlayClassName="modal-overlay"
+ parentSelector={[Function]}
+ portalClassName="ReactModalPortal"
+ shouldCloseOnOverlayClick={true}
+>
+ <div
+ className="modal-head"
+ >
+ <h2>
+ background_tasks.scanner_context
+ :
+ foo
+ [
+ background_task.type.REPORT
+ ]
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <pre
+ className="js-task-scanner-context"
+ >
+ context
+ </pre>
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <a
+ className="js-modal-close"
+ href="#"
+ onClick={[Function]}
+ >
+ close
+ </a>
+ </div>
+</Modal>
+`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/Stacktrace-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/Stacktrace-test.tsx.snap
new file mode 100644
index 00000000000..d1fad07e61d
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/Stacktrace-test.tsx.snap
@@ -0,0 +1,57 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<Modal
+ ariaHideApp={true}
+ bodyOpenClassName="ReactModal__Body--open"
+ className="modal modal-large"
+ closeTimeoutMS={0}
+ contentLabel="stacktrace"
+ isOpen={true}
+ onRequestClose={[Function]}
+ overlayClassName="modal-overlay"
+ parentSelector={[Function]}
+ portalClassName="ReactModalPortal"
+ shouldCloseOnOverlayClick={true}
+>
+ <div
+ className="modal-head"
+ >
+ <h2>
+ background_tasks.error_stacktrace
+ :
+ foo
+ [
+ background_task.type.REPORT
+ ]
+ </h2>
+ </div>
+ <div
+ className="modal-body modal-container"
+ >
+ <div>
+ <h4
+ className="spacer-bottom"
+ >
+ background_tasks.error_stacktrace
+ </h4>
+ <pre
+ className="js-task-stacktrace"
+ >
+ stacktrace
+ </pre>
+ </div>
+ </div>
+ <div
+ className="modal-foot"
+ >
+ <a
+ className="js-modal-close"
+ href="#"
+ onClick={[Function]}
+ >
+ close
+ </a>
+ </div>
+</Modal>
+`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/Task-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/Task-test.tsx.snap
new file mode 100644
index 00000000000..0fab9afcace
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/Task-test.tsx.snap
@@ -0,0 +1,49 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<tr>
+ <TaskStatus
+ status="PENDING"
+ />
+ <TaskComponent
+ task={
+ Object {
+ "componentName": "foo",
+ "id": "123",
+ "status": "PENDING",
+ "submittedAt": "2017-01-01",
+ "type": "REPORT",
+ }
+ }
+ />
+ <TaskId
+ id="123"
+ />
+ <TaskDay
+ submittedAt="2017-01-01"
+ />
+ <TaskDate
+ date="2017-01-01"
+ />
+ <TaskDate
+ baseDate="2017-01-01"
+ />
+ <TaskDate
+ baseDate="2017-01-01"
+ />
+ <TaskExecutionTime />
+ <TaskActions
+ onCancelTask={[Function]}
+ onFilterTask={[Function]}
+ task={
+ Object {
+ "componentName": "foo",
+ "id": "123",
+ "status": "PENDING",
+ "submittedAt": "2017-01-01",
+ "type": "REPORT",
+ }
+ }
+ />
+</tr>
+`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskActions-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskActions-test.tsx.snap
new file mode 100644
index 00000000000..9de3ec891a0
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskActions-test.tsx.snap
@@ -0,0 +1,272 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<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"
+ >
+ <li>
+ <a
+ className="js-task-filter"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-filter icon-gray"
+ />
+ background_tasks.filter_by_component_x.foo
+ </a>
+ </li>
+ <li>
+ <a
+ className="js-task-cancel"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-delete"
+ />
+ background_tasks.cancel_task
+ </a>
+ </li>
+ </ul>
+ </div>
+</td>
+`;
+
+exports[`renders 2`] = `
+<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"
+ >
+ <li>
+ <a
+ className="js-task-filter"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-filter icon-gray"
+ />
+ background_tasks.filter_by_component_x.foo
+ </a>
+ </li>
+ </ul>
+ </div>
+</td>
+`;
+
+exports[`renders 3`] = `
+<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"
+ >
+ <li>
+ <a
+ className="js-task-filter"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-filter icon-gray"
+ />
+ background_tasks.filter_by_component_x.foo
+ </a>
+ </li>
+ <li>
+ <a
+ className="js-task-cancel"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-delete"
+ />
+ background_tasks.cancel_task
+ </a>
+ </li>
+ <li>
+ <a
+ className="js-task-show-scanner-context"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-list icon-gray"
+ />
+ background_tasks.show_scanner_context
+ </a>
+ </li>
+ </ul>
+ </div>
+</td>
+`;
+
+exports[`renders 4`] = `
+<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"
+ >
+ <li>
+ <a
+ className="js-task-filter"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-filter icon-gray"
+ />
+ background_tasks.filter_by_component_x.foo
+ </a>
+ </li>
+ <li>
+ <a
+ className="js-task-cancel"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-delete"
+ />
+ background_tasks.cancel_task
+ </a>
+ </li>
+ <li>
+ <a
+ className="js-task-show-stacktrace"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-list icon-red"
+ />
+ background_tasks.show_stacktrace
+ </a>
+ </li>
+ </ul>
+ </div>
+</td>
+`;
+
+exports[`renders 5`] = `
+<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"
+ >
+ <li>
+ <a
+ className="js-task-cancel"
+ href="#"
+ onClick={[Function]}
+ >
+ <i
+ className="spacer-right icon-delete"
+ />
+ background_tasks.cancel_task
+ </a>
+ </li>
+ </ul>
+ </div>
+</td>
+`;
+
+exports[`shows scanner context 1`] = `
+<ScannerContext
+ onClose={[Function]}
+ task={
+ Object {
+ "componentName": "foo",
+ "hasScannerContext": true,
+ "id": "123",
+ "status": "PENDING",
+ "submittedAt": "2017-01-01",
+ "type": "REPORT",
+ }
+ }
+/>
+`;
+
+exports[`shows scanner context 2`] = `undefined`;
+
+exports[`shows stack trace 1`] = `
+<Stacktrace
+ onClose={[Function]}
+ task={
+ Object {
+ "componentName": "foo",
+ "errorMessage": "error!",
+ "id": "123",
+ "status": "PENDING",
+ "submittedAt": "2017-01-01",
+ "type": "REPORT",
+ }
+ }
+/>
+`;
+
+exports[`shows stack trace 2`] = `undefined`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskComponent-test.js.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskComponent-test.tsx.snap
index 703c9f27eea..b8fec515315 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskComponent-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskComponent-test.tsx.snap
@@ -27,16 +27,7 @@ exports[`renders 1`] = `
foo
</Link>
<TaskType
- task={
- Object {
- "componentKey": "foo",
- "componentName": "foo",
- "componentQualifier": "TRK",
- "id": "bar",
- "organization": "org",
- "type": "REPORT",
- }
- }
+ type="REPORT"
/>
</td>
`;
@@ -49,16 +40,7 @@ exports[`renders 2`] = `
bar
</span>
<TaskType
- task={
- Object {
- "componentKey": undefined,
- "componentName": "foo",
- "componentQualifier": "TRK",
- "id": "bar",
- "organization": "org",
- "type": "REPORT",
- }
- }
+ type="REPORT"
/>
</td>
`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskDate-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskDate-test.tsx.snap
new file mode 100644
index 00000000000..2222e541e98
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskDate-test.tsx.snap
@@ -0,0 +1,45 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<td
+ className="thin nowrap text-right"
+/>
+`;
+
+exports[`renders 2`] = `
+<td
+ className="thin nowrap text-right"
+>
+ <TimeFormatter
+ date={2016-12-31T23:00:00.000Z}
+ long={true}
+ />
+</td>
+`;
+
+exports[`renders 3`] = `
+<td
+ className="thin nowrap text-right"
+>
+ <TimeFormatter
+ date={2016-12-31T23:00:00.000Z}
+ long={true}
+ />
+</td>
+`;
+
+exports[`renders 4`] = `
+<td
+ className="thin nowrap text-right"
+>
+ <span
+ className="text-warning little-spacer-right"
+ >
+ (+4d)
+ </span>
+ <TimeFormatter
+ date={2017-01-04T23:00:00.000Z}
+ long={true}
+ />
+</td>
+`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskDay-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskDay-test.tsx.snap
new file mode 100644
index 00000000000..7fccb036da2
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskDay-test.tsx.snap
@@ -0,0 +1,18 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<td
+ className="thin nowrap text-right"
+>
+ <DateFormatter
+ date="2017-01-02"
+ long={true}
+ />
+</td>
+`;
+
+exports[`renders 2`] = `
+<td
+ className="thin nowrap text-right"
+/>
+`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskExecutionTime-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskExecutionTime-test.tsx.snap
new file mode 100644
index 00000000000..536d0bff76b
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskExecutionTime-test.tsx.snap
@@ -0,0 +1,15 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<td
+ className="thin nowrap text-right"
+/>
+`;
+
+exports[`renders 2`] = `
+<td
+ className="thin nowrap text-right"
+>
+ 12s
+</td>
+`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskId-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskId-test.tsx.snap
new file mode 100644
index 00000000000..0fe227570dc
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskId-test.tsx.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<td
+ className="thin nowrap"
+>
+ <div
+ className="note"
+ >
+ 173
+ </div>
+</td>
+`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskStatus-test.tsx.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskStatus-test.tsx.snap
new file mode 100644
index 00000000000..02e803cd510
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskStatus-test.tsx.snap
@@ -0,0 +1,55 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders 1`] = `
+<td
+ className="thin spacer-right"
+>
+ <PendingIcon />
+</td>
+`;
+
+exports[`renders 2`] = `
+<td
+ className="thin spacer-right"
+>
+ <i
+ className="spinner"
+ />
+</td>
+`;
+
+exports[`renders 3`] = `
+<td
+ className="thin spacer-right"
+>
+ <span
+ className="badge badge-success"
+ >
+ background_task.status.SUCCESS
+ </span>
+</td>
+`;
+
+exports[`renders 4`] = `
+<td
+ className="thin spacer-right"
+>
+ <span
+ className="badge badge-danger"
+ >
+ background_task.status.FAILED
+ </span>
+</td>
+`;
+
+exports[`renders 5`] = `
+<td
+ className="thin spacer-right"
+>
+ <span
+ className="badge badge-muted"
+ >
+ background_task.status.CANCELED
+ </span>
+</td>
+`;
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskType-test.js.snap b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskType-test.tsx.snap
index 92b09f70f85..649856a4680 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskType-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/TaskType-test.tsx.snap
@@ -5,7 +5,7 @@ exports[`renders 1`] = `
className="note nowrap spacer-left"
>
[
- background_task.type.
+ background_task.type.REPORT
]
</span>
`;
@@ -15,7 +15,7 @@ exports[`renders 2`] = `
className="note nowrap spacer-left"
>
[
- background_task.type.
+ background_task.type.REPORT
- incremental
]
</span>
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/types.ts b/server/sonar-web/src/main/js/apps/background-tasks/types.ts
index c517f201399..b0e1003be03 100644
--- a/server/sonar-web/src/main/js/apps/background-tasks/types.ts
+++ b/server/sonar-web/src/main/js/apps/background-tasks/types.ts
@@ -18,8 +18,19 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-export interface ITask {
- incremental: boolean;
+export interface Task {
+ componentKey?: string;
+ componentName?: string;
+ componentQualifier?: string;
+ errorMessage?: string;
+ executedAt?: string;
+ executionTimeMs?: number;
+ hasScannerContext?: boolean;
+ incremental?: boolean;
id: string;
+ organization?: string;
+ startedAt?: string;
+ status: string;
submittedAt: string;
+ type: string;
}