ruby_raider 3.13.0 → 4.0.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/runtime.yml +38 -0
- data/.github/workflows/system_tests.yml +1 -23
- data/.reek.yml +1 -0
- data/.rspec +1 -0
- data/Gemfile +2 -0
- data/README.md +16 -49
- data/RELEASE.md +22 -0
- data/bin/raider +5 -0
- data/lib/commands/scaffolding_commands.rb +2 -25
- data/lib/commands/utility_commands.rb +23 -3
- data/lib/generators/automation/automation_generator.rb +0 -5
- data/lib/generators/automation/templates/component.tt +1 -0
- data/lib/generators/automation/templates/home.tt +2 -2
- data/lib/generators/automation/templates/login.tt +6 -26
- data/lib/generators/automation/templates/page.tt +23 -18
- data/lib/generators/automation/templates/partials/home_page_selector.tt +1 -2
- data/lib/generators/automation/templates/partials/initialize_selector.tt +0 -8
- data/lib/generators/automation/templates/partials/pdp_page_selector.tt +1 -2
- data/lib/generators/automation/templates/partials/url_methods.tt +8 -2
- data/lib/generators/automation/templates/partials/visit_method.tt +0 -5
- data/lib/generators/automation/templates/pdp.tt +1 -9
- data/lib/generators/common_generator.rb +0 -2
- data/lib/generators/generator.rb +12 -19
- data/lib/generators/helper_generator.rb +21 -19
- data/lib/generators/infrastructure/templates/azure_pipelines.tt +1 -1
- data/lib/generators/infrastructure/templates/github.tt +2 -3
- data/lib/generators/infrastructure/templates/github_appium.tt +0 -8
- data/lib/generators/invoke_generators.rb +4 -23
- data/lib/generators/menu_generator.rb +1 -9
- data/lib/generators/rspec/templates/accessibility_spec.tt +1 -9
- data/lib/generators/rspec/templates/spec.tt +8 -24
- data/lib/generators/template_renderer/partial_cache.rb +3 -1
- data/lib/generators/template_renderer.rb +1 -1
- data/lib/generators/templates/common/gemfile.tt +3 -10
- data/lib/generators/templates/common/git_ignore.tt +0 -5
- data/lib/generators/templates/common/partials/mobile_config.tt +3 -1
- data/lib/generators/templates/common/partials/web_config.tt +10 -1
- data/lib/generators/templates/common/rakefile.tt +0 -15
- data/lib/generators/templates/common/read_me.tt +357 -250
- data/lib/generators/templates/common/rubocop.tt +0 -2
- data/lib/generators/templates/helpers/driver_helper.tt +8 -0
- data/lib/generators/templates/helpers/gesture_helper.tt +78 -0
- data/lib/generators/templates/helpers/network_helper.tt +521 -0
- data/lib/generators/templates/helpers/partials/quit_driver.tt +0 -2
- data/lib/generators/templates/helpers/partials/screenshot.tt +0 -2
- data/lib/generators/templates/helpers/partials/selenium_driver.tt +5 -2
- data/lib/generators/templates/helpers/screenshot_helper.tt +490 -0
- data/lib/generators/templates/helpers/spec_helper.tt +39 -29
- data/lib/generators/templates/helpers/trace_helper.tt +240 -95
- data/lib/generators/templates/helpers/video_helper.tt +3 -8
- data/lib/ruby_raider/runtime/actionability.rb +129 -0
- data/lib/ruby_raider/runtime/actionable.rb +49 -0
- data/lib/ruby_raider/runtime/by_role.rb +55 -0
- data/lib/ruby_raider/runtime/config.rb +79 -0
- data/lib/ruby_raider/runtime/context.rb +38 -0
- data/lib/ruby_raider/runtime/errors.rb +69 -0
- data/lib/ruby_raider/runtime/finders.rb +73 -0
- data/lib/ruby_raider/runtime/js/actionability.js +134 -0
- data/lib/ruby_raider/runtime/js/role_engine.js +315 -0
- data/lib/ruby_raider/runtime/locator_converter.rb +72 -0
- data/lib/ruby_raider/runtime/matchers/base.rb +222 -0
- data/lib/ruby_raider/runtime/matchers/element.rb +183 -0
- data/lib/ruby_raider/runtime/matchers/page.rb +71 -0
- data/lib/ruby_raider/runtime/matchers/presence.rb +41 -0
- data/lib/ruby_raider/runtime/matchers/retrying_block.rb +104 -0
- data/lib/ruby_raider/runtime/observer.rb +170 -0
- data/lib/ruby_raider/runtime/role_finder.rb +83 -0
- data/lib/ruby_raider/runtime/rspec.rb +78 -0
- data/lib/ruby_raider/runtime/selectors.rb +60 -0
- data/lib/ruby_raider/runtime/strict.rb +142 -0
- data/lib/ruby_raider/runtime/wait.rb +84 -0
- data/lib/ruby_raider/runtime.rb +20 -0
- data/lib/scaffolding/name_normalizer.rb +1 -1
- data/lib/scaffolding/project_detector.rb +2 -28
- data/lib/scaffolding/scaffolding.rb +0 -20
- data/lib/scaffolding/templates/component.tt +0 -14
- data/lib/scaffolding/templates/page_object.tt +2 -14
- data/lib/scaffolding/templates/spec.tt +1 -9
- data/lib/utilities/utilities.rb +10 -8
- data/lib/version +1 -1
- data/ruby_raider.gemspec +2 -1
- data/sig/commands/scaffolding_commands.rbs +0 -2
- data/sig/commands/utility_commands.rbs +6 -0
- data/sig/generators/generator.rbs +0 -4
- data/sig/generators/helper_generator.rbs +0 -1
- data/sig/generators/menu_generator.rbs +0 -1
- data/sig/ruby_raider/runtime/actionability.rbs +25 -0
- data/sig/ruby_raider/runtime/actionable.rbs +13 -0
- data/sig/ruby_raider/runtime/by_role.rbs +15 -0
- data/sig/ruby_raider/runtime/config.rbs +26 -0
- data/sig/ruby_raider/runtime/context.rbs +12 -0
- data/sig/ruby_raider/runtime/errors.rbs +36 -0
- data/sig/ruby_raider/runtime/finders.rbs +26 -0
- data/sig/ruby_raider/runtime/locator_converter.rbs +21 -0
- data/sig/ruby_raider/runtime/matchers/base.rbs +64 -0
- data/sig/ruby_raider/runtime/matchers/element.rbs +78 -0
- data/sig/ruby_raider/runtime/matchers/page.rbs +38 -0
- data/sig/ruby_raider/runtime/matchers/presence.rbs +21 -0
- data/sig/ruby_raider/runtime/matchers/retrying_block.rbs +27 -0
- data/sig/ruby_raider/runtime/observer.rbs +46 -0
- data/sig/ruby_raider/runtime/role_finder.rbs +18 -0
- data/sig/ruby_raider/runtime/selectors.rbs +21 -0
- data/sig/ruby_raider/runtime/strict.rbs +35 -0
- data/sig/ruby_raider/runtime/wait.rbs +17 -0
- data/sig/ruby_raider/runtime.rbs +2 -0
- data/sig/scaffolding/project_detector.rbs +0 -4
- data/sig/scaffolding/scaffolding.rbs +0 -5
- data/sig/utilities/utilities.rbs +2 -1
- data/sig/vendor/selenium_webdriver.rbs +71 -0
- data/spec/commands/raider_commands_spec.rb +38 -3
- data/spec/commands/scaffolding_commands_spec.rb +27 -0
- data/spec/commands/utility_commands_spec.rb +53 -0
- data/spec/generators/gesture_helper_spec.rb +123 -0
- data/spec/generators/network_helper_spec.rb +634 -0
- data/spec/generators/screenshot_helper_spec.rb +776 -0
- data/spec/generators/template_renderer_spec.rb +0 -4
- data/spec/generators/trace_helper_spec.rb +489 -97
- data/spec/generators/video_helper_spec.rb +0 -9
- data/spec/integration/commands/browser_update_after_creation_spec.rb +0 -8
- data/spec/integration/commands/scaffolding_commands_spec.rb +12 -70
- data/spec/integration/commands/utility_commands_spec.rb +19 -41
- data/spec/integration/content/azure_content_spec.rb +2 -6
- data/spec/integration/content/ci_content_spec.rb +1 -55
- data/spec/integration/content/common_content_spec.rb +1 -118
- data/spec/integration/content/config_content_spec.rb +34 -31
- data/spec/integration/content/gemfile_content_spec.rb +7 -72
- data/spec/integration/content/helper_content_spec.rb +105 -99
- data/spec/integration/content/page_content_spec.rb +85 -87
- data/spec/integration/content/readme_content_spec.rb +134 -75
- data/spec/integration/content/rspec_reporter_content_spec.rb +2 -2
- data/spec/integration/content/rubocop_content_spec.rb +1 -1
- data/spec/integration/content/syntax_validation_spec.rb +2 -2
- data/spec/integration/content/test_content_spec.rb +23 -147
- data/spec/integration/end_to_end_features_spec.rb +1 -43
- data/spec/integration/end_to_end_spec.rb +319 -326
- data/spec/integration/generators/automation_generator_spec.rb +3 -37
- data/spec/integration/generators/axe_addon_spec.rb +2 -35
- data/spec/integration/generators/azure_generator_spec.rb +1 -1
- data/spec/integration/generators/common_generator_spec.rb +1 -40
- data/spec/integration/generators/config_features_spec.rb +1 -24
- data/spec/integration/generators/github_generator_spec.rb +0 -12
- data/spec/integration/generators/helpers_generator_spec.rb +74 -80
- data/spec/integration/generators/invoke_generators_spec.rb +54 -45
- data/spec/integration/generators/rspec_generator_spec.rb +0 -6
- data/spec/integration/scaffolding_e2e_spec.rb +17 -179
- data/spec/integration/spec_helper.rb +4 -6
- data/spec/integration/trace_format_checker.rb +11 -2
- data/spec/integration/trace_page_server.rb +72 -5
- data/spec/menus/menu_generator_spec.rb +14 -39
- data/spec/runtime/actionability_spec.rb +207 -0
- data/spec/runtime/actionable_spec.rb +125 -0
- data/spec/runtime/browser/actionability_script_browser_spec.rb +150 -0
- data/spec/runtime/browser/actionable_browser_spec.rb +98 -0
- data/spec/runtime/browser/finders_browser_spec.rb +148 -0
- data/spec/runtime/browser/matchers_browser_spec.rb +67 -0
- data/spec/runtime/browser/retrying_block_browser_spec.rb +37 -0
- data/spec/runtime/browser/role_engine_browser_spec.rb +184 -0
- data/spec/runtime/browser/strict_browser_spec.rb +38 -0
- data/spec/runtime/by_role_spec.rb +52 -0
- data/spec/runtime/config_spec.rb +79 -0
- data/spec/runtime/context_spec.rb +73 -0
- data/spec/runtime/errors_spec.rb +89 -0
- data/spec/runtime/finders_spec.rb +165 -0
- data/spec/runtime/fixtures/actionability.html +70 -0
- data/spec/runtime/fixtures/locators.html +46 -0
- data/spec/runtime/fixtures/matchers.html +33 -0
- data/spec/runtime/fixtures/roles.html +162 -0
- data/spec/runtime/matchers/base_spec.rb +165 -0
- data/spec/runtime/matchers/element_spec.rb +277 -0
- data/spec/runtime/matchers/page_spec.rb +102 -0
- data/spec/runtime/matchers/presence_spec.rb +59 -0
- data/spec/runtime/matchers/retrying_block_spec.rb +165 -0
- data/spec/runtime/observer_spec.rb +341 -0
- data/spec/runtime/role_finder_spec.rb +156 -0
- data/spec/runtime/role_query_spec.rb +75 -0
- data/spec/runtime/selectors_spec.rb +135 -0
- data/spec/runtime/strict_spec.rb +257 -0
- data/spec/runtime/support/browser.rb +48 -0
- data/spec/runtime/support/fake_bridge.rb +117 -0
- data/spec/runtime/wait_spec.rb +71 -0
- data/spec/scaffolding/name_normalizer_spec.rb +3 -2
- data/spec/scaffolding/scaffold_project_detector_spec.rb +4 -43
- data/spec/system/selenium_spec.rb +1 -5
- data/spec/system/support/system_test_helper.rb +2 -5
- data/spec/utilities/headless_config_spec.rb +0 -7
- data/spec/utilities/utilities_spec.rb +24 -0
- metadata +113 -48
- data/lib/generators/automation/templates/header.tt +0 -9
- data/lib/generators/cucumber/cucumber_generator.rb +0 -58
- data/lib/generators/cucumber/templates/accessibility_feature.tt +0 -5
- data/lib/generators/cucumber/templates/accessibility_steps.tt +0 -17
- data/lib/generators/cucumber/templates/cucumber.tt +0 -1
- data/lib/generators/cucumber/templates/env.tt +0 -7
- data/lib/generators/cucumber/templates/feature.tt +0 -21
- data/lib/generators/cucumber/templates/partials/appium_env.tt +0 -26
- data/lib/generators/cucumber/templates/partials/driver_world.tt +0 -18
- data/lib/generators/cucumber/templates/partials/mobile_steps.tt +0 -20
- data/lib/generators/cucumber/templates/partials/selenium_env.tt +0 -120
- data/lib/generators/cucumber/templates/partials/watir_env.tt +0 -48
- data/lib/generators/cucumber/templates/partials/watir_world.tt +0 -4
- data/lib/generators/cucumber/templates/partials/web_steps.tt +0 -28
- data/lib/generators/cucumber/templates/steps.tt +0 -5
- data/lib/generators/cucumber/templates/user_factory.tt +0 -15
- data/lib/generators/cucumber/templates/world.tt +0 -7
- data/lib/generators/templates/helpers/browser_helper.tt +0 -31
- data/lib/generators/templates/helpers/raider_element.tt +0 -159
- data/lib/generators/templates/helpers/wait_helper.tt +0 -611
- data/lib/scaffolding/templates/feature.tt +0 -6
- data/lib/scaffolding/templates/steps.tt +0 -19
- data/sig/generators/cucumber/cucumber_generator.rbs +0 -12
- data/spec/fixtures/watir_master/cucumber_watir/Readme.md.snapshot +0 -175
- data/spec/fixtures/watir_master/cucumber_watir/features/step_definitions/login_steps.rb.snapshot +0 -24
- data/spec/fixtures/watir_master/cucumber_watir/page_objects/abstract/page.rb.snapshot +0 -37
- data/spec/fixtures/watir_master/cucumber_watir/page_objects/pages/login.rb.snapshot +0 -33
- data/spec/fixtures/watir_master/rspec_watir/Readme.md.snapshot +0 -174
- data/spec/fixtures/watir_master/rspec_watir/page_objects/abstract/page.rb.snapshot +0 -37
- data/spec/fixtures/watir_master/rspec_watir/page_objects/pages/login.rb.snapshot +0 -33
- data/spec/fixtures/watir_master/rspec_watir/spec/login_page_spec.rb.snapshot +0 -49
- data/spec/integration/content/cucumber_reporter_content_spec.rb +0 -161
- data/spec/integration/generators/cucumber_generator_spec.rb +0 -100
- data/spec/integration/helpers/wait_helper_mobile_spec.rb +0 -281
- data/spec/integration/helpers/wait_helper_spec.rb +0 -679
- data/spec/integration/helpers/wait_helper_support.rb +0 -183
- data/spec/system/watir_spec.rb +0 -38
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<%- if web? -%>
|
|
2
|
-
Feature: Login Page
|
|
3
|
-
|
|
4
|
-
Scenario: A user can login
|
|
5
|
-
Given I'm a registered user on the login page
|
|
6
|
-
When I login with my credentials
|
|
7
|
-
Then I'm logged in
|
|
8
|
-
|
|
9
|
-
@logged_in
|
|
10
|
-
Scenario: A logged-in user opens the account page
|
|
11
|
-
Given I'm a registered user
|
|
12
|
-
Then I'm logged in
|
|
13
|
-
|
|
14
|
-
<%- else -%>
|
|
15
|
-
Feature: Home Page
|
|
16
|
-
|
|
17
|
-
Scenario: A user can go to the product details page
|
|
18
|
-
Given I'm an anonymous user on the home page
|
|
19
|
-
When I select one of the products
|
|
20
|
-
Then I'm redirected to the product details page
|
|
21
|
-
<%- end %>
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'raider_reporter/cucumber'
|
|
4
|
-
require 'tmpdir'
|
|
5
|
-
require_relative '../../helpers/video_helper'
|
|
6
|
-
|
|
7
|
-
Before do
|
|
8
|
-
driver.start_driver
|
|
9
|
-
@video_recorder = VideoHelper.recorder_for(driver)
|
|
10
|
-
@video_recorder.start
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
After do |scenario|
|
|
14
|
-
video_path = @video_recorder&.stop(keep: scenario.failed?)
|
|
15
|
-
RaiderReporter.attach('video', video_path, type: :mp4) if video_path
|
|
16
|
-
if scenario.failed?
|
|
17
|
-
Dir.mktmpdir do |temp_folder|
|
|
18
|
-
screenshot_path = File.join(temp_folder, 'screenshot.png')
|
|
19
|
-
driver.screenshot(screenshot_path)
|
|
20
|
-
RaiderReporter.attach('screenshot', screenshot_path, type: :png)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
ensure
|
|
24
|
-
@video_recorder&.cleanup
|
|
25
|
-
driver.quit_driver
|
|
26
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
require_relative '../../helpers/driver_helper'
|
|
2
|
-
<%- if wait_helper? -%>
|
|
3
|
-
require_relative '../../helpers/wait_helper'
|
|
4
|
-
<%- end -%>
|
|
5
|
-
<%- if selenium_based? -%>
|
|
6
|
-
<%- if examples? -%>
|
|
7
|
-
require_relative '../../models/user_factory'
|
|
8
|
-
<%- end -%>
|
|
9
|
-
|
|
10
|
-
World(DriverHelper)
|
|
11
|
-
World(WaitHelper)
|
|
12
|
-
<%- else -%>
|
|
13
|
-
|
|
14
|
-
World(DriverHelper)
|
|
15
|
-
<%- if wait_helper? -%>
|
|
16
|
-
World(WaitHelper)
|
|
17
|
-
<%- end -%>
|
|
18
|
-
<%- end -%>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
<%- if cross_platform? -%>
|
|
4
|
-
require_relative '../../helpers/appium_helper'
|
|
5
|
-
<%- end -%>
|
|
6
|
-
require_relative '../../page_objects/pages/home'
|
|
7
|
-
require_relative '../../page_objects/pages/pdp'
|
|
8
|
-
|
|
9
|
-
Given("I'm an anonymous user on the home page") do
|
|
10
|
-
@home_page = Home.new(driver)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
When('I select one of the products') do
|
|
14
|
-
@home_page.go_to_product_detail
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
Then("I'm redirected to the product details page") do
|
|
18
|
-
pdp_page = Pdp.new(driver)
|
|
19
|
-
eventually { expect(pdp_page.add_to_cart_text).to eq 'Add to Cart' }
|
|
20
|
-
end
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
<%- if axe_addon? && cucumber? -%>
|
|
4
|
-
require 'axe-rspec'
|
|
5
|
-
<%- end -%>
|
|
6
|
-
require 'rspec'
|
|
7
|
-
require 'raider_reporter/cucumber'
|
|
8
|
-
require 'tmpdir'
|
|
9
|
-
require 'yaml'
|
|
10
|
-
require_relative '../../helpers/video_helper'
|
|
11
|
-
<%- if trace_helper? -%>
|
|
12
|
-
require_relative '../../helpers/trace_helper'
|
|
13
|
-
<%- end -%>
|
|
14
|
-
require_relative '../../helpers/session_state'
|
|
15
|
-
<%- if examples? -%>
|
|
16
|
-
require_relative '../../models/user_factory'
|
|
17
|
-
require_relative '../../page_objects/pages/account'
|
|
18
|
-
require_relative '../../page_objects/pages/login'
|
|
19
|
-
<%- end -%>
|
|
20
|
-
|
|
21
|
-
<%- if trace_helper? -%>
|
|
22
|
-
# Attempts per scenario across --retry, keyed on the scenario's location, for the trace of each attempt.
|
|
23
|
-
TRACE_ATTEMPTS = Hash.new(0) unless defined?(TRACE_ATTEMPTS)
|
|
24
|
-
|
|
25
|
-
# Each Gherkin step becomes a group in the trace, named by its keyword and text; hook steps are not steps.
|
|
26
|
-
InstallPlugin do |config, _registry|
|
|
27
|
-
if defined?(TraceHelper)
|
|
28
|
-
begin
|
|
29
|
-
ast_lookup = Cucumber::Formatter::AstLookup.new(config)
|
|
30
|
-
groups = {}
|
|
31
|
-
config.on_event(:test_step_started) do |event|
|
|
32
|
-
next if event.test_step.hook?
|
|
33
|
-
|
|
34
|
-
step = event.test_step
|
|
35
|
-
keyword = begin
|
|
36
|
-
ast_lookup.step_source(step).step.keyword.strip
|
|
37
|
-
rescue StandardError
|
|
38
|
-
nil
|
|
39
|
-
end
|
|
40
|
-
location = { file: step.location.file, line: step.location.lines.min }
|
|
41
|
-
groups[step.id] = TraceHelper.active_recorder&.step_started(name: [keyword, step.text].compact.join(' '), source: location)
|
|
42
|
-
rescue StandardError => e
|
|
43
|
-
TraceHelper.disable!("step groups failed: #{e.message}") if defined?(TraceHelper)
|
|
44
|
-
end
|
|
45
|
-
config.on_event(:test_step_finished) do |event|
|
|
46
|
-
next if event.test_step.hook?
|
|
47
|
-
|
|
48
|
-
status = %i[passed failed].include?(event.result.to_sym) ? event.result.to_sym : :skipped
|
|
49
|
-
error = event.result.failed? ? event.result.exception : nil
|
|
50
|
-
TraceHelper.active_recorder&.step_finished(groups.delete(event.test_step.id), status: status, error: error)
|
|
51
|
-
rescue StandardError => e
|
|
52
|
-
TraceHelper.disable!("step groups failed: #{e.message}") if defined?(TraceHelper)
|
|
53
|
-
end
|
|
54
|
-
rescue StandardError => e
|
|
55
|
-
TraceHelper.warn_once("Gherkin step groups unavailable: #{e.message}")
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
<%- end -%>
|
|
61
|
-
Before do<%= trace_helper? ? ' |scenario|' : '' %>
|
|
62
|
-
viewport = YAML.load_file('config/config.yml')['viewport']
|
|
63
|
-
if viewport
|
|
64
|
-
driver.manage.window.resize_to(viewport['width'], viewport['height'])
|
|
65
|
-
else
|
|
66
|
-
driver.manage.window.maximize
|
|
67
|
-
end
|
|
68
|
-
@video_recorder = VideoHelper.recorder_for(driver)
|
|
69
|
-
@video_recorder.start
|
|
70
|
-
<%- if trace_helper? -%>
|
|
71
|
-
if defined?(TraceHelper)
|
|
72
|
-
@trace_attempt = (TRACE_ATTEMPTS[scenario.location.to_s] += 1)
|
|
73
|
-
@trace_test = { identifier: scenario.location.to_s, full_name: scenario.name, attempt: @trace_attempt }
|
|
74
|
-
@trace_recorder = TraceHelper.recorder_for(driver)
|
|
75
|
-
@trace_recorder.start
|
|
76
|
-
end
|
|
77
|
-
<%- end -%>
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
<%- if examples? -%>
|
|
81
|
-
Before('@logged_in') do
|
|
82
|
-
user = UserFactory.for('registered user')
|
|
83
|
-
account = Account.new(driver)
|
|
84
|
-
SessionState.new(driver).reuse(
|
|
85
|
-
valid: -> { account.tap(&:visit).header.customer_name == "Welcome back #{user['name']}" }
|
|
86
|
-
) do
|
|
87
|
-
login = Login.new(driver)
|
|
88
|
-
login.visit
|
|
89
|
-
login.login(user['username'], user['password'])
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
<%- end -%>
|
|
94
|
-
After do |scenario|
|
|
95
|
-
<%- if trace_helper? -%>
|
|
96
|
-
if defined?(TraceHelper)
|
|
97
|
-
keep_trace = TraceHelper.keep_all? || scenario.failed?
|
|
98
|
-
trace_test = @trace_test&.merge(status: scenario.failed? ? 'failed' : 'passed', error: scenario.exception)
|
|
99
|
-
trace_path = @trace_recorder&.stop(keep: keep_trace, test: trace_test)
|
|
100
|
-
end
|
|
101
|
-
<%- end -%>
|
|
102
|
-
video_path = @video_recorder&.stop(keep: scenario.failed?)
|
|
103
|
-
RaiderReporter.attach('video', video_path, type: :webm) if video_path
|
|
104
|
-
<%- if trace_helper? -%>
|
|
105
|
-
RaiderReporter.attach('trace', trace_path, type: :trace, attempt: @trace_attempt) if trace_path
|
|
106
|
-
<%- end -%>
|
|
107
|
-
if scenario.failed?
|
|
108
|
-
Dir.mktmpdir do |temp_folder|
|
|
109
|
-
screenshot_path = File.join(temp_folder, 'screenshot.png')
|
|
110
|
-
driver.save_screenshot(screenshot_path)
|
|
111
|
-
RaiderReporter.attach('screenshot', screenshot_path, type: :png)
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
ensure
|
|
115
|
-
<%- if trace_helper? -%>
|
|
116
|
-
@trace_recorder&.cleanup
|
|
117
|
-
<%- end -%>
|
|
118
|
-
@video_recorder&.cleanup
|
|
119
|
-
driver.quit
|
|
120
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'raider_reporter/cucumber'
|
|
4
|
-
require 'tmpdir'
|
|
5
|
-
require 'yaml'
|
|
6
|
-
require_relative '../../helpers/video_helper'
|
|
7
|
-
require_relative '../../helpers/session_state'
|
|
8
|
-
require_relative '../../models/user_factory'
|
|
9
|
-
require_relative '../../page_objects/pages/account'
|
|
10
|
-
require_relative '../../page_objects/pages/login'
|
|
11
|
-
|
|
12
|
-
Before do
|
|
13
|
-
viewport = YAML.load_file('config/config.yml')['viewport']
|
|
14
|
-
if viewport
|
|
15
|
-
browser.window.resize_to(viewport['width'], viewport['height'])
|
|
16
|
-
else
|
|
17
|
-
browser.window.maximize
|
|
18
|
-
end
|
|
19
|
-
@video_recorder = VideoHelper.recorder_for(browser)
|
|
20
|
-
@video_recorder.start
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
Before('@logged_in') do
|
|
24
|
-
user = UserFactory.for('registered user')
|
|
25
|
-
account = Account.new(browser)
|
|
26
|
-
SessionState.new(browser.driver).reuse(
|
|
27
|
-
valid: -> { account.tap(&:visit).header.customer_name == "Welcome back #{user['name']}" }
|
|
28
|
-
) do
|
|
29
|
-
login = Login.new(browser)
|
|
30
|
-
login.visit
|
|
31
|
-
login.login(user['username'], user['password'])
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
After do |scenario|
|
|
36
|
-
video_path = @video_recorder&.stop(keep: scenario.failed?)
|
|
37
|
-
RaiderReporter.attach('video', video_path, type: :webm) if video_path
|
|
38
|
-
if scenario.failed?
|
|
39
|
-
Dir.mktmpdir do |temp_folder|
|
|
40
|
-
screenshot_path = File.join(temp_folder, 'screenshot.png')
|
|
41
|
-
browser.screenshot.save(screenshot_path)
|
|
42
|
-
RaiderReporter.attach('screenshot', screenshot_path, type: :png)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
ensure
|
|
46
|
-
@video_recorder&.cleanup
|
|
47
|
-
browser.quit
|
|
48
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../../page_objects/pages/account'
|
|
4
|
-
require_relative '../../page_objects/pages/login'
|
|
5
|
-
|
|
6
|
-
Given("I'm a {user} on the login page") do |user|
|
|
7
|
-
@user = user
|
|
8
|
-
@login_page = <% if watir? %>Login.new(browser)<% else %>Login.new(driver)<% end %>
|
|
9
|
-
@login_page.visit
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
Given("I'm a {user}") do |user|
|
|
13
|
-
@user = user
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
When('I login with my credentials') do
|
|
17
|
-
@login_page.login(@user['username'], @user['password'])
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
Then("I'm logged in") do
|
|
21
|
-
account_page = <% if watir? %>Account.new(browser)<% else %>Account.new(driver)<% end %>
|
|
22
|
-
account_page.visit
|
|
23
|
-
<%- if watir? -%>
|
|
24
|
-
expect(account_page.header.customer_name).to eq "Welcome back #{@user['name']}"
|
|
25
|
-
<%- else -%>
|
|
26
|
-
eventually { expect(account_page.header.customer_name).to eq "Welcome back #{@user['name']}" }
|
|
27
|
-
<%- end -%>
|
|
28
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'model_factory'
|
|
4
|
-
|
|
5
|
-
class UserFactory < ModelFactory
|
|
6
|
-
def self.for(user)
|
|
7
|
-
super('users')[user]
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
ParameterType(
|
|
12
|
-
name: 'user',
|
|
13
|
-
regexp: /[A-Za-z0-9]+ user/,
|
|
14
|
-
transformer: ->(user) { UserFactory.for(user) }
|
|
15
|
-
)
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'active_support/core_ext/string/inflections'
|
|
4
|
-
require 'yaml'
|
|
5
|
-
require 'watir'
|
|
6
|
-
require_relative 'video_helper'
|
|
7
|
-
|
|
8
|
-
module BrowserHelper
|
|
9
|
-
def browser(*args)
|
|
10
|
-
@browser ||= create_browser(*args)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
def config
|
|
16
|
-
@config ||= YAML.load_file('config/config.yml')
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def create_browser(*args)
|
|
20
|
-
Watir.default_timeout = config.fetch('timeout', 10)
|
|
21
|
-
browser_name = config['browser'].to_s
|
|
22
|
-
args = args.empty? ? config['browser_arguments'][browser_name] : args
|
|
23
|
-
args += ['--headless'] if (ENV['HEADLESS'] || config['headless']) && !args.include?('--headless')
|
|
24
|
-
capitalized = browser_name == 'ie' ? browser_name.upcase : browser_name.capitalize
|
|
25
|
-
browser_options = "Selenium::WebDriver::#{capitalized}::Options".constantize.new(args: args)
|
|
26
|
-
arguments = { options: browser_options }
|
|
27
|
-
listener = VideoHelper.listener
|
|
28
|
-
arguments[:listener] = listener if listener
|
|
29
|
-
Watir::Browser.new(browser_name.to_sym, **arguments)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
<%- if mobile? -%>
|
|
4
|
-
# An element found through WaitHelper. It has the same waiting methods as the
|
|
5
|
-
# mixin, minus the locator, so calls chain:
|
|
6
|
-
# find_element(accessibility_id: 'list').find_element(accessibility_id: 'row').tap
|
|
7
|
-
# find_element(accessibility_id: 'card').swipe('left')
|
|
8
|
-
# Everything else (tag_name, rect, location, ...) goes to the raw Appium
|
|
9
|
-
# element without waiting. APIs that type-check their argument
|
|
10
|
-
# (driver.action, execute_script) need .native.
|
|
11
|
-
<%- else -%>
|
|
12
|
-
# An element found through WaitHelper. It has the same waiting methods as the
|
|
13
|
-
# mixin, minus the locator, so calls chain:
|
|
14
|
-
# find_element(css: '.form').find_element(id: 'email').send_keys('a')
|
|
15
|
-
# Everything else (tag_name, rect, property, ...) goes to the raw Selenium
|
|
16
|
-
# element without waiting. Selenium APIs that type-check their argument
|
|
17
|
-
# (switch_to.frame, Support::Select, driver.action, execute_script) need .native.
|
|
18
|
-
<%- end -%>
|
|
19
|
-
class RaiderElement
|
|
20
|
-
def initialize(driver, lookup)
|
|
21
|
-
@driver = driver
|
|
22
|
-
@lookup = lookup
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def native
|
|
26
|
-
@lookup.element
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def find_element(locator = nil, visible: true, timeout: nil, **by)
|
|
30
|
-
waiter(timeout).find_element(child(locator, by), visible)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def find_elements(locator = nil, timeout: nil, **by)
|
|
34
|
-
waiter(timeout).find_elements(child(locator, by))
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
<%- if mobile? -%>
|
|
38
|
-
%i[click clear].each do |action|
|
|
39
|
-
define_method(action) do |timeout: nil|
|
|
40
|
-
perform(action, timeout) { |element| element.public_send(action) }
|
|
41
|
-
self
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# tap is Appium's word for click. With a block it stays Ruby's Object#tap.
|
|
46
|
-
def tap(timeout: nil, &block)
|
|
47
|
-
return super(&block) if block
|
|
48
|
-
|
|
49
|
-
perform(:tap, timeout, &:click)
|
|
50
|
-
self
|
|
51
|
-
end
|
|
52
|
-
<%- else -%>
|
|
53
|
-
%i[click clear submit].each do |action|
|
|
54
|
-
define_method(action) do |timeout: nil|
|
|
55
|
-
perform(action, timeout) { |element| element.public_send(action) }
|
|
56
|
-
self
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
<%- end -%>
|
|
60
|
-
|
|
61
|
-
%i[text displayed? enabled? selected?].each do |reader|
|
|
62
|
-
define_method(reader) do |timeout: nil|
|
|
63
|
-
perform(reader, timeout) { |element| element.public_send(reader) }
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def send_keys(*keys, timeout: nil)
|
|
68
|
-
perform(:send_keys, timeout, args: keys) { |element| element.send_keys(*keys) }
|
|
69
|
-
self
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
<%- unless mobile? -%>
|
|
73
|
-
def select_by(how, what, timeout: nil)
|
|
74
|
-
perform(:select_by, timeout, args: [how, what]) { |element| Selenium::WebDriver::Support::Select.new(element).select_by(how, what) }
|
|
75
|
-
self
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
<%- end -%>
|
|
79
|
-
def attribute(name, timeout: nil)
|
|
80
|
-
perform(:attribute, timeout) { |element| element.attribute(name) }
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
<%- if mobile? -%>
|
|
84
|
-
# direction: 'up', 'down', 'left' or 'right'.
|
|
85
|
-
%i[swipe scroll].each do |kind|
|
|
86
|
-
define_method(kind) do |direction, timeout: nil|
|
|
87
|
-
gesture = WaitHelper::Gesture.new(@driver, kind, direction)
|
|
88
|
-
perform(kind, timeout) { |element| gesture.perform(element) }
|
|
89
|
-
self
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Scrolls the screen until this element is visible, up to max_scrolls times.
|
|
94
|
-
def scroll_to(direction: 'down', max_scrolls: 10, timeout: nil)
|
|
95
|
-
scroller = WaitHelper::Scroller.new(WaitHelper::Gesture.new(@driver, :scroll, direction), max_scrolls)
|
|
96
|
-
waiter(timeout).perform_action(:scroll_to, @lookup, WaitHelper::Waiter::CHECKS[:scroll_to], between: scroller) { nil }
|
|
97
|
-
self
|
|
98
|
-
end
|
|
99
|
-
<%- else -%>
|
|
100
|
-
def hover(timeout: nil)
|
|
101
|
-
perform(:hover, timeout) { |element| @driver.action.move_to(element).perform }
|
|
102
|
-
self
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def scroll_into_view(timeout: nil)
|
|
106
|
-
perform(:scroll_into_view, timeout) { |element| @driver.action.scroll_to(element).perform }
|
|
107
|
-
self
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# target: a RaiderElement, a raw element, or a driver-scoped locator.
|
|
111
|
-
def drag_and_drop(target, timeout: nil)
|
|
112
|
-
drop = WaitHelper::Lookup.for(@driver, target, {})
|
|
113
|
-
waiter(timeout).perform_action(:drag_and_drop, @lookup, WaitHelper::Waiter::CHECKS[:drag_and_drop],
|
|
114
|
-
target: drop) do |source, destination|
|
|
115
|
-
@driver.action.drag_and_drop(source, destination).perform
|
|
116
|
-
end
|
|
117
|
-
self
|
|
118
|
-
end
|
|
119
|
-
<%- end -%>
|
|
120
|
-
|
|
121
|
-
def ==(other)
|
|
122
|
-
native == (other.is_a?(RaiderElement) ? other.native : other)
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def eql?(other)
|
|
126
|
-
self == other
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def hash
|
|
130
|
-
native.hash
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
private
|
|
134
|
-
|
|
135
|
-
# WaitHelper::Lookup.for reads this to reuse how a wrapper was found.
|
|
136
|
-
attr_reader :lookup
|
|
137
|
-
|
|
138
|
-
def waiter(timeout)
|
|
139
|
-
WaitHelper::Waiter.new(@driver, timeout: timeout)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def child(locator, by)
|
|
143
|
-
WaitHelper::Lookup.for(@driver, locator, by, scope: @lookup)
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def perform(action, timeout, args: nil, &block)
|
|
147
|
-
waiter(timeout).perform_action(action, @lookup, WaitHelper::Waiter::CHECKS.fetch(action), args: args, &block)
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def method_missing(name, *args, **options, &block)
|
|
151
|
-
return super unless native.respond_to?(name)
|
|
152
|
-
|
|
153
|
-
native.public_send(name, *args, **options, &block)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def respond_to_missing?(name, include_private = false)
|
|
157
|
-
native.respond_to?(name) || super
|
|
158
|
-
end
|
|
159
|
-
end
|