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
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Minimal Selenium WebDriver stubs for type checking (covers only what Raider's runtime touches)
|
|
2
|
+
module Selenium
|
|
3
|
+
module WebDriver
|
|
4
|
+
VERSION: String
|
|
5
|
+
|
|
6
|
+
module Error
|
|
7
|
+
class WebDriverError < StandardError
|
|
8
|
+
end
|
|
9
|
+
class ElementNotInteractableError < WebDriverError
|
|
10
|
+
end
|
|
11
|
+
class UnsupportedOperationError < WebDriverError
|
|
12
|
+
end
|
|
13
|
+
class TimeoutError < WebDriverError
|
|
14
|
+
end
|
|
15
|
+
class NoSuchElementError < WebDriverError
|
|
16
|
+
end
|
|
17
|
+
class StaleElementReferenceError < WebDriverError
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module SearchContext
|
|
22
|
+
FINDERS: Hash[Symbol, String]
|
|
23
|
+
|
|
24
|
+
def self.extra_finders: () -> Hash[Symbol, String]?
|
|
25
|
+
def self.extra_finders=: (Hash[Symbol, String]?) -> Hash[Symbol, String]?
|
|
26
|
+
def self.finders: () -> Hash[Symbol, String]
|
|
27
|
+
|
|
28
|
+
def bridge: () -> untyped
|
|
29
|
+
def find_element: (*untyped) -> Element
|
|
30
|
+
def find_elements: (*untyped) -> Array[Element]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class Element
|
|
34
|
+
include SearchContext
|
|
35
|
+
|
|
36
|
+
def initialize: (untyped bridge, String id) -> void
|
|
37
|
+
def tag_name: () -> String
|
|
38
|
+
def attribute: (String) -> String?
|
|
39
|
+
def text: () -> String
|
|
40
|
+
def displayed?: () -> bool
|
|
41
|
+
def enabled?: () -> bool
|
|
42
|
+
def ref: () -> [Symbol, String?]
|
|
43
|
+
def click: () -> void
|
|
44
|
+
def send_keys: (*untyped) -> void
|
|
45
|
+
def clear: () -> void
|
|
46
|
+
def submit: () -> void
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class Driver
|
|
50
|
+
include SearchContext
|
|
51
|
+
|
|
52
|
+
def ref: () -> [Symbol, String?]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
module Remote
|
|
56
|
+
class Bridge
|
|
57
|
+
class LocatorConverter
|
|
58
|
+
def convert: (String | Symbol, untyped) -> [String, untyped]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.locator_converter: () -> untyped
|
|
62
|
+
def self.locator_converter=: (untyped) -> untyped
|
|
63
|
+
|
|
64
|
+
def find_element_by: (*untyped) -> untyped
|
|
65
|
+
def find_elements_by: (*untyped) -> untyped
|
|
66
|
+
def execute_script: (String, *untyped) -> untyped
|
|
67
|
+
def current_context: () -> String
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -121,8 +121,8 @@ RSpec.describe RubyRaider::Raider do # rubocop:disable RSpec/FilePath
|
|
|
121
121
|
|
|
122
122
|
let(:raider_bin) { File.expand_path('../../bin/raider', __dir__) }
|
|
123
123
|
|
|
124
|
-
def run_raider(*args, chdir: Dir.pwd)
|
|
125
|
-
Open3.capture3(RbConfig.ruby, raider_bin, *args, chdir:)
|
|
124
|
+
def run_raider(*args, chdir: Dir.pwd, env: {})
|
|
125
|
+
Open3.capture3(env, RbConfig.ruby, raider_bin, *args, chdir:)
|
|
126
126
|
end
|
|
127
127
|
|
|
128
128
|
it 'exits non-zero for an unknown command' do
|
|
@@ -143,7 +143,8 @@ RSpec.describe RubyRaider::Raider do # rubocop:disable RSpec/FilePath
|
|
|
143
143
|
out, err, status = run_raider('new', 'x', '-p', 'framework:minitest', 'automation:selenium', chdir: dir)
|
|
144
144
|
|
|
145
145
|
expect(status.exitstatus).not_to eq(0)
|
|
146
|
-
expect(out + err).to include('framework', 'rspec'
|
|
146
|
+
expect(out + err).to include('framework', 'rspec')
|
|
147
|
+
expect(out + err).not_to include('cucumber')
|
|
147
148
|
expect(File.exist?(File.join(dir, 'x'))).to be(false)
|
|
148
149
|
end
|
|
149
150
|
end
|
|
@@ -167,5 +168,39 @@ RSpec.describe RubyRaider::Raider do # rubocop:disable RSpec/FilePath
|
|
|
167
168
|
expect(File.exist?(File.join(dir, 'x'))).to be(false)
|
|
168
169
|
end
|
|
169
170
|
end
|
|
171
|
+
|
|
172
|
+
it 'exits 1 with the Invalid automation message for automation:watir and creates nothing' do
|
|
173
|
+
Dir.mktmpdir do |dir|
|
|
174
|
+
out, err, status = run_raider('new', 'x', '-p', 'framework:rspec', 'automation:watir', chdir: dir)
|
|
175
|
+
|
|
176
|
+
expect(status.exitstatus).to eq(1)
|
|
177
|
+
expect(out + err).to include('Invalid automation "watir"')
|
|
178
|
+
expect(File.exist?(File.join(dir, 'x'))).to be(false)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
describe 'raider new under a US-ASCII locale' do
|
|
183
|
+
# macOS gives GUI apps no LANG, so a shell spawned by the desktop runs Ruby with a US-ASCII
|
|
184
|
+
# default_external; the templates hold UTF-8 bytes and must still render. The generated README holds
|
|
185
|
+
# an ellipsis, so the rendered file proves the bytes came through. RUBYOPT is unset so a
|
|
186
|
+
# -E or -K flag from the outer environment cannot hide the locale.
|
|
187
|
+
{ 'LC_ALL=C' => { 'LANG' => nil, 'LC_CTYPE' => nil, 'LC_ALL' => 'C', 'RUBYOPT' => nil },
|
|
188
|
+
'no locale variables' => { 'LANG' => nil, 'LC_CTYPE' => nil, 'LC_ALL' => nil, 'RUBYOPT' => nil } }
|
|
189
|
+
.each do |label, env|
|
|
190
|
+
it "renders the config under #{label}" do
|
|
191
|
+
Dir.mktmpdir do |dir|
|
|
192
|
+
_out, err, status = run_raider('new', 'x', '-p', 'framework:rspec', 'automation:selenium',
|
|
193
|
+
chdir: dir, env:)
|
|
194
|
+
|
|
195
|
+
expect(err).not_to include('invalid multibyte')
|
|
196
|
+
expect(status.exitstatus).to eq(0)
|
|
197
|
+
readme = File.read(File.join(dir, 'x/Readme.md'), encoding: 'UTF-8')
|
|
198
|
+
expect(readme).to include("`expect { account_page.welcome_message }.to have_text(\u2026)`")
|
|
199
|
+
config = File.read(File.join(dir, 'x/config/config.yml'), encoding: 'UTF-8')
|
|
200
|
+
expect(YAML.safe_load(config, permitted_classes: [Symbol])['url']).to include('http')
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
170
205
|
end
|
|
171
206
|
end
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'open3'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
require 'rbconfig'
|
|
6
|
+
require_relative '../../lib/commands/scaffolding_commands'
|
|
4
7
|
|
|
5
8
|
RSpec.describe 'ScaffoldingCommands' do
|
|
6
9
|
describe 'dependencies' do
|
|
@@ -19,4 +22,28 @@ RSpec.describe 'ScaffoldingCommands' do
|
|
|
19
22
|
expect(stdout.strip).to eq('OK')
|
|
20
23
|
end
|
|
21
24
|
end
|
|
25
|
+
|
|
26
|
+
describe 'commands' do
|
|
27
|
+
it 'has no feature or steps command' do
|
|
28
|
+
expect(ScaffoldingCommands.all_commands.keys).not_to include('feature', 'steps')
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe 'scaffold in a directory that looks like a Cucumber project' do
|
|
33
|
+
let(:raider_bin) { File.expand_path('../../bin/raider', __dir__) }
|
|
34
|
+
|
|
35
|
+
it 'writes the spec and the page and nothing under features' do
|
|
36
|
+
Dir.mktmpdir do |dir|
|
|
37
|
+
File.write(File.join(dir, 'Gemfile'), "gem 'cucumber'\n")
|
|
38
|
+
FileUtils.mkdir_p(File.join(dir, 'features'))
|
|
39
|
+
|
|
40
|
+
_out, err, status = Open3.capture3(RbConfig.ruby, raider_bin, 'g', 'scaffold', 'login', chdir: dir)
|
|
41
|
+
|
|
42
|
+
expect(status.success?).to be(true), err
|
|
43
|
+
expect(File).to exist(File.join(dir, 'spec/login_page_spec.rb'))
|
|
44
|
+
expect(File).to exist(File.join(dir, 'page_objects/pages/login.rb'))
|
|
45
|
+
expect(Dir.glob(File.join(dir, 'features/**/*')).select { |f| File.file?(f) }).to be_empty
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
22
49
|
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'yaml'
|
|
5
|
+
require_relative '../../lib/ruby_raider'
|
|
6
|
+
|
|
7
|
+
RSpec.describe UtilityCommands do
|
|
8
|
+
let(:tmp_dir) { 'tmp_utility_commands_test' }
|
|
9
|
+
|
|
10
|
+
before do
|
|
11
|
+
FileUtils.mkdir_p("#{tmp_dir}/config")
|
|
12
|
+
Dir.chdir(tmp_dir)
|
|
13
|
+
File.write('config/config.yml', "browser: chrome\ntimeout: 10\n")
|
|
14
|
+
Utilities.instance_variable_set(:@config, nil)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
after do
|
|
18
|
+
Dir.chdir('..')
|
|
19
|
+
FileUtils.rm_rf(tmp_dir)
|
|
20
|
+
Utilities.instance_variable_set(:@config, nil)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe 'strict' do
|
|
24
|
+
it 'writes strict: false for off' do
|
|
25
|
+
described_class.new.invoke(:strict, nil, %w[off])
|
|
26
|
+
expect(YAML.load_file('config/config.yml')['strict']).to be false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'writes strict: true for on' do
|
|
30
|
+
described_class.new.invoke(:strict, nil, %w[on])
|
|
31
|
+
expect(YAML.load_file('config/config.yml')['strict']).to be true
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe 'actionability' do
|
|
36
|
+
it 'writes actionability: true for on' do
|
|
37
|
+
described_class.new.invoke(:actionability, nil, %w[on])
|
|
38
|
+
expect(YAML.load_file('config/config.yml')['actionability']).to be true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'writes actionability: false for off' do
|
|
42
|
+
described_class.new.invoke(:actionability, nil, %w[off])
|
|
43
|
+
expect(YAML.load_file('config/config.yml')['actionability']).to be false
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe 'help' do
|
|
48
|
+
it 'lists both toggles' do
|
|
49
|
+
expect { described_class.start(%w[help]) }
|
|
50
|
+
.to output(%r{actionability \[on/off\].*strict \[on/off\]}m).to_stdout
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'erb'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
require_relative '../../lib/generators/helper_generator'
|
|
6
|
+
require_relative '../../lib/ruby_raider/runtime'
|
|
7
|
+
|
|
8
|
+
# Stands in for the Appium driver: only the calls the gestures make.
|
|
9
|
+
class GestureDriver
|
|
10
|
+
Rect = Struct.new(:x, :y, :width, :height)
|
|
11
|
+
Element = Struct.new(:id)
|
|
12
|
+
|
|
13
|
+
attr_reader :appium_device
|
|
14
|
+
|
|
15
|
+
def initialize(device)
|
|
16
|
+
@appium_device = device
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def execute_script(*); end
|
|
20
|
+
|
|
21
|
+
def find_element(*); end
|
|
22
|
+
|
|
23
|
+
def window_rect
|
|
24
|
+
Rect.new(0, 10, 400, 800)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class GesturePage
|
|
29
|
+
attr_reader :driver
|
|
30
|
+
|
|
31
|
+
def initialize(driver)
|
|
32
|
+
@driver = driver
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.rendered
|
|
36
|
+
generator = HelpersGenerator.new(%w[ios rspec proj])
|
|
37
|
+
template = File.expand_path('../../lib/generators/templates/helpers/gesture_helper.tt', __dir__)
|
|
38
|
+
ERB.new(File.read(template), trim_mode: '-').result(generator.instance_eval { binding })
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Dir.mktmpdir do |dir|
|
|
43
|
+
path = File.join(dir, 'gesture_helper.rb')
|
|
44
|
+
File.write(path, GesturePage.rendered)
|
|
45
|
+
load path
|
|
46
|
+
end
|
|
47
|
+
GesturePage.include(GestureHelper)
|
|
48
|
+
|
|
49
|
+
describe 'gesture_helper template' do
|
|
50
|
+
let(:element) { GestureDriver::Element.new('el-1') }
|
|
51
|
+
let(:driver) { GestureDriver.new(:android) }
|
|
52
|
+
let(:page) { GesturePage.new(driver) }
|
|
53
|
+
|
|
54
|
+
context 'on iOS' do
|
|
55
|
+
let(:driver) { GestureDriver.new(:ios) }
|
|
56
|
+
|
|
57
|
+
it 'swipes the screen with mobile: swipe' do
|
|
58
|
+
expect(driver).to receive(:execute_script).with('mobile: swipe', { direction: 'left' })
|
|
59
|
+
page.swipe('left')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'scrolls an element with mobile: scroll and its id' do
|
|
63
|
+
expect(driver).to receive(:execute_script).with('mobile: scroll', { direction: 'down', element: 'el-1' })
|
|
64
|
+
page.scroll(:down, element)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context 'on Android' do
|
|
69
|
+
let(:driver) { GestureDriver.new(:android) }
|
|
70
|
+
|
|
71
|
+
it 'swipes the screen with mobile: swipeGesture over the window rect' do
|
|
72
|
+
expect(driver).to receive(:execute_script)
|
|
73
|
+
.with('mobile: swipeGesture', { left: 0, top: 10, width: 400, height: 800, direction: 'up', percent: 0.75 })
|
|
74
|
+
page.swipe('up')
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'scrolls an element with mobile: scrollGesture and its element id' do
|
|
78
|
+
expect(driver).to receive(:execute_script)
|
|
79
|
+
.with('mobile: scrollGesture', { elementId: 'el-1', direction: 'down', percent: 0.75 })
|
|
80
|
+
page.scroll('down', element)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'rejects a direction other than up, down, left or right' do
|
|
85
|
+
driver = GestureDriver.new(:ios)
|
|
86
|
+
page = GesturePage.new(driver)
|
|
87
|
+
expect { page.swipe('diagonal') }.to raise_error(ArgumentError, /direction must be up, down, left or right/)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe '#scroll_to' do
|
|
91
|
+
let(:locator) { { accessibility_id: 'footer' } }
|
|
92
|
+
|
|
93
|
+
let(:driver) { GestureDriver.new(:android) }
|
|
94
|
+
|
|
95
|
+
it 'returns the element without scrolling when it is already there' do
|
|
96
|
+
allow(driver).to receive(:find_element).with(locator).and_return(element)
|
|
97
|
+
expect(driver).not_to receive(:execute_script)
|
|
98
|
+
expect(page.scroll_to(locator)).to eq(element)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it 'scrolls between tries until the element appears' do
|
|
102
|
+
attempts = 0
|
|
103
|
+
immediate = []
|
|
104
|
+
allow(driver).to receive(:find_element).with(locator) do
|
|
105
|
+
immediate << Raider::Wait.immediate?
|
|
106
|
+
attempts += 1
|
|
107
|
+
raise Selenium::WebDriver::Error::NoSuchElementError, 'gone' if attempts < 3
|
|
108
|
+
|
|
109
|
+
element
|
|
110
|
+
end
|
|
111
|
+
expect(driver).to receive(:execute_script).twice
|
|
112
|
+
expect(page.scroll_to(locator, direction: 'up')).to eq(element)
|
|
113
|
+
expect(immediate).to eq([true, true, true])
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'gives up after max_scrolls and names the locator' do
|
|
117
|
+
allow(driver).to receive(:find_element).and_raise(Selenium::WebDriver::Error::NoSuchElementError, 'gone')
|
|
118
|
+
expect(driver).to receive(:execute_script).exactly(3).times
|
|
119
|
+
expect { page.scroll_to(locator, max_scrolls: 3) }
|
|
120
|
+
.to raise_error(Selenium::WebDriver::Error::NoSuchElementError, /accessibility_id.*footer.*after 3 scrolls/)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|