foreman-tasks 12.1.1 → 12.2.2

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/app/views/foreman_tasks/api/tasks/show.json.rabl +1 -1
  4. data/foreman-tasks.gemspec +1 -3
  5. data/lib/foreman_tasks/version.rb +1 -1
  6. data/test/controllers/api/tasks_controller_test.rb +2 -2
  7. data/webpack/ForemanTasks/Components/TaskDetails/Components/Dependencies.js +69 -58
  8. data/webpack/ForemanTasks/Components/TaskDetails/Components/Errors.js +25 -5
  9. data/webpack/ForemanTasks/Components/TaskDetails/Components/Locks.js +170 -43
  10. data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +12 -4
  11. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +217 -201
  12. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskSkeleton.js +30 -34
  13. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Dependencies.test.js +90 -29
  14. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Errors.test.js +50 -27
  15. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Locks.test.js +256 -23
  16. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Raw.test.js +44 -22
  17. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +56 -24
  18. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +42 -22
  19. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +45 -54
  20. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +65 -25
  21. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +37 -13
  22. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +53 -8
  23. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.test.js +53 -7
  24. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.test.js +53 -7
  25. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.js +5 -4
  26. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.test.js +44 -14
  27. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +6 -5
  28. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.js +5 -4
  29. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.scss +3 -8
  30. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.test.js +75 -34
  31. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.test.js +57 -34
  32. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChartHelper.test.js +23 -9
  33. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.fixtures.js +14 -11
  34. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.js +19 -21
  35. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.test.js +63 -14
  36. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.js +9 -17
  37. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.test.js +49 -13
  38. metadata +2 -46
  39. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Errors.test.js.snap +0 -77
  40. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Locks.test.js.snap +0 -116
  41. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Raw.test.js.snap +0 -174
  42. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/RunningSteps.test.js.snap +0 -62
  43. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +0 -127
  44. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +0 -580
  45. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +0 -172
  46. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +0 -52
  47. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/__snapshots__/PausedTasksCard.test.js.snap +0 -38
  48. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/__snapshots__/RunningTasksCard.test.js.snap +0 -38
  49. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/__snapshots__/ScheduledTasksCard.test.js.snap +0 -97
  50. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/__snapshots__/TasksDonutCard.test.js.snap +0 -183
  51. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/__snapshots__/TasksDonutChart.test.js.snap +0 -302
  52. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/__snapshots__/TasksDonutChartHelper.test.js.snap +0 -21
  53. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/__snapshots__/TasksCardsGrid.test.js.snap +0 -210
  54. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/__snapshots__/TimeDropDown.test.js.snap +0 -85
