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.
Files changed (225) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/runtime.yml +38 -0
  3. data/.github/workflows/system_tests.yml +1 -23
  4. data/.reek.yml +1 -0
  5. data/.rspec +1 -0
  6. data/Gemfile +2 -0
  7. data/README.md +16 -49
  8. data/RELEASE.md +22 -0
  9. data/bin/raider +5 -0
  10. data/lib/commands/scaffolding_commands.rb +2 -25
  11. data/lib/commands/utility_commands.rb +23 -3
  12. data/lib/generators/automation/automation_generator.rb +0 -5
  13. data/lib/generators/automation/templates/component.tt +1 -0
  14. data/lib/generators/automation/templates/home.tt +2 -2
  15. data/lib/generators/automation/templates/login.tt +6 -26
  16. data/lib/generators/automation/templates/page.tt +23 -18
  17. data/lib/generators/automation/templates/partials/home_page_selector.tt +1 -2
  18. data/lib/generators/automation/templates/partials/initialize_selector.tt +0 -8
  19. data/lib/generators/automation/templates/partials/pdp_page_selector.tt +1 -2
  20. data/lib/generators/automation/templates/partials/url_methods.tt +8 -2
  21. data/lib/generators/automation/templates/partials/visit_method.tt +0 -5
  22. data/lib/generators/automation/templates/pdp.tt +1 -9
  23. data/lib/generators/common_generator.rb +0 -2
  24. data/lib/generators/generator.rb +12 -19
  25. data/lib/generators/helper_generator.rb +21 -19
  26. data/lib/generators/infrastructure/templates/azure_pipelines.tt +1 -1
  27. data/lib/generators/infrastructure/templates/github.tt +2 -3
  28. data/lib/generators/infrastructure/templates/github_appium.tt +0 -8
  29. data/lib/generators/invoke_generators.rb +4 -23
  30. data/lib/generators/menu_generator.rb +1 -9
  31. data/lib/generators/rspec/templates/accessibility_spec.tt +1 -9
  32. data/lib/generators/rspec/templates/spec.tt +8 -24
  33. data/lib/generators/template_renderer/partial_cache.rb +3 -1
  34. data/lib/generators/template_renderer.rb +1 -1
  35. data/lib/generators/templates/common/gemfile.tt +3 -10
  36. data/lib/generators/templates/common/git_ignore.tt +0 -5
  37. data/lib/generators/templates/common/partials/mobile_config.tt +3 -1
  38. data/lib/generators/templates/common/partials/web_config.tt +10 -1
  39. data/lib/generators/templates/common/rakefile.tt +0 -15
  40. data/lib/generators/templates/common/read_me.tt +357 -250
  41. data/lib/generators/templates/common/rubocop.tt +0 -2
  42. data/lib/generators/templates/helpers/driver_helper.tt +8 -0
  43. data/lib/generators/templates/helpers/gesture_helper.tt +78 -0
  44. data/lib/generators/templates/helpers/network_helper.tt +521 -0
  45. data/lib/generators/templates/helpers/partials/quit_driver.tt +0 -2
  46. data/lib/generators/templates/helpers/partials/screenshot.tt +0 -2
  47. data/lib/generators/templates/helpers/partials/selenium_driver.tt +5 -2
  48. data/lib/generators/templates/helpers/screenshot_helper.tt +490 -0
  49. data/lib/generators/templates/helpers/spec_helper.tt +39 -29
  50. data/lib/generators/templates/helpers/trace_helper.tt +240 -95
  51. data/lib/generators/templates/helpers/video_helper.tt +3 -8
  52. data/lib/ruby_raider/runtime/actionability.rb +129 -0
  53. data/lib/ruby_raider/runtime/actionable.rb +49 -0
  54. data/lib/ruby_raider/runtime/by_role.rb +55 -0
  55. data/lib/ruby_raider/runtime/config.rb +79 -0
  56. data/lib/ruby_raider/runtime/context.rb +38 -0
  57. data/lib/ruby_raider/runtime/errors.rb +69 -0
  58. data/lib/ruby_raider/runtime/finders.rb +73 -0
  59. data/lib/ruby_raider/runtime/js/actionability.js +134 -0
  60. data/lib/ruby_raider/runtime/js/role_engine.js +315 -0
  61. data/lib/ruby_raider/runtime/locator_converter.rb +72 -0
  62. data/lib/ruby_raider/runtime/matchers/base.rb +222 -0
  63. data/lib/ruby_raider/runtime/matchers/element.rb +183 -0
  64. data/lib/ruby_raider/runtime/matchers/page.rb +71 -0
  65. data/lib/ruby_raider/runtime/matchers/presence.rb +41 -0
  66. data/lib/ruby_raider/runtime/matchers/retrying_block.rb +104 -0
  67. data/lib/ruby_raider/runtime/observer.rb +170 -0
  68. data/lib/ruby_raider/runtime/role_finder.rb +83 -0
  69. data/lib/ruby_raider/runtime/rspec.rb +78 -0
  70. data/lib/ruby_raider/runtime/selectors.rb +60 -0
  71. data/lib/ruby_raider/runtime/strict.rb +142 -0
  72. data/lib/ruby_raider/runtime/wait.rb +84 -0
  73. data/lib/ruby_raider/runtime.rb +20 -0
  74. data/lib/scaffolding/name_normalizer.rb +1 -1
  75. data/lib/scaffolding/project_detector.rb +2 -28
  76. data/lib/scaffolding/scaffolding.rb +0 -20
  77. data/lib/scaffolding/templates/component.tt +0 -14
  78. data/lib/scaffolding/templates/page_object.tt +2 -14
  79. data/lib/scaffolding/templates/spec.tt +1 -9
  80. data/lib/utilities/utilities.rb +10 -8
  81. data/lib/version +1 -1
  82. data/ruby_raider.gemspec +2 -1
  83. data/sig/commands/scaffolding_commands.rbs +0 -2
  84. data/sig/commands/utility_commands.rbs +6 -0
  85. data/sig/generators/generator.rbs +0 -4
  86. data/sig/generators/helper_generator.rbs +0 -1
  87. data/sig/generators/menu_generator.rbs +0 -1
  88. data/sig/ruby_raider/runtime/actionability.rbs +25 -0
  89. data/sig/ruby_raider/runtime/actionable.rbs +13 -0
  90. data/sig/ruby_raider/runtime/by_role.rbs +15 -0
  91. data/sig/ruby_raider/runtime/config.rbs +26 -0
  92. data/sig/ruby_raider/runtime/context.rbs +12 -0
  93. data/sig/ruby_raider/runtime/errors.rbs +36 -0
  94. data/sig/ruby_raider/runtime/finders.rbs +26 -0
  95. data/sig/ruby_raider/runtime/locator_converter.rbs +21 -0
  96. data/sig/ruby_raider/runtime/matchers/base.rbs +64 -0
  97. data/sig/ruby_raider/runtime/matchers/element.rbs +78 -0
  98. data/sig/ruby_raider/runtime/matchers/page.rbs +38 -0
  99. data/sig/ruby_raider/runtime/matchers/presence.rbs +21 -0
  100. data/sig/ruby_raider/runtime/matchers/retrying_block.rbs +27 -0
  101. data/sig/ruby_raider/runtime/observer.rbs +46 -0
  102. data/sig/ruby_raider/runtime/role_finder.rbs +18 -0
  103. data/sig/ruby_raider/runtime/selectors.rbs +21 -0
  104. data/sig/ruby_raider/runtime/strict.rbs +35 -0
  105. data/sig/ruby_raider/runtime/wait.rbs +17 -0
  106. data/sig/ruby_raider/runtime.rbs +2 -0
  107. data/sig/scaffolding/project_detector.rbs +0 -4
  108. data/sig/scaffolding/scaffolding.rbs +0 -5
  109. data/sig/utilities/utilities.rbs +2 -1
  110. data/sig/vendor/selenium_webdriver.rbs +71 -0
  111. data/spec/commands/raider_commands_spec.rb +38 -3
  112. data/spec/commands/scaffolding_commands_spec.rb +27 -0
  113. data/spec/commands/utility_commands_spec.rb +53 -0
  114. data/spec/generators/gesture_helper_spec.rb +123 -0
  115. data/spec/generators/network_helper_spec.rb +634 -0
  116. data/spec/generators/screenshot_helper_spec.rb +776 -0
  117. data/spec/generators/template_renderer_spec.rb +0 -4
  118. data/spec/generators/trace_helper_spec.rb +489 -97
  119. data/spec/generators/video_helper_spec.rb +0 -9
  120. data/spec/integration/commands/browser_update_after_creation_spec.rb +0 -8
  121. data/spec/integration/commands/scaffolding_commands_spec.rb +12 -70
  122. data/spec/integration/commands/utility_commands_spec.rb +19 -41
  123. data/spec/integration/content/azure_content_spec.rb +2 -6
  124. data/spec/integration/content/ci_content_spec.rb +1 -55
  125. data/spec/integration/content/common_content_spec.rb +1 -118
  126. data/spec/integration/content/config_content_spec.rb +34 -31
  127. data/spec/integration/content/gemfile_content_spec.rb +7 -72
  128. data/spec/integration/content/helper_content_spec.rb +105 -99
  129. data/spec/integration/content/page_content_spec.rb +85 -87
  130. data/spec/integration/content/readme_content_spec.rb +134 -75
  131. data/spec/integration/content/rspec_reporter_content_spec.rb +2 -2
  132. data/spec/integration/content/rubocop_content_spec.rb +1 -1
  133. data/spec/integration/content/syntax_validation_spec.rb +2 -2
  134. data/spec/integration/content/test_content_spec.rb +23 -147
  135. data/spec/integration/end_to_end_features_spec.rb +1 -43
  136. data/spec/integration/end_to_end_spec.rb +319 -326
  137. data/spec/integration/generators/automation_generator_spec.rb +3 -37
  138. data/spec/integration/generators/axe_addon_spec.rb +2 -35
  139. data/spec/integration/generators/azure_generator_spec.rb +1 -1
  140. data/spec/integration/generators/common_generator_spec.rb +1 -40
  141. data/spec/integration/generators/config_features_spec.rb +1 -24
  142. data/spec/integration/generators/github_generator_spec.rb +0 -12
  143. data/spec/integration/generators/helpers_generator_spec.rb +74 -80
  144. data/spec/integration/generators/invoke_generators_spec.rb +54 -45
  145. data/spec/integration/generators/rspec_generator_spec.rb +0 -6
  146. data/spec/integration/scaffolding_e2e_spec.rb +17 -179
  147. data/spec/integration/spec_helper.rb +4 -6
  148. data/spec/integration/trace_format_checker.rb +11 -2
  149. data/spec/integration/trace_page_server.rb +72 -5
  150. data/spec/menus/menu_generator_spec.rb +14 -39
  151. data/spec/runtime/actionability_spec.rb +207 -0
  152. data/spec/runtime/actionable_spec.rb +125 -0
  153. data/spec/runtime/browser/actionability_script_browser_spec.rb +150 -0
  154. data/spec/runtime/browser/actionable_browser_spec.rb +98 -0
  155. data/spec/runtime/browser/finders_browser_spec.rb +148 -0
  156. data/spec/runtime/browser/matchers_browser_spec.rb +67 -0
  157. data/spec/runtime/browser/retrying_block_browser_spec.rb +37 -0
  158. data/spec/runtime/browser/role_engine_browser_spec.rb +184 -0
  159. data/spec/runtime/browser/strict_browser_spec.rb +38 -0
  160. data/spec/runtime/by_role_spec.rb +52 -0
  161. data/spec/runtime/config_spec.rb +79 -0
  162. data/spec/runtime/context_spec.rb +73 -0
  163. data/spec/runtime/errors_spec.rb +89 -0
  164. data/spec/runtime/finders_spec.rb +165 -0
  165. data/spec/runtime/fixtures/actionability.html +70 -0
  166. data/spec/runtime/fixtures/locators.html +46 -0
  167. data/spec/runtime/fixtures/matchers.html +33 -0
  168. data/spec/runtime/fixtures/roles.html +162 -0
  169. data/spec/runtime/matchers/base_spec.rb +165 -0
  170. data/spec/runtime/matchers/element_spec.rb +277 -0
  171. data/spec/runtime/matchers/page_spec.rb +102 -0
  172. data/spec/runtime/matchers/presence_spec.rb +59 -0
  173. data/spec/runtime/matchers/retrying_block_spec.rb +165 -0
  174. data/spec/runtime/observer_spec.rb +341 -0
  175. data/spec/runtime/role_finder_spec.rb +156 -0
  176. data/spec/runtime/role_query_spec.rb +75 -0
  177. data/spec/runtime/selectors_spec.rb +135 -0
  178. data/spec/runtime/strict_spec.rb +257 -0
  179. data/spec/runtime/support/browser.rb +48 -0
  180. data/spec/runtime/support/fake_bridge.rb +117 -0
  181. data/spec/runtime/wait_spec.rb +71 -0
  182. data/spec/scaffolding/name_normalizer_spec.rb +3 -2
  183. data/spec/scaffolding/scaffold_project_detector_spec.rb +4 -43
  184. data/spec/system/selenium_spec.rb +1 -5
  185. data/spec/system/support/system_test_helper.rb +2 -5
  186. data/spec/utilities/headless_config_spec.rb +0 -7
  187. data/spec/utilities/utilities_spec.rb +24 -0
  188. metadata +113 -48
  189. data/lib/generators/automation/templates/header.tt +0 -9
  190. data/lib/generators/cucumber/cucumber_generator.rb +0 -58
  191. data/lib/generators/cucumber/templates/accessibility_feature.tt +0 -5
  192. data/lib/generators/cucumber/templates/accessibility_steps.tt +0 -17
  193. data/lib/generators/cucumber/templates/cucumber.tt +0 -1
  194. data/lib/generators/cucumber/templates/env.tt +0 -7
  195. data/lib/generators/cucumber/templates/feature.tt +0 -21
  196. data/lib/generators/cucumber/templates/partials/appium_env.tt +0 -26
  197. data/lib/generators/cucumber/templates/partials/driver_world.tt +0 -18
  198. data/lib/generators/cucumber/templates/partials/mobile_steps.tt +0 -20
  199. data/lib/generators/cucumber/templates/partials/selenium_env.tt +0 -120
  200. data/lib/generators/cucumber/templates/partials/watir_env.tt +0 -48
  201. data/lib/generators/cucumber/templates/partials/watir_world.tt +0 -4
  202. data/lib/generators/cucumber/templates/partials/web_steps.tt +0 -28
  203. data/lib/generators/cucumber/templates/steps.tt +0 -5
  204. data/lib/generators/cucumber/templates/user_factory.tt +0 -15
  205. data/lib/generators/cucumber/templates/world.tt +0 -7
  206. data/lib/generators/templates/helpers/browser_helper.tt +0 -31
  207. data/lib/generators/templates/helpers/raider_element.tt +0 -159
  208. data/lib/generators/templates/helpers/wait_helper.tt +0 -611
  209. data/lib/scaffolding/templates/feature.tt +0 -6
  210. data/lib/scaffolding/templates/steps.tt +0 -19
  211. data/sig/generators/cucumber/cucumber_generator.rbs +0 -12
  212. data/spec/fixtures/watir_master/cucumber_watir/Readme.md.snapshot +0 -175
  213. data/spec/fixtures/watir_master/cucumber_watir/features/step_definitions/login_steps.rb.snapshot +0 -24
  214. data/spec/fixtures/watir_master/cucumber_watir/page_objects/abstract/page.rb.snapshot +0 -37
  215. data/spec/fixtures/watir_master/cucumber_watir/page_objects/pages/login.rb.snapshot +0 -33
  216. data/spec/fixtures/watir_master/rspec_watir/Readme.md.snapshot +0 -174
  217. data/spec/fixtures/watir_master/rspec_watir/page_objects/abstract/page.rb.snapshot +0 -37
  218. data/spec/fixtures/watir_master/rspec_watir/page_objects/pages/login.rb.snapshot +0 -33
  219. data/spec/fixtures/watir_master/rspec_watir/spec/login_page_spec.rb.snapshot +0 -49
  220. data/spec/integration/content/cucumber_reporter_content_spec.rb +0 -161
  221. data/spec/integration/generators/cucumber_generator_spec.rb +0 -100
  222. data/spec/integration/helpers/wait_helper_mobile_spec.rb +0 -281
  223. data/spec/integration/helpers/wait_helper_spec.rb +0 -679
  224. data/spec/integration/helpers/wait_helper_support.rb +0 -183
  225. data/spec/system/watir_spec.rb +0 -38
