foreman-tasks 0.15.1 → 0.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/.babelrc +9 -1
  3. data/.eslintrc +6 -0
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +6 -0
  6. data/.storybook/webpack.config.js +51 -54
  7. data/app/controllers/foreman_tasks/api/tasks_controller.rb +0 -2
  8. data/app/controllers/foreman_tasks/tasks_controller.rb +6 -1
  9. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +8 -0
  10. data/app/lib/actions/base.rb +7 -0
  11. data/app/lib/actions/helpers/lifecycle_logging.rb +21 -0
  12. data/app/lib/actions/proxy_action.rb +4 -2
  13. data/app/models/foreman_tasks/task.rb +23 -0
  14. data/app/models/foreman_tasks/task/summarizer.rb +96 -6
  15. data/app/models/foreman_tasks/triggering.rb +2 -2
  16. data/app/models/setting/foreman_tasks.rb +8 -1
  17. data/app/services/foreman_tasks/dashboard_table_filter.rb +47 -0
  18. data/app/services/foreman_tasks/troubleshooting_help_generator.rb +92 -0
  19. data/app/services/ui_notifications/tasks.rb +20 -0
  20. data/app/services/ui_notifications/tasks/task_paused_admin.rb +43 -0
  21. data/app/services/ui_notifications/tasks/task_paused_owner.rb +30 -0
  22. data/app/views/foreman_tasks/tasks/_details.html.erb +5 -3
  23. data/app/views/foreman_tasks/tasks/index.html.erb +13 -0
  24. data/config/routes.rb +1 -0
  25. data/db/migrate/20190318153925_add_task_state_updated_at.foreman_tasks.rb +5 -0
  26. data/db/migrate/20190404132157_add_implicit_varchar_uuid_cast.rb +25 -0
  27. data/db/seeds.d/30-notification_blueprints.rb +33 -0
  28. data/foreman-tasks.gemspec +1 -1
  29. data/lib/foreman_tasks/cleaner.rb +5 -4
  30. data/lib/foreman_tasks/engine.rb +1 -1
  31. data/lib/foreman_tasks/test_helpers.rb +10 -0
  32. data/lib/foreman_tasks/version.rb +1 -1
  33. data/package.json +14 -11
  34. data/test/controllers/tasks_controller_test.rb +10 -0
  35. data/test/foreman_tasks_test_helper.rb +4 -0
  36. data/test/support/dummy_dynflow_action.rb +29 -0
  37. data/test/support/history_tasks_builder.rb +42 -0
  38. data/test/unit/actions/action_with_sub_plans_test.rb +4 -1
  39. data/test/unit/actions/bulk_action_test.rb +2 -0
  40. data/test/unit/cleaner_test.rb +15 -0
  41. data/test/unit/dashboard_table_filter_test.rb +65 -0
  42. data/test/unit/summarizer_test.rb +39 -0
  43. data/test/unit/task_test.rb +14 -0
  44. data/test/unit/troubleshooting_help_generator_test.rb +71 -0
  45. data/test/unit/ui_notifications_test.rb +86 -0
  46. data/webpack/ForemanTasks/Components/Chart/Chart.js +128 -0
  47. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.js +20 -0
  48. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.stories.js +51 -0
  49. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.test.js +11 -0
  50. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/__snapshots__/PausedTasksCard.test.js.snap +36 -0
  51. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.js +20 -0
  52. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.stories.js +51 -0
  53. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.test.js +11 -0
  54. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/__snapshots__/RunningTasksCard.test.js.snap +36 -0
  55. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.js +64 -0
  56. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +25 -0
  57. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.stories.js +28 -0
  58. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.test.js +18 -0
  59. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/__snapshots__/ScheduledTasksCard.test.js.snap +94 -0
  60. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +89 -0
  61. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +46 -0
  62. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.stories.js +72 -0
  63. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.test.js +48 -0
  64. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardHelper.js +63 -0
  65. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +973 -0
  66. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.js +96 -0
  67. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.scss +17 -0
  68. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.stories.js +46 -0
  69. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.test.js +43 -0
  70. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/__snapshots__/TasksDonutCard.test.js.snap +183 -0
  71. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.js +166 -0
  72. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.scss +24 -0
  73. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.stories.js +25 -0
  74. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.test.js +40 -0
  75. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChartConstants.js +13 -0
  76. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChartHelper.js +94 -0
  77. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChartHelper.test.js +152 -0
  78. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/__snapshots__/TasksDonutChart.test.js.snap +302 -0
  79. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/__snapshots__/TasksDonutChartHelper.test.js.snap +21 -0
  80. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.fixtures.js +25 -0
  81. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.js +72 -0
  82. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.stories.js +52 -0
  83. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/TasksCardsGrid.test.js +21 -0
  84. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/__snapshots__/TasksCardsGrid.test.js.snap +223 -0
  85. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.js +57 -0
  86. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.scss +26 -0
  87. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.stories.js +22 -0
  88. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.test.js +57 -0
  89. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/__snapshots__/TasksLabelsRow.test.js.snap +47 -0
  90. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.js +51 -0
  91. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.stories.js +23 -0
  92. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/TimeDropDown.test.js +19 -0
  93. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/Components/TimeDropDown/__snapshots__/TimeDropDown.test.js.snap +85 -0
  94. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.js +33 -0
  95. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.scss +11 -0
  96. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.stories.js +22 -0
  97. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/TasksTimeRow.test.js +15 -0
  98. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksTimeRow/__snapshots__/TasksTimeRow.test.js.snap +41 -0
  99. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.js +77 -0
  100. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.scss +6 -0
  101. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardActions.js +62 -0
  102. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardConstants.js +94 -0
  103. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardHelper.js +78 -0
  104. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardPropTypes.js +13 -0
  105. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardReducer.js +50 -0
  106. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboardSelectors.js +44 -0
  107. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboard.test.js +13 -0
  108. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardActions.test.js +37 -0
  109. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardHelper.test.js +36 -0
  110. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardReducer.test.js +58 -0
  111. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/TasksDashboardSelectors.test..js +59 -0
  112. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboard.test.js.snap +51 -0
  113. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardActions.test.js.snap +61 -0
  114. data/webpack/ForemanTasks/Components/TasksDashboard/__tests__/__snapshots__/TasksDashboardReducer.test.js.snap +280 -0
  115. data/webpack/ForemanTasks/Components/TasksDashboard/index.js +25 -0
  116. data/webpack/ForemanTasks/ForemanTasksReducers.js +10 -0
  117. data/webpack/ForemanTasks/ForemanTasksSelectors.js +1 -0
  118. data/webpack/__mocks__/foremanReact/API.js +7 -0
  119. data/webpack/__mocks__/foremanReact/common/I18n.js +5 -0
  120. data/webpack/__mocks__/foremanReact/common/helpers.js +3 -0
  121. data/webpack/index.js +13 -1
  122. data/webpack/stories/decorators/index.js +1 -0
  123. data/webpack/stories/decorators/withCardsDecorator.js +14 -0
  124. data/webpack/stories/index.js +1 -3
  125. data/webpack/stories/index.scss +6 -0
  126. metadata +101 -8
  127. data/webpack/ForemanTasks/components/Hello/Hello.stories.js +0 -5
  128. data/webpack/ForemanTasks/components/Hello/__tests__/Hello.test.js +0 -11
  129. data/webpack/ForemanTasks/components/Hello/__tests__/__snapshots__/Hello.test.js.snap +0 -7
  130. data/webpack/ForemanTasks/components/Hello/index.js +0 -5
