foreman-tasks 12.1.1 → 12.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/app/views/foreman_tasks/api/tasks/show.json.rabl +1 -1
- data/foreman-tasks.gemspec +1 -3
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/controllers/api/tasks_controller_test.rb +2 -2
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Errors.js +25 -5
- data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +12 -4
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +217 -201
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskSkeleton.js +30 -34
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Dependencies.test.js +30 -30
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Errors.test.js +50 -27
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Raw.test.js +44 -22
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +56 -24
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +42 -22
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +45 -54
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +65 -25
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +37 -13
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +53 -8
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.test.js +53 -7
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.test.js +53 -7
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.js +5 -4
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.test.js +44 -14
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +6 -5
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.js +5 -4
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.scss +3 -8
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.test.js +75 -34
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.test.js +57 -34
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChartHelper.test.js +23 -9
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.fixtures.js +14 -11
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.js +19 -21
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.test.js +63 -14
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.js +9 -17
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.test.js +49 -13
- metadata +2 -45
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Errors.test.js.snap +0 -77
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Raw.test.js.snap +0 -174
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/RunningSteps.test.js.snap +0 -62
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +0 -127
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +0 -580
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +0 -172
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +0 -52
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/__snapshots__/PausedTasksCard.test.js.snap +0 -38
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/__snapshots__/RunningTasksCard.test.js.snap +0 -38
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/__snapshots__/ScheduledTasksCard.test.js.snap +0 -97
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/__snapshots__/TasksDonutCard.test.js.snap +0 -183
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/__snapshots__/TasksDonutChart.test.js.snap +0 -302
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/__snapshots__/TasksDonutChartHelper.test.js.snap +0 -21
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/__snapshots__/TasksCardsGrid.test.js.snap +0 -210
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/__snapshots__/TimeDropDown.test.js.snap +0 -85
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { render, screen, within } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
|
+
|
|
3
5
|
import Dependencies from '../Dependencies';
|
|
4
6
|
|
|
5
7
|
describe('Dependencies', () => {
|
|
6
|
-
it('
|
|
7
|
-
|
|
8
|
-
expect(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
it('renders info alert and None for both tables when there are no tasks', () => {
|
|
9
|
+
render(<Dependencies dependsOn={[]} blocks={[]} />);
|
|
10
|
+
expect(
|
|
11
|
+
screen.getByRole('heading', { name: /task dependencies/i })
|
|
12
|
+
).toBeInTheDocument();
|
|
13
|
+
const noneLabels = screen.getAllByText(/^none$/i);
|
|
14
|
+
expect(noneLabels.length).toBeGreaterThanOrEqual(2);
|
|
12
15
|
});
|
|
13
16
|
|
|
14
|
-
it('
|
|
17
|
+
it('renders depends_on tasks in the first table', () => {
|
|
15
18
|
const dependsOn = [
|
|
16
19
|
{
|
|
17
20
|
id: '123',
|
|
@@ -28,16 +31,15 @@ describe('Dependencies', () => {
|
|
|
28
31
|
result: 'pending',
|
|
29
32
|
},
|
|
30
33
|
];
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
expect(
|
|
34
|
-
expect(
|
|
35
|
-
expect(
|
|
36
|
-
expect(
|
|
37
|
-
expect(wrapper.text()).toContain('success');
|
|
34
|
+
render(<Dependencies dependsOn={dependsOn} blocks={[]} />);
|
|
35
|
+
const table = screen.getByRole('grid', { name: /depends on/i });
|
|
36
|
+
expect(within(table).getByText('Foo Bar Action')).toBeInTheDocument();
|
|
37
|
+
expect(within(table).getByText('Baz Qux Action')).toBeInTheDocument();
|
|
38
|
+
expect(within(table).getByText('stopped')).toBeInTheDocument();
|
|
39
|
+
expect(within(table).getByText('success')).toBeInTheDocument();
|
|
38
40
|
});
|
|
39
41
|
|
|
40
|
-
it('
|
|
42
|
+
it('renders blocks in the second table', () => {
|
|
41
43
|
const blocks = [
|
|
42
44
|
{
|
|
43
45
|
id: '789',
|
|
@@ -47,15 +49,14 @@ describe('Dependencies', () => {
|
|
|
47
49
|
result: 'warning',
|
|
48
50
|
},
|
|
49
51
|
];
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
expect(
|
|
53
|
-
expect(
|
|
54
|
-
expect(
|
|
55
|
-
expect(wrapper.text()).toContain('warning');
|
|
52
|
+
render(<Dependencies dependsOn={[]} blocks={blocks} />);
|
|
53
|
+
const table = screen.getByRole('grid', { name: /^blocks$/i });
|
|
54
|
+
expect(within(table).getByText('Test Action')).toBeInTheDocument();
|
|
55
|
+
expect(within(table).getByText('paused')).toBeInTheDocument();
|
|
56
|
+
expect(within(table).getByText('warning')).toBeInTheDocument();
|
|
56
57
|
});
|
|
57
58
|
|
|
58
|
-
it('
|
|
59
|
+
it('renders both tables when dependsOn and blocks are present', () => {
|
|
59
60
|
const dependsOn = [
|
|
60
61
|
{
|
|
61
62
|
id: '123',
|
|
@@ -81,12 +82,11 @@ describe('Dependencies', () => {
|
|
|
81
82
|
result: 'error',
|
|
82
83
|
},
|
|
83
84
|
];
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
expect(
|
|
88
|
-
expect(
|
|
89
|
-
expect(
|
|
90
|
-
expect(wrapper.text()).toContain('Baz Action');
|
|
85
|
+
render(<Dependencies dependsOn={dependsOn} blocks={blocks} />);
|
|
86
|
+
expect(screen.getByRole('grid', { name: /depends on/i })).toBeInTheDocument();
|
|
87
|
+
expect(screen.getByText('Foo Action')).toBeInTheDocument();
|
|
88
|
+
expect(screen.getByRole('grid', { name: /^blocks$/i })).toBeInTheDocument();
|
|
89
|
+
expect(screen.getByText('Bar Action')).toBeInTheDocument();
|
|
90
|
+
expect(screen.getByText('Baz Action')).toBeInTheDocument();
|
|
91
91
|
});
|
|
92
92
|
});
|
|
@@ -1,36 +1,59 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
2
4
|
|
|
3
5
|
import Errors from '../Errors';
|
|
4
6
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
failedSteps: [
|
|
13
|
-
{
|
|
14
|
-
error: {
|
|
15
|
-
exception_class: 'RuntimeError',
|
|
16
|
-
message:
|
|
17
|
-
'Action Actions::Katello::EventQueue::Monitor is already active',
|
|
18
|
-
backtrace: [
|
|
19
|
-
"/home/vagrant/.gem/ruby/gems/dynflow-1.2.3/lib/dynflow/action/singleton.rb:15:in `rescue in singleton_lock!'",
|
|
20
|
-
"/home/vagrant/.gem/ruby/gems/dynflow-1.2.3/lib/dynflow/action/singleton.rb:12:in `singleton_lock!'",
|
|
21
|
-
],
|
|
22
|
-
},
|
|
23
|
-
action_class: 'Actions::Katello::EventQueue::Monitor',
|
|
24
|
-
state: 'error',
|
|
25
|
-
input:
|
|
26
|
-
'{"locale"=>"en",\n "current_request_id"=>nil,\n "current_user_id"=>4,\n "current_organization_id"=>nil,\n "current_location_id"=>nil}\n',
|
|
27
|
-
output: '{}\n',
|
|
28
|
-
},
|
|
7
|
+
const failedStepFixture = {
|
|
8
|
+
error: {
|
|
9
|
+
exception_class: 'RuntimeError',
|
|
10
|
+
message: 'Action Actions::Katello::EventQueue::Monitor is already active',
|
|
11
|
+
backtrace: [
|
|
12
|
+
"/home/vagrant/.gem/ruby/gems/dynflow-1.2.3/lib/dynflow/action/singleton.rb:15:in `rescue in singleton_lock!'",
|
|
13
|
+
"/home/vagrant/.gem/ruby/gems/dynflow-1.2.3/lib/dynflow/action/singleton.rb:12:in `singleton_lock!'",
|
|
29
14
|
],
|
|
30
15
|
},
|
|
16
|
+
action_class: 'Actions::Katello::EventQueue::Monitor',
|
|
17
|
+
state: 'error',
|
|
18
|
+
input:
|
|
19
|
+
'{"locale"=>"en",\n "current_request_id"=>nil,\n "current_user_id"=>4,\n "current_organization_id"=>nil,\n "current_location_id"=>nil}\n',
|
|
20
|
+
output: '{}\n',
|
|
31
21
|
};
|
|
32
22
|
|
|
33
23
|
describe('Errors', () => {
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
it('renders warning when execution plan is missing', () => {
|
|
25
|
+
render(<Errors failedSteps={[]} executionPlan={null} />);
|
|
26
|
+
expect(
|
|
27
|
+
screen.getByText(/execution plan data not available/i)
|
|
28
|
+
).toBeInTheDocument();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('renders success state when there are no failed steps', () => {
|
|
32
|
+
render(<Errors failedSteps={[]} executionPlan={{ state: 'paused' }} />);
|
|
33
|
+
const noErrors = screen.getAllByText(/^no errors$/i);
|
|
34
|
+
expect(noErrors.length).toBeGreaterThanOrEqual(1);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('renders failed step details when failedSteps is non-empty', () => {
|
|
38
|
+
const { container } = render(
|
|
39
|
+
<Errors
|
|
40
|
+
executionPlan={{ state: 'paused', cancellable: false }}
|
|
41
|
+
failedSteps={[failedStepFixture]}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
const stepAlert = container.querySelector(
|
|
45
|
+
'[data-ouia-component-id="task-error-0"]'
|
|
46
|
+
);
|
|
47
|
+
expect(stepAlert).toBeInTheDocument();
|
|
48
|
+
expect(stepAlert).toHaveClass('pf-m-inline');
|
|
49
|
+
expect(
|
|
50
|
+
screen.getByText('Actions::Katello::EventQueue::Monitor')
|
|
51
|
+
).toBeInTheDocument();
|
|
52
|
+
expect(screen.getByText(/runtimeerror/i)).toBeInTheDocument();
|
|
53
|
+
expect(
|
|
54
|
+
screen.getByText(
|
|
55
|
+
/action actions::katello::eventqueue::monitor is already active/i
|
|
56
|
+
)
|
|
57
|
+
).toBeInTheDocument();
|
|
58
|
+
});
|
|
36
59
|
});
|
|
@@ -1,27 +1,49 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
2
4
|
|
|
3
5
|
import Raw from '../Raw';
|
|
4
6
|
|
|
5
|
-
const fixtures = {
|
|
6
|
-
'render without Props': {},
|
|
7
|
-
'render with Props': {
|
|
8
|
-
startedAt: '2019-06-17 16:04:09 +0300',
|
|
9
|
-
endedAt: '2019-06-17 16:05:09 +0300',
|
|
10
|
-
id: '6b0d6db2-e9ab-40da-94e5-b6842ac50bd0',
|
|
11
|
-
label: 'Actions::Katello::EventQueue::Monitor',
|
|
12
|
-
input: {
|
|
13
|
-
locale: 'en',
|
|
14
|
-
current_request_id: 1,
|
|
15
|
-
current_user_id: 4,
|
|
16
|
-
current_organization_id: 2,
|
|
17
|
-
current_location_id: 3,
|
|
18
|
-
},
|
|
19
|
-
output: {},
|
|
20
|
-
externalId: 'test',
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
|
|
24
7
|
describe('Raw', () => {
|
|
25
|
-
|
|
26
|
-
|
|
8
|
+
it('renders id and label when minimal props are given', () => {
|
|
9
|
+
render(
|
|
10
|
+
<Raw
|
|
11
|
+
id="x"
|
|
12
|
+
label=""
|
|
13
|
+
startedAt=""
|
|
14
|
+
endedAt=""
|
|
15
|
+
input={[]}
|
|
16
|
+
output={{}}
|
|
17
|
+
externalId=""
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
expect(screen.getByText('x')).toBeInTheDocument();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('renders raw task fields from props', () => {
|
|
24
|
+
render(
|
|
25
|
+
<Raw
|
|
26
|
+
startedAt="2019-06-17 16:04:09 +0300"
|
|
27
|
+
endedAt="2019-06-17 16:05:09 +0300"
|
|
28
|
+
id="6b0d6db2-e9ab-40da-94e5-b6842ac50bd0"
|
|
29
|
+
label="Actions::Katello::EventQueue::Monitor"
|
|
30
|
+
input={{
|
|
31
|
+
locale: 'en',
|
|
32
|
+
current_request_id: 1,
|
|
33
|
+
current_user_id: 4,
|
|
34
|
+
current_organization_id: 2,
|
|
35
|
+
current_location_id: 3,
|
|
36
|
+
}}
|
|
37
|
+
output={{}}
|
|
38
|
+
externalId="test"
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
expect(
|
|
42
|
+
screen.getByText('6b0d6db2-e9ab-40da-94e5-b6842ac50bd0')
|
|
43
|
+
).toBeInTheDocument();
|
|
44
|
+
expect(
|
|
45
|
+
screen.getByText('Actions::Katello::EventQueue::Monitor')
|
|
46
|
+
).toBeInTheDocument();
|
|
47
|
+
expect(screen.getByText(/"locale":/)).toBeInTheDocument();
|
|
48
|
+
});
|
|
27
49
|
});
|
|
@@ -1,36 +1,68 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
2
4
|
|
|
3
5
|
import RunningSteps from '../RunningSteps';
|
|
4
6
|
|
|
5
|
-
const
|
|
7
|
+
const baseProps = {
|
|
6
8
|
id: 'task-id1',
|
|
7
9
|
taskReload: true,
|
|
8
10
|
cancelStep: jest.fn(),
|
|
9
11
|
taskReloadStart: jest.fn(),
|
|
10
12
|
};
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
cancellable: false,
|
|
22
|
-
id: 1,
|
|
23
|
-
action_class: 'test',
|
|
24
|
-
state: 'paused',
|
|
25
|
-
input:
|
|
26
|
-
'{"locale"=>"en",\n "current_request_id"=>nil,\n "current_user_id"=>4,\n "current_organization_id"=>nil,\n "current_location_id"=>nil}\n',
|
|
27
|
-
output: '{}\n',
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
},
|
|
13
|
+
|
|
14
|
+
const sampleStep = {
|
|
15
|
+
cancellable: false,
|
|
16
|
+
id: 1,
|
|
17
|
+
action_class: 'test',
|
|
18
|
+
state: 'paused',
|
|
19
|
+
input:
|
|
20
|
+
'{"locale"=>"en",\n "current_request_id"=>nil,\n "current_user_id"=>4,\n "current_organization_id"=>nil,\n "current_location_id"=>nil}\n',
|
|
21
|
+
output: '{}\n',
|
|
31
22
|
};
|
|
32
23
|
|
|
33
24
|
describe('RunningSteps', () => {
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
it('renders empty message when there are no running steps', () => {
|
|
26
|
+
render(<RunningSteps {...baseProps} runningSteps={[]} />);
|
|
27
|
+
expect(screen.getByText(/no running steps/i)).toBeInTheDocument();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders running step fields and Cancel when step is cancellable', () => {
|
|
31
|
+
const cancelStep = jest.fn();
|
|
32
|
+
render(
|
|
33
|
+
<RunningSteps
|
|
34
|
+
{...baseProps}
|
|
35
|
+
cancelStep={cancelStep}
|
|
36
|
+
runningSteps={[
|
|
37
|
+
{
|
|
38
|
+
...sampleStep,
|
|
39
|
+
cancellable: true,
|
|
40
|
+
id: 99,
|
|
41
|
+
},
|
|
42
|
+
]}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
expect(
|
|
46
|
+
screen.getByRole('heading', { name: 'Warning alert: Running step 1' })
|
|
47
|
+
).toBeInTheDocument();
|
|
48
|
+
expect(screen.getByText('test')).toBeInTheDocument();
|
|
49
|
+
expect(screen.getByText('paused')).toBeInTheDocument();
|
|
50
|
+
fireEvent.click(screen.getByRole('button', { name: /cancel/i }));
|
|
51
|
+
expect(cancelStep).toHaveBeenCalledWith('task-id1', 99);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('uses sprintf so each running step title shows a 1-based step index', () => {
|
|
55
|
+
render(
|
|
56
|
+
<RunningSteps
|
|
57
|
+
{...baseProps}
|
|
58
|
+
runningSteps={[sampleStep, { ...sampleStep, id: 2, state: 'running' }]}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
expect(
|
|
62
|
+
screen.getByRole('heading', { name: 'Warning alert: Running step 1' })
|
|
63
|
+
).toBeInTheDocument();
|
|
64
|
+
expect(
|
|
65
|
+
screen.getByRole('heading', { name: 'Warning alert: Running step 2' })
|
|
66
|
+
).toBeInTheDocument();
|
|
67
|
+
});
|
|
36
68
|
});
|
|
@@ -1,26 +1,46 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
2
4
|
import { STATUS } from 'foremanReact/constants';
|
|
5
|
+
|
|
3
6
|
import Task from '../Task';
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
canEdit: true,
|
|
19
|
-
status: STATUS.RESOLVED,
|
|
20
|
-
taskProgressToggle: jest.fn(),
|
|
21
|
-
taskReloadStart: jest.fn(),
|
|
22
|
-
},
|
|
23
|
-
};
|
|
8
|
+
describe('Task', () => {
|
|
9
|
+
it('renders task controls from TaskButtons with minimal props', () => {
|
|
10
|
+
render(
|
|
11
|
+
<Task
|
|
12
|
+
id="test"
|
|
13
|
+
taskReloadStart={jest.fn()}
|
|
14
|
+
taskProgressToggle={jest.fn()}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
expect(
|
|
18
|
+
screen.getByRole('button', { name: /start auto-reloading/i })
|
|
19
|
+
).toBeInTheDocument();
|
|
20
|
+
});
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
it('renders parent task and sub tasks links when provided', () => {
|
|
23
|
+
render(
|
|
24
|
+
<Task
|
|
25
|
+
id="test"
|
|
26
|
+
state="paused"
|
|
27
|
+
hasSubTasks
|
|
28
|
+
dynflowEnableConsole
|
|
29
|
+
parentTask="parent-id"
|
|
30
|
+
taskReload
|
|
31
|
+
canEdit
|
|
32
|
+
status={STATUS.RESOLVED}
|
|
33
|
+
taskProgressToggle={jest.fn()}
|
|
34
|
+
taskReloadStart={jest.fn()}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
expect(screen.getByRole('link', { name: /parent task/i })).toHaveAttribute(
|
|
38
|
+
'href',
|
|
39
|
+
'/foreman_tasks/tasks/parent-id'
|
|
40
|
+
);
|
|
41
|
+
expect(screen.getByRole('link', { name: /sub tasks/i })).toHaveAttribute(
|
|
42
|
+
'href',
|
|
43
|
+
'/foreman_tasks/tasks/test/sub_tasks'
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -1,59 +1,50 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
jest.mock('foremanReact/components/common/dates/RelativeDateTime', () => {
|
|
6
|
+
const RelativeDateTime = ({ date, defaultValue }) => (
|
|
7
|
+
<span>{date || defaultValue}</span>
|
|
8
|
+
);
|
|
9
|
+
return RelativeDateTime;
|
|
10
|
+
});
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
'render without Props': { id: 'test' },
|
|
7
|
-
'render with Props': {
|
|
8
|
-
id: 'test',
|
|
9
|
-
startAt: '2019-06-17 16:04:09 +0300',
|
|
10
|
-
label: 'Actions::Katello::EventQueue::Monitor',
|
|
11
|
-
pending: true,
|
|
12
|
-
action: 'Monitor Event Queue',
|
|
13
|
-
username: 'admin',
|
|
14
|
-
startedAt: '2019-06-17 16:04:09 +0300',
|
|
15
|
-
endedAt: null,
|
|
16
|
-
state: 'paused',
|
|
17
|
-
result: 'error',
|
|
18
|
-
progress: 0.5,
|
|
19
|
-
input: {
|
|
20
|
-
locale: 'en',
|
|
21
|
-
current_request_id: null,
|
|
22
|
-
current_timezone: 'Asia/Jerusalem',
|
|
23
|
-
current_user_id: 4,
|
|
24
|
-
current_organization_id: null,
|
|
25
|
-
current_location_id: null,
|
|
26
|
-
},
|
|
27
|
-
output: {},
|
|
28
|
-
humanized: {
|
|
29
|
-
action: 'Monitor Event Queue',
|
|
30
|
-
input: '',
|
|
31
|
-
output: '',
|
|
32
|
-
errors: [
|
|
33
|
-
'Action Actions::Katello::EventQueue::Monitor is already active',
|
|
34
|
-
],
|
|
35
|
-
},
|
|
36
|
-
cli_example: null,
|
|
37
|
-
executionPlan: {
|
|
38
|
-
state: 'paused',
|
|
39
|
-
cancellable: false,
|
|
40
|
-
},
|
|
41
|
-
help:
|
|
42
|
-
"A paused task represents a process that has not finished properly. Any task in paused state can lead to potential inconsistency and needs to be resolved.\nThe recommended approach is to investigate the error messages below and in 'errors' tab, address the primary cause of the issue and resume the task.",
|
|
43
|
-
hasSubTasks: false,
|
|
44
|
-
locks: [
|
|
45
|
-
{
|
|
46
|
-
name: 'task_owner',
|
|
47
|
-
exclusive: false,
|
|
48
|
-
resource_type: 'User',
|
|
49
|
-
resource_id: 4,
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
username_path: '<a href="/users/4-admin/edit">admin</a>',
|
|
53
|
-
},
|
|
54
|
-
};
|
|
12
|
+
import TaskInfo from '../TaskInfo';
|
|
55
13
|
|
|
56
14
|
describe('TaskInfo', () => {
|
|
57
|
-
|
|
58
|
-
|
|
15
|
+
it('renders default metadata labels when given minimal props', () => {
|
|
16
|
+
render(<TaskInfo id="test" />);
|
|
17
|
+
expect(screen.getByText(/name:/i)).toBeInTheDocument();
|
|
18
|
+
expect(screen.getByText(/start at:/i)).toBeInTheDocument();
|
|
19
|
+
expect(screen.getByText(/result:/i)).toBeInTheDocument();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('renders task fields and troubleshooting when full props are provided', () => {
|
|
23
|
+
render(
|
|
24
|
+
<TaskInfo
|
|
25
|
+
id="test"
|
|
26
|
+
startAt="2019-06-17 16:04:09 +0300"
|
|
27
|
+
label="Actions::Katello::EventQueue::Monitor"
|
|
28
|
+
action="Monitor Event Queue"
|
|
29
|
+
username="admin"
|
|
30
|
+
startedAt="2019-06-17 16:04:09 +0300"
|
|
31
|
+
endedAt={null}
|
|
32
|
+
state="paused"
|
|
33
|
+
result="error"
|
|
34
|
+
progress={0.5}
|
|
35
|
+
help={
|
|
36
|
+
"A paused task represents a process that has not finished properly. Any task in paused state can lead to potential inconsistency and needs to be resolved.\nThe recommended approach is to investigate the error messages below and in 'errors' tab, address the primary cause of the issue and resume the task."
|
|
37
|
+
}
|
|
38
|
+
output={{}}
|
|
39
|
+
usernamePath=""
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
expect(screen.getByText('Monitor Event Queue')).toBeInTheDocument();
|
|
43
|
+
expect(screen.getByText(/troubleshooting/i)).toBeInTheDocument();
|
|
44
|
+
expect(
|
|
45
|
+
screen.getByText(/a paused task represents a process/i)
|
|
46
|
+
).toBeInTheDocument();
|
|
47
|
+
expect(screen.getByText(/^paused$/)).toBeInTheDocument();
|
|
48
|
+
expect(screen.getByText(/^error$/)).toBeInTheDocument();
|
|
49
|
+
});
|
|
59
50
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, { useEffect } from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import { Tab,
|
|
3
|
+
import { Tabs, Tab, TabTitleText } from '@patternfly/react-core';
|
|
4
4
|
import { translate as __, sprintf } from 'foremanReact/common/I18n';
|
|
5
5
|
import { STATUS } from 'foremanReact/constants';
|
|
6
6
|
import MessageBox from 'foremanReact/components/common/MessageBox';
|
|
@@ -31,6 +31,7 @@ const TaskDetails = ({
|
|
|
31
31
|
}) => {
|
|
32
32
|
const id = getTaskID();
|
|
33
33
|
const { taskReload, status, isLoading } = props;
|
|
34
|
+
const [activeTabKey, setActiveTabKey] = useState(1);
|
|
34
35
|
|
|
35
36
|
useEffect(() => {
|
|
36
37
|
taskReloadStart(id);
|
|
@@ -58,27 +59,42 @@ const TaskDetails = ({
|
|
|
58
59
|
}
|
|
59
60
|
const resumable = executionPlan ? executionPlan.state === 'paused' : false;
|
|
60
61
|
const cancellable = executionPlan ? executionPlan.cancellable : false;
|
|
62
|
+
const lockRecords = locks.concat(links);
|
|
63
|
+
|
|
64
|
+
const taskComponentProps = {
|
|
65
|
+
...props,
|
|
66
|
+
cancellable,
|
|
67
|
+
resumable,
|
|
68
|
+
id,
|
|
69
|
+
status,
|
|
70
|
+
taskProgressToggle,
|
|
71
|
+
taskReloadStart,
|
|
72
|
+
};
|
|
73
|
+
|
|
61
74
|
return (
|
|
62
75
|
<div className="task-details-react well">
|
|
63
|
-
<Tabs
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}}
|
|
78
|
-
/>
|
|
79
|
-
)}
|
|
76
|
+
<Tabs
|
|
77
|
+
id="task-details-tabs"
|
|
78
|
+
ouiaId="task-details-tabs"
|
|
79
|
+
activeKey={activeTabKey}
|
|
80
|
+
onSelect={(_event, tabKey) => setActiveTabKey(tabKey)}
|
|
81
|
+
mountOnEnter
|
|
82
|
+
>
|
|
83
|
+
<Tab
|
|
84
|
+
eventKey={1}
|
|
85
|
+
title={<TabTitleText>{__('Task')}</TabTitleText>}
|
|
86
|
+
aria-label={__('Task')}
|
|
87
|
+
ouiaId="task-details-tab-task"
|
|
88
|
+
>
|
|
89
|
+
{isLoading ? <TaskSkeleton /> : <Task {...taskComponentProps} />}
|
|
80
90
|
</Tab>
|
|
81
|
-
<Tab
|
|
91
|
+
<Tab
|
|
92
|
+
eventKey={2}
|
|
93
|
+
title={<TabTitleText>{__('Running Steps')}</TabTitleText>}
|
|
94
|
+
isDisabled={isLoading}
|
|
95
|
+
aria-label={__('Running Steps')}
|
|
96
|
+
ouiaId="task-details-tab-running-steps"
|
|
97
|
+
>
|
|
82
98
|
<RunningSteps
|
|
83
99
|
runningSteps={runningSteps}
|
|
84
100
|
id={id}
|
|
@@ -87,16 +103,40 @@ const TaskDetails = ({
|
|
|
87
103
|
taskReloadStart={taskReloadStart}
|
|
88
104
|
/>
|
|
89
105
|
</Tab>
|
|
90
|
-
<Tab
|
|
106
|
+
<Tab
|
|
107
|
+
eventKey={3}
|
|
108
|
+
title={<TabTitleText>{__('Errors')}</TabTitleText>}
|
|
109
|
+
isDisabled={isLoading}
|
|
110
|
+
aria-label={__('Errors')}
|
|
111
|
+
ouiaId="task-details-tab-errors"
|
|
112
|
+
>
|
|
91
113
|
<Errors executionPlan={executionPlan} failedSteps={failedSteps} />
|
|
92
114
|
</Tab>
|
|
93
|
-
<Tab
|
|
94
|
-
|
|
115
|
+
<Tab
|
|
116
|
+
eventKey={4}
|
|
117
|
+
title={<TabTitleText>{__('Locks')}</TabTitleText>}
|
|
118
|
+
isDisabled={isLoading}
|
|
119
|
+
aria-label={__('Locks')}
|
|
120
|
+
ouiaId="task-details-tab-locks"
|
|
121
|
+
>
|
|
122
|
+
<Locks locks={lockRecords} />
|
|
95
123
|
</Tab>
|
|
96
|
-
<Tab
|
|
124
|
+
<Tab
|
|
125
|
+
eventKey={5}
|
|
126
|
+
title={<TabTitleText>{__('Dependencies')}</TabTitleText>}
|
|
127
|
+
isDisabled={isLoading}
|
|
128
|
+
aria-label={__('Dependencies')}
|
|
129
|
+
ouiaId="task-details-tab-dependencies"
|
|
130
|
+
>
|
|
97
131
|
<Dependencies dependsOn={dependsOn} blocks={blocks} />
|
|
98
132
|
</Tab>
|
|
99
|
-
<Tab
|
|
133
|
+
<Tab
|
|
134
|
+
eventKey={6}
|
|
135
|
+
title={<TabTitleText>{__('Raw')}</TabTitleText>}
|
|
136
|
+
isDisabled={isLoading}
|
|
137
|
+
aria-label={__('Raw')}
|
|
138
|
+
ouiaId="task-details-tab-raw"
|
|
139
|
+
>
|
|
100
140
|
<Raw
|
|
101
141
|
id={id}
|
|
102
142
|
label={props.label}
|