@@ -1,183 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'erb'
4
- require 'rspec/expectations'
5
- # The real gem by its inner paths, not 'selenium-webdriver': spec/generators/video_helper_spec.rb puts a
6
- # stub selenium-webdriver.rb first on $LOAD_PATH, and the stub's Support module would mask the autoload.
7
- require 'selenium/webdriver'
8
- require 'selenium/webdriver/support'
9
- require 'tmpdir'
10
- require 'yaml'
11
-
12
- # Renders the WaitHelper templates and fakes the drivers and elements they talk to.
13
- module WaitHelperSpec
14
- TEMPLATES = File.expand_path('../../../lib/generators/templates/helpers', __dir__)
15
-
16
- # Answers the template's ERB conditionals the way the generator does.
17
- class Render
18
- def initialize(mobile)
19
- @mobile = mobile
20
- end
21
-
22
- def mobile?
23
- @mobile
24
- end
25
-
26
- def context
27
- binding
28
- end
29
- end
30
-
31
- # Renders both templates into one temp dir, so wait_helper.rb's require_relative finds raider_element.rb.
32
- # The web render loads at the top level, as in a generated project. A mobile render loads inside
33
- # `into` instead (load's wrap module), so both renders live in one process without clashing.
34
- def self.load_templates(mobile: false, into: nil)
35
- Dir.mktmpdir('raider_tt') do |dir|
36
- paths = %w[raider_element wait_helper].to_h do |name|
37
- source = File.read(File.join(TEMPLATES, "#{name}.tt"))
38
- path = File.join(dir, "#{name}.rb")
39
- File.write(path, ERB.new(source, trim_mode: '-').result(Render.new(mobile).context))
40
- [name, path]
41
- end
42
- next load(paths['wait_helper']) unless into
43
-
44
- # require_relative never wraps, so raider_element.rb is loaded into the namespace first
45
- # and marked as required, which makes wait_helper.rb's require_relative a no-op.
46
- load(paths['raider_element'], into)
47
- $LOADED_FEATURES << File.realpath(paths['raider_element'])
48
- load(paths['wait_helper'], into)
49
- end
50
- end
51
-
52
- # Scripted lookups shared by the fake driver and fake elements. Each locator answers from its
53
- # queue, one answer per call, repeating the last: nil is "no such element", an error class is raised.
54
- module Finder
55
- def script(locator, *answers)
56
- @fake[:one][locator] = answers
57
- self
58
- end
59
-
60
- def script_many(locator, *answers)
61
- @fake[:many][locator] = answers
62
- self
63
- end
64
-
65
- def finds = @fake[:finds]
66
-
67
- def find_element(**locator)
68
- finds << locator
69
- answer = next_answer(:one, locator, nil)
70
- raise answer if answer.is_a?(Class)
71
- raise Selenium::WebDriver::Error::NoSuchElementError, 'no such element' unless answer
72
-
73
- answer
74
- end
75
-
76
- def find_elements(**locator)
77
- finds << locator
78
- next_answer(:many, locator, [])
79
- end
80
-
81
- private
82
-
83
- def next_answer(kind, locator, default)
84
- queue = @fake[kind].fetch(locator) { [default] }
85
- queue.size > 1 ? queue.shift : queue.first
86
- end
87
- end
88
-
89
- # Records driver.action chains into the driver's log.
90
- class FakeActions
91
- def initialize(log)
92
- @log = log
93
- end
94
-
95
- %i[move_to scroll_to drag_and_drop perform].each do |step|
96
- define_method(step) do |*elements|
97
- @log << [step, *elements]
98
- self
99
- end
100
- end
101
- end
102
-
103
- # Selenium's driver, plus the Appium calls the mobile render makes.
104
- class FakeDriver
105
- include Finder
106
-
107
- WINDOW = Selenium::WebDriver::Rectangle.new(0, 20, 390, 800)
108
-
109
- def initialize(device: :ios)
110
- @fake = { one: {}, many: {}, finds: [], actions: [], scripts: [], device: }
111
- end
112
-
113
- def appium_device = @fake[:device]
114
- def actions = @fake[:actions]
115
- def action = FakeActions.new(actions)
116
- def scripts = @fake[:scripts]
117
- def window_rect = WINDOW
118
-
119
- def execute_script(command, *args)
120
- scripts << [command, *args]
121
- nil
122
- end
123
- end
124
-
125
- class FakeElement
126
- include Finder
127
-
128
- STALE = Selenium::WebDriver::Error::StaleElementReferenceError
129
-
130
- def initialize(**state)
131
- @fake = { one: {}, many: {}, finds: [] }
132
- @state = { displayed: true, enabled: true, selected: false, rects: [[0, 0, 10, 10]], text: 'hi',
133
- attributes: {}, tag_name: 'div', errors: [], log: [], stale: false, id: "el-#{object_id}" }.merge(state)
134
- end
135
-
136
- def log = @state[:log]
137
- def go_stale = @state[:stale] = true
138
- def go_hidden = @state[:displayed] = false
139
- def id = @state[:id]
140
- def displayed? = live(@state[:displayed])
141
- def enabled? = live(@state[:enabled])
142
- def selected? = live(@state[:selected])
143
- def text = live(@state[:text])
144
- def tag_name = live(@state[:tag_name])
145
- def attribute(name) = live(@state[:attributes][name])
146
- def dom_attribute(name) = live(@state[:attributes][name.to_s])
147
- def property(name) = live(@state[name.to_sym])
148
-
149
- # A stale element cannot be searched inside, as in Selenium.
150
- def find_element(**locator)
151
- live(nil)
152
- super
153
- end
154
-
155
- def find_elements(**locator)
156
- live(nil)
157
- super
158
- end
159
-
160
- def rect
161
- rects = @state[:rects]
162
- live(rects.size > 1 ? rects.shift : rects.first)
163
- end
164
-
165
- %i[click clear submit send_keys].each do |action|
166
- define_method(action) do |*keys|
167
- live(nil)
168
- error = @state[:errors].shift
169
- raise error if error
170
-
171
- log << [action, *keys]
172
- end
173
- end
174
-
175
- private
176
-
177
- def live(value)
178
- raise STALE, 'stale element reference' if @state[:stale]
179
-
180
- value
181
- end
182
- end
183
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../lib/ruby_raider'
4
- require_relative 'support/system_test_helper'
5
-
6
- FRAMEWORKS = %w[cucumber rspec].freeze unless defined?(FRAMEWORKS)
7
-
8
- describe 'Watir based frameworks' do
9
- include SystemTestHelper
10
-
11
- before(:all) do # rubocop:disable RSpec/BeforeAfterAll
12
- FRAMEWORKS.each do |framework|
13
- RubyRaider::Raider
14
- .new.invoke(:new, nil, %W[watir_#{framework} -p framework:#{framework} automation:watir])
15
- end
16
- end
17
-
18
- after(:all) do # rubocop:disable RSpec/BeforeAfterAll
19
- FRAMEWORKS.each { |framework| FileUtils.rm_rf("watir_#{framework}") }
20
- end
21
-
22
- shared_examples 'runs tests successfully' do |framework|
23
- it 'installs dependencies and runs tests without errors' do
24
- result = run_tests_with(framework, 'watir')
25
- expect(result[:success]).to be(true),
26
- "Tests failed for watir_#{framework}.\n" \
27
- "STDOUT: #{result[:stdout]}\nSTDERR: #{result[:stderr]}"
28
- end
29
- end
30
-
31
- context 'with rspec' do
32
- include_examples 'runs tests successfully', 'rspec'
33
- end
34
-
35
- context 'with cucumber' do
36
- include_examples 'runs tests successfully', 'cucumber'
37
- end
38
- end