ruby_raider 3.11.0 → 3.12.1
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/.ruby-version +1 -1
- data/README.md +43 -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 +18 -6
- data/lib/generators/automation/templates/partials/home_page_selector.tt +4 -6
- data/lib/generators/automation/templates/partials/initialize_selector.tt +3 -3
- data/lib/generators/automation/templates/partials/pdp_page_selector.tt +4 -6
- data/lib/generators/automation/templates/partials/url_methods.tt +3 -2
- data/lib/generators/automation/templates/partials/visit_method.tt +5 -5
- data/lib/generators/automation/templates/pdp.tt +3 -2
- data/lib/generators/cucumber/cucumber_generator.rb +16 -3
- data/lib/generators/cucumber/templates/env.tt +3 -3
- 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 +4 -0
- data/lib/generators/cucumber/templates/partials/web_steps.tt +4 -0
- data/lib/generators/cucumber/templates/steps.tt +2 -2
- data/lib/generators/cucumber/templates/user_factory.tt +2 -0
- data/lib/generators/cucumber/templates/world.tt +5 -3
- data/lib/generators/generator.rb +29 -14
- data/lib/generators/helper_generator.rb +8 -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/accessibility_spec.tt +10 -10
- data/lib/generators/rspec/templates/spec.tt +17 -2
- data/lib/generators/template_renderer/template_error.rb +8 -8
- data/lib/generators/templates/common/gemfile.tt +9 -9
- data/lib/generators/templates/common/partials/mobile_config.tt +1 -0
- data/lib/generators/templates/common/partials/web_config.tt +1 -1
- data/lib/generators/templates/common/read_me.tt +508 -24
- data/lib/generators/templates/helpers/appium_helper.tt +17 -15
- data/lib/generators/templates/helpers/browser_helper.tt +1 -2
- data/lib/generators/templates/helpers/partials/appium_driver.tt +1 -1
- 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 +46 -6
- data/lib/generators/templates/helpers/spec_helper.tt +10 -2
- data/lib/generators/templates/helpers/wait_helper.tt +470 -0
- data/lib/ruby_raider/ffmpeg.rb +7 -7
- data/lib/ruby_raider.rb +9 -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/sig/generators/generator.rbs +4 -0
- data/sig/ruby_raider.rbs +1 -0
- data/sig/scaffolding/project_detector.rbs +1 -0
- data/sig/scaffolding/scaffolding.rbs +1 -0
- data/spec/commands/raider_commands_spec.rb +48 -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 +37 -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 +37 -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/config_content_spec.rb +44 -0
- data/spec/integration/content/content_helper.rb +1 -5
- data/spec/integration/content/helper_content_spec.rb +79 -0
- data/spec/integration/content/page_content_spec.rb +75 -4
- data/spec/integration/content/readme_content_spec.rb +126 -5
- data/spec/integration/content/rubocop_content_spec.rb +87 -0
- data/spec/integration/content/syntax_validation_spec.rb +33 -30
- data/spec/integration/content/test_content_spec.rb +60 -0
- data/spec/integration/end_to_end_spec.rb +73 -28
- data/spec/integration/frozen_string_literal_matcher.rb +13 -0
- 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 +38 -0
- data/spec/integration/generators/invoke_generators_spec.rb +130 -0
- data/spec/integration/generators/rspec_generator_spec.rb +20 -0
- data/spec/integration/helpers/session_state_spec.rb +46 -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/scaffolding_e2e_spec.rb +1 -5
- 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 +17 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1312bb43aceb9be9a70d5e3d09e6694d901f6b5dc3ec80f27b6973de6c8d60c
|
|
4
|
+
data.tar.gz: ad4e86e9f7dd6bbbacac033fe48f18a93d6397040ab29490d0add8456f6ad2cc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b913021e191c5ff9fddc114590bc7b6a4a1b0e340a0fb2257da5477c2e3344dcd73088ea1cbac4eb1b28953b7bc3c250d56c648f15e85977088b8d96d3ddbc2b
|
|
7
|
+
data.tar.gz: c1d12da3f4447bbabecc6638895129dc0dd9d23dc08389a8b9d6ee9077c3936855b28746b9a6d9d049b3ced2c2e296462154c88e1845d6357078bb41ab8f75f6
|
data/.github/workflows/reek.yml
CHANGED
|
@@ -15,10 +15,14 @@ jobs:
|
|
|
15
15
|
with:
|
|
16
16
|
ruby-version: '3.3'
|
|
17
17
|
bundler-cache: true
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
- name: reek
|
|
20
20
|
uses: reviewdog/action-reek@v1
|
|
21
21
|
with:
|
|
22
22
|
reek_version: gemfile
|
|
23
23
|
reporter: github-pr-review # Default is github-pr-check
|
|
24
24
|
fail_on_error: true
|
|
25
|
+
|
|
26
|
+
- name: reek (whole repo)
|
|
27
|
+
# With a path: bare `reek` reads stdin when there is no terminal, which checks nothing in CI
|
|
28
|
+
run: bundle exec reek .
|
data/.reek.yml
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# setup-ruby's bundler-cache installs gems into vendor/bundle inside the checkout
|
|
2
|
+
exclude_paths:
|
|
3
|
+
- vendor
|
|
4
|
+
|
|
1
5
|
detectors:
|
|
2
6
|
Attribute:
|
|
3
7
|
enabled: false
|
|
@@ -49,3 +53,12 @@ detectors:
|
|
|
49
53
|
|
|
50
54
|
UtilityFunction:
|
|
51
55
|
enabled: false
|
|
56
|
+
|
|
57
|
+
# Baseline of warnings that predate whole-repo reek in CI (2026-10-31). Remove an
|
|
58
|
+
# entry when its code is reworked.
|
|
59
|
+
MissingSafeMethod:
|
|
60
|
+
exclude:
|
|
61
|
+
- 'ScaffoldingCommands' # validate_project! is a Thor command guard; a non-raising twin has no caller
|
|
62
|
+
TooManyConstants:
|
|
63
|
+
exclude:
|
|
64
|
+
- 'RubyRaider::Ffmpeg' # pinned version, release URL and manifest constants
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.4.
|
|
1
|
+
3.4.12
|
data/README.md
CHANGED
|
@@ -33,10 +33,12 @@ Ruby Raider is a CLI gem for scaffolding and generating UI test automation frame
|
|
|
33
33
|
|
|
34
34
|
### Web Testing
|
|
35
35
|
|
|
36
|
-
| Test Framework | Selenium | Watir |
|
|
37
|
-
|
|
38
|
-
| RSpec | ✅ | ✅
|
|
39
|
-
| Cucumber | ✅ | ✅
|
|
36
|
+
| Test Framework | Selenium | Watir (deprecated) |
|
|
37
|
+
|----------------|----------|--------------------|
|
|
38
|
+
| RSpec | ✅ | ✅ |
|
|
39
|
+
| Cucumber | ✅ | ✅ |
|
|
40
|
+
|
|
41
|
+
Watir is deprecated and will be removed in the next major version of ruby_raider (4.0); new projects should use Selenium. It is no longer offered in the interactive menu and is available only through `-p automation:watir` until 4.0. See [Migrating from Watir](#migrating-from-watir).
|
|
40
42
|
|
|
41
43
|
### Mobile Testing (Appium)
|
|
42
44
|
|
|
@@ -61,6 +63,8 @@ Every generated project comes with:
|
|
|
61
63
|
- **Page Object Model** — Base page and component classes with example pages
|
|
62
64
|
- **Test examples** — Working login tests against the [Raider Test Store](https://raider-test-site.onrender.com/)
|
|
63
65
|
- **Raider reporting** — RSpec and Cucumber projects include [raider_reporter](https://github.com/RaiderHQ/raider_reporter), which writes results to `raider-results/` and uploads runs to your Raider Hideout server when `RAIDER_TOKEN` and `RAIDER_ENDPOINT` are set; generated CI runs the suite through `raider-reporter exec` with `RAIDER_QUARANTINE`, so quarantined tests do not fail the build; an opt-in `raider-gate` job (`RAIDER_GATE=1`) fails CI when the Raider quality gate fails
|
|
66
|
+
- **Waiting** — generated Selenium and Appium projects wait for elements by themselves (`WaitHelper` and `RaiderElement`): `click`, `send_keys`, `text` and the rest poll until the element is ready, and `eventually { … }` retries assertions, so there is no implicit wait and no `sleep`; `timeout` in `config.yml` sets how long to wait
|
|
67
|
+
- **Example tests or a skeleton (`examples:false`)** — start from the working login examples, or pass `examples:false` for an empty skeleton with the helpers, config, CI and README (see [Getting Started](#getting-started))
|
|
64
68
|
- **Login reuse** — generated web projects (Selenium or Watir) log in once and restore the saved session for examples tagged `:logged_in` (RSpec) or `@logged_in` (Cucumber); `RAIDER_LOGIN_STATE=off|refresh` and `login_state: max_age:` control it, and the state stays in git-ignored `.raider/auth/`
|
|
65
69
|
- **Failure video replay** — Every test is recorded and the video is kept only for failing tests, attached to the report as `video` (WebM from page screenshots for Selenium and Watir, Appium's own MP4 for mobile, which needs `ffmpeg` on the Appium server host for iOS and for Android recordings over 180 s). Turn it off per run with `VIDEO=off`, or per project with `raider u video off`; ffmpeg is downloaded once, SHA-256 checked and cached in `~/.cache/raider`. The RaiderHQ `ffmpeg-7.1` build that the download uses is not published yet, so for now set `RAIDER_FFMPEG_PATH` to an ffmpeg with libvpx to get web videos
|
|
66
70
|
- **GitHub Actions CI** — Ready-to-use test pipeline that caches ffmpeg for failure videos
|
|
@@ -118,6 +122,41 @@ raider new my_project -p framework:rspec automation:selenium ci:azure
|
|
|
118
122
|
Azure Pipelines for mobile (Appium) projects is not available yet: with `ci:azure` no pipeline file is generated and a notice is printed.
|
|
119
123
|
Azure Repos ignores `pr:` triggers, so add the pipeline as a Build validation branch policy to get pull request builds.
|
|
120
124
|
|
|
125
|
+
Generate an empty skeleton, without the example pages and tests (the menu asks `Do you want example tests?`):
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
raider new my_project -p framework:rspec automation:selenium examples:false
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The skeleton keeps the helpers, config, CI and README, and its empty suite passes; grow it with `raider g`. Watir projects always include the examples.
|
|
132
|
+
|
|
133
|
+
## Migrating from Watir
|
|
134
|
+
|
|
135
|
+
Watir is deprecated; to move a Watir project to Selenium, generate a Selenium project and port your pages. The common mappings:
|
|
136
|
+
|
|
137
|
+
| Watir | Selenium project (waiting layer) |
|
|
138
|
+
|-------|----------------------------------|
|
|
139
|
+
| `browser.goto(url)` | `driver.navigate.to(url)` |
|
|
140
|
+
| `browser.text_field(id: 'x').set(v)` | `clear({ id: 'x' })` and `send_keys({ id: 'x' }, v)` |
|
|
141
|
+
| `browser.button(id: 'x').click` | `click({ id: 'x' })` |
|
|
142
|
+
| `Watir.default_timeout = n` | `timeout: n` in `config/config.yml` |
|
|
143
|
+
|
|
144
|
+
## Adopting waiting in an existing project
|
|
145
|
+
|
|
146
|
+
Gem upgrades do not rewrite generated code, so existing projects keep their implicit wait until you opt in:
|
|
147
|
+
|
|
148
|
+
1. Copy both `helpers/wait_helper.rb` and `helpers/raider_element.rb` from a freshly generated project into your
|
|
149
|
+
`helpers/` folder. Keep them side by side: `wait_helper.rb` loads the other with `require_relative 'raider_element'`.
|
|
150
|
+
2. Include it in `Page`, the spec helper, or the World, after loading it with `require_relative`, for example
|
|
151
|
+
`require_relative '../../helpers/wait_helper'` at the top of `page_objects/abstract/page.rb`.
|
|
152
|
+
3. Set how long it waits: add `timeout: 10` to `config/config.yml`. Single-platform mobile projects (iOS or Android
|
|
153
|
+
only) have no `config/config.yml`, so pass `timeout:` to a call, or create `config/config.yml` with that line;
|
|
154
|
+
without either, it waits 10 seconds.
|
|
155
|
+
4. Remove the `implicit_wait` line.
|
|
156
|
+
5. Move flaky spots to `click`, `send_keys` and `eventually` first.
|
|
157
|
+
|
|
158
|
+
Keep in mind that keeping the implicit wait while using the layer makes every `find` miss cost up to `timeout` seconds per poll cycle, so remove it once you have moved over.
|
|
159
|
+
|
|
121
160
|
## Commands
|
|
122
161
|
|
|
123
162
|
###### Anything between square brackets ([...]) is where your input goes
|
|
@@ -4,31 +4,36 @@ require_relative '../generator'
|
|
|
4
4
|
|
|
5
5
|
class AutomationGenerator < Generator
|
|
6
6
|
def generate_automation_files
|
|
7
|
+
generate_appium_settings if mobile?
|
|
8
|
+
generate_abstract_component unless mobile?
|
|
9
|
+
examples? ? generate_examples : generate_empty_folders
|
|
10
|
+
generate_abstract_page
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def generate_examples
|
|
7
16
|
if mobile?
|
|
8
|
-
generate_appium_settings
|
|
9
17
|
generate_home_page
|
|
10
18
|
generate_pdp_page
|
|
11
19
|
else
|
|
12
|
-
|
|
20
|
+
generate_header_component
|
|
13
21
|
generate_model_files
|
|
14
22
|
generate_pages
|
|
15
23
|
end
|
|
16
|
-
|
|
17
|
-
generate_abstract_page
|
|
18
24
|
end
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
# A skeleton keeps the folders for the pages and components it will grow with `raider g`
|
|
27
|
+
def generate_empty_folders
|
|
28
|
+
create_file("#{name}/page_objects/pages/.keep", '')
|
|
29
|
+
create_file("#{name}/page_objects/components/.keep", '') unless mobile?
|
|
30
|
+
end
|
|
21
31
|
|
|
22
32
|
def generate_pages
|
|
23
33
|
generate_login_page
|
|
24
34
|
generate_account_page
|
|
25
35
|
end
|
|
26
36
|
|
|
27
|
-
def generate_components
|
|
28
|
-
generate_abstract_component
|
|
29
|
-
generate_header_component
|
|
30
|
-
end
|
|
31
|
-
|
|
32
37
|
def generate_model_files
|
|
33
38
|
generate_model_factory
|
|
34
39
|
generate_model_data
|
|
@@ -18,14 +18,13 @@ browserstack:
|
|
|
18
18
|
platformName: Android
|
|
19
19
|
os_version: '9.0'
|
|
20
20
|
deviceName: Google Pixel 3
|
|
21
|
-
app:
|
|
21
|
+
app: <%= ENV['APP_URL'] %>
|
|
22
22
|
browserstack.user: <%= ENV['BROWSERSTACK_USER'] %>
|
|
23
23
|
browserstack.key: <%= ENV['BROWSERSTACK_KEY'] %>
|
|
24
24
|
project: 'RaiderTestApp'
|
|
25
25
|
name: 'RaiderTestApp-Android'
|
|
26
26
|
<% elsif ios? %>platformName: iOS
|
|
27
27
|
appium:options:
|
|
28
|
-
url: http://localhost:4723/wd/hub
|
|
29
28
|
platformVersion: '17.0'
|
|
30
29
|
deviceName: iPhone 15
|
|
31
30
|
automationName: XCUITest
|
|
@@ -43,7 +42,6 @@ browserstack:
|
|
|
43
42
|
name: 'RaiderTestApp-IOS'
|
|
44
43
|
<% elsif android? %>platformName: Android
|
|
45
44
|
appium:options:
|
|
46
|
-
url: http://localhost:4723/wd/hub
|
|
47
45
|
platformVersion: '14'
|
|
48
46
|
automationName: UiAutomator2
|
|
49
47
|
deviceName: Pixel 8 API 34
|
|
@@ -53,7 +51,7 @@ browserstack:
|
|
|
53
51
|
platformName: Android
|
|
54
52
|
os_version: '9.0'
|
|
55
53
|
deviceName: Google Pixel 3
|
|
56
|
-
app:
|
|
54
|
+
app: <%= ENV['APP_URL'] %>
|
|
57
55
|
browserstack.user: <%= ENV['BROWSERSTACK_USER'] %>
|
|
58
56
|
browserstack.key: <%= ENV['BROWSERSTACK_KEY'] %>
|
|
59
57
|
project: 'RaiderTestApp'
|
|
@@ -11,9 +11,9 @@ class Login < Page
|
|
|
11
11
|
|
|
12
12
|
<%- if selenium_based? -%>
|
|
13
13
|
def login(username, password)
|
|
14
|
-
username_field
|
|
15
|
-
password_field
|
|
16
|
-
login_button
|
|
14
|
+
send_keys(username_field, username)
|
|
15
|
+
send_keys(password_field, password)
|
|
16
|
+
click(login_button)
|
|
17
17
|
end
|
|
18
18
|
alias log_as login
|
|
19
19
|
<%- else -%>
|
|
@@ -30,7 +30,7 @@ class Login < Page
|
|
|
30
30
|
|
|
31
31
|
def username_field
|
|
32
32
|
<%- if selenium_based? -%>
|
|
33
|
-
|
|
33
|
+
{ id: 'loginFrm_loginname' }
|
|
34
34
|
<%- else -%>
|
|
35
35
|
browser.text_field(id: 'loginFrm_loginname')
|
|
36
36
|
<%- end -%>
|
|
@@ -38,7 +38,7 @@ class Login < Page
|
|
|
38
38
|
|
|
39
39
|
def password_field
|
|
40
40
|
<%- if selenium_based? -%>
|
|
41
|
-
|
|
41
|
+
{ id: 'loginFrm_password' }
|
|
42
42
|
<%- else -%>
|
|
43
43
|
browser.text_field(id: 'loginFrm_password')
|
|
44
44
|
<%- end -%>
|
|
@@ -46,7 +46,7 @@ class Login < Page
|
|
|
46
46
|
|
|
47
47
|
def login_button
|
|
48
48
|
<%- if selenium_based? -%>
|
|
49
|
-
|
|
49
|
+
{ xpath: "//button[@title='Login']" }
|
|
50
50
|
<%- else -%>
|
|
51
51
|
browser.button(xpath: "//button[@title='Login']")
|
|
52
52
|
<%- end -%>
|
|
@@ -1,26 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
<%- if web? && examples? -%>
|
|
2
4
|
require_relative '../components/header'
|
|
3
5
|
<%- end -%>
|
|
6
|
+
<%- if wait_helper? -%>
|
|
7
|
+
require_relative '../../helpers/wait_helper'
|
|
8
|
+
<%- end -%>
|
|
4
9
|
|
|
5
10
|
class Page
|
|
6
11
|
<%- if cross_platform? -%>
|
|
7
12
|
include AppiumHelper
|
|
8
13
|
<%- end -%>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
<%- if wait_helper? -%>
|
|
15
|
+
include WaitHelper
|
|
16
|
+
<%- end -%>
|
|
17
|
+
<%- if cross_platform? || wait_helper? -%>
|
|
18
|
+
|
|
19
|
+
<%- end -%>
|
|
20
|
+
<%= partial('initialize_selector') -%>
|
|
21
|
+
<%= partial('visit_method') -%>
|
|
22
|
+
<%= partial('url_methods') -%>
|
|
12
23
|
|
|
13
24
|
def to_s
|
|
14
25
|
self.class.to_s.sub('Page', ' Page')
|
|
15
26
|
end
|
|
27
|
+
<%- if selenium_based? && examples? -%>
|
|
16
28
|
|
|
17
|
-
<%- if selenium_based? -%>
|
|
18
29
|
# Components
|
|
19
30
|
|
|
20
31
|
def header
|
|
21
|
-
Header.new(
|
|
32
|
+
Header.new(find_element(css: '.welcome-msg'))
|
|
22
33
|
end
|
|
23
34
|
<%- elsif watir? -%>
|
|
35
|
+
|
|
24
36
|
# Components
|
|
25
37
|
|
|
26
38
|
def header
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
<%- if
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
driver.find_element(accessibility_id: 'product-item-1')
|
|
1
|
+
<%- if cross_platform? -%>
|
|
2
|
+
{ ios: { accessibility_id: 'product-item-1' },
|
|
3
|
+
android: { accessibility_id: 'product-item-1' } }
|
|
5
4
|
<%- else -%>
|
|
6
|
-
|
|
7
|
-
android: { accessibility_id: 'product-item-1' })
|
|
5
|
+
{ accessibility_id: 'product-item-1' }
|
|
8
6
|
<%- end -%>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
<%- if watir? -%>
|
|
2
2
|
attr_reader :browser
|
|
3
3
|
|
|
4
4
|
def initialize(browser)
|
|
5
5
|
@browser = browser
|
|
6
6
|
end
|
|
7
|
-
|
|
7
|
+
<%- else -%>
|
|
8
8
|
attr_reader :driver
|
|
9
9
|
|
|
10
10
|
def initialize(driver)
|
|
11
11
|
@driver = driver
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
<%- end -%>
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
<%- if
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
driver.find_element(accessibility_id: 'add-to-cart-button')
|
|
1
|
+
<%- if cross_platform? -%>
|
|
2
|
+
{ ios: { accessibility_id: 'add-to-cart-button' },
|
|
3
|
+
android: { accessibility_id: 'add-to-cart-button' } }
|
|
5
4
|
<%- else -%>
|
|
6
|
-
|
|
7
|
-
android: { accessibility_id: 'add-to-cart-button' })
|
|
5
|
+
{ accessibility_id: 'add-to-cart-button' }
|
|
8
6
|
<%- end -%>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
<%- if selenium_based? -%>
|
|
2
|
+
|
|
3
3
|
def visit(*page)
|
|
4
4
|
@driver.navigate.to full_url(page.first)
|
|
5
5
|
end
|
|
6
|
-
|
|
6
|
+
<%- elsif watir? -%>
|
|
7
|
+
|
|
7
8
|
def visit(*page)
|
|
8
9
|
@browser.goto full_url(page.first)
|
|
9
10
|
end
|
|
10
|
-
|
|
11
|
-
<% end %>
|
|
11
|
+
<%- end -%>
|
|
@@ -4,14 +4,27 @@ require_relative '../generator'
|
|
|
4
4
|
|
|
5
5
|
class CucumberGenerator < Generator
|
|
6
6
|
def generate_feature
|
|
7
|
+
return unless examples?
|
|
8
|
+
|
|
7
9
|
template('feature.tt', "#{name}/features/#{template_name}.feature")
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
def generate_steps
|
|
13
|
+
return unless examples?
|
|
14
|
+
|
|
11
15
|
template('steps.tt', "#{name}/features/step_definitions/#{template_name}_steps.rb")
|
|
12
16
|
end
|
|
13
17
|
|
|
18
|
+
# A skeleton keeps an empty step_definitions/ for the steps it will grow with `raider g steps`
|
|
19
|
+
def generate_empty_steps_folder
|
|
20
|
+
return if examples?
|
|
21
|
+
|
|
22
|
+
create_file("#{name}/features/step_definitions/.keep", '')
|
|
23
|
+
end
|
|
24
|
+
|
|
14
25
|
def generate_user_factory
|
|
26
|
+
return unless examples?
|
|
27
|
+
|
|
15
28
|
template('user_factory.tt', "#{name}/models/user_factory.rb")
|
|
16
29
|
end
|
|
17
30
|
|
|
@@ -28,18 +41,18 @@ class CucumberGenerator < Generator
|
|
|
28
41
|
end
|
|
29
42
|
|
|
30
43
|
def generate_accessibility_feature
|
|
31
|
-
return unless axe_addon? && web?
|
|
44
|
+
return unless axe_addon? && web? && examples?
|
|
32
45
|
|
|
33
46
|
template('accessibility_feature.tt', "#{name}/features/accessibility.feature")
|
|
34
47
|
end
|
|
35
48
|
|
|
36
49
|
def generate_accessibility_steps
|
|
37
|
-
return unless axe_addon? && web?
|
|
50
|
+
return unless axe_addon? && web? && examples?
|
|
38
51
|
|
|
39
52
|
template('accessibility_steps.tt', "#{name}/features/step_definitions/accessibility_steps.rb")
|
|
40
53
|
end
|
|
41
54
|
|
|
42
55
|
def template_name
|
|
43
|
-
@template_name ||=
|
|
56
|
+
@template_name ||= mobile? ? 'home' : 'login'
|
|
44
57
|
end
|
|
45
58
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<%- if selenium_based? -%>
|
|
2
|
-
|
|
2
|
+
<%= partial('selenium_env') -%>
|
|
3
3
|
<%- elsif mobile? -%>
|
|
4
|
-
|
|
4
|
+
<%= partial('appium_env') -%>
|
|
5
5
|
<%- else -%>
|
|
6
|
-
|
|
6
|
+
<%= partial('watir_env') -%>
|
|
7
7
|
<%- end -%>
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
require_relative '../../helpers/driver_helper'
|
|
2
|
+
<%- if wait_helper? -%>
|
|
3
|
+
require_relative '../../helpers/wait_helper'
|
|
4
|
+
<%- end -%>
|
|
2
5
|
<%- if selenium_based? -%>
|
|
6
|
+
<%- if examples? -%>
|
|
3
7
|
require_relative '../../models/user_factory'
|
|
8
|
+
<%- end -%>
|
|
4
9
|
|
|
5
10
|
World(DriverHelper)
|
|
11
|
+
World(WaitHelper)
|
|
6
12
|
<%- else -%>
|
|
7
13
|
|
|
8
14
|
World(DriverHelper)
|
|
15
|
+
<%- if wait_helper? -%>
|
|
16
|
+
World(WaitHelper)
|
|
17
|
+
<%- end -%>
|
|
9
18
|
<%- end -%>
|
|
@@ -9,9 +9,11 @@ require 'tmpdir'
|
|
|
9
9
|
require 'yaml'
|
|
10
10
|
require_relative '../../helpers/video_helper'
|
|
11
11
|
require_relative '../../helpers/session_state'
|
|
12
|
+
<%- if examples? -%>
|
|
12
13
|
require_relative '../../models/user_factory'
|
|
13
14
|
require_relative '../../page_objects/pages/account'
|
|
14
15
|
require_relative '../../page_objects/pages/login'
|
|
16
|
+
<%- end -%>
|
|
15
17
|
|
|
16
18
|
Before do
|
|
17
19
|
viewport = YAML.load_file('config/config.yml')['viewport']
|
|
@@ -24,6 +26,7 @@ Before do
|
|
|
24
26
|
@video_recorder.start
|
|
25
27
|
end
|
|
26
28
|
|
|
29
|
+
<%- if examples? -%>
|
|
27
30
|
Before('@logged_in') do
|
|
28
31
|
user = UserFactory.for('registered user')
|
|
29
32
|
account = Account.new(driver)
|
|
@@ -36,6 +39,7 @@ Before('@logged_in') do
|
|
|
36
39
|
end
|
|
37
40
|
end
|
|
38
41
|
|
|
42
|
+
<%- end -%>
|
|
39
43
|
After do |scenario|
|
|
40
44
|
video_path = @video_recorder&.stop(keep: scenario.failed?)
|
|
41
45
|
RaiderReporter.attach('video', video_path, type: :webm) if video_path
|
|
@@ -20,5 +20,9 @@ end
|
|
|
20
20
|
Then("I'm logged in") do
|
|
21
21
|
account_page = <% if watir? %>Account.new(browser)<% else %>Account.new(driver)<% end %>
|
|
22
22
|
account_page.visit
|
|
23
|
+
<%- if watir? -%>
|
|
23
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 -%>
|
|
24
28
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
<%- if watir? -%>
|
|
2
|
-
|
|
4
|
+
<%= partial('watir_world', strip: true) %>
|
|
3
5
|
<%- else -%>
|
|
4
|
-
|
|
5
|
-
<%- end -%>
|
|
6
|
+
<%= partial('driver_world', strip: true) %>
|
|
7
|
+
<%- end -%>
|