foreman-tasks 0.15.1 → 0.15.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 (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