@@ -1,3 +1,3 @@
1
1
  module ForemanTasks
2
- VERSION = '0.15.1'.freeze
2
+ VERSION = '0.15.2'.freeze
3
3
  end
data/package.json CHANGED
@@ -10,6 +10,8 @@
10
10
  "test:current": "node node_modules/.bin/jest --watch",
11
11
  "coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
12
12
  "storybook": "start-storybook -p 6006",
13
+ "storybook:build": "node --max_old_space_size=2048 ./node_modules/.bin/build-storybook --config-dir .storybook --output-dir .storybook-dist",
14
+ "storybook:deploy": "surge --project .storybook-dist",
13
15
  "create-react-component": "yo react-domain"
14
16
  },
15
17
  "repository": {
@@ -20,9 +22,9 @@
20
22
  "url": "http://projects.theforeman.org/projects/foreman-tasks/issues"
21
23
  },
22
24
  "devDependencies": {
23
- "@storybook/addon-actions": "~3.4.11",
24
- "@storybook/addon-knobs": "~3.4.11",
25
- "@storybook/react": "~3.4.11",
25
+ "@storybook/addon-actions": "^5.0.1",
26
+ "@storybook/addon-knobs": "^5.0.1",
27
+ "@storybook/react": "^5.0.1",
26
28
  "babel-cli": "^6.10.1",
27
29
  "babel-core": "^6.26.3",
28
30
  "babel-eslint": "^8.2.3",
@@ -44,19 +46,25 @@
44
46
  "eslint": "^4.10.0",
45
47
  "eslint-import-resolver-babel-module": "^4.0.0",
46
48
  "eslint-plugin-patternfly-react": "0.2.0",
49
+ "identity-obj-proxy": "^3.0.0",
50
+ "jed": "^1.1.1",
47
51
  "jest-cli": "^23.6.0",
48
52
  "jest-prop-type-error": "^1.1.0",
49
- "patternfly": "^3.59.1",
53
+ "node-sass": "^4.5.0",
54
+ "patternfly": "^3.58.0",
50
55
  "prettier": "^1.13.5",
51
56
  "raf": "^3.4.0",
52
57
  "react-redux-test-utils": "^0.1.1",
53
58
  "react-remarkable": "^1.1.3",
59
+ "sass-loader": "^6.0.7",
54
60
  "stylelint": "^9.3.0",
55
- "stylelint-config-standard": "^18.0.0"
61
+ "stylelint-config-standard": "^18.0.0",
62
+ "surge": "^0.20.3"
56
63
  },
