foreman-tasks 0.17.0 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/foreman_tasks/tasks.css.scss +3 -3
  3. data/app/controllers/foreman_tasks/api/tasks_controller.rb +50 -30
  4. data/app/controllers/foreman_tasks/tasks_controller.rb +8 -17
  5. data/app/models/foreman_tasks/task.rb +6 -4
  6. data/app/models/foreman_tasks/task/search.rb +0 -25
  7. data/app/models/setting/foreman_tasks.rb +19 -23
  8. data/app/views/foreman_tasks/api/tasks/show.json.rabl +1 -0
  9. data/app/views/foreman_tasks/layouts/react.html.erb +4 -1
  10. data/config/routes.rb +17 -3
  11. data/db/migrate/20180927120509_add_user_id.foreman_tasks.rb +4 -2
  12. data/lib/foreman_tasks/dynflow.rb +1 -1
  13. data/lib/foreman_tasks/dynflow/console_authorizer.rb +13 -2
  14. data/lib/foreman_tasks/engine.rb +1 -1
  15. data/lib/foreman_tasks/version.rb +1 -1
  16. data/package.json +1 -0
  17. data/test/controllers/tasks_controller_test.rb +35 -4
  18. data/test/unit/dynflow_console_authorizer_test.rb +1 -1
  19. data/test/unit/otp_manager_test.rb +24 -17
  20. data/test/unit/task_test.rb +48 -2
  21. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +29 -16
  22. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskHelper.js +3 -17
  23. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +18 -5
  24. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskHelper.test.js +1 -56
  25. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +24 -44
  26. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +22 -10
  27. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +6 -0
  28. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +1 -1
  29. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +2 -0
  30. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.js +6 -3
  31. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +2 -3
  32. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardHelper.js +10 -41
  33. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardReducer.js +0 -1
  34. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboard.test.js +1 -1
  35. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardReducer.test.js.snap +1 -6
  36. data/webpack/ForemanTasks/Components/TasksTable/SubTasksPage.js +30 -0
  37. data/webpack/ForemanTasks/Components/TasksTable/TaskTableFormmatters.js +53 -0
  38. data/webpack/ForemanTasks/Components/TasksTable/TasksIndexPage.js +10 -0
  39. data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +119 -0
  40. data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +67 -0
  41. data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +5 -0
  42. data/webpack/ForemanTasks/Components/TasksTable/TasksTableHelpers.js +64 -0
  43. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +63 -0
  44. data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.scss +29 -0
  45. data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +35 -0
  46. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +67 -0
  47. data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +39 -0
  48. data/webpack/ForemanTasks/Components/TasksTable/__tests__/SubTasksPage.test.js +20 -0
  49. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksIndexPage.test.js +12 -0
  50. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +42 -0
  51. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.test.js +9 -0
  52. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +48 -0
  53. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableHelpers.test.js +28 -0
  54. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTablePage.test.js +26 -0
  55. data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableReducer.test.js +37 -0
  56. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +49 -0
  57. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +42 -0
  58. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTable.test.js.snap +72 -0
  59. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +115 -0
  60. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +194 -0
  61. data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +32 -0
  62. data/webpack/ForemanTasks/Components/TasksTable/index.js +32 -0
  63. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +39 -0
  64. data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +45 -0
  65. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.js +23 -0
  66. data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.test.js +27 -0
  67. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.js +23 -0
  68. data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.test.js +27 -0
  69. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +28 -0
  70. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/CancelButton.test.js.snap +15 -0
  71. data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ResumeButton.test.js.snap +15 -0
  72. data/webpack/ForemanTasks/ForemanTasks.js +1 -17
  73. data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -0
  74. data/webpack/ForemanTasks/Routes/ForemanTasksRouter.test.js +5 -1
  75. data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.js +9 -3
  76. data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +1 -1
  77. data/webpack/ForemanTasks/Routes/ShowTask/__tests__/ShowTask.test.js +5 -1
  78. data/webpack/ForemanTasks/Routes/__snapshots__/ForemanTasksRoutes.test.js.snap +18 -2
  79. data/webpack/ForemanTasks/__snapshots__/ForemanTasks.test.js.snap +1 -54
  80. data/webpack/__mocks__/foremanReact/common/helpers.js +1 -0
  81. data/webpack/__mocks__/foremanReact/common/urlHelpers.js +1 -0
  82. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
  83. data/webpack/__mocks__/foremanReact/components/common/MessageBox.js +4 -0
  84. data/webpack/__mocks__/foremanReact/components/common/dates/LongDateTime.js +5 -0
  85. data/webpack/__mocks__/foremanReact/components/common/dates/RelativeDateTime.js +3 -0
  86. data/webpack/__mocks__/foremanReact/components/common/table.js +4 -0
  87. data/webpack/__mocks__/foremanReact/components/common/table/actionsHelpers/actionTypeCreator.js +7 -0
  88. data/webpack/__mocks__/foremanReact/constants.js +24 -0
  89. data/webpack/__mocks__/foremanReact/redux/actions/toasts.js +8 -0
  90. data/webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js +10 -0
  91. data/webpack/__mocks__/foremanReact/routes/common/PageLayout/components/ExportButton/ExportButton.js +5 -0
  92. data/webpack/index.js +5 -0
  93. metadata +49 -9
  94. data/app/views/foreman_tasks/tasks/index.html.erb +0 -46
  95. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskHelper.test.js.snap +0 -37
  96. data/webpack/ForemanTasks/Routes/IndexTasks/IndexTasks.js +0 -10
  97. data/webpack/ForemanTasks/Routes/IndexTasks/__tests__/IndexTasks.test.js +0 -10
  98. data/webpack/ForemanTasks/Routes/IndexTasks/__tests__/__snapshots__/IndexTasks.test.js.snap +0 -12
  99. data/webpack/ForemanTasks/Routes/IndexTasks/index.js +0 -1
  100. data/webpack/ForemanTasks/Routes/IndexTasks/indexTasks.scss +0 -0
