ruby_raider 3.10.0 → 3.12.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/reek.yml +5 -1
- data/.github/workflows/release.yml +2 -1
- data/.github/workflows/system_tests.yml +1 -1
- data/.reek.yml +13 -0
- data/README.md +44 -4
- data/lib/commands/utility_commands.rb +1 -1
- data/lib/generators/automation/automation_generator.rb +15 -10
- data/lib/generators/automation/templates/appium_caps.tt +2 -4
- data/lib/generators/automation/templates/home.tt +1 -2
- data/lib/generators/automation/templates/login.tt +6 -6
- data/lib/generators/automation/templates/page.tt +10 -3
- data/lib/generators/automation/templates/partials/home_page_selector.tt +4 -6
- data/lib/generators/automation/templates/partials/pdp_page_selector.tt +4 -6
- data/lib/generators/automation/templates/pdp.tt +3 -2
- data/lib/generators/cucumber/cucumber_generator.rb +15 -2
- data/lib/generators/cucumber/templates/feature.tt +5 -0
- data/lib/generators/cucumber/templates/partials/driver_world.tt +9 -0
- data/lib/generators/cucumber/templates/partials/mobile_steps.tt +1 -1
- data/lib/generators/cucumber/templates/partials/selenium_env.tt +20 -0
- data/lib/generators/cucumber/templates/partials/watir_env.tt +16 -0
- data/lib/generators/cucumber/templates/partials/web_steps.tt +8 -0
- data/lib/generators/generator.rb +15 -4
- data/lib/generators/helper_generator.rb +15 -0
- data/lib/generators/invoke_generators.rb +23 -0
- data/lib/generators/menu_generator.rb +26 -14
- data/lib/generators/rspec/rspec_generator.rb +10 -3
- data/lib/generators/rspec/templates/spec.tt +27 -1
- data/lib/generators/template_renderer/template_error.rb +8 -8
- data/lib/generators/templates/common/git_ignore.tt +4 -1
- data/lib/generators/templates/common/partials/mobile_config.tt +1 -0
- data/lib/generators/templates/common/partials/web_config.tt +5 -2
- data/lib/generators/templates/common/read_me.tt +508 -0
- data/lib/generators/templates/helpers/partials/selenium_driver.tt +1 -3
- data/lib/generators/templates/helpers/raider_element.tt +159 -0
- data/lib/generators/templates/helpers/session_state.tt +246 -0
- data/lib/generators/templates/helpers/spec_helper.tt +28 -0
- data/lib/generators/templates/helpers/wait_helper.tt +470 -0
- data/lib/ruby_raider/ffmpeg.rb +7 -7
- data/lib/ruby_raider.rb +2 -0
- data/lib/scaffolding/project_detector.rb +6 -0
- data/lib/scaffolding/scaffolding.rb +4 -0
- data/lib/scaffolding/templates/component.tt +4 -0
- data/lib/scaffolding/templates/page_object.tt +8 -0
- data/lib/version +1 -1
- data/ruby_raider.gemspec +1 -0
- data/sig/generators/generator.rbs +2 -0
- data/sig/scaffolding/project_detector.rbs +1 -0
- data/sig/scaffolding/scaffolding.rbs +1 -0
- data/spec/commands/raider_commands_spec.rb +24 -0
- data/spec/fixtures/watir_master/cucumber_watir/Readme.md.snapshot +175 -0
- data/spec/fixtures/watir_master/cucumber_watir/features/step_definitions/login_steps.rb.snapshot +24 -0
- data/spec/fixtures/watir_master/cucumber_watir/page_objects/abstract/page.rb.snapshot +39 -0
- data/spec/fixtures/watir_master/cucumber_watir/page_objects/pages/login.rb.snapshot +33 -0
- data/spec/fixtures/watir_master/rspec_watir/Readme.md.snapshot +174 -0
- data/spec/fixtures/watir_master/rspec_watir/page_objects/abstract/page.rb.snapshot +39 -0
- data/spec/fixtures/watir_master/rspec_watir/page_objects/pages/login.rb.snapshot +33 -0
- data/spec/fixtures/watir_master/rspec_watir/spec/login_page_spec.rb.snapshot +49 -0
- data/spec/integration/commands/scaffolding_commands_spec.rb +49 -0
- data/spec/integration/commands/utility_commands_spec.rb +8 -0
- data/spec/integration/content/azure_content_spec.rb +4 -0
- data/spec/integration/content/ci_content_spec.rb +11 -0
- data/spec/integration/content/common_content_spec.rb +27 -0
- data/spec/integration/content/config_content_spec.rb +62 -0
- data/spec/integration/content/cucumber_reporter_content_spec.rb +25 -0
- data/spec/integration/content/helper_content_spec.rb +111 -0
- data/spec/integration/content/page_content_spec.rb +75 -4
- data/spec/integration/content/readme_content_spec.rb +149 -0
- data/spec/integration/content/syntax_validation_spec.rb +38 -0
- data/spec/integration/content/test_content_spec.rb +82 -0
- data/spec/integration/end_to_end_spec.rb +73 -28
- data/spec/integration/generators/automation_generator_spec.rb +50 -0
- data/spec/integration/generators/common_generator_spec.rb +20 -0
- data/spec/integration/generators/config_features_spec.rb +2 -2
- data/spec/integration/generators/cucumber_generator_spec.rb +36 -0
- data/spec/integration/generators/helpers_generator_spec.rb +60 -0
- data/spec/integration/generators/invoke_generators_spec.rb +70 -0
- data/spec/integration/generators/rspec_generator_spec.rb +20 -0
- data/spec/integration/helpers/session_state_spec.rb +474 -0
- data/spec/integration/helpers/wait_helper_mobile_spec.rb +281 -0
- data/spec/integration/helpers/wait_helper_spec.rb +496 -0
- data/spec/integration/helpers/wait_helper_support.rb +183 -0
- data/spec/integration/settings_helper.rb +4 -1
- data/spec/integration/spec_helper.rb +2 -2
- data/spec/menus/menu_generator_spec.rb +64 -2
- data/spec/scaffolding/scaffold_project_detector_spec.rb +12 -0
- metadata +31 -2
|
@@ -116,18 +116,41 @@ describe 'Test file content' do
|
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
+
shared_examples 'logged in example' do |project_name|
|
|
120
|
+
it 'adds a :logged_in example that reuses the saved login and keeps the login example' do
|
|
121
|
+
spec = read_generated(project_name, 'spec/login_page_spec.rb')
|
|
122
|
+
expect(spec).to include("describe 'Account', :logged_in", 'opens the account page with the saved login',
|
|
123
|
+
"describe 'Login' do", 'can successfully log in')
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
shared_examples 'logged in scenario' do |project_name|
|
|
128
|
+
it 'adds a @logged_in scenario and keeps the login scenario' do
|
|
129
|
+
feature = read_generated(project_name, 'features/login.feature')
|
|
130
|
+
expect(feature).to include("@logged_in\nScenario: A logged-in user opens the account page",
|
|
131
|
+
"Given I'm a registered user\n", 'Scenario: A user can login')
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'defines the step that picks the user without logging in' do
|
|
135
|
+
steps = read_generated(project_name, 'features/step_definitions/login_steps.rb')
|
|
136
|
+
expect(steps).to include(%q(Given("I'm a {user}") do |user|))
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
119
140
|
# --- RSpec contexts ---
|
|
120
141
|
|
|
121
142
|
context 'with rspec and selenium' do
|
|
122
143
|
name = "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
|
|
123
144
|
include_examples 'valid rspec spec', name
|
|
124
145
|
include_examples 'selenium rspec spec', name
|
|
146
|
+
include_examples 'logged in example', name
|
|
125
147
|
end
|
|
126
148
|
|
|
127
149
|
context 'with rspec and watir' do
|
|
128
150
|
name = "#{FrameworkIndex::RSPEC}_#{AutomationIndex::WATIR}"
|
|
129
151
|
include_examples 'valid rspec spec', name
|
|
130
152
|
include_examples 'watir rspec spec', name
|
|
153
|
+
include_examples 'logged in example', name
|
|
131
154
|
end
|
|
132
155
|
|
|
133
156
|
# --- Cucumber contexts ---
|
|
@@ -138,6 +161,7 @@ describe 'Test file content' do
|
|
|
138
161
|
include_examples 'valid cucumber env', name
|
|
139
162
|
include_examples 'valid cucumber world', name
|
|
140
163
|
include_examples 'valid cucumber config', name
|
|
164
|
+
include_examples 'logged in scenario', name
|
|
141
165
|
end
|
|
142
166
|
|
|
143
167
|
context 'with cucumber and watir' do
|
|
@@ -146,5 +170,63 @@ describe 'Test file content' do
|
|
|
146
170
|
include_examples 'valid cucumber env', name
|
|
147
171
|
include_examples 'valid cucumber world', name
|
|
148
172
|
include_examples 'valid cucumber config', name
|
|
173
|
+
include_examples 'logged in scenario', name
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
describe 'Cucumber world WaitHelper wiring' do
|
|
178
|
+
%w[selenium ios android cross_platform].each do |automation|
|
|
179
|
+
it "makes WaitHelper available to steps in #{automation}" do
|
|
180
|
+
world = read_generated("cucumber_#{automation}", 'features/support/world.rb')
|
|
181
|
+
expect(world).to include("require_relative '../../helpers/wait_helper'", 'World(WaitHelper)')
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'leaves the watir world without WaitHelper' do
|
|
186
|
+
expect(read_generated('cucumber_watir', 'features/support/world.rb')).not_to include('WaitHelper')
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
describe 'Example tests on the wait helper' do
|
|
191
|
+
it 'wraps every assertion of the selenium rspec spec in eventually' do
|
|
192
|
+
spec = read_generated('rspec_selenium', 'spec/login_page_spec.rb')
|
|
193
|
+
expect(spec.scan('eventually { expect(').size).to eq(3)
|
|
194
|
+
expect(spec.scan(/^ +expect\(/)).to be_empty
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it "wraps the selenium cucumber Then step's assertion in eventually" do
|
|
198
|
+
steps = read_generated('cucumber_selenium', 'features/step_definitions/login_steps.rb')
|
|
199
|
+
expect(steps).to include('eventually { expect(account_page.header.customer_name).to eq ')
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
%w[ios android cross_platform].each do |automation|
|
|
203
|
+
it "wraps the #{automation} rspec assertion in eventually" do
|
|
204
|
+
spec = read_generated("rspec_#{automation}", 'spec/pdp_page_spec.rb')
|
|
205
|
+
expect(spec).to include("eventually { expect(pdp_page.add_to_cart_text).to eq 'Add to Cart' }")
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "wraps the #{automation} cucumber Then step's assertion in eventually" do
|
|
209
|
+
steps = read_generated("cucumber_#{automation}", 'features/step_definitions/home_steps.rb')
|
|
210
|
+
expect(steps).to include("eventually { expect(pdp_page.add_to_cart_text).to eq 'Add to Cart' }")
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# The Watir output must stay as master generated it (1274a66); the snapshots in
|
|
216
|
+
# spec/fixtures/watir_master were generated from that commit's lib.
|
|
217
|
+
# To regenerate: `git archive 1274a66 lib` into a scratch dir, generate rspec and cucumber Watir projects there,
|
|
218
|
+
# then apply only the Readme deprecation-line delta (the `> **Deprecated:**` line under the heading block).
|
|
219
|
+
describe 'Watir example output' do
|
|
220
|
+
snapshots = File.expand_path('../../fixtures/watir_master', __dir__)
|
|
221
|
+
|
|
222
|
+
{ 'rspec_watir' => %w[page_objects/pages/login.rb page_objects/abstract/page.rb spec/login_page_spec.rb Readme.md],
|
|
223
|
+
'cucumber_watir' => %w[page_objects/pages/login.rb page_objects/abstract/page.rb
|
|
224
|
+
features/step_definitions/login_steps.rb Readme.md] }.each do |project, files|
|
|
225
|
+
files.each do |file|
|
|
226
|
+
it "keeps #{project}/#{file} as master generates it" do
|
|
227
|
+
expected = File.read(File.join(snapshots, project, "#{file}.snapshot"))
|
|
228
|
+
expect(read_generated(project, file)).to eq(expected)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
149
231
|
end
|
|
150
232
|
end
|
|
@@ -269,6 +269,29 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
269
269
|
context 'Web Automation Frameworks' do
|
|
270
270
|
describe 'Selenium + RSpec' do
|
|
271
271
|
include_examples 'executable rspec project', 'rspec_selenium'
|
|
272
|
+
|
|
273
|
+
it 'saves the login once and reuses it', :aggregate_failures, :slow do
|
|
274
|
+
skip 'Bundle install failed' unless bundle_install('rspec_selenium')
|
|
275
|
+
|
|
276
|
+
state_file = File.join('rspec_selenium', '.raider', 'auth', 'user.json')
|
|
277
|
+
FileUtils.rm_rf(File.join('rspec_selenium', '.raider'))
|
|
278
|
+
first = run_in_project('rspec_selenium', 'bundle exec rspec spec/', env: { 'HEADLESS' => 'true' })
|
|
279
|
+
failed = ->(run, index) { "Run #{index} failed.\nSTDOUT: #{run[:stdout]}\nSTDERR: #{run[:stderr]}" }
|
|
280
|
+
raise failed.call(first, 1) unless first[:exit_code].zero? # show run 1's output, not a missing state file
|
|
281
|
+
|
|
282
|
+
expect(File).to exist(state_file)
|
|
283
|
+
saved = JSON.parse(File.read(state_file))
|
|
284
|
+
second = run_in_project('rspec_selenium', 'bundle exec rspec spec/', env: { 'HEADLESS' => 'true' })
|
|
285
|
+
expect(second[:exit_code]).to eq(0), failed.call(second, 2)
|
|
286
|
+
expect(File.stat(state_file).mode & 0o777).to eq(0o600)
|
|
287
|
+
expect(saved).to include('format' => 1, 'origin' => 'https://raider-test-site.onrender.com')
|
|
288
|
+
expect(JSON.parse(File.read(state_file))['saved_at']).to eq(saved['saved_at'])
|
|
289
|
+
cookie_values = saved['cookies'].map { |cookie| cookie['value'].to_s }
|
|
290
|
+
expect(cookie_values.reject(&:empty?)).not_to be_empty
|
|
291
|
+
output = [first, second].map { |run| run[:stdout] + run[:stderr] }.join
|
|
292
|
+
# Short values like "1" or "en" can appear in any output; a leaked token is long.
|
|
293
|
+
cookie_values.select { |value| value.length >= 8 }.each { |value| expect(output).not_to include(value) }
|
|
294
|
+
end
|
|
272
295
|
end
|
|
273
296
|
|
|
274
297
|
describe 'Watir + RSpec' do
|
|
@@ -375,6 +398,40 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
375
398
|
end
|
|
376
399
|
end
|
|
377
400
|
|
|
401
|
+
# An empty skeleton (examples: false) still passes its run, so its CI is green until tests are added
|
|
402
|
+
def generate_skeleton_project(framework)
|
|
403
|
+
name = "skeleton_e2e_#{framework}_selenium"
|
|
404
|
+
unless LazyProjectGenerator::GENERATED.include?(name)
|
|
405
|
+
generate_framework(framework:, automation: 'selenium', name:, examples: false)
|
|
406
|
+
LazyProjectGenerator::GENERATED.add(name)
|
|
407
|
+
end
|
|
408
|
+
name
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
context 'Empty skeleton projects (examples: false)' do
|
|
412
|
+
it 'runs bundle exec rspec on a selenium rspec skeleton with 0 examples', :aggregate_failures do
|
|
413
|
+
project = generate_skeleton_project('rspec')
|
|
414
|
+
skip 'Bundle install failed' unless bundle_install(project)
|
|
415
|
+
|
|
416
|
+
['rspec', 'rspec spec/'].each do |command|
|
|
417
|
+
result = run_in_project(project, "bundle exec #{command}", timeout: 120)
|
|
418
|
+
expect(result[:exit_code]).to eq(0), "#{command}\nSTDOUT: #{result[:stdout]}\nSTDERR: #{result[:stderr]}"
|
|
419
|
+
expect(result[:stdout]).to include('0 examples, 0 failures')
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
it 'runs bundle exec cucumber on a selenium cucumber skeleton with 0 scenarios', :aggregate_failures do
|
|
424
|
+
project = generate_skeleton_project('cucumber')
|
|
425
|
+
skip 'Bundle install failed' unless bundle_install(project)
|
|
426
|
+
|
|
427
|
+
['cucumber', 'cucumber features'].each do |command|
|
|
428
|
+
result = run_in_project(project, "bundle exec #{command}", timeout: 120)
|
|
429
|
+
expect(result[:exit_code]).to eq(0), "#{command}\nSTDOUT: #{result[:stdout]}\nSTDERR: #{result[:stderr]}"
|
|
430
|
+
expect(result[:stdout]).to include('0 scenarios')
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
378
435
|
# Failure video replay against real browsers. Needs an ffmpeg with libvpx (RAIDER_FFMPEG_PATH), because the
|
|
379
436
|
# RaiderHQ ffmpeg release has no checksums yet. Skipped when it, or the browser, is missing. Firefox can be
|
|
380
437
|
# pointed at a specific binary with FIREFOX_BINARY.
|
|
@@ -660,38 +717,26 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
660
717
|
|
|
661
718
|
# Verify template system performance (caching working)
|
|
662
719
|
context 'Template System Performance' do
|
|
663
|
-
it '
|
|
720
|
+
it 'compiles each partial once and reuses it on the second generation' do
|
|
664
721
|
require_relative '../../lib/generators/generator'
|
|
665
722
|
|
|
666
|
-
# Clear cache
|
|
667
723
|
Generator.clear_template_cache
|
|
724
|
+
compiled = []
|
|
725
|
+
allow_any_instance_of(TemplateRenderer::PartialCache).to(
|
|
726
|
+
receive(:compile_template).and_wrap_original { |original, *args| compiled << args.first && original.call(*args) }
|
|
727
|
+
)
|
|
668
728
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
generate_framework(settings2)
|
|
681
|
-
second_duration = Time.now - start_time
|
|
682
|
-
|
|
683
|
-
# Second generation should be faster (or similar if I/O dominates)
|
|
684
|
-
# At minimum, cache should not slow things down
|
|
685
|
-
expect(second_duration).to be <= (first_duration * 1.2)
|
|
686
|
-
|
|
687
|
-
# Cleanup
|
|
688
|
-
FileUtils.rm_rf('test_cache_1')
|
|
689
|
-
FileUtils.rm_rf('test_cache_2')
|
|
690
|
-
|
|
691
|
-
# Verify cache has entries
|
|
692
|
-
stats = Generator.template_cache_stats
|
|
693
|
-
expect(stats[:size]).to be > 0
|
|
694
|
-
puts "\n📊 Template cache: #{stats[:size]} entries, ~#{stats[:memory_estimate] / 1024}KB"
|
|
729
|
+
%w[test_cache_1 test_cache_2].map do |name|
|
|
730
|
+
before = compiled.size
|
|
731
|
+
generate_framework(create_settings(framework: 'rspec', automation: 'selenium').merge(name:))
|
|
732
|
+
compiled.size - before
|
|
733
|
+
end => [first, second]
|
|
734
|
+
|
|
735
|
+
expect(first).to be_positive
|
|
736
|
+
expect(second).to eq(0)
|
|
737
|
+
expect(Generator.template_cache_stats[:size]).to be_positive
|
|
738
|
+
ensure
|
|
739
|
+
FileUtils.rm_rf(%w[test_cache_1 test_cache_2])
|
|
695
740
|
end
|
|
696
741
|
end
|
|
697
742
|
end
|
|
@@ -71,4 +71,54 @@ describe AutomationGenerator do
|
|
|
71
71
|
context 'with cucumber and appium cross platform' do
|
|
72
72
|
include_examples 'creates mobile automation framework', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
73
73
|
end
|
|
74
|
+
|
|
75
|
+
describe 'without example tests' do
|
|
76
|
+
%w[rspec cucumber].product(%w[selenium ios cross_platform]).each do |framework, automation|
|
|
77
|
+
context "with #{framework} and #{automation}" do
|
|
78
|
+
let(:name) { ensure_project(framework:, automation:, examples: false) }
|
|
79
|
+
|
|
80
|
+
it 'creates no example pages' do
|
|
81
|
+
expect(Dir.glob("#{name}/page_objects/pages/*.rb")).to be_empty
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'keeps the pages folder with a .keep' do
|
|
85
|
+
expect(File).to exist("#{name}/page_objects/pages/.keep")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'creates the abstract page' do
|
|
89
|
+
expect(File).to exist("#{name}/page_objects/abstract/page.rb")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'gives the abstract page no header component' do
|
|
93
|
+
expect(File.read("#{name}/page_objects/abstract/page.rb")).not_to include('Header')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'creates no models' do
|
|
97
|
+
expect(File).not_to exist("#{name}/models")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'with a web project' do
|
|
103
|
+
let(:name) { ensure_project(framework: 'rspec', automation: 'selenium', examples: false) }
|
|
104
|
+
|
|
105
|
+
it 'creates the abstract component' do
|
|
106
|
+
expect(File).to exist("#{name}/page_objects/abstract/component.rb")
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'keeps the components folder with a .keep and no example component' do
|
|
110
|
+
expect(Dir.children("#{name}/page_objects/components")).to eq(['.keep'])
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
context 'with watir' do
|
|
115
|
+
it 'still creates the examples, because the Watir templates are frozen' do
|
|
116
|
+
InvokeGenerators.generate_framework(framework: 'rspec', automation: 'watir', name: 'skeleton_watir',
|
|
117
|
+
examples: false)
|
|
118
|
+
expect(File).to exist('skeleton_watir/page_objects/pages/login.rb')
|
|
119
|
+
ensure
|
|
120
|
+
FileUtils.rm_rf('skeleton_watir')
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
74
124
|
end
|
|
@@ -107,4 +107,24 @@ describe CommonGenerator do
|
|
|
107
107
|
include_examples 'creates a config file', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
108
108
|
include_examples 'creates a gitignore file', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
109
109
|
end
|
|
110
|
+
|
|
111
|
+
describe 'without example tests' do
|
|
112
|
+
%w[rspec cucumber].product(%w[selenium ios cross_platform]).each do |framework, automation|
|
|
113
|
+
context "with #{framework} and #{automation}" do
|
|
114
|
+
let(:name) { ensure_project(framework:, automation:, examples: false) }
|
|
115
|
+
let(:ci_file) { automation == 'selenium' ? 'test_pipeline.yml' : 'appium_pipeline.yml' }
|
|
116
|
+
|
|
117
|
+
it 'creates the README, Gemfile, Rakefile and CI file' do
|
|
118
|
+
%W[Readme.md Gemfile Rakefile .github/workflows/#{ci_file}].each do |file|
|
|
119
|
+
expect(File).to exist("#{name}/#{file}")
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'creates the settings' do
|
|
124
|
+
settings = automation == 'ios' ? 'config/capabilities.yml' : 'config/config.yml'
|
|
125
|
+
expect(File).to exist("#{name}/#{settings}")
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
110
130
|
end
|
|
@@ -35,9 +35,9 @@ describe 'Config features for generated projects' do
|
|
|
35
35
|
expect(config['driver_options']).to be_nil
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
it 'generates driver_helper
|
|
38
|
+
it 'generates driver_helper without an implicit wait' do
|
|
39
39
|
helper = File.read('config_selenium_test/helpers/driver_helper.rb')
|
|
40
|
-
expect(helper).
|
|
40
|
+
expect(helper).not_to include('implicit_wait')
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
it 'generates spec_helper with viewport-aware window setup' do
|
|
@@ -61,4 +61,40 @@ describe CucumberGenerator do
|
|
|
61
61
|
include_examples 'creates cucumber files', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::WATIR}", 'login'
|
|
62
62
|
include_examples 'creates factories for web projects', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::WATIR}", 'login'
|
|
63
63
|
end
|
|
64
|
+
|
|
65
|
+
describe 'without example tests' do
|
|
66
|
+
%w[selenium ios cross_platform].each do |automation|
|
|
67
|
+
context "with cucumber and #{automation}" do
|
|
68
|
+
let(:name) { ensure_project(framework: 'cucumber', automation:, examples: false) }
|
|
69
|
+
|
|
70
|
+
it 'creates no feature files' do
|
|
71
|
+
expect(Dir.glob("#{name}/features/**/*.feature")).to be_empty
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'keeps an empty step_definitions folder' do
|
|
75
|
+
expect(Dir.children("#{name}/features/step_definitions")).to eq(['.keep'])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'creates the support files' do
|
|
79
|
+
expect(Dir.children("#{name}/features/support")).to contain_exactly('env.rb', 'world.rb')
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'creates the cucumber.yml file' do
|
|
83
|
+
expect(File).to exist("#{name}/cucumber.yml")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'creates no user factory' do
|
|
87
|
+
expect(File).not_to exist("#{name}/models/user_factory.rb")
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'creates no accessibility example' do
|
|
93
|
+
InvokeGenerators.generate_framework(framework: 'cucumber', automation: 'selenium', name: 'skeleton_axe_cucumber',
|
|
94
|
+
examples: false, accessibility: true)
|
|
95
|
+
expect(Dir.glob('skeleton_axe_cucumber/features/**/accessibility*')).to be_empty
|
|
96
|
+
ensure
|
|
97
|
+
FileUtils.rm_rf('skeleton_axe_cucumber')
|
|
98
|
+
end
|
|
99
|
+
end
|
|
64
100
|
end
|
|
@@ -10,6 +10,18 @@ describe HelpersGenerator do
|
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
shared_examples 'creates a session state helper' do |name|
|
|
14
|
+
it 'creates a session state helper file' do
|
|
15
|
+
expect(File).to exist("#{name}/helpers/session_state.rb")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
shared_examples 'skips the session state helper' do |name|
|
|
20
|
+
it 'does not create a session state helper file' do
|
|
21
|
+
expect(File).not_to exist("#{name}/helpers/session_state.rb")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
13
25
|
shared_examples 'creates selenium helpers' do |name|
|
|
14
26
|
it 'creates a driver helper file' do
|
|
15
27
|
expect(File).to exist("#{name}/helpers/driver_helper.rb")
|
|
@@ -20,6 +32,18 @@ describe HelpersGenerator do
|
|
|
20
32
|
it 'creates a browser helper file' do
|
|
21
33
|
expect(File).to exist("#{name}/helpers/browser_helper.rb")
|
|
22
34
|
end
|
|
35
|
+
|
|
36
|
+
it 'does not create the wait helper or the element wrapper' do
|
|
37
|
+
expect(File).not_to exist("#{name}/helpers/wait_helper.rb")
|
|
38
|
+
expect(File).not_to exist("#{name}/helpers/raider_element.rb")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
shared_examples 'creates the wait helper' do |name|
|
|
43
|
+
it 'creates the wait helper and the element wrapper' do
|
|
44
|
+
expect(File).to exist("#{name}/helpers/wait_helper.rb")
|
|
45
|
+
expect(File).to exist("#{name}/helpers/raider_element.rb")
|
|
46
|
+
end
|
|
23
47
|
end
|
|
24
48
|
|
|
25
49
|
shared_examples 'creates rspec helpers' do |name|
|
|
@@ -42,63 +66,99 @@ describe HelpersGenerator do
|
|
|
42
66
|
|
|
43
67
|
context 'with rspec and selenium' do
|
|
44
68
|
include_examples 'creates common helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
|
|
69
|
+
include_examples 'creates a session state helper', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
|
|
45
70
|
include_examples 'creates selenium helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
|
|
71
|
+
include_examples 'creates the wait helper', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
|
|
46
72
|
include_examples 'creates rspec helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
|
|
47
73
|
end
|
|
48
74
|
|
|
49
75
|
context 'with rspec and watir' do
|
|
50
76
|
include_examples 'creates common helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::WATIR}"
|
|
77
|
+
include_examples 'creates a session state helper', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::WATIR}"
|
|
51
78
|
include_examples 'creates watir helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::WATIR}"
|
|
52
79
|
include_examples 'creates rspec helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::WATIR}"
|
|
53
80
|
end
|
|
54
81
|
|
|
55
82
|
context 'with cucumber and selenium' do
|
|
56
83
|
include_examples 'creates common helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::SELENIUM}"
|
|
84
|
+
include_examples 'creates a session state helper', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::SELENIUM}"
|
|
57
85
|
include_examples 'creates selenium helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::SELENIUM}"
|
|
86
|
+
include_examples 'creates the wait helper', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::SELENIUM}"
|
|
58
87
|
include_examples 'creates cucumber helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::SELENIUM}"
|
|
59
88
|
end
|
|
60
89
|
|
|
61
90
|
context 'with cucumber and watir' do
|
|
62
91
|
include_examples 'creates common helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::WATIR}"
|
|
92
|
+
include_examples 'creates a session state helper', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::WATIR}"
|
|
63
93
|
include_examples 'creates watir helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::WATIR}"
|
|
64
94
|
include_examples 'creates cucumber helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::WATIR}"
|
|
65
95
|
end
|
|
66
96
|
|
|
67
97
|
context 'with rspec and appium android' do
|
|
68
98
|
include_examples 'creates common helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::ANDROID}"
|
|
99
|
+
include_examples 'skips the session state helper', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::ANDROID}"
|
|
69
100
|
include_examples 'creates selenium helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::ANDROID}"
|
|
101
|
+
include_examples 'creates the wait helper', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::ANDROID}"
|
|
70
102
|
include_examples 'creates rspec helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::ANDROID}"
|
|
71
103
|
end
|
|
72
104
|
|
|
73
105
|
context 'with rspec and appium ios' do
|
|
74
106
|
include_examples 'creates common helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::IOS}"
|
|
107
|
+
include_examples 'skips the session state helper', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::IOS}"
|
|
75
108
|
include_examples 'creates selenium helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::IOS}"
|
|
109
|
+
include_examples 'creates the wait helper', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::IOS}"
|
|
76
110
|
include_examples 'creates rspec helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::IOS}"
|
|
77
111
|
end
|
|
78
112
|
|
|
79
113
|
context 'with cucumber and appium android' do
|
|
80
114
|
include_examples 'creates common helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::ANDROID}"
|
|
115
|
+
include_examples 'skips the session state helper', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::ANDROID}"
|
|
81
116
|
include_examples 'creates selenium helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::ANDROID}"
|
|
117
|
+
include_examples 'creates the wait helper', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::ANDROID}"
|
|
82
118
|
include_examples 'creates cucumber helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::ANDROID}"
|
|
83
119
|
end
|
|
84
120
|
|
|
85
121
|
context 'with cucumber and appium ios' do
|
|
86
122
|
include_examples 'creates common helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::IOS}"
|
|
123
|
+
include_examples 'skips the session state helper', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::IOS}"
|
|
87
124
|
include_examples 'creates selenium helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::IOS}"
|
|
125
|
+
include_examples 'creates the wait helper', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::IOS}"
|
|
88
126
|
include_examples 'creates cucumber helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::IOS}"
|
|
89
127
|
end
|
|
90
128
|
|
|
91
129
|
context 'with rspec and appium cross platform' do
|
|
92
130
|
include_examples 'creates common helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
131
|
+
include_examples 'skips the session state helper', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
93
132
|
include_examples 'creates selenium helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
133
|
+
include_examples 'creates the wait helper', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
94
134
|
include_examples 'creates rspec helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
95
135
|
include_examples 'creates cross platform helpers', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
96
136
|
end
|
|
97
137
|
|
|
98
138
|
context 'with cucumber and appium cross platform' do
|
|
99
139
|
include_examples 'creates common helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
140
|
+
include_examples 'skips the session state helper', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
100
141
|
include_examples 'creates selenium helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
142
|
+
include_examples 'creates the wait helper', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
101
143
|
include_examples 'creates cucumber helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
102
144
|
include_examples 'creates cross platform helpers', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::CROSS_PLATFORM}"
|
|
103
145
|
end
|
|
146
|
+
|
|
147
|
+
describe 'without example tests' do
|
|
148
|
+
%w[rspec cucumber].product(%w[selenium ios cross_platform]).each do |framework, automation|
|
|
149
|
+
context "with #{framework} and #{automation}" do
|
|
150
|
+
let(:name) { ensure_project(framework:, automation:, examples: false) }
|
|
151
|
+
|
|
152
|
+
it 'creates the wait helper and RaiderElement' do
|
|
153
|
+
expect(File).to exist("#{name}/helpers/wait_helper.rb")
|
|
154
|
+
expect(File).to exist("#{name}/helpers/raider_element.rb")
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'keeps the session state for web' do
|
|
160
|
+
name = ensure_project(framework: 'rspec', automation: 'selenium', examples: false)
|
|
161
|
+
expect(File).to exist("#{name}/helpers/session_state.rb")
|
|
162
|
+
end
|
|
163
|
+
end
|
|
104
164
|
end
|
|
@@ -49,4 +49,74 @@ describe InvokeGenerators do
|
|
|
49
49
|
expect(File).not_to exist('case_bad_ci')
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
|
+
|
|
53
|
+
describe '.collect_flags' do
|
|
54
|
+
it 'adds no_examples when examples is false' do
|
|
55
|
+
expect(described_class.collect_flags(automation: 'selenium', examples: false)).to include('no_examples')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'keeps the examples by default' do
|
|
59
|
+
expect(described_class.collect_flags(automation: 'selenium')).not_to include('no_examples')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'keeps the examples for watir, whose templates are frozen' do
|
|
63
|
+
expect(described_class.collect_flags(automation: 'watir', examples: false)).not_to include('no_examples')
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'with the Watir deprecation notice' do
|
|
68
|
+
let(:notice) do
|
|
69
|
+
'Watir is deprecated and will be removed in the next major version of ruby_raider; new projects should use Selenium.'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'prints it for watir' do
|
|
73
|
+
expect { described_class.generate_framework(framework: 'rspec', automation: 'watir', name: 'case_dep') }
|
|
74
|
+
.to output(/#{Regexp.escape(notice)}/).to_stdout
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'does not print it for selenium' do
|
|
78
|
+
expect { described_class.generate_framework(framework: 'rspec', automation: 'selenium', name: 'case_nodep') }
|
|
79
|
+
.not_to output(/Watir is deprecated/).to_stdout
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'still prints it for raider new with automation:watir' do
|
|
83
|
+
root = File.expand_path('../../..', __dir__)
|
|
84
|
+
out, status = Open3.capture2e('ruby', "#{root}/bin/raider", 'new', 'case_cli_watir', '-p',
|
|
85
|
+
'framework:rspec', 'automation:watir')
|
|
86
|
+
expect(status.success?).to be(true)
|
|
87
|
+
expect(out).to include(notice)
|
|
88
|
+
expect(File).to exist('case_cli_watir/.rspec')
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context 'with examples false for watir' do
|
|
93
|
+
it 'says the examples are kept' do
|
|
94
|
+
expect { described_class.generate_framework(framework: 'rspec', automation: 'watir', name: 'case_watir', examples: false) }
|
|
95
|
+
.to output(/Watir projects always include the example tests/).to_stdout
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
describe 'Projects named like a generator option' do
|
|
101
|
+
after { FileUtils.rm_rf(%w[no_examples watir selenium]) }
|
|
102
|
+
|
|
103
|
+
it 'keeps the example tests in a project named no_examples' do
|
|
104
|
+
InvokeGenerators.generate_framework(automation: 'selenium', framework: 'rspec', name: 'no_examples')
|
|
105
|
+
expect(File).to exist('no_examples/spec/login_page_spec.rb')
|
|
106
|
+
expect(File).to exist('no_examples/page_objects/pages/login.rb')
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'gives a Selenium project named watir the wait helper it wires in' do
|
|
110
|
+
InvokeGenerators.generate_framework(automation: 'selenium', framework: 'cucumber', name: 'watir')
|
|
111
|
+
expect(File).to exist('watir/helpers/wait_helper.rb')
|
|
112
|
+
expect(File.read('watir/features/support/env.rb')).not_to include('Watir')
|
|
113
|
+
expect(File.read('watir/page_objects/abstract/page.rb')).to include('include WaitHelper')
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'keeps a Watir project named selenium on Watir' do
|
|
117
|
+
InvokeGenerators.generate_framework(automation: 'watir', framework: 'rspec', name: 'selenium')
|
|
118
|
+
expect(File).not_to exist('selenium/helpers/wait_helper.rb')
|
|
119
|
+
expect(File.read('selenium/page_objects/abstract/page.rb')).to include('browser.element')
|
|
120
|
+
expect(File.read('selenium/page_objects/abstract/page.rb')).not_to include('find_element')
|
|
121
|
+
end
|
|
52
122
|
end
|
|
@@ -46,4 +46,24 @@ describe RspecGenerator do
|
|
|
46
46
|
include_examples 'creates rspec files examples',
|
|
47
47
|
"#{FrameworkIndex::RSPEC}_#{AutomationIndex::CROSS_PLATFORM}", 'pdp'
|
|
48
48
|
end
|
|
49
|
+
|
|
50
|
+
describe 'without example tests' do
|
|
51
|
+
%w[selenium ios cross_platform].each do |automation|
|
|
52
|
+
context "with rspec and #{automation}" do
|
|
53
|
+
let(:name) { ensure_project(framework: 'rspec', automation:, examples: false) }
|
|
54
|
+
|
|
55
|
+
it 'creates an empty spec folder' do
|
|
56
|
+
expect(Dir.children("#{name}/spec")).to eq(['.keep'])
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'creates no accessibility example' do
|
|
62
|
+
InvokeGenerators.generate_framework(framework: 'rspec', automation: 'selenium', name: 'skeleton_axe_rspec',
|
|
63
|
+
examples: false, accessibility: true)
|
|
64
|
+
expect(Dir.children('skeleton_axe_rspec/spec')).to eq(['.keep'])
|
|
65
|
+
ensure
|
|
66
|
+
FileUtils.rm_rf('skeleton_axe_rspec')
|
|
67
|
+
end
|
|
68
|
+
end
|
|
49
69
|
end
|