@@ -1,22 +1,17 @@
1
1
  .tasks-donut-card {
2
2
  &.not-focused {
3
- .card-pf-title,
3
+ .pf-v5-c-card__title-text,
4
4
  .card-pf-body {
5
5
  opacity: 0.6;
6
6
  }
7
7
  }
8
- .card-pf-title {
8
+ .pf-v5-c-card__title-text {
9
9
  text-align: center;
10
- font-size: 180%;
11
10
  cursor: pointer;
12
11
  }
13
12
 
14
- .card-pf-body {
15
- padding-left: 15px;
16
- }
17
-
18
13
  &.selected-tasks-card {
19
- .card-pf-title {
14
+ .pf-v5-c-card__title-text {
20
15
  font-weight: bold;
21
16
  }
22
17
  }
@@ -1,4 +1,6 @@
1
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
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 {
4
6
  TASKS_DASHBOARD_AVAILABLE_TIMES,
@@ -6,38 +8,77 @@ import {
6
8
  } from '../../../../TasksDashboardConstants';
7
9
  import TasksDonutCard from './TasksDonutCard';
8
10
 
9
- const fixtures = {
10
- 'render with minimal props': {},
11
- 'render with props': {
12
- title: 'some title',
13
- time: TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK,
14
- wantedQueryState: 'some-state',
15
- className: 'some-classname',
11
+ jest.mock('../TasksDonutChart/TasksDonutChart', () => {
12
+ const React = require('react');
13
+ const Stub = props => (
14
+ <div
15
+ data-testid="tasks-donut-chart-stub"
16
+ data-focused-on={props.focusedOn}
17
+ data-time={props.time}
18
+ />
19
+ );
20
+ Stub.displayName = 'TasksDonutChart';
21
+ return Stub;
22
+ });
23
+
24
+ describe('TasksDonutCard', () => {
25
+ const baseProps = {
26
+ title: 'Card title',
27
+ wantedQueryState: 'running',
16
28
  data: { last: 3, older: 5 },
17
- },
18
- 'render with total selected': {
19
- wantedQueryState: 'some-state',
20
- query: { state: 'some-state' },
21
- },
22
- 'render with last selected': {
23
- wantedQueryState: 'some-state',
24
- time: TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK,
25
- query: {
26
- state: 'some-state',
27
- mode: TASKS_DASHBOARD_AVAILABLE_QUERY_MODES.LAST,
28
- time: TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK,
29
- },
30
- },
31
- 'render with older selected': {
32
- wantedQueryState: 'some-state',
33
29
  time: TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK,
34
- query: {
35
- state: 'some-state',
36
- mode: TASKS_DASHBOARD_AVAILABLE_QUERY_MODES.OLDER,
37
- time: TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK,
38
- },
39
- },
40
- };
41
-
42
- describe('TasksDonutCard', () =>
43
- testComponentSnapshotsWithFixtures(TasksDonutCard, fixtures));
30
+ };
31
+
32
+ it('renders title and wires chart stub with time and focus from query', () => {
33
+ render(
34
+ <TasksDonutCard
35
+ {...baseProps}
36
+ query={{ state: 'running', mode: TASKS_DASHBOARD_AVAILABLE_QUERY_MODES.LAST, time: TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK }}
37
+ />
38
+ );
39
+ expect(screen.getByText('Card title')).toBeInTheDocument();
40
+ const chart = screen.getByTestId('tasks-donut-chart-stub');
41
+ expect(chart).toHaveAttribute('data-focused-on', 'last');
42
+ });
43
+
44
+ it('clicking the title requests the wanted query state', () => {
45
+ const updateQuery = jest.fn();
46
+ render(<TasksDonutCard {...baseProps} updateQuery={updateQuery} />);
47
+ fireEvent.click(screen.getByText('Card title'));
48
+ expect(updateQuery).toHaveBeenCalledWith({ state: 'running' });
49
+ });
50
+
51
+ it('applies selected styling when this card state matches the query (total focus)', () => {
52
+ const { container } = render(
53
+ <TasksDonutCard {...baseProps} query={{ state: 'running' }} />
54
+ );
55
+ expect(container.querySelector('.tasks-donut-card')).toHaveClass(
56
+ 'selected-tasks-card'
57
+ );
58
+ });
59
+
60
+ it('applies not-focused when another dashboard state is active', () => {
61
+ const { container } = render(
62
+ <TasksDonutCard {...baseProps} query={{ state: 'paused' }} />
63
+ );
64
+ expect(container.querySelector('.tasks-donut-card')).toHaveClass(
65
+ 'not-focused'
66
+ );
67
+ });
68
+
69
+ it('merges className onto the card', () => {
70
+ const { container } = render(
71
+ <TasksDonutCard {...baseProps} className="extra-donut" />
72
+ );
73
+ expect(container.querySelector('.tasks-donut-card')).toHaveClass(
74
+ 'extra-donut'
75
+ );
76
+ });
77
+
78
+ it('does not mark the card selected or dimmed when the query is empty', () => {
79
+ const { container } = render(<TasksDonutCard {...baseProps} query={{}} />);
80
+ const card = container.querySelector('.tasks-donut-card');
81
+ expect(card).not.toHaveClass('selected-tasks-card');
82
+ expect(card).not.toHaveClass('not-focused');
83
+ });
84
+ });
@@ -1,40 +1,63 @@
1
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
2
4
 
3
- import { TASKS_DONUT_CHART_FOCUSED_ON_OPTIONS_ARRAY } from './TasksDonutChartConstants';
5
+ import { TASKS_DONUT_CHART_FOCUSED_ON_OPTIONS } from './TasksDonutChartConstants';
4
6
  import TasksDonutChart from './TasksDonutChart';
5
7
 
6
- jest.mock('./TasksDonutChartHelper', () => ({
7
- shouleBeSelected: focusedOn => focusedOn !== 'normal' && focusedOn !== 'none',
8
- getBaseChartConfig: jest.fn(() => ({ base: 'some-base-config' })),
9
- createChartData: jest.fn(() => ({
10
- columns: 'some-columns',
11
- names: 'some-names',
12
- onItemClick: jest.fn(),
13
- })),
14
- updateChartTitle: jest.fn(),
15
- }));
16
-
17
- const createRequiredProps = () => ({ last: 3, older: 5 });
18
-
19
- const fixtures = {
20
- 'render with minimal props': { ...createRequiredProps() },
21
- 'render with props': {
22
- ...createRequiredProps(),
23
- className: 'some-class',
24
- time: 'time-period',
25
- colorsPattern: ['color1', 'color2'],
26
- onTotalClick: jest.fn(),
27
- onLastClick: jest.fn(),
28
- onOlderClick: jest.fn(),
29
- },
30
- };
31
-
32
- TASKS_DONUT_CHART_FOCUSED_ON_OPTIONS_ARRAY.forEach(mode => {
33
- fixtures[`render with focused-on ${mode}`] = {
34
- ...createRequiredProps(),
35
- focusedOn: mode,
8
+ jest.mock('./TasksDonutChartHelper', () => {
9
+ const actual = jest.requireActual('./TasksDonutChartHelper');
10
+ return {
11
+ ...actual,
12
+ getBaseChartConfig: jest.fn(() => ({ mockBase: true })),
13
+ updateChartTitle: jest.fn(),
14
+ assignExtraChartEvents: jest.fn(),
15
+ clearExtraChartEvents: jest.fn(),
36
16
  };
37
17
  });
38
18
 
39
- describe('TasksDonutChart', () =>
40
- testComponentSnapshotsWithFixtures(TasksDonutChart, fixtures));
19
+ jest.mock('../../../../../../Components/Chart/Chart', () => {
20
+ const React = require('react');
21
+ return class MockChart extends React.Component {
22
+ componentDidMount() {
23
+ this.props.onChartCreate?.({
24
+ element: {},
25
+ focus: jest.fn(),
26
+ revert: jest.fn(),
27
+ });
28
+ }
29
+
30
+ render() {
31
+ return <div data-testid="chart-root" className={this.props.className} />;
32
+ }
33
+ };
34
+ });
35
+
36
+ const { NORMAL, TOTAL } = TASKS_DONUT_CHART_FOCUSED_ON_OPTIONS;
37
+
38
+ describe('TasksDonutChart', () => {
39
+ const required = { last: 3, older: 5 };
40
+
41
+ it('renders a chart with donut classes', () => {
42
+ render(<TasksDonutChart {...required} />);
43
+ const root = screen.getByTestId('chart-root');
44
+ expect(root).toHaveClass('donut-chart-pf', 'tasks-donut-chart');
45
+ });
46
+
47
+ it('adds selection class when focusedOn is not normal or none', () => {
48
+ render(<TasksDonutChart {...required} focusedOn={TOTAL} />);
49
+ expect(screen.getByTestId('chart-root')).toHaveClass('tasks-donut-selected');
50
+ });
51
+
52
+ it('does not add selection class in normal focus', () => {
53
+ render(<TasksDonutChart {...required} focusedOn={NORMAL} />);
54
+ expect(screen.getByTestId('chart-root')).not.toHaveClass(
55
+ 'tasks-donut-selected'
56
+ );
57
+ });
58
+
59
+ it('merges custom className', () => {
60
+ render(<TasksDonutChart {...required} className="custom-chart" />);
61
+ expect(screen.getByTestId('chart-root')).toHaveClass('custom-chart');
62
+ });
63
+ });
@@ -99,15 +99,29 @@ describe('TasksDonutChartHelper', () => {
99
99
  });
100
100
 
101
101
  it('should create chart-data', () => {
102
- expect(
103
- createChartData({
104
- last: 1,
105
- older: 3,
106
- time: '24h',
107
- onLastClick: jest.fn(),
108
- onOlderClick: jest.fn(),
109
- })
110
- ).toMatchSnapshot();
102
+ const onLastClick = jest.fn();
103
+ const onOlderClick = jest.fn();
104
+ const result = createChartData({
105
+ last: 1,
106
+ older: 3,
107
+ time: '24h',
108
+ onLastClick,
109
+ onOlderClick,
110
+ });
111
+
112
+ expect(result.columns).toEqual([
113
+ [LAST, 1],
114
+ [OLDER, 3],
115
+ ]);
116
+ expect(result.names[LAST]).toMatch(/1/);
117
+ expect(result.names[LAST]).toMatch(/24h/);
118
+ expect(result.names[OLDER]).toMatch(/3/);
119
+ expect(result.names[OLDER]).toMatch(/24h/);
120
+
121
+ result.onItemClick(LAST);
122
+ expect(onLastClick).toHaveBeenCalledTimes(1);
123
+ result.onItemClick(OLDER);
124
+ expect(onOlderClick).toHaveBeenCalledTimes(1);
111
125
  });
112
126
 
113
127
  it('should update chart-title', () => {
@@ -8,18 +8,21 @@ export const MOCKED_DATA = {
8
8
  older: 5,
9
9
  },
10
10
  stopped: {
11
- error: {
12
- total: 8,
13
- last: 1,
14
- },
15
- warning: {
16
- total: 20,
17
- last: 2,
18
- },
19
- success: {
20
- total: 25,
21
- last: 3,
11
+ results: {
12
+ error: {
13
+ total: 8,
14
+ last: 1,
15
+ },
16
+ warning: {
17
+ total: 20,
18
+ last: 2,
19
+ },
20
+ success: {
21
+ total: 25,
22
+ last: 3,
23
+ },
22
24
  },
25
+ other: 0,
23
26
  },
24
27
  scheduled: 1,
25
28
  };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { CardGrid } from 'patternfly-react';
3
+ import { Grid, GridItem } from '@patternfly/react-core';
4
4
  import { noop } from 'foremanReact/common/helpers';
5
5
 
6
6
  import RunningTasksCard from './Components/RunningTasksCard/RunningTasksCard';
@@ -15,26 +15,24 @@ import {
15
15
  import { timePropType, queryPropType } from '../../TasksDashboardPropTypes';
16
16
 
17
17
  const TasksCardsGrid = ({ time, query, data, updateQuery }) => (
18
- <CardGrid matchHeight fluid>
19
- <CardGrid.Row>
20
- {[
21
- [TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.RUNNING, RunningTasksCard],
22
- [TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.PAUSED, PausedTasksCard],
23
- [TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.STOPPED, StoppedTasksCard],
24
- [TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.SCHEDULED, ScheduledTasksCard],
25
- ].map(([key, Card]) => (
26
- <CardGrid.Col key={key}>
27
- <Card
28
- matchHeight
29
- data={data[key]}
30
- query={query}
31
- time={time}
32
- updateQuery={updateQuery}
33
- />
34
- </CardGrid.Col>
35
- ))}
36
- </CardGrid.Row>
37
- </CardGrid>
18
+ <Grid hasGutter className="tasks-cards-grid">
19
+ {[
20
+ [TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.RUNNING, RunningTasksCard],
21
+ [TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.PAUSED, PausedTasksCard],
22
+ [TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.STOPPED, StoppedTasksCard],
23
+ [TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.SCHEDULED, ScheduledTasksCard],
24
+ ].map(([key, Card]) => (
25
+ <GridItem key={key} sm={12} xl={6} xl2={3}>
26
+ <Card
27
+ isFullHeight
28
+ data={data[key]}
29
+ query={query}
30
+ time={time}
31
+ updateQuery={updateQuery}
32
+ />
33
+ </GridItem>
34
+ ))}
35
+ </Grid>
38
36
  );
39
37
 
40
38
  TasksCardsGrid.propTypes = {
@@ -1,5 +1,6 @@
1
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
-
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
3
4
  import {
4
5
  TASKS_DASHBOARD_AVAILABLE_TIMES,
5
6
  TASKS_DASHBOARD_AVAILABLE_QUERY_STATES,
@@ -7,15 +8,63 @@ import {
7
8
  import { MOCKED_DATA } from './TasksCardsGrid.fixtures';
8
9
  import TasksCardsGrid from './TasksCardsGrid';
9
10
 
10
- const fixtures = {
11
- 'render with minimal props': {},
12
- 'render with props': {
13
- time: TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK,
14
- query: { state: TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.RUNNING },
15
- data: MOCKED_DATA,
16
- updateQuery: jest.fn(),
17
- },
18
- };
19
-
20
- describe('TasksCardsGrid', () =>
21
- testComponentSnapshotsWithFixtures(TasksCardsGrid, fixtures));
11
+ jest.mock('./Components/TasksDonutChart/TasksDonutChart', () => {
12
+ const React = require('react');
13
+ const Stub = () => <div data-testid="tasks-donut-chart-stub" />;
14
+ Stub.displayName = 'TasksDonutChart';
15
+ return Stub;
16
+ });
17
+
18
+ describe('TasksCardsGrid layout', () => {
19
+ it('uses PatternFly Grid with gutter and four responsive columns', () => {
20
+ const { container } = render(<TasksCardsGrid />);
21
+ const grid = container.querySelector('.tasks-cards-grid');
22
+ expect(grid).toBeInTheDocument();
23
+
24
+ const items = Array.from(grid.children);
25
+ expect(items).toHaveLength(4);
26
+
27
+ items.forEach(item => {
28
+ expect(item).toHaveClass('pf-m-12-col-on-sm');
29
+ expect(item).toHaveClass('pf-m-6-col-on-xl');
30
+ expect(item).toHaveClass('pf-m-3-col-on-2xl');
31
+ });
32
+ });
33
+
34
+ it('renders each card full-height and reflects dashboard query and data', () => {
35
+ const updateQuery = jest.fn();
36
+ const query = { state: TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.RUNNING };
37
+ const { container } = render(
38
+ <TasksCardsGrid
39
+ query={query}
40
+ updateQuery={updateQuery}
41
+ time={TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK}
42
+ data={MOCKED_DATA}
43
+ />
44
+ );
45
+
46
+ const cardIds = [
47
+ 'running-tasks-card',
48
+ 'paused-tasks-card',
49
+ 'stopped-tasks-card',
50
+ 'scheduled-tasks-card',
51
+ ];
52
+
53
+ cardIds.forEach(id => {
54
+ const card = container.querySelector(`#${id}`);
55
+ expect(card).toBeInTheDocument();
56
+ expect(card).toHaveClass('pf-m-full-height');
57
+ });
58
+
59
+ expect(container.querySelector('#running-tasks-card')).toHaveClass(
60
+ 'selected-tasks-card'
61
+ );
62
+
63
+ const scheduledDataEl = container.querySelector(
64
+ '#scheduled-tasks-card .scheduled-data'
65
+ );
66
+ expect(scheduledDataEl?.textContent).toContain(
67
+ String(MOCKED_DATA[TASKS_DASHBOARD_AVAILABLE_QUERY_STATES.SCHEDULED])
68
+ );
69
+ });
70
+ });
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { DropdownButton, MenuItem } from 'patternfly-react';
3
+ import { SimpleDropdown } from '@patternfly/react-templates';
4
4
  import { noop } from 'foremanReact/common/helpers';
5
5
 
6
6
  import { TASKS_DASHBOARD_AVAILABLE_TIMES } from '../../../../TasksDashboardConstants';
@@ -9,29 +9,21 @@ import { getQueryValueText } from '../../../../TasksDashboardHelper';
9
9
  const TimeDropDown = ({ id, className, selectedTime, onChange, ...props }) => {
10
10
  const availableTimes = Object.keys(TASKS_DASHBOARD_AVAILABLE_TIMES).map(
11
11
  key => ({
12
- key,
13
- text: getQueryValueText(key),
14
- active: key === selectedTime,
12
+ value: key,
13
+ content: getQueryValueText(key),
14
+ onClick: () => key === selectedTime || onChange(key),
15
15
  })
16
16
  );
17
17
 
18
18
  return (
19
- <DropdownButton
19
+ <SimpleDropdown
20
20
  id={id}
21
21
  className={className}
22
- title={getQueryValueText(selectedTime)}
22
+ toggleVariant="plainText"
23
+ toggleContent={getQueryValueText(selectedTime)}
24
+ initialItems={availableTimes}
23
25
  {...props}
24
- >
25
- {availableTimes.map(({ key, text, active }) => (
26
- <MenuItem
27
- key={key}
28
- active={active}
29
- onClick={() => active || onChange(key)}
30
- >
31
- {text}
32
- </MenuItem>
33
- ))}
34
- </DropdownButton>
26
+ />
35
27
  );
36
28
  };
37
29
 
@@ -1,19 +1,55 @@
1
- import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
1
+ import React from 'react';
2
+ import { render, screen, fireEvent, waitFor, within } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
2
4
 
3
5
  import { TASKS_DASHBOARD_AVAILABLE_TIMES } from '../../../../TasksDashboardConstants';
4
6
  import TimeDropDown from './TimeDropDown';
5
7
 
6
- const createRequiredProps = () => ({ id: 'some-id' });
8
+ describe('TimeDropDown interactions', () => {
9
+ beforeEach(() => {
10
+ jest.clearAllMocks();
11
+ });
7
12
 
8
- const fixtures = {
9
- 'render with minimal props': { ...createRequiredProps() },
10
- 'render with all props': {
11
- ...createRequiredProps(),
12
- className: 'some-class',
13
- selectedTime: TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK,
14
- onChange: jest.fn(),
15
- },
16
- };
13
+ it('calls onChange when a different time option is selected', async () => {
14
+ const onChange = jest.fn();
17
15
 
18
- describe('TimeDropDown', () =>
19
- testComponentSnapshotsWithFixtures(TimeDropDown, fixtures));
16
+ render(
17
+ <TimeDropDown
18
+ id="time-dropdown"
19
+ selectedTime={TASKS_DASHBOARD_AVAILABLE_TIMES.H24}
20
+ onChange={onChange}
21
+ />
22
+ );
23
+
24
+ fireEvent.click(screen.getByRole('button', { name: /24h/i }));
25
+
26
+ const menu = await screen.findByRole('menu');
27
+ fireEvent.click(within(menu).getByRole('menuitem', { name: /^12h$/i }));
28
+
29
+ await waitFor(() => {
30
+ expect(onChange).toHaveBeenCalledTimes(1);
31
+ expect(onChange).toHaveBeenCalledWith(
32
+ TASKS_DASHBOARD_AVAILABLE_TIMES.H12
33
+ );
34
+ });
35
+ });
36
+
37
+ it('does not call onChange when the already-selected option is clicked', async () => {
38
+ const onChange = jest.fn();
39
+
40
+ render(
41
+ <TimeDropDown
42
+ id="time-dropdown"
43
+ selectedTime={TASKS_DASHBOARD_AVAILABLE_TIMES.WEEK}
44
+ onChange={onChange}
45
+ />
46
+ );
47
+
48
+ fireEvent.click(screen.getByRole('button', { name: /^week$/i }));
49
+
50
+ const menu = await screen.findByRole('menu');
51
+ fireEvent.click(within(menu).getByRole('menuitem', { name: /^week$/i }));
52
+
53
+ expect(onChange).not.toHaveBeenCalled();
54
+ });
55
+ });