@@ -20,7 +20,7 @@ module ForemanTasks
20
20
  dynflow_path += task.external_id.to_s if task
21
21
  dynflow_rack_env = { 'rack.session' => { 'user' => user.id, 'expires_at' => Time.zone.now + 100 },
22
22
  'PATH_INFO' => dynflow_path }.with_indifferent_access
23
- ForemanTasks::Dynflow::ConsoleAuthorizer.new(dynflow_rack_env).allow?
23
+ ForemanTasks::Dynflow::ConsoleAuthorizer.from_env(dynflow_rack_env).allow?
24
24
  end
25
25
 
26
26
  describe 'admin user' do
@@ -9,6 +9,10 @@ module ForemanTasksCore
9
9
  end
10
10
  end
11
11
 
12
+ def try_to_authenticate(username, password)
13
+ TestOtpManager.authenticate(OtpManager.tokenize(username, password))
14
+ end
15
+
12
16
  before do
13
17
  TestOtpManager.reset!
14
18
  end
@@ -18,7 +22,7 @@ module ForemanTasksCore
18
22
  let(:base64) { 'bXl1c2VyOjEyMzQ1Njc4OQ==' }
19
23
 
20
24
  it 'it doesn\'t raise when no passwords were generated yet' do
21
- assert_nil TestOtpManager.drop_otp('missing', 'password')
25
+ assert_not try_to_authenticate('missing', 'password')
22
26
  end
23
27
 
24
28
  it 'generates OTPs using SecureRandom.hex and converts them to strings' do
@@ -27,33 +31,36 @@ module ForemanTasksCore
27
31
  TestOtpManager.generate_otp(username).must_equal otp.to_s
28
32
  end
29
33
 
30
- it 'removes OTP only when correct username and password is provided' do
34
+ it 'provides #drop_otp method that removes OTP only when correct username and password is provided' do
31
35
  otp = TestOtpManager.generate_otp(username)
