Skip to content

Commit c45933b

Browse files
committed
Refs #39167 - add tests for job wizard templates
1 parent 0588a71 commit c45933b

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# frozen_string_literal: true
2+
3+
require File.expand_path('../test_plugin_helper', __dir__)
4+
require 'integration_test_helper'
5+
6+
class JobWizardCategoryJsTest < IntegrationTestWithJavascript
7+
WIZARD_INPUT_NAME = 'wizard_integration_input'
8+
WIZARD_FEATURE_INPUT_NAME = 'wizard_integration_feature_input'
9+
10+
setup do
11+
@original_rex_form_template = Setting[:remote_execution_form_job_template]
12+
as_admin do
13+
@default_job_template = FactoryBot.create(
14+
:job_template,
15+
:name => 'Integration Default REX Form Template',
16+
:job_category => 'Default Form Category'
17+
)
18+
@feature_job_template = FactoryBot.create(
19+
:job_template,
20+
:name => 'Integration Feature REX Template',
21+
:job_category => 'Feature Linked Category'
22+
)
23+
add_plain_template_input!(@default_job_template, :name => WIZARD_INPUT_NAME)
24+
add_plain_template_input!(@feature_job_template, :name => WIZARD_FEATURE_INPUT_NAME)
25+
Setting[:remote_execution_form_job_template] = @default_job_template.name
26+
@remote_execution_feature = FactoryBot.create(
27+
:remote_execution_feature,
28+
:label => 'integration_rex_category_feature',
29+
:name => 'Integration REX Category Feature',
30+
:job_template => @feature_job_template
31+
)
32+
@rex_host = FactoryBot.create(:host, :with_execution)
33+
end
34+
end
35+
36+
teardown do
37+
Setting[:remote_execution_form_job_template] = @original_rex_form_template
38+
end
39+
40+
test 'job wizard shows feature template job category when feature query param is present' do
41+
visit new_job_invocation_path(:feature => @remote_execution_feature.label)
42+
assert_text 'Category and template', :wait => 30
43+
wait_for_ajax
44+
assert_selector(:ouia_component_id, 'job_category', :text => 'Feature Linked Category', :wait => 30)
45+
end
46+
47+
test 'job wizard shows default form category when no feature query param' do
48+
visit new_job_invocation_path
49+
assert_text 'Category and template', :wait => 30
50+
wait_for_ajax
51+
assert_selector(:ouia_component_id, 'job_category', :text => 'Default Form Category', :wait => 30)
52+
end
53+
54+
test 'job wizard prefills template input from inputs query param' do
55+
visit new_job_invocation_path(
56+
:inputs => { WIZARD_INPUT_NAME => 'from_query_string' },
57+
:search => ''
58+
)
59+
go_to_target_hosts_and_inputs_step!
60+
assert_selector "textarea##{WIZARD_INPUT_NAME}", :wait => 30
61+
assert_equal 'from_query_string', find("textarea##{WIZARD_INPUT_NAME}").value
62+
end
63+
64+
test 'job wizard does not prefill template input when inputs query param is omitted' do
65+
visit new_job_invocation_path(:search => '')
66+
go_to_target_hosts_and_inputs_step!
67+
assert_selector "textarea##{WIZARD_INPUT_NAME}", :wait => 30
68+
assert_equal '', find("textarea##{WIZARD_INPUT_NAME}").value
69+
end
70+
71+
test 'job wizard prefills template input when feature and inputs query params are present' do
72+
visit new_job_invocation_path(
73+
:feature => @remote_execution_feature.label,
74+
:inputs => { WIZARD_FEATURE_INPUT_NAME => 'feature_and_inputs' },
75+
:search => ''
76+
)
77+
go_to_target_hosts_and_inputs_step!
78+
assert_selector "textarea##{WIZARD_FEATURE_INPUT_NAME}", :wait => 30
79+
assert_equal 'feature_and_inputs', find("textarea##{WIZARD_FEATURE_INPUT_NAME}").value
80+
end
81+
82+
test 'job wizard run on selected hosts is enabled on review and posts to job invocations API' do
83+
posted_to_job_invocations_create = false
84+
subscriber = ActiveSupport::Notifications.subscribe('start_processing.action_controller') do |_n, _s, _f, _i, payload|
85+
if payload[:controller].to_s.end_with?('JobInvocationsController') && payload[:action].to_s == 'create'
86+
posted_to_job_invocations_create = true
87+
end
88+
end
89+
90+
begin
91+
visit new_job_invocation_path(:search => "id = #{@rex_host.id}")
92+
navigate_job_wizard_to_review_step!
93+
94+
assert_selector(:ouia_component_id, 'run-on-selected-hosts-footer', :wait => 30)
95+
run_on_hosts = find(:ouia_component_id, 'run-on-selected-hosts-footer')
96+
assert_includes [nil, 'false'], run_on_hosts[:'aria-disabled']
97+
assert_text 'Run on selected hosts'
98+
find(:ouia_component_id, 'run-on-selected-hosts-footer').click
99+
wait_for_ajax
100+
assert posted_to_job_invocations_create, 'expected Api::V2::JobInvocationsController#create to run'
101+
assert_match(%r{\A/job_invocations/\d+\z}, page.current_path)
102+
ensure
103+
ActiveSupport::Notifications.unsubscribe(subscriber)
104+
end
105+
end
106+
107+
test 'job wizard create API request sends job_template_id and inputs for default template' do
108+
input_value = 'api_payload_default_template'
109+
job_inv_params = capture_api_job_invocation_params_during do
110+
visit new_job_invocation_path(
111+
:search => "id = #{@rex_host.id}",
112+
:inputs => { WIZARD_INPUT_NAME => input_value }
113+
)
114+
navigate_job_wizard_to_review_step!
115+
find(:ouia_component_id, 'run-on-selected-hosts-footer').click
116+
wait_for_ajax
117+
end
118+
119+
assert job_inv_params, 'expected job_invocation key in POST /api/job_invocations'
120+
assert job_inv_params[:job_template_id].present?, 'expected job_template_id to be present'
121+
assert_equal @default_job_template.id, job_inv_params[:job_template_id].to_i
122+
assert job_inv_params[:feature].blank?
123+
assert_equal input_value, hash_from_params_object(job_inv_params[:inputs])[WIZARD_INPUT_NAME]
124+
job_invocation_id = page.current_path.split('/').last.to_i
125+
assert_equal @default_job_template.job_category, JobInvocation.find(job_invocation_id).job_category, 'expected job category to be the default template category'
126+
end
127+
128+
test 'job wizard create API request sends feature label and inputs without job_template_id' do
129+
input_value = 'api_payload_feature_template'
130+
job_inv_params = capture_api_job_invocation_params_during do
131+
visit new_job_invocation_path(
132+
:feature => @remote_execution_feature.label,
133+
:search => "id = #{@rex_host.id}",
134+
:inputs => { WIZARD_FEATURE_INPUT_NAME => input_value }
135+
)
136+
navigate_job_wizard_to_review_step!
137+
find(:ouia_component_id, 'run-on-selected-hosts-footer').click
138+
wait_for_ajax
139+
end
140+
141+
assert job_inv_params, 'expected job_invocation key in POST /api/job_invocations'
142+
assert_not job_inv_params[:job_template_id].present?
143+
assert_equal @remote_execution_feature.label, job_inv_params[:feature]
144+
assert_equal input_value, hash_from_params_object(job_inv_params[:inputs])[WIZARD_FEATURE_INPUT_NAME]
145+
job_invocation_id = page.current_path.split('/').last.to_i
146+
assert_equal @feature_job_template.job_category, JobInvocation.find(job_invocation_id).job_category, 'expected job category to be the feature template category'
147+
end
148+
149+
private
150+
151+
def capture_api_job_invocation_params_during
152+
captured = nil
153+
subscriber = ActiveSupport::Notifications.subscribe('start_processing.action_controller') do |_n, _s, _f, _i, payload|
154+
next unless payload[:controller].to_s.end_with?('JobInvocationsController') && payload[:action].to_s == 'create'
155+
root = payload[:params]
156+
root = root.to_unsafe_h if root.respond_to?(:to_unsafe_h)
157+
job_inv_params = root[:job_invocation] || root['job_invocation']
158+
next unless job_inv_params
159+
job_inv_params = job_inv_params.to_unsafe_h if job_inv_params.respond_to?(:to_unsafe_h)
160+
captured = job_inv_params.with_indifferent_access
161+
end
162+
begin
163+
yield
164+
ensure
165+
ActiveSupport::Notifications.unsubscribe(subscriber)
166+
end
167+
captured
168+
end
169+
170+
def hash_from_params_object(obj)
171+
return {}.with_indifferent_access if obj.blank?
172+
h = obj.respond_to?(:to_unsafe_h) ? obj.to_unsafe_h : obj.to_h
173+
h.with_indifferent_access
174+
end
175+
176+
def add_plain_template_input!(job_template, name: WIZARD_INPUT_NAME)
177+
job_template.template_inputs << FactoryBot.build(
178+
:template_input,
179+
:name => name,
180+
:input_type => 'user',
181+
:value_type => 'plain',
182+
:required => false
183+
)
184+
job_template.save!
185+
end
186+
187+
def job_wizard_click_next!
188+
wait_for_ajax
189+
find(:ouia_component_id, 'next-footer').click
190+
wait_for_ajax
191+
end
192+
193+
def go_to_target_hosts_and_inputs_step!
194+
assert_text 'Category and template', :wait => 30
195+
wait_for_ajax
196+
job_wizard_click_next!
197+
assert_text 'Target hosts and inputs', :wait => 30
198+
wait_for_ajax
199+
end
200+
201+
def navigate_job_wizard_to_review_step!
202+
assert_text 'Category and template', :wait => 30
203+
wait_for_ajax
204+
job_wizard_click_next!
205+
assert_text 'Target hosts and inputs', :wait => 30
206+
job_wizard_click_next!
207+
assert_text 'Advanced fields', :wait => 30
208+
job_wizard_click_next!
209+
assert_text 'Immediate execution', :wait => 30
210+
job_wizard_click_next!
211+
assert_text 'Review details', :wait => 30
212+
wait_for_ajax
213+
end
214+
end

0 commit comments

Comments
 (0)