Browse Source

SONAR-14128 display node name in background tasks for DCE

tags/9.9.0.65466
Aurelien Poscia 1 year ago
parent
commit
ba6ee4d669

+ 54
- 3
server/sonar-web/src/main/js/apps/background-tasks/__tests__/BackgroundTasks-it.tsx View File

@@ -22,7 +22,9 @@ import { screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { UserEvent } from '@testing-library/user-event/dist/types/setup/setup';
import ComputeEngineServiceMock from '../../../api/mocks/ComputeEngineServiceMock';
import { renderAppWithAdminContext } from '../../../helpers/testReactTestingUtils';
import { mockAppState } from '../../../helpers/testMocks';
import { renderAppWithAdminContext, RenderContext } from '../../../helpers/testReactTestingUtils';
import { EditionKey } from '../../../types/editions';
import { TaskStatuses, TaskTypes } from '../../../types/tasks';
import routes from '../routes';

@@ -141,6 +143,36 @@ describe('The Global background task page', () => {
expect(await screen.findAllByRole('row')).toHaveLength(2);
});

it.each([[EditionKey.community], [EditionKey.developer], [EditionKey.enterprise]])(
'Editions %s should not display node name',
async (editionKey: EditionKey) => {
givenOneTaskWithoutNodeNameAndOneWithNodeName();

renderGlobalBackgroundTasksApp({ appState: mockAppState({ edition: editionKey }) });

await waitFor(() => {
expect(screen.getAllByRole('row')).toHaveLength(3); // including header
});

expect(screen.queryByText('background_tasks.table.nodeName')).not.toBeInTheDocument();
expect(screen.queryByText('best_node_ever')).not.toBeInTheDocument();
}
);

it('Node name should be shown in DCE edition', async () => {
givenOneTaskWithoutNodeNameAndOneWithNodeName();

renderGlobalBackgroundTasksApp({ appState: mockAppState({ edition: EditionKey.datacenter }) });

await waitFor(async () => {
expect(await screen.findByText('background_tasks.table.nodeName')).toBeInTheDocument();
});

expect(
within(await screen.getAllByRole('row')[1]).getByText('best_node_ever')
).toBeInTheDocument();
});

it('should handle task pagination', async () => {
const user = userEvent.setup();

@@ -167,11 +199,30 @@ describe('The Global background task page', () => {
*/
});

function givenOneTaskWithoutNodeNameAndOneWithNodeName() {
computeEngineServiceMock.clearTasks();
computeEngineServiceMock.addTask({
executedAt: '2022-02-03T11:45:36+0200',
submittedAt: '2022-02-03T11:45:35+0200',
executionTimeMs: 167,
status: TaskStatuses.InProgress,
type: TaskTypes.IssueSync,
nodeName: 'best_node_ever',
});
computeEngineServiceMock.addTask({
executedAt: '2022-02-03T11:45:35+0200',
submittedAt: '2022-02-03T11:45:34+0200',
executionTimeMs: 167,
status: TaskStatuses.InProgress,
type: TaskTypes.IssueSync,
});
}

async function changeTaskFilter(user: UserEvent, fieldLabel: string, value: string) {
await user.click(screen.getByLabelText(fieldLabel, { selector: 'input' }));
await user.click(screen.getByText(value));
}

function renderGlobalBackgroundTasksApp() {
renderAppWithAdminContext('admin/background_tasks', routes, {});
function renderGlobalBackgroundTasksApp(context: RenderContext = {}) {
renderAppWithAdminContext('admin/background_tasks', routes, context);
}

+ 6
- 1
server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx View File

@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { AppState } from '../../../types/appstate';
import { EditionKey } from '../../../types/editions';
import { Task as ITask } from '../../../types/tasks';
import TaskActions from './TaskActions';
import TaskComponent from './TaskComponent';
@@ -25,6 +27,7 @@ import TaskDate from './TaskDate';
import TaskDay from './TaskDay';
import TaskExecutionTime from './TaskExecutionTime';
import TaskId from './TaskId';
import TaskNodeName from './TaskNodeName';
import TaskStatus from './TaskStatus';
import TaskSubmitter from './TaskSubmitter';

@@ -34,10 +37,11 @@ interface Props {
onFilterTask: (task: ITask) => void;
task: ITask;
previousTask?: ITask;
appState: AppState;
}

export default function Task(props: Props) {
const { task, component, onCancelTask, onFilterTask, previousTask } = props;
const { task, component, onCancelTask, onFilterTask, previousTask, appState } = props;

return (
<tr>
@@ -45,6 +49,7 @@ export default function Task(props: Props) {
<TaskComponent task={task} />
<TaskId id={task.id} />
<TaskSubmitter submitter={task.submitterLogin} />
{appState?.edition === EditionKey.datacenter && <TaskNodeName nodeName={task.nodeName} />}
<TaskDay
prevSubmittedAt={previousTask && previousTask.submittedAt}
submittedAt={task.submittedAt}

+ 32
- 0
server/sonar-web/src/main/js/apps/background-tasks/components/TaskNodeName.tsx View File

@@ -0,0 +1,32 @@
/*
* SonarQube
* Copyright (C) 2009-2022 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';

interface Props {
nodeName?: string;
}

export default function TaskNodeName({ nodeName }: Props) {
return (
<td className="thin">
<div className="note">{nodeName}</div>
</td>
);
}

+ 11
- 1
server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.tsx View File

@@ -19,7 +19,10 @@
*/
import classNames from 'classnames';
import * as React from 'react';
import withAppStateContext from '../../../app/components/app-state/withAppStateContext';
import { translate } from '../../../helpers/l10n';
import { AppState } from '../../../types/appstate';
import { EditionKey } from '../../../types/editions';
import { Task as ITask } from '../../../types/tasks';
import Task from './Task';

@@ -29,9 +32,10 @@ interface Props {
loading: boolean;
onCancelTask: (task: ITask) => Promise<void>;
onFilterTask: (task: ITask) => void;
appState: AppState;
}

export default function Tasks({ tasks, component, loading, onCancelTask, onFilterTask }: Props) {
export function Tasks({ tasks, component, loading, onCancelTask, onFilterTask, appState }: Props) {
const className = classNames('data zebra zebra-hover background-tasks', {
'new-loading': loading,
});
@@ -45,6 +49,9 @@ export default function Tasks({ tasks, component, loading, onCancelTask, onFilte
<th>{translate('background_tasks.table.task')}</th>
<th>{translate('background_tasks.table.id')}</th>
<th>{translate('background_tasks.table.submitter')}</th>
{appState?.edition === EditionKey.datacenter && (
<th>{translate('background_tasks.table.nodeName')}</th>
)}
<th>&nbsp;</th>
<th className="text-right">{translate('background_tasks.table.submitted')}</th>
<th className="text-right">{translate('background_tasks.table.started')}</th>
@@ -62,6 +69,7 @@ export default function Tasks({ tasks, component, loading, onCancelTask, onFilte
onFilterTask={onFilterTask}
previousTask={index > 0 ? tasks[index - 1] : undefined}
task={task}
appState={appState}
/>
))}
</tbody>
@@ -69,3 +77,5 @@ export default function Tasks({ tasks, component, loading, onCancelTask, onFilte
</div>
);
}

export default withAppStateContext(Tasks);

+ 1
- 0
server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/BackgroundTasksApp-test.tsx View File

@@ -33,6 +33,7 @@ jest.mock('../../../../api/ce', () => ({
{
id: 'AWkGcOThOiAPiP5AE-kM',
type: 'VIEW_REFRESH',
nodeName: 'node_CE_server_1',
componentId: 'AWBLZYhGOUrjxRA-u6ex',
componentKey: 'sonar-csharp',
componentName: 'SonarC#',

+ 2
- 1
server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/BackgroundTasksApp-test.tsx.snap View File

@@ -116,7 +116,7 @@ exports[`should render correctly: loaded 1`] = `
}
}
/>
<Tasks
<withAppStateContext(Tasks)
component={
{
"breadcrumbs": [],
@@ -156,6 +156,7 @@ exports[`should render correctly: loaded 1`] = `
"hasScannerContext": false,
"id": "AWkGcOThOiAPiP5AE-kM",
"logs": false,
"nodeName": "node_CE_server_1",
"startedAt": "2019-02-19T16:47:36+0100",
"status": "FAILED",
"submittedAt": "2019-02-19T16:47:35+0100",

+ 1
- 0
server/sonar-web/src/main/js/types/tasks.ts View File

@@ -39,6 +39,7 @@ export enum TaskStatuses {
export interface Task {
analysisId?: string;
branch?: string;
nodeName?: string;
componentKey?: string;
componentName?: string;
componentQualifier?: string;

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

@@ -3109,6 +3109,7 @@ background_tasks.table.submitter=Submitter
background_tasks.table.started=Started
background_tasks.table.finished=Finished
background_tasks.table.duration=Duration
background_tasks.table.nodeName=Node

background_tasks.filter_by_component_x=Filter by Component "{0}"
background_tasks.cancel_task=Cancel Task

Loading…
Cancel
Save