32
- assert_nil TestOtpManager.drop_otp('wrong_username', 'wrong_password')
33
- assert_nil TestOtpManager.drop_otp(username, 'wrong_password')
34
- assert_nil TestOtpManager.drop_otp('wrong_username', otp)
35
- TestOtpManager.drop_otp(username, otp).must_equal otp
36
+ assert_not TestOtpManager.drop_otp('wrong_username', 'wrong_password')
37
+ assert_not TestOtpManager.drop_otp(username, 'wrong_password')
38
+ assert_not TestOtpManager.drop_otp('wrong_username', otp)
39
+ assert TestOtpManager.drop_otp(username, otp)
36
40
  end
37
41
 
38
- it 'parses the hash correctly' do
39
- SecureRandom.stubs(:hex).returns(password)
40
- TestOtpManager.expects(:drop_otp).with(username, password.to_s)
41
- TestOtpManager.authenticate(base64)
42
+ it 'authenticate removes OTP only when correct username and password is provided' do
43
+ otp = TestOtpManager.generate_otp(username)
44
+ assert_not try_to_authenticate('wrong_username', 'wrong_password')
45
+ assert_not try_to_authenticate(username, 'wrong_password')
46
+ assert_not try_to_authenticate(username, 'wrong_password')
47
+ assert_not try_to_authenticate('wrong_username', otp)
48
+ assert try_to_authenticate(username, otp)
42
49
  end
43
50
 
44
51
  it 'authenticates correctly' do
45
52
  SecureRandom.stubs(:hex).returns(password)
46
- generated = TestOtpManager.generate_otp(username)
53
+ TestOtpManager.generate_otp(username)
47
54
 
48
- TestOtpManager.authenticate(base64).must_equal generated
55
+ assert TestOtpManager.authenticate(base64)
49
56
  end
50
57
 
51
58
  it 'OTPs can be used only once' do
52
59
  SecureRandom.stubs(:hex).returns(password)
53
- generated = TestOtpManager.generate_otp(username)
60
+ TestOtpManager.generate_otp(username)
54
61
 
55
- TestOtpManager.authenticate(base64).must_equal generated
56
- assert_nil TestOtpManager.authenticate(base64)
62
+ assert TestOtpManager.authenticate(base64)
63
+ assert_not TestOtpManager.authenticate(base64)
57
64
  end
58
65
 
59
66
  it 'creates token from username and password correctly' do
@@ -63,8 +70,8 @@ module ForemanTasksCore
63
70
  it 'overwrites old OTP when generating a new one for the same username' do
64
71
  old = TestOtpManager.generate_otp(username)
65
72
  new = TestOtpManager.generate_otp(username)
66
- assert_nil TestOtpManager.drop_otp(username, old)
67
- TestOtpManager.drop_otp(username, new).must_equal new
73
+ assert_not try_to_authenticate(username, old)
74
+ assert try_to_authenticate(username, new)
68
75
  end
69
76
  end
70
77
  end
@@ -30,20 +30,66 @@ class TasksTest < ActiveSupport::TestCase
30
30
  assert_equal [@task_one], ForemanTasks::Task.search_for("user = #{@user_one.login}")
31
31
  end
32
32
 
33
+ test 'cannot search by arbitrary key' do
34
+ proc { ForemanTasks::Task.search_for('user.my_key ~ 5') }.must_raise(ScopedSearch::QueryNotSupported)
35
+ proc { ForemanTasks::Task.search_for('user. = 5') }.must_raise(ScopedSearch::QueryNotSupported)
36
+ end
37
+
38
+ test 'can search the tasks by negated user' do
39
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user != #{@user_two.login}")
40
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user <> #{@user_two.login}")
41
+ SecureRandom.stubs(:hex).returns('abc')
42
+ assert_equal ForemanTasks::Task.search_for("user != #{@user_two.login}").to_sql,
43
+ ForemanTasks::Task.search_for("user <> #{@user_two.login}").to_sql
44
+ end
45
+
33
46
  test 'can search the tasks by user\'s id' do