57
64
  "dependencies": {
58
65
  "babel-polyfill": "^6.26.0",
59
66
  "classnames": "^2.2.5",
67
+ "lodash": "^4.17.11",
60
68
  "patternfly-react": "^2.29.0",
61
69
  "prop-types": "^15.6.0",
62
70
  "react": "^16.8.1",
@@ -69,10 +77,10 @@
69
77
  "redux-thunk": "^2.3.0",
70
78
  "reselect": "^3.0.1",
71
79
  "seamless-immutable": "^7.1.2",
80
+ "urijs": "^1.19.1",
72
81
  "uuid": "^3.3.2"
73
82
  },
74
83
  "jest": {
75
- "automock": true,
76
84
  "verbose": true,
77
85
  "testMatch": [
78
86
  "**/*.test.js"
@@ -90,11 +98,6 @@
90
98
  "coverageReporters": [
91
99
  "lcov"
92
100
  ],
93
- "unmockedModulePathPatterns": [
94
- "webpack/",
95
- "react",
96
- "node_modules/"
97
- ],
98
101
  "moduleNameMapper": {
99
102
  "^.+\\.(png|gif|css|scss)$": "identity-obj-proxy"
100
103
  },
@@ -24,6 +24,16 @@ module ForemanTasks
24
24
  Organization.current = Location.current = nil
25
25
  end
26
26
 
27
+ describe 'summary' do
28
+ it 'works' do
29
+ FactoryBot.create(:some_task, :action => 'Some action')
30
+ get(:summary, params: { recent_timeframe: 24 }, session: set_session_user)
31
+ assert_response :success
32
+ response = JSON.parse(@response.body)
33
+ assert response['running']
34
+ end
35
+ end
36
+
27
37
  it 'supports csv export' do
28
38
  FactoryBot.create(:some_task, :action => 'Some action')
29
39
  get(:index, params: { format: :csv }, session: set_session_user)
@@ -4,8 +4,10 @@ require_relative './support/dummy_dynflow_action'
4
4
  require_relative './support/dummy_recurring_dynflow_action'
5
5
  require_relative './support/dummy_proxy_action'
6
6
  require_relative './support/dummy_task_group'
7
+ require_relative './support/history_tasks_builder'
7
8
 
8
9
  require 'dynflow/testing'
10
+ require 'foreman_tasks/test_helpers'
9
11
 
10
12
  FactoryBot.definition_file_paths = ["#{ForemanTasks::Engine.root}/test/factories"]
11
13
  FactoryBot.find_definitions
@@ -13,6 +15,8 @@ FactoryBot.find_definitions
13
15
  ForemanTasks.dynflow.require!
14
16
  ForemanTasks.dynflow.config.disable_active_record_actions = true
15
17
 
18
+ ForemanTasks::TestHelpers.use_in_memory_sqlite!
19
+
16
20
  # waits for the passed block to return non-nil value and reiterates it while getting false
17
21
  # (till some reasonable timeout). Useful for forcing the tests for some event to occur
18
22
  def wait_for(waiting_message = 'something to happen')
@@ -1,4 +1,33 @@
1
1
  module Support
2
2
  class DummyDynflowAction < Dynflow::Action
3
3
  end
4
+
5
+ class DummyPauseAction < Actions::EntryAction
6
+ def plan
7
+ plan_action(DummyPauseActionWithCustomTroubleshooting)
8
+ plan_self
9
+ end
10
+
11
+ def run
12
+ error! "This is an error"
13
+ end
14
+ end
15
+
16
+ class DummyPauseActionWithCustomTroubleshooting < Actions::EntryAction
17
+ def run
18
+ error! "This is an error"
19
+ end
20
+
21
+ def troubleshooting_info
22
+ ForemanTasks::TroubleshootingHelpGenerator::Info.new.tap do |i|
23
+ i.add_line _('This task requires special handling.')
24
+ i.add_link(ForemanTasks::TroubleshootingHelpGenerator::Link.new(
25
+ name: :custom_link,
26
+ title: _('custom link'),
27
+ href: "/additional_troubleshooting_page",
28
+ description: _("Investigate %{link} on more details for this custom error.")
29
+ ))
30
+ end
31
+ end
32
+ end
4
33
  end
@@ -0,0 +1,42 @@
1
+ class HistoryTasksBuilder
2
+ def distribution
3
+ { 'running' => { recent: 3, total: 6 },
4
+ 'stopped' => { recent: 3, total: 7,
5
+ by_result: {
6
+ 'success' => { recent: 2, total: 4 },
7
+ 'warning' => { recent: 1, total: 2 },
8
+ 'error' => { recent: 0, total: 1 }
9
+ } } }
10
+ end
11
+
12
+ # rubocop:disable Performance/TimesMap
13
+ def build
14
+ distribution.each do |(state, status_summary)|
15
+ tasks = status_summary[:total].times.map do
16
+ ForemanTasks::Task.create(type: ForemanTasks::Task.name,
17
+ label: 'test',
18
+ state: state,
19
+ result: 'pending').tap do |task|
20
+ task.update(state_updated_at: nil)
21
+ end
22
+ end
23
+ recent_tasks = tasks.take(status_summary[:recent])
24
+ recent_tasks.each { |t| t.update(state_updated_at: Time.now.utc) }
25
+
26
+ untouched_recent_tasks = recent_tasks
27
+ untouched_old_tasks = tasks - recent_tasks
28
+ status_summary.fetch(:by_result, {}).each do |(result, result_summary)|
29
+ result_summary[:recent].times do |_i|
30
+ task = untouched_recent_tasks.shift
31
+ task.update(result: result)
32
+ end
33
+
34
+ (result_summary[:total] - result_summary[:recent]).times do |_i|
35
+ task = untouched_old_tasks.shift
36
+ task.update(result: result)
37
+ end
38
+ end
39
+ end
40
+ # rubocop:enable Performance/TimesMap
41
+ end
42
+ end
@@ -1,4 +1,5 @@
1
1
  require 'foreman_tasks_test_helper'
2
+ require 'foreman_tasks/test_helpers'
2
3
 
3
4
  module ForemanTasks
4
5
  class ActionWithSubPlansTest < ActiveSupport::TestCase
@@ -31,11 +32,13 @@ module ForemanTasks
31
32
  end
32
33
 
33
34
  describe Actions::ActionWithSubPlans do
35
+ include ForemanTasks::TestHelpers::WithInThreadExecutor
36
+
34
37
  let(:task) do
35
38
  user = FactoryBot.create(:user)
36
39
  triggered = ForemanTasks.trigger(ParentAction, user)
37
40
  raise triggered.error if triggered.respond_to?(:error)
38
- triggered.finished.wait(2)
41
+ triggered.finished.wait(30)
39
42
  ForemanTasks::Task.where(:external_id => triggered.id).first
40
43
  end
41
44
 
@@ -17,6 +17,8 @@ module ForemanTasks
17
17
  end
18
18
 
19
19
  describe Actions::BulkAction do
20
+ include ForemanTasks::TestHelpers::WithInThreadExecutor
21
+
20
22
  let(:targets) { (1..5).map { |i| Target.new i } }
21
23
  let(:task) do
22
24
  triggered = ForemanTasks.trigger(ParentAction, ChildAction, targets)
@@ -68,6 +68,21 @@ class TasksTest < ActiveSupport::TestCase
68
68
  ForemanTasks::Task.where(id: tasks_to_keep).must_equal tasks_to_keep
69
69
  end
70
70
 
71
+ it 'matches tasks with compound filters properly' do
72
+ cleaner = ForemanTasks::Cleaner.new(:filter => 'result = pending or result = error',
73
+ :states => %w[paused planning])
74
+ tasks_to_delete = [FactoryBot.create(:some_task),
75
+ FactoryBot.create(:some_task)]
76
+ tasks_to_delete[0].update!(:result => 'error', :state => 'paused')
77
+ tasks_to_delete[1].update!(:result => 'pending', :state => 'planning')
78
+ task_to_keep = FactoryBot.create(:some_task)
79
+ task_to_keep.update!(:result => 'pending', :state => 'planned')
80
+ cleaner.expects(:tasks_to_csv)
81
+ cleaner.delete
82
+ ForemanTasks::Task.where(id: tasks_to_delete).must_be_empty
83
+ ForemanTasks::Task.where(id: task_to_keep).must_equal [task_to_keep]
84
+ end
85
+
71
86
  it 'backs tasks up before deleting' do
72
87
  dir = '/tmp'
73
88
  cleaner = ForemanTasks::Cleaner.new(:filter => '', :after => '10d', :backup_dir => dir)
@@ -0,0 +1,65 @@
1
+ require 'foreman_tasks_test_helper'
2
+
3
+ class DashboardTableFilterTest < ActiveSupport::TestCase
4
+ before do
5
+ ::ForemanTasks::Task.delete_all
6
+ end
7
+
8
+ describe ForemanTasks::DashboardTableFilter do
9
+ before do
10
+ @tasks_builder = HistoryTasksBuilder.new
11
+ @scope = ForemanTasks::Task.all
12
+ @tasks_builder.build
13
+ end
14
+
15
+ let :subject do
16
+ ForemanTasks::DashboardTableFilter.new(@scope, params)
17
+ end
18
+
19
+ let :filtered_scope do
20
+ subject.scope
21
+ end
22
+
23
+ describe 'by result' do
24
+ let(:params) { { result: 'warning' } }
25
+
26
+ it 'filters' do
27
+ filtered_scope.count.must_equal @tasks_builder.distribution['stopped'][:by_result]['warning'][:total]
28
+ end
29
+ end
30
+
31
+ describe 'by state' do
32
+ let(:params) { { state: 'running' } }
33
+
34
+ it 'filters' do
35
+ filtered_scope.count.must_equal @tasks_builder.distribution['running'][:total]
36
+ end
37
+ end
38
+
39
+ describe 'recent' do
40
+ let(:params) do
41
+ { state: 'running',
42
+ time_horizon: 'H24',
43
+ time_mode: 'recent' }
44
+ end
45
+
46
+ it 'filters' do
47
+ filtered_scope.count.must_equal @tasks_builder.distribution['running'][:recent]
48
+ end
49
+ end
50
+
51
+ describe 'older' do
52
+ let(:params) do
53
+ { state: 'running',
54
+ time_horizon: 'H24',
55
+ time_mode: 'older' }
56
+ end
57
+
58
+ it 'filters' do
59
+ old_tasks_count = @tasks_builder.distribution['running'][:total] -
60
+ @tasks_builder.distribution['running'][:recent]
61
+ filtered_scope.count.must_equal old_tasks_count
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,39 @@
1
+ require 'foreman_tasks_test_helper'
2
+
3
+ class SummarizerTest < ActiveSupport::TestCase
4
+ before do
5
+ ::ForemanTasks::Task.delete_all
6
+ end
7
+
8
+ describe ForemanTasks::Task::Summarizer do
9
+ before do
10
+ @tasks_builder = HistoryTasksBuilder.new
11
+ @tasks_builder.build
12
+ end
13
+
14
+ let :subject do
15
+ ForemanTasks::Task::Summarizer.new
16
+ end
17
+
18
+ let :expected do
19
+ @tasks_builder.distribution
20
+ end
21
+
22
+ it 'is able to group tasks counts by state and result' do
23
+ summary = subject.summary
24
+ expected.each do |(state, expected_state_vals)|
25
+ assert_summary(expected_state_vals, summary[state], "summary[#{state}]")
26
+ expected_state_vals.fetch(:by_result, {}).each do |result, expected_result_vals|
27
+ assert_summary expected_result_vals, summary[state][:by_result][result], "summary[#{state}][#{result}]"
28
+ end
29
+ end
30
+ end
31
+
32
+ def assert_summary(expected_summary, summary, value_desc)
33
+ %I[recent total].each do |key|
34
+ assert_equal expected_summary[key], summary[key],
35
+ "#{value_desc}[#{key}] expected to be #{expected_summary[key]}, was #{summary[key]}"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -41,6 +41,20 @@ class TasksTest < ActiveSupport::TestCase
41
41
  end
42
42
  end
43
43
 
44
+ describe 'state_updated_at' do
45
+ it 'updates the state_updated_at when the state changes' do
46
+ task = FactoryBot.create(:some_task)
47
+ assert task.state_updated_at > Time.now.utc - 1.minute, "Newly created task has to have state_updated_at set"
48
+ task.update(state_updated_at: nil)
49
+ task.result = 'error'
50
+ task.save
51
+ assert_not task.state_updated_at, "Other than state change should not affect 'state_updated_at'"
52
+ task.state = 'running'
53
+ task.save
54
+ assert task.state_updated_at, "State change should set 'state_updated_at'"
55
+ end
56
+ end
57
+
44
58
  describe 'authorization filtering' do
45
59
  it 'can filter by the task subject' do
46
60
  user_role = FactoryBot.create(:user_user_role)
@@ -0,0 +1,71 @@
1
+ require 'foreman_tasks_test_helper'
2
+
3
+ module ForemanTasks
4
+ class TroubleshootingHelpGeneratorTest < ActiveSupport::TestCase
5
+ include ForemanTasks::TestHelpers::WithInThreadExecutor
6
+
7
+ subject do
8
+ TroubleshootingHelpGenerator.new(@task.main_action)
9
+ end
10
+
11
+ let :sample_troubleshooting_url do
12
+ 'https://theforeman.org/manuals/%{version}/tasks_troubleshooting.html#%{label}'
13
+ end
14
+
15
+ let :expected_troubleshooting_url do
16
+ "https://theforeman.org/manuals/#{SETTINGS[:version].short}/tasks_troubleshooting.html#Support::DummyPauseAction"
17
+ end
18
+
19
+ let :action_class do
20
+ Support::DummyPauseAction
21
+ end
22
+
23
+ before do
24
+ Setting::ForemanTasks.load_defaults
25
+ ::ForemanTasks::Task.delete_all
26
+ @task = trigger_task
27
+ Setting[:foreman_tasks_troubleshooting_url] = sample_troubleshooting_url
28
+ end
29
+
30
+ it 'generates html from the main action troubleshooting_info' do
31
+ generated_html = subject.generate_html
32
+ generated_html.must_include "A paused task represents a process that has not finished properly"
33
+ generated_html.must_include %(See <a href="#{expected_troubleshooting_url}">troubleshooting documentation</a> for more details on how to resolve the issue)
34
+ end
35
+
36
+ it 'exposes link details' do
37
+ link = subject.links.find do |l|
38
+ l.name == :troubleshooting && l.title == 'troubleshooting documentation' &&
39
+ l.href == expected_troubleshooting_url
40
+ end
41
+ assert link, "#{subject.links} doesn't contain expected link"
42
+ end
43
+
44
+ describe 'additional troubleshooting info' do
45
+ let(:action_class) do
46
+ Support::DummyPauseActionWithCustomTroubleshooting
47
+ end
48
+
49
+ it 'includes additional description in generated html' do
50
+ generated_html = subject.generate_html
51
+ generated_html.must_include 'A paused task represents a process that has not finished properly'
52
+ generated_html.must_match %r{See <a href=".*">troubleshooting documentation</a> for more details on how to resolve the issue}
53
+ generated_html.must_include 'This task requires special handling'
54
+ generated_html.must_include 'Investigate <a href="/additional_troubleshooting_page">custom link</a> on more details for this custom error'
55
+ end
56
+
57
+ it 'includes additional links' do
58
+ link = subject.links.find do |l|
59
+ l.name == :custom_link && l.title == 'custom link' && l.href == '/additional_troubleshooting_page'
60
+ end
61
+ assert link, "#{subject.links} doesn't contain expected link"
62
+ end
63
+ end
64
+
65
+ def trigger_task
66
+ t = ForemanTasks.trigger(action_class)
67
+ t.finished.wait
68
+ ForemanTasks::Task.find_by(external_id: t.execution_plan_id)
69
+ end
70
+ end
71
+ end