34
47
  assert_equal [@task_one], ForemanTasks::Task.search_for("user.id = #{@user_one.id}")
35
48
  assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id = #{@user_one.id}")
49
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user.id != #{@user_two.id}")
50
+ assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id != #{@user_two.id}")
51
+ end
52
+
53
+ test 'can search by array of user ids' do
54
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user.id ^ (#{@user_one.id})")
55
+ assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id ^ (#{@user_one.id})")
56
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user.id !^ (#{@user_two.id})")
57
+ assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id !^ (#{@user_two.id})")
58
+ end
59
+
60
+ test 'cannot glob on user\'s id' do
61
+ proc { ForemanTasks::Task.search_for("user.id ~ something") }.must_raise(ScopedSearch::QueryNotSupported)
62
+ proc { ForemanTasks::Task.search_for("user.id ~ 5") }.must_raise(ScopedSearch::QueryNotSupported)
36
63
  end
37
64
 
38
65
  test 'can search the tasks by user with wildcards' do
39
- glob = '*' + @user_one.login[1..-1] # search for '*ser1' if login is 'user1'
40
- assert_equal [@task_one], ForemanTasks::Task.search_for("user ~ #{glob}")
66
+ part = @user_one.login[1..-1] # search for '*ser1' if login is 'user1'
67
+ # The following two should be equivalent
68
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user ~ #{part}")
69
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user ~ *#{part}*")
70
+ SecureRandom.stubs(:hex).returns('abc')
71
+ assert_equal ForemanTasks::Task.search_for("user ~ #{part}").to_sql,
72
+ ForemanTasks::Task.search_for("user ~ *#{part}*").to_sql
73
+ end
74
+
75
+ test 'can search the tasks by user with negated wildcards' do
76
+ part = @user_two.login[1..-1] # search for '*ser1' if login is 'user1'
77
+ # The following two should be equivalent
78
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user !~ #{part}")
79
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user !~ *#{part}*")
80
+ SecureRandom.stubs(:hex).returns('abc')
81
+ assert_equal ForemanTasks::Task.search_for("user !~ #{part}").to_sql,
82
+ ForemanTasks::Task.search_for("user !~ *#{part}*").to_sql
41
83
  end
42
84
 
43
85
  test 'can search the tasks by array' do
44
86
  assert_equal [@task_one], ForemanTasks::Task.search_for("user ^ (this_user, #{@user_one.login}, that_user)")
45
87
  end
46
88
 
89
+ test 'can search the tasks by negated array' do
90
+ assert_equal [@task_one], ForemanTasks::Task.search_for("user !^ (this_user, #{@user_two.login}, that_user)")
91
+ end
92
+
47
93
  test 'properly returns username' do
48
94
  assert_equal @task_one.username, @user_one.login
49
95
  end
@@ -4,6 +4,8 @@ import { Grid, Row, Col, Button } from 'patternfly-react';
4
4
  import { translate as __ } from 'foremanReact/common/I18n';
5
5
  import TaskInfo from './TaskInfo';
6
6
  import { ClickConfirmation } from '../../common/ClickConfirmation';
7
+ import { ResumeButton } from '../../common/ActionButtons/ResumeButton';
8
+ import { CancelButton } from '../../common/ActionButtons/CancelButton';
7
9
 
8
10
  class Task extends Component {
9
11
  taskProgressToggle = () => {
@@ -37,6 +39,9 @@ class Task extends Component {
37
39
  showForceUnlockModal,
38
40
  toggleUnlockModal,
39
41
  toggleForceUnlockModal,
42
+ cancelTaskRequest,
43
+ resumeTaskRequest,
44
+ action,
40
45
  } = this.props;
41
46
  const modalUnlock = (
42
47
  <ClickConfirmation
@@ -97,24 +102,28 @@ class Task extends Component {
97
102
  >
98
103
  {__('Dynflow console')}
99
104
  </Button>
100
- <Button
101
- bsSize="small"
102
- bsStyle="primary"
103
- data-method="post"
104
- href={`/foreman_tasks/tasks/${id}/resume`}
105
+ <ResumeButton
106
+ id={id}
107
+ onClick={() => {
108
+ if (!taskReload) {
109
+ this.taskProgressToggle();
110
+ }
111
+ resumeTaskRequest(id, action);
112
+ }}
113
+ name={action}
105
114
  disabled={!resumable}
106
- >
107
- {__('Resume')}
108
- </Button>
109
- <Button
110
- bsSize="small"
111
- data-method="post"
112
- href={`/foreman_tasks/tasks/${id}/cancel`}
115
+ />
116
+ <CancelButton
117
+ id={id}
118
+ name={action}
113
119
  disabled={!cancellable}
114
- >
115
- {__('Cancel')}
116
- </Button>
117
-
120
+ onClick={() => {
121
+ if (!taskReload) {
122
+ this.taskProgressToggle();
123
+ }
124
+ cancelTaskRequest(id, action);
125
+ }}
126
+ />
118
127
  {parentTask && (
119
128
  <Button
120
129
  bsSize="small"
@@ -177,6 +186,8 @@ Task.propTypes = {
177
186
  showForceUnlockModal: PropTypes.bool,
178
187
  toggleUnlockModal: PropTypes.func,
179
188
  toggleForceUnlockModal: PropTypes.func,
189
+ cancelTaskRequest: PropTypes.func,
190
+ resumeTaskRequest: PropTypes.func,
180
191
  };
181
192
 
182
193
  Task.defaultProps = {
@@ -197,6 +208,8 @@ Task.defaultProps = {
197
208
  showForceUnlockModal: false,
198
209
  toggleUnlockModal: () => null,
199
210
  toggleForceUnlockModal: () => null,
211
+ cancelTaskRequest: () => null,
212
+ resumeTaskRequest: () => null,
200
213
  };
201
214
 
202
215
  export default Task;
@@ -1,29 +1,15 @@
1
1
  import { translate as __, documentLocale } from 'foremanReact/common/I18n';
2
- import React from 'react';
3
- import { FormattedRelative } from 'react-intl';
2
+ import { isoCompatibleDate } from 'foremanReact/common/helpers';
4
3
  import humanizeDuration from 'humanize-duration';
5
4
 
6
- const formatDate = date => {
7
- // Firefox doesnt format dd-mm-yyyy type strings to date
8
- if (typeof date === 'string' || date instanceof String)
9
- return new Date(date.replace(/-/, '/').replace(/-/, '/'));
10
- return date;
11
- };
12
-
13
- export const timeInWords = time => {
14
- if (!time) return __('N/A');
15
- time = formatDate(time);
16
- return <FormattedRelative value={time} />;
17
- };
18
-
19
5
  export const durationInWords = (
20
6
  start,
21
7
  finish,
22
8
  selectedLocale = documentLocale()
23
9
  ) => {
24
10
  if (!start) return __('N/A');
25
- start = formatDate(start).getTime();
26
- finish = formatDate(finish).getTime();
11
+ start = new Date(isoCompatibleDate(start)).getTime();
12
+ finish = new Date(isoCompatibleDate(finish)).getTime();
27
13
  return {
28
14
  text: humanizeDuration(new Date(finish - start).getTime(), {
29
15
  largest: 1,
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import { Grid, Row, Col, ProgressBar } from 'patternfly-react';
4
4
  import { translate as __ } from 'foremanReact/common/I18n';
5
5
  import EllipsisWithTooltip from 'react-ellipsis-with-tooltip';
6
- import { timeInWords } from './TaskHelper';
6
+ import RelativeDateTime from 'foremanReact/components/common/dates/RelativeDateTime';
7
7
 
8
8
  class TaskInfo extends Component {
9
9
  isDelayed = () => {
@@ -73,7 +73,10 @@ class TaskInfo extends Component {
73
73
  <EllipsisWithTooltip>{action || __('N/A')}</EllipsisWithTooltip>
74
74
  ),
75
75
  },
76
- { title: 'Start at', value: timeInWords(startAt) },
76
+ {
77
+ title: 'Start at',
78
+ value: <RelativeDateTime defaultValue={__('N/A')} date={startAt} />,
79
+ },
77
80
  ],
78
81
  [
79
82
  {
@@ -85,7 +88,10 @@ class TaskInfo extends Component {
85
88
  </React.Fragment>
86
89
  ),
87
90
  },
88
- { title: 'Started at', value: timeInWords(startedAt) },
91
+ {
92
+ title: 'Started at',
93
+ value: <RelativeDateTime defaultValue={__('N/A')} date={startedAt} />,
94
+ },
89
95
  ],
90
96
  [
91
97
  {
@@ -96,7 +102,10 @@ class TaskInfo extends Component {
96
102
  username || ''
97
103
  ),
98
104
  },
99
- { title: 'Ended at', value: timeInWords(endedAt) },
105
+ {
106
+ title: 'Ended at',
107
+ value: <RelativeDateTime defaultValue={__('N/A')} date={endedAt} />,
108
+ },
100
109
  ],
101
110
  [
102
111
  {
@@ -105,7 +114,11 @@ class TaskInfo extends Component {
105
114
  },
106
115
  {
107
116
  title: 'Start before',
108
- value: startBefore ? timeInWords(startBefore) : '-',
117
+ value: startBefore ? (
118
+ <RelativeDateTime defaultValue={__('N/A')} date={startBefore} />
119
+ ) : (
120
+ '-'
121
+ ),
109
122
  },
110
123
  ],
111
124
  ];
@@ -1,59 +1,4 @@
1
- import React from 'react';
2
- import { mount } from 'enzyme';
3
- import toJson from 'enzyme-to-json';
4
- import { IntlProvider } from 'react-intl';
5
- import { timeInWords, durationInWords } from '../TaskHelper';
6
-
7
- describe('timeInWords', () => {
8
- it('should work for past minutes', () => {
9
- const component = mount(
10
- <IntlProvider locale="en">
11
- {timeInWords(new Date().getTime() - 1000 * 60 * 5)}
12
- </IntlProvider>
13
- );
14
- expect(toJson(component.render())).toMatchSnapshot();
15
- });
16
- it('should work for past hours', () => {
17
- const component = mount(
18
- <IntlProvider locale="en">
19
- {timeInWords(new Date().getTime() - 1000 * 60 * 60 * 5)}
20
- </IntlProvider>
21
- );
22
- expect(toJson(component.render())).toMatchSnapshot();
23
- });
24
- it('should work for past days', () => {
25
- const component = mount(
26
- <IntlProvider locale="en">
27
- {timeInWords(new Date().getTime() - 1000 * 60 * 60 * 24 * 5)}
28
- </IntlProvider>
29
- );
30
- expect(toJson(component.render())).toMatchSnapshot();
31
- });
32
- it('should work for future minutes', () => {
33
- const component = mount(
34
- <IntlProvider locale="en">
35
- {timeInWords(new Date().getTime() + 1000 * 60 * 5)}
36
- </IntlProvider>
37
- );
38
- expect(toJson(component.render())).toMatchSnapshot();
39
- });
40
- it('should work for future hours', () => {
41
- const component = mount(
42
- <IntlProvider locale="en">
43
- {timeInWords(new Date().getTime() + 1000 * 60 * 60 * 5)}
44
- </IntlProvider>
45
- );
46
- expect(toJson(component.render())).toMatchSnapshot();
47
- });
48
- it('should work for future days', () => {
49
- const component = mount(
50
- <IntlProvider locale="en">
51
- {timeInWords(new Date().getTime() + 1000 * 60 * 60 * 24 * 5)}
52
- </IntlProvider>
53
- );
54
- expect(toJson(component.render())).toMatchSnapshot();
55
- });
56
- });
1
+ import { durationInWords } from '../TaskHelper';
57
2
 
58
3
  describe('durationInWords', () => {
59
4
  it('should work for seconds', () => {
@@ -63,30 +63,18 @@ exports[`Task rendering render with some Props 1`] = `
63
63
  >
64
64
  Dynflow console
65
65
  </Button>
66
- <Button
67
- active={false}
68
- block={false}
69
- bsClass="btn"
70
- bsSize="small"
71
- bsStyle="primary"
72
- data-method="post"
66
+ <ResumeButton
73
67
  disabled={true}
74
- href="/foreman_tasks/tasks/test/resume"
75
- >
76
- Resume
77
- </Button>
78
- <Button
79
- active={false}
80
- block={false}
81
- bsClass="btn"
82
- bsSize="small"
83
- bsStyle="default"
84
- data-method="post"
68
+ id="test"
69
+ name=""
70
+ onClick={[Function]}
71
+ />
72
+ <CancelButton
85
73
  disabled={true}
86
- href="/foreman_tasks/tasks/test/cancel"
87
- >
88
- Cancel
89
- </Button>
74
+ id="test"
75
+ name=""
76
+ onClick={[Function]}
77
+ />
90
78
  <Button
91
79
  active={false}
92
80
  block={false}
@@ -125,6 +113,7 @@ exports[`Task rendering render with some Props 1`] = `
125
113
  <TaskInfo
126
114
  action=""
127
115
  allowDangerousActions={true}
116
+ cancelTaskRequest={[Function]}
128
117
  cancellable={false}
129
118
  endedAt=""
130
119
  error={Array []}
@@ -138,6 +127,7 @@ exports[`Task rendering render with some Props 1`] = `
138
127
  refetchTaskDetails={[Function]}
139
128
  result="error"
140
129
  resumable={false}
130
+ resumeTaskRequest={[Function]}
141
131
  showForceUnlockModal={false}
142
132
  showUnlockModal={false}
143
133
  startAt=""
@@ -220,35 +210,24 @@ exports[`Task rendering render without Props 1`] = `
220
210
  >
221
211
  Dynflow console
222
212
  </Button>
223
- <Button
224
- active={false}
225
- block={false}
226
- bsClass="btn"
227
- bsSize="small"
228
- bsStyle="primary"
229
- data-method="post"
213
+ <ResumeButton
230
214
  disabled={true}
231
- href="/foreman_tasks/tasks/test/resume"
232
- >
233
- Resume
234
- </Button>
235
- <Button
236
- active={false}
237
- block={false}
238
- bsClass="btn"
239
- bsSize="small"
240
- bsStyle="default"
241
- data-method="post"
215
+ id="test"
216
+ name=""
217
+ onClick={[Function]}
218
+ />
219
+ <CancelButton
242
220
  disabled={true}
243
- href="/foreman_tasks/tasks/test/cancel"
244
- >
245
- Cancel
246
- </Button>
221
+ id="test"
222
+ name=""
223
+ onClick={[Function]}
224
+ />
247
225
  </Col>
248
226
  </Row>
249
227
  <TaskInfo
250
228
  action=""
251
229
  allowDangerousActions={false}
230
+ cancelTaskRequest={[Function]}
252
231
  cancellable={false}
253
232
  endedAt=""
254
233
  error={Array []}
@@ -262,6 +241,7 @@ exports[`Task rendering render without Props 1`] = `
262
241
  refetchTaskDetails={[Function]}
263
242
  result="error"
264
243
  resumable={false}
244
+ resumeTaskRequest={[Function]}
265
245
  showForceUnlockModal={false}
266
246
  showUnlockModal={false}
267
247
  startAt=""