ruby_raider 3.2.1 → 3.3.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/README.md +21 -9
- data/RELEASE.md +11 -0
- data/lib/commands/scaffolding_commands.rb +6 -14
- data/lib/generators/cucumber/templates/accessibility_steps.tt +10 -10
- data/lib/generators/generator.rb +5 -0
- data/lib/generators/infrastructure/templates/github.tt +18 -0
- data/lib/generators/infrastructure/templates/github_appium.tt +26 -2
- data/lib/generators/templates/common/gemfile.tt +2 -1
- data/lib/generators/templates/common/git_ignore.tt +1 -0
- data/lib/generators/templates/common/read_me.tt +17 -0
- data/lib/generators/templates/helpers/partials/screenshot.tt +3 -3
- data/lib/generators/templates/helpers/spec_helper.tt +10 -5
- data/lib/generators/templates/helpers/test_helper.tt +1 -0
- data/lib/scaffolding/scaffolding.rb +0 -6
- data/lib/scaffolding/templates/page_object.tt +0 -3
- data/lib/scaffolding/templates/spec.tt +0 -6
- data/lib/scaffolding/templates/steps.tt +0 -3
- data/lib/version +1 -1
- data/sig/commands/scaffolding_commands.rbs +1 -1
- data/sig/scaffolding/scaffolding.rbs +0 -3
- data/spec/integration/content/ci_content_spec.rb +85 -0
- data/spec/integration/content/common_content_spec.rb +12 -1
- data/spec/integration/content/gemfile_content_spec.rb +38 -0
- data/spec/integration/content/helper_content_spec.rb +62 -0
- data/spec/integration/content/readme_content_spec.rb +31 -0
- data/spec/integration/end_to_end_spec.rb +30 -1
- data/spec/integration/scaffolding_e2e_spec.rb +0 -37
- data/spec/scaffolding/scaffolding_features_spec.rb +0 -20
- data/spec/system/support/system_test_helper.rb +8 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f5fc3418c82e5a121ebecbc862acd716ded56f9d7dc49be670e9f0361917deb
|
|
4
|
+
data.tar.gz: b7464935c9d32155bd30d80750c914e6fd3ba95b3db3d6ed8eb95d5461f86fcb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 827db06d8dab522391496aeedbff5e199119ac287e548241e1ce23bb9ff65616043c1626cb35226ce1230a8c154953c9eb0bc3f65d5a7abaa9ee323dfd76522d
|
|
7
|
+
data.tar.gz: e37a2899b4e8f78c941dd0f570f2a5c2833a61cc74cb30e392cc7e53565f1df78374853b0fd73b38aeabb7d8849fd22210cf534e153f3c8d9664128bd1566b5a
|
data/README.md
CHANGED
|
@@ -51,18 +51,30 @@ Ruby Raider is a CLI gem and API backend for scaffolding and generating UI test
|
|
|
51
51
|
|--------|------|-------------|
|
|
52
52
|
| Accessibility | `--accessibility` | Adds axe gem + example accessibility tests |
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
This works on all platforms (Mac OS, Linux and Windows).
|
|
55
|
+
|
|
56
|
+
## What's Included
|
|
57
|
+
|
|
58
|
+
Every generated project comes with:
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
- **Page Object Model** — Base page and component classes with example pages
|
|
61
|
+
- **Test examples** — Working login tests against the [Raider Test Store](https://raider-test-site.onrender.com/)
|
|
62
|
+
- **Allure reporting** — Pre-configured with screenshot capture on failure
|
|
63
|
+
- **Raider reporting** — RSpec projects include [raider_reporter](https://github.com/RaiderHQ/raider_reporter), which writes results to `raider-results/` and uploads runs when `RAIDER_TOKEN` and `RAIDER_ENDPOINT` are set
|
|
64
|
+
- **GitHub Actions CI** — Ready-to-use test pipeline
|
|
65
|
+
- **Rake tasks** — Default, smoke, and regression tasks with tag-based filtering
|
|
66
|
+
- **Retry support** — RSpec retry with configurable retry count via `RETRY_COUNT` env var
|
|
67
|
+
- **Re-run failed tests** — Persistence file for tracking example status
|
|
68
|
+
- **Parallel execution** — parallel_tests and parallel_split_test gems included
|
|
69
|
+
- **Configurable browser** — Chrome/Firefox with customizable arguments, viewport, timeout, and headless mode
|
|
70
|
+
- **Linting** — RuboCop and Reek configs included
|
|
57
71
|
|
|
58
|
-
|
|
72
|
+
For Appium projects, download the example [app](https://github.com/RaiderHQ/raider_test_app) and start the server:
|
|
59
73
|
|
|
60
74
|
```bash
|
|
61
75
|
raider u start_appium
|
|
62
76
|
```
|
|
63
77
|
|
|
64
|
-
This works on all platforms (Mac OS, Linux and Windows).
|
|
65
|
-
|
|
66
78
|
## Getting Started
|
|
67
79
|
|
|
68
80
|
Install the gem:
|
|
@@ -83,7 +95,7 @@ Or skip the menu with parameters:
|
|
|
83
95
|
raider new [project_name] -p framework:rspec automation:selenium
|
|
84
96
|
```
|
|
85
97
|
|
|
86
|
-
Add
|
|
98
|
+
Add accessibility testing:
|
|
87
99
|
|
|
88
100
|
```bash
|
|
89
101
|
raider new my_project -p framework:rspec automation:selenium --accessibility
|
|
@@ -119,7 +131,6 @@ raider g scaffold [NAME(S)] # Create page + test + steps
|
|
|
119
131
|
|
|
120
132
|
Options:
|
|
121
133
|
|
|
122
|
-
* `--uses [PAGES]` — Specify page dependencies
|
|
123
134
|
* `--path [PATH]` — Custom output path
|
|
124
135
|
|
|
125
136
|
### Utility Commands
|
|
@@ -128,8 +139,9 @@ Options:
|
|
|
128
139
|
raider u path [PATH] # Set default paths for scaffolding
|
|
129
140
|
raider u url [URL] # Set default project URL
|
|
130
141
|
raider u browser [BROWSER] # Set default browser
|
|
131
|
-
raider u browser_options [OPTS] # Set browser
|
|
132
|
-
raider u
|
|
142
|
+
raider u browser_options [OPTS] # Set browser arguments (e.g., no-sandbox, headless)
|
|
143
|
+
raider u headless [on/off] # Toggle headless mode
|
|
144
|
+
raider u raid # Run all tests (-p for parallel)
|
|
133
145
|
raider u timeout [SECONDS] # Set test timeout
|
|
134
146
|
raider u viewport [DIMENSIONS] # Set viewport size (e.g., 1920x1080)
|
|
135
147
|
raider u platform [PLATFORM] # Set platform for cross-platform tests
|
data/RELEASE.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Release Process Documentation
|
|
2
2
|
|
|
3
|
+
## Release Notes
|
|
4
|
+
|
|
5
|
+
### 3.3.0
|
|
6
|
+
|
|
7
|
+
- Generated RSpec projects now include `raider_reporter`: results are written to `raider-results/` and uploaded when `RAIDER_TOKEN` and `RAIDER_ENDPOINT` are set. Allure is still produced. Cucumber projects are unchanged.
|
|
8
|
+
- Screenshots (Allure too) are now taken only when an example fails, and are attached to both Allure and Raider.
|
|
9
|
+
- Generated GitHub CI now runs on push (main, master), pull requests and manual dispatch, passes the Raider settings to RSpec runs and uploads `raider-results/` as an artifact.
|
|
10
|
+
- Fixed the generated Gemfile `ruby_raider` pin so it follows the gem's own major.minor version.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
3
14
|
## Overview
|
|
4
15
|
|
|
5
16
|
Ruby Raider uses a **fully automated release process**. You only need to run a single command, and everything else happens automatically via GitHub Actions.
|
|
@@ -13,11 +13,9 @@ class ScaffoldingCommands < Thor
|
|
|
13
13
|
desc 'page [PAGE_NAME]', 'Creates a new page object'
|
|
14
14
|
option :path, type: :string, required: false,
|
|
15
15
|
desc: 'The path where your page will be created', aliases: '-p'
|
|
16
|
-
option :uses, type: :array, required: false,
|
|
17
|
-
desc: 'Dependent pages to require', aliases: '-u'
|
|
18
16
|
|
|
19
17
|
def page(name)
|
|
20
|
-
generate_scaffolding(name, 'page', options[:path]
|
|
18
|
+
generate_scaffolding(name, 'page', options[:path])
|
|
21
19
|
end
|
|
22
20
|
|
|
23
21
|
desc 'feature [NAME]', 'Creates a new feature'
|
|
@@ -31,11 +29,9 @@ class ScaffoldingCommands < Thor
|
|
|
31
29
|
desc 'spec [SPEC_NAME]', 'Creates a new spec'
|
|
32
30
|
option :path, type: :string, required: false,
|
|
33
31
|
desc: 'The path where your spec will be created', aliases: '-p'
|
|
34
|
-
option :uses, type: :array, required: false,
|
|
35
|
-
desc: 'Dependent pages to require', aliases: '-u'
|
|
36
32
|
|
|
37
33
|
def spec(name)
|
|
38
|
-
generate_scaffolding(name, 'spec', options[:path]
|
|
34
|
+
generate_scaffolding(name, 'spec', options[:path])
|
|
39
35
|
end
|
|
40
36
|
|
|
41
37
|
desc 'helper [HELPER_NAME]', 'Creates a new helper'
|
|
@@ -63,8 +59,6 @@ class ScaffoldingCommands < Thor
|
|
|
63
59
|
end
|
|
64
60
|
|
|
65
61
|
desc 'scaffold [NAMES...]', 'Generates pages, specs/features, and helpers for one or more names'
|
|
66
|
-
option :uses, type: :array, required: false,
|
|
67
|
-
desc: 'Dependent pages to require', aliases: '-u'
|
|
68
62
|
|
|
69
63
|
def scaffold(*names)
|
|
70
64
|
names.each { |name| generate_default_scaffold(name) }
|
|
@@ -95,23 +89,21 @@ class ScaffoldingCommands < Thor
|
|
|
95
89
|
end
|
|
96
90
|
end
|
|
97
91
|
|
|
98
|
-
def generate_scaffolding(name, type, path
|
|
92
|
+
def generate_scaffolding(name, type, path)
|
|
99
93
|
path ||= load_config_path(type)
|
|
100
94
|
scaffolding = Scaffolding.new([name, path])
|
|
101
|
-
scaffolding.uses = Array(uses) if uses
|
|
102
95
|
scaffolding.send("generate_#{type}")
|
|
103
96
|
end
|
|
104
97
|
|
|
105
98
|
def generate_default_scaffold(name)
|
|
106
99
|
validate_project!
|
|
107
|
-
uses = options[:uses]
|
|
108
100
|
if Pathname.new('spec').exist? && !Pathname.new('features').exist?
|
|
109
|
-
generate_scaffolding(name, 'spec', load_config_path('spec')
|
|
101
|
+
generate_scaffolding(name, 'spec', load_config_path('spec'))
|
|
110
102
|
else
|
|
111
103
|
generate_scaffolding(name, 'feature', load_config_path('feature'))
|
|
112
|
-
generate_scaffolding(name, 'steps', load_config_path('steps')
|
|
104
|
+
generate_scaffolding(name, 'steps', load_config_path('steps'))
|
|
113
105
|
end
|
|
114
|
-
generate_scaffolding(name, 'page', load_config_path('page')
|
|
106
|
+
generate_scaffolding(name, 'page', load_config_path('page'))
|
|
115
107
|
end
|
|
116
108
|
end
|
|
117
109
|
end
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
Given('I am on the home page') do
|
|
4
|
-
|
|
5
|
-
browser.goto 'https://raider-test-site.onrender.com/'
|
|
6
|
-
|
|
7
|
-
driver.get 'https://raider-test-site.onrender.com/'
|
|
8
|
-
|
|
4
|
+
<%- if watir? -%>
|
|
5
|
+
browser.goto 'https://raider-test-site.onrender.com/'
|
|
6
|
+
<%- else -%>
|
|
7
|
+
driver.get 'https://raider-test-site.onrender.com/'
|
|
8
|
+
<%- end -%>
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
Then('the page should be accessible') do
|
|
12
|
-
|
|
13
|
-
expect(browser.driver).to be_axe_clean
|
|
14
|
-
|
|
15
|
-
expect(driver).to be_axe_clean
|
|
16
|
-
|
|
12
|
+
<%- if watir? -%>
|
|
13
|
+
expect(browser.driver).to be_axe_clean
|
|
14
|
+
<%- else -%>
|
|
15
|
+
expect(driver).to be_axe_clean
|
|
16
|
+
<%- end -%>
|
|
17
17
|
end
|
data/lib/generators/generator.rb
CHANGED
|
@@ -71,6 +71,11 @@ class Generator < Thor::Group
|
|
|
71
71
|
args.include?('selenium')
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
def ruby_raider_version_requirement
|
|
75
|
+
major, minor = File.read(File.expand_path('../version', __dir__)).strip.split('.')
|
|
76
|
+
"~> #{major}.#{minor}"
|
|
77
|
+
end
|
|
78
|
+
|
|
74
79
|
private
|
|
75
80
|
|
|
76
81
|
def _initializer
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
name: <%- if framework == 'cucumber' -%>Cucumber Tests<%- else -%>Rspec Tests<%- end -%>
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, master ]
|
|
6
|
+
pull_request:
|
|
4
7
|
workflow_dispatch:
|
|
5
8
|
inputs:
|
|
6
9
|
browser:
|
|
@@ -37,6 +40,21 @@ jobs:
|
|
|
37
40
|
run: <%- if framework == 'cucumber' -%>bundle exec cucumber features --format pretty<%- else -%>bundle exec rspec spec --format documentation<%- end %>
|
|
38
41
|
env:
|
|
39
42
|
HEADLESS: true
|
|
43
|
+
<%- unless framework == 'cucumber' -%>
|
|
44
|
+
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
45
|
+
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
46
|
+
<%- end -%>
|
|
47
|
+
|
|
48
|
+
<%- unless framework == 'cucumber' -%>
|
|
49
|
+
- name: Upload Raider results
|
|
50
|
+
uses: actions/upload-artifact@v4
|
|
51
|
+
if: always()
|
|
52
|
+
with:
|
|
53
|
+
name: raider-results
|
|
54
|
+
path: raider-results/
|
|
55
|
+
if-no-files-found: ignore
|
|
56
|
+
|
|
57
|
+
<%- end -%>
|
|
40
58
|
|
|
41
59
|
- name: Get Allure history
|
|
42
60
|
uses: actions/checkout@v2
|
|
@@ -2,9 +2,9 @@ name: Appium Tests
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
branches: [ main ]
|
|
5
|
+
branches: [ main, master ]
|
|
6
6
|
pull_request:
|
|
7
|
-
|
|
7
|
+
workflow_dispatch:
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
<%- if ios? || cross_platform? -%>
|
|
@@ -52,6 +52,18 @@ jobs:
|
|
|
52
52
|
<%- end -%>
|
|
53
53
|
env:
|
|
54
54
|
APP_PATH: ${{ github.workspace }}/apps/RaiderTestApp.app
|
|
55
|
+
<%- unless cucumber? -%>
|
|
56
|
+
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
57
|
+
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
58
|
+
|
|
59
|
+
- name: Upload Raider results
|
|
60
|
+
uses: actions/upload-artifact@v4
|
|
61
|
+
if: always()
|
|
62
|
+
with:
|
|
63
|
+
name: raider-results-ios
|
|
64
|
+
path: raider-results/
|
|
65
|
+
if-no-files-found: ignore
|
|
66
|
+
<%- end -%>
|
|
55
67
|
<%- end -%>
|
|
56
68
|
|
|
57
69
|
<%- if android? || cross_platform? -%>
|
|
@@ -101,4 +113,16 @@ jobs:
|
|
|
101
113
|
<%- end -%>
|
|
102
114
|
env:
|
|
103
115
|
APP_PATH: ${{ github.workspace }}/apps/app-release.apk
|
|
116
|
+
<%- unless cucumber? -%>
|
|
117
|
+
RAIDER_TOKEN: ${{ secrets.RAIDER_TOKEN }}
|
|
118
|
+
RAIDER_ENDPOINT: ${{ vars.RAIDER_ENDPOINT }}
|
|
119
|
+
|
|
120
|
+
- name: Upload Raider results
|
|
121
|
+
uses: actions/upload-artifact@v4
|
|
122
|
+
if: always()
|
|
123
|
+
with:
|
|
124
|
+
name: raider-results-android
|
|
125
|
+
path: raider-results/
|
|
126
|
+
if-no-files-found: ignore
|
|
127
|
+
<%- end -%>
|
|
104
128
|
<%- end -%>
|
|
@@ -20,6 +20,7 @@ gem 'parallel_tests'
|
|
|
20
20
|
gem 'rake'
|
|
21
21
|
gem 'reek'
|
|
22
22
|
<%- if rspec? -%>
|
|
23
|
+
gem 'raider_reporter', '~> 0.2'
|
|
23
24
|
gem 'rspec-retry'
|
|
24
25
|
<%- end -%>
|
|
25
26
|
gem '<%= framework %>'
|
|
@@ -30,7 +31,7 @@ gem 'rubocop'
|
|
|
30
31
|
<%- if rspec? -%>
|
|
31
32
|
gem 'rubocop-rspec'
|
|
32
33
|
<%- end -%>
|
|
33
|
-
gem 'ruby_raider', '
|
|
34
|
+
gem 'ruby_raider', '<%= ruby_raider_version_requirement %>'
|
|
34
35
|
<%- if selenium_based? %>
|
|
35
36
|
gem 'selenium-webdriver'
|
|
36
37
|
<%- end -%>
|
|
@@ -82,6 +82,23 @@ raider g steps [NAME] # Create step definitions
|
|
|
82
82
|
raider g scaffold [NAME] # Create page + test + steps
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
<%- if rspec? -%>
|
|
86
|
+
## Reporting
|
|
87
|
+
|
|
88
|
+
Every run writes machine-readable results to `raider-results/` (including `run.json`), next to the usual Allure results.
|
|
89
|
+
Allure reports are still produced.
|
|
90
|
+
|
|
91
|
+
To upload runs to Raider, set these environment variables before running the suite:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
export RAIDER_TOKEN=your-token
|
|
95
|
+
export RAIDER_ENDPOINT=https://your-raider-endpoint
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Without `RAIDER_TOKEN`, nothing is uploaded and the suite output is unchanged. Failure screenshots are attached to both
|
|
99
|
+
Allure and Raider. See the [raider_reporter README](https://github.com/RaiderHQ/raider_reporter) for details.
|
|
100
|
+
|
|
101
|
+
<%- end -%>
|
|
85
102
|
### Sponsors
|
|
86
103
|
|
|
87
104
|
This project is tested with BrowserStack.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<% if selenium_based? %>
|
|
2
|
-
screenshot = driver.save_screenshot(
|
|
2
|
+
screenshot = driver.save_screenshot(screenshot_path)
|
|
3
3
|
<% elsif watir? %>
|
|
4
|
-
screenshot = browser.screenshot.save(
|
|
4
|
+
screenshot = browser.screenshot.save(screenshot_path)
|
|
5
5
|
<% else %>
|
|
6
|
-
screenshot = driver.screenshot(
|
|
6
|
+
screenshot = driver.screenshot(screenshot_path)
|
|
7
7
|
<% end %>
|
|
@@ -5,6 +5,8 @@ require 'axe-rspec'
|
|
|
5
5
|
<%- end -%>
|
|
6
6
|
require 'rspec'
|
|
7
7
|
require 'rspec/retry'
|
|
8
|
+
require 'digest'
|
|
9
|
+
require 'raider_reporter/rspec'
|
|
8
10
|
require 'tmpdir'
|
|
9
11
|
require_relative 'allure_helper'
|
|
10
12
|
<%- if watir? -%>
|
|
@@ -21,7 +23,8 @@ module SpecHelper
|
|
|
21
23
|
config.verbose_retry = true
|
|
22
24
|
config.display_try_failure_messages = true
|
|
23
25
|
config.default_retry_count = ENV.fetch('RETRY_COUNT', 0).to_i
|
|
24
|
-
config.
|
|
26
|
+
config.add_formatter(AllureHelper.formatter)
|
|
27
|
+
config.add_formatter(RaiderReporter::RSpec::Formatter)
|
|
25
28
|
<%- if watir? -%>
|
|
26
29
|
config.include(BrowserHelper)
|
|
27
30
|
<%- else -%>
|
|
@@ -53,10 +56,12 @@ module SpecHelper
|
|
|
53
56
|
example_name = example.description
|
|
54
57
|
if example.exception
|
|
55
58
|
@_exception = example.exception
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
Dir.mktmpdir do |temp_folder|
|
|
60
|
+
screenshot_path = "#{temp_folder}/#{example_name}.png"
|
|
61
|
+
<%= partial('screenshot', strip: true) %>
|
|
62
|
+
AllureHelper.add_screenshot(example_name, screenshot)
|
|
63
|
+
RaiderReporter.attach('screenshot', screenshot_path, type: :png)
|
|
64
|
+
end
|
|
60
65
|
end
|
|
61
66
|
<%= partial('quit_driver', strip: true) %>
|
|
62
67
|
end
|
|
@@ -74,6 +74,7 @@ module TestHelper
|
|
|
74
74
|
<%- end -%>
|
|
75
75
|
<%- end -%>
|
|
76
76
|
Dir.mktmpdir do |temp_folder|
|
|
77
|
+
screenshot_path = "#{temp_folder}/#{example_name}.png"
|
|
77
78
|
<%= partial('screenshot', strip: true) %>
|
|
78
79
|
<%- if allure_reporter? -%>
|
|
79
80
|
AllureHelper.add_screenshot(example_name, screenshot)
|
|
@@ -11,8 +11,6 @@ class Scaffolding < Thor::Group
|
|
|
11
11
|
argument :name, optional: true
|
|
12
12
|
argument :path, optional: true
|
|
13
13
|
|
|
14
|
-
attr_writer :uses
|
|
15
|
-
|
|
16
14
|
def self.source_root
|
|
17
15
|
"#{File.dirname(__FILE__)}/templates"
|
|
18
16
|
end
|
|
@@ -94,10 +92,6 @@ class Scaffolding < Thor::Group
|
|
|
94
92
|
automation_type == 'watir'
|
|
95
93
|
end
|
|
96
94
|
|
|
97
|
-
def uses_list
|
|
98
|
-
Array(@uses).reject(&:empty?)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
95
|
def default_path(standard_path, file_type)
|
|
102
96
|
path ? "#{path}/#{normalized_name}#{file_type}" : standard_path
|
|
103
97
|
end
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../page_objects/pages/<%= normalized_name %>'
|
|
4
|
-
<%- uses_list.each do |dep| -%>
|
|
5
|
-
require_relative '../page_objects/pages/<%= dep %>'
|
|
6
|
-
<%- end -%>
|
|
7
4
|
|
|
8
5
|
describe '<%= page_class_name %>' do
|
|
9
6
|
<%- if selenium? -%>
|
|
@@ -11,9 +8,6 @@ describe '<%= page_class_name %>' do
|
|
|
11
8
|
<%- elsif watir? -%>
|
|
12
9
|
let(:page) { <%= page_class_name %>.new(browser) }
|
|
13
10
|
<%- end -%>
|
|
14
|
-
<%- uses_list.each do |dep| -%>
|
|
15
|
-
let(:<%= dep %>) { <%= NameNormalizer.to_page_class(dep) %>.new<%= selenium? ? '(driver)' : '(browser)' %> }
|
|
16
|
-
<%- end -%>
|
|
17
11
|
<%- if project_config['url'] -%>
|
|
18
12
|
|
|
19
13
|
before do
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../../page_objects/pages/<%= normalized_name %>'
|
|
4
|
-
<%- uses_list.each do |dep| -%>
|
|
5
|
-
require_relative '../../page_objects/pages/<%= dep %>'
|
|
6
|
-
<%- end -%>
|
|
7
4
|
|
|
8
5
|
Given('I am on the <%= normalized_name.tr("_", " ") %> page') do
|
|
9
6
|
<%- if selenium? -%>
|
data/lib/version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.3.0
|
|
@@ -11,6 +11,6 @@ class ScaffoldingCommands < Thor
|
|
|
11
11
|
private
|
|
12
12
|
|
|
13
13
|
def load_config_path: (String type) -> String?
|
|
14
|
-
def generate_scaffolding: (String name, String type, String? path
|
|
14
|
+
def generate_scaffolding: (String name, String type, String? path) -> void
|
|
15
15
|
def generate_default_scaffold: (String name) -> void
|
|
16
16
|
end
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
class Scaffolding < Thor::Group
|
|
3
3
|
include Thor::Actions
|
|
4
4
|
|
|
5
|
-
attr_writer uses: Array[String]
|
|
6
|
-
|
|
7
5
|
def self.source_root: () -> String
|
|
8
6
|
|
|
9
7
|
# Generation methods
|
|
@@ -27,6 +25,5 @@ class Scaffolding < Thor::Group
|
|
|
27
25
|
def project_config: () -> Hash[String, untyped]
|
|
28
26
|
def selenium?: () -> bool
|
|
29
27
|
def watir?: () -> bool
|
|
30
|
-
def uses_list: () -> Array[String]
|
|
31
28
|
def default_path: (String standard_path, String file_type) -> String
|
|
32
29
|
end
|
|
@@ -44,21 +44,106 @@ describe 'CI pipeline content' do
|
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
shared_examples 'github triggers' do |project_name, file|
|
|
48
|
+
subject(:pipeline) { read_generated(project_name, ".github/workflows/#{file}") }
|
|
49
|
+
|
|
50
|
+
let(:triggers) { YAML.safe_load(pipeline)[true] }
|
|
51
|
+
|
|
52
|
+
it 'triggers on push to main and master' do
|
|
53
|
+
expect(triggers['push']['branches']).to include('main', 'master')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'triggers on pull_request' do
|
|
57
|
+
expect(triggers).to have_key('pull_request')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'triggers on workflow_dispatch' do
|
|
61
|
+
expect(triggers).to have_key('workflow_dispatch')
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
shared_examples 'github raider wiring' do |project_name, file|
|
|
66
|
+
subject(:pipeline) { read_generated(project_name, ".github/workflows/#{file}") }
|
|
67
|
+
|
|
68
|
+
let(:steps) { YAML.safe_load(pipeline)['jobs'].values.flat_map { |job| job['steps'] } }
|
|
69
|
+
|
|
70
|
+
let(:test_steps) do
|
|
71
|
+
steps.select { |step| step['run'].to_s.include?('rspec') || step['with'].to_h['script'].to_s.include?('rspec') }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'passes Raider settings to every test step' do
|
|
75
|
+
expect(test_steps).not_to be_empty
|
|
76
|
+
test_steps.each do |step|
|
|
77
|
+
expect(step['env']).to include('RAIDER_TOKEN' => '${{ secrets.RAIDER_TOKEN }}',
|
|
78
|
+
'RAIDER_ENDPOINT' => '${{ vars.RAIDER_ENDPOINT }}')
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'uploads raider-results as an artifact even on failure in every job' do
|
|
83
|
+
uploads = steps.select { |step| step['uses'] == 'actions/upload-artifact@v4' }
|
|
84
|
+
expect(uploads.size).to eq(YAML.safe_load(pipeline)['jobs'].size)
|
|
85
|
+
uploads.each do |upload|
|
|
86
|
+
expect(upload['with']['path']).to eq('raider-results/')
|
|
87
|
+
expect(upload['if']).to eq('always()')
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
shared_examples 'github without raider wiring' do |project_name, file|
|
|
93
|
+
subject(:pipeline) { read_generated(project_name, ".github/workflows/#{file}") }
|
|
94
|
+
|
|
95
|
+
it 'has no Raider settings or artifact' do
|
|
96
|
+
expect(pipeline).not_to include('RAIDER_')
|
|
97
|
+
expect(pipeline).not_to include('raider-results')
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
shared_examples 'github allure steps' do |project_name|
|
|
102
|
+
subject(:pipeline) { read_generated(project_name, '.github/workflows/test_pipeline.yml') }
|
|
103
|
+
|
|
104
|
+
it 'keeps the Allure steps' do
|
|
105
|
+
expect(pipeline).to include('simple-elf/allure-report-action', 'peaceiris/actions-gh-pages')
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
47
109
|
context 'with rspec and selenium' do
|
|
48
110
|
name = "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
|
|
49
111
|
include_examples 'valid github pipeline', name
|
|
50
112
|
include_examples 'github rspec pipeline', name
|
|
113
|
+
include_examples 'github triggers', name, 'test_pipeline.yml'
|
|
114
|
+
include_examples 'github raider wiring', name, 'test_pipeline.yml'
|
|
115
|
+
include_examples 'github allure steps', name
|
|
51
116
|
end
|
|
52
117
|
|
|
53
118
|
context 'with cucumber and selenium' do
|
|
54
119
|
name = "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::SELENIUM}"
|
|
55
120
|
include_examples 'valid github pipeline', name
|
|
56
121
|
include_examples 'github cucumber pipeline', name
|
|
122
|
+
include_examples 'github triggers', name, 'test_pipeline.yml'
|
|
123
|
+
include_examples 'github without raider wiring', name, 'test_pipeline.yml'
|
|
124
|
+
include_examples 'github allure steps', name
|
|
57
125
|
end
|
|
58
126
|
|
|
59
127
|
context 'with rspec and watir' do
|
|
60
128
|
name = "#{FrameworkIndex::RSPEC}_#{AutomationIndex::WATIR}"
|
|
61
129
|
include_examples 'valid github pipeline', name
|
|
62
130
|
include_examples 'github rspec pipeline', name
|
|
131
|
+
include_examples 'github triggers', name, 'test_pipeline.yml'
|
|
132
|
+
include_examples 'github raider wiring', name, 'test_pipeline.yml'
|
|
133
|
+
include_examples 'github allure steps', name
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
%w[android ios cross_platform].each do |automation|
|
|
137
|
+
context "with rspec and #{automation}" do
|
|
138
|
+
name = "#{FrameworkIndex::RSPEC}_#{automation}"
|
|
139
|
+
include_examples 'github triggers', name, 'appium_pipeline.yml'
|
|
140
|
+
include_examples 'github raider wiring', name, 'appium_pipeline.yml'
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context "with cucumber and #{automation}" do
|
|
144
|
+
name = "#{FrameworkIndex::CUCUMBER}_#{automation}"
|
|
145
|
+
include_examples 'github triggers', name, 'appium_pipeline.yml'
|
|
146
|
+
include_examples 'github without raider wiring', name, 'appium_pipeline.yml'
|
|
147
|
+
end
|
|
63
148
|
end
|
|
64
149
|
end
|
|
@@ -89,6 +89,10 @@ describe 'Common file content' do
|
|
|
89
89
|
it 'uses documentation format' do
|
|
90
90
|
expect(rspec_file).to include('--format documentation')
|
|
91
91
|
end
|
|
92
|
+
|
|
93
|
+
it 'leaves the raider formatter to spec_helper, since a command-line --format replaces .rspec formatters' do
|
|
94
|
+
expect(rspec_file).not_to include('RaiderReporter')
|
|
95
|
+
end
|
|
92
96
|
end
|
|
93
97
|
|
|
94
98
|
shared_examples 'no rspec dotfile' do |project_name|
|
|
@@ -109,6 +113,10 @@ describe 'Common file content' do
|
|
|
109
113
|
it 'includes spec/examples.txt' do
|
|
110
114
|
expect(gitignore).to include('spec/examples.txt')
|
|
111
115
|
end
|
|
116
|
+
|
|
117
|
+
it 'includes raider-results' do
|
|
118
|
+
expect(gitignore).to include('raider-results')
|
|
119
|
+
end
|
|
112
120
|
end
|
|
113
121
|
|
|
114
122
|
shared_examples 'non-rspec gitignore' do |project_name|
|
|
@@ -121,6 +129,10 @@ describe 'Common file content' do
|
|
|
121
129
|
it 'does not include spec/examples.txt' do
|
|
122
130
|
expect(gitignore).not_to include('spec/examples.txt')
|
|
123
131
|
end
|
|
132
|
+
|
|
133
|
+
it 'does not include raider-results' do
|
|
134
|
+
expect(gitignore).not_to include('raider-results')
|
|
135
|
+
end
|
|
124
136
|
end
|
|
125
137
|
|
|
126
138
|
# --- Spec helper retry config (C4) ---
|
|
@@ -220,5 +232,4 @@ describe 'Common file content' do
|
|
|
220
232
|
it_behaves_like 'gemfile without rspec-retry', name
|
|
221
233
|
it_behaves_like 'cucumber config with retry', name
|
|
222
234
|
end
|
|
223
|
-
|
|
224
235
|
end
|
|
@@ -119,4 +119,42 @@ describe 'Gemfile content' do
|
|
|
119
119
|
include_examples 'contains watir gems', name
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
+
describe 'raider_reporter and ruby_raider pin' do
|
|
123
|
+
major_minor = File.read('lib/version').strip.split('.').first(2).join('.')
|
|
124
|
+
|
|
125
|
+
AUTOMATION_TYPES.each do |automation|
|
|
126
|
+
context "with rspec and #{automation}" do
|
|
127
|
+
let(:gemfile) { read_generated("#{FrameworkIndex::RSPEC}_#{automation}", 'Gemfile') }
|
|
128
|
+
|
|
129
|
+
it 'includes raider_reporter' do
|
|
130
|
+
expect(gemfile).to include("gem 'raider_reporter', '~> 0.2'")
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'keeps allure gems' do
|
|
134
|
+
expect(gemfile).to include("gem 'allure-rspec', '2.28.0'", "gem 'allure-ruby-commons', '2.28.0'")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'pins ruby_raider to the generator major.minor' do
|
|
138
|
+
expect(gemfile).to include("gem 'ruby_raider', '~> #{major_minor}'")
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
context "with cucumber and #{automation}" do
|
|
143
|
+
let(:gemfile) { read_generated("#{FrameworkIndex::CUCUMBER}_#{automation}", 'Gemfile') }
|
|
144
|
+
|
|
145
|
+
it 'does not include raider_reporter' do
|
|
146
|
+
expect(gemfile).not_to include('raider_reporter')
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'keeps allure-cucumber' do
|
|
150
|
+
expect(gemfile).to include("gem 'allure-cucumber', '2.28.0'")
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it 'pins ruby_raider to the generator major.minor' do
|
|
154
|
+
expect(gemfile).to include("gem 'ruby_raider', '~> #{major_minor}'")
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
122
160
|
end
|
|
@@ -109,6 +109,47 @@ describe 'Helper file content' do
|
|
|
109
109
|
end
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
+
shared_examples 'raider reporter spec helper' do |project_name, screenshot_call|
|
|
113
|
+
subject(:helper) { read_generated(project_name, 'helpers/spec_helper.rb') }
|
|
114
|
+
|
|
115
|
+
it 'requires raider_reporter/rspec' do
|
|
116
|
+
expect(helper).to include("require 'raider_reporter/rspec'")
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it 'requires digest, which allure-ruby-commons uses without requiring' do
|
|
120
|
+
expect(helper).to include("require 'digest'")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'adds the raider formatter in spec_helper so a command-line --format cannot drop it' do
|
|
124
|
+
expect(helper).to include('config.add_formatter(RaiderReporter::RSpec::Formatter)')
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it 'does not replace the formatter' do
|
|
128
|
+
expect(helper).not_to match(/config\.formatter\s*=/)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it 'adds the allure formatter' do
|
|
132
|
+
expect(helper).to include('config.add_formatter(AllureHelper.formatter)')
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it 'screenshots only on failure' do
|
|
136
|
+
lines = helper.lines
|
|
137
|
+
start = lines.index { |line| line.include?('if example.exception') }
|
|
138
|
+
expect(start).not_to be_nil
|
|
139
|
+
indent = lines[start][/\A */].size
|
|
140
|
+
body = lines[(start + 1)..].take_while { |line| line.strip.empty? || line[/\A */].size > indent }
|
|
141
|
+
guarded = body.join
|
|
142
|
+
|
|
143
|
+
expect(guarded).to include('AllureHelper.add_screenshot', 'RaiderReporter.attach', screenshot_call)
|
|
144
|
+
expect(lines.select { |line| line.include?('AllureHelper.add_screenshot') }.size).to eq(1)
|
|
145
|
+
expect(lines.select { |line| line.include?(screenshot_call) }.size).to eq(1)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'attaches the screenshot to raider by path' do
|
|
149
|
+
expect(helper).to include("RaiderReporter.attach('screenshot', screenshot_path, type: :png)")
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
112
153
|
shared_examples 'selenium spec helper' do |project_name|
|
|
113
154
|
subject(:helper) { read_generated(project_name, 'helpers/spec_helper.rb') }
|
|
114
155
|
|
|
@@ -200,4 +241,25 @@ describe 'Helper file content' do
|
|
|
200
241
|
name = "#{FrameworkIndex::RSPEC}_#{AutomationIndex::IOS}"
|
|
201
242
|
|
|
202
243
|
end
|
|
244
|
+
|
|
245
|
+
# --- Raider reporter wiring (every rspec automation) ---
|
|
246
|
+
|
|
247
|
+
AUTOMATION_TYPES.each do |automation|
|
|
248
|
+
context "with rspec and #{automation} raider reporter wiring" do
|
|
249
|
+
name = "#{FrameworkIndex::RSPEC}_#{automation}"
|
|
250
|
+
screenshot_call = {
|
|
251
|
+
'selenium' => 'driver.save_screenshot(screenshot_path)',
|
|
252
|
+
'watir' => 'browser.screenshot.save(screenshot_path)'
|
|
253
|
+
}.fetch(automation, 'driver.screenshot(screenshot_path)')
|
|
254
|
+
it_behaves_like 'raider reporter spec helper', name, screenshot_call
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
context "with cucumber and #{automation}" do
|
|
258
|
+
it 'has no raider reporter wiring' do
|
|
259
|
+
project = "#{FrameworkIndex::CUCUMBER}_#{automation}"
|
|
260
|
+
files = Dir.glob("#{project}/**/*", File::FNM_DOTMATCH).select { |f| File.file?(f) }
|
|
261
|
+
expect(files.select { |f| File.read(f).match?(/raider_reporter|RaiderReporter/) }).to be_empty
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
203
265
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'content_helper'
|
|
4
|
+
|
|
5
|
+
describe 'Generated Readme content' do
|
|
6
|
+
AUTOMATION_TYPES.each do |automation|
|
|
7
|
+
context "with rspec and #{automation}" do
|
|
8
|
+
subject(:readme) { read_generated("#{FrameworkIndex::RSPEC}_#{automation}", 'Readme.md') }
|
|
9
|
+
|
|
10
|
+
it 'has a Reporting section' do
|
|
11
|
+
expect(readme).to include('## Reporting')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'documents local results, upload settings and the raider_reporter README' do
|
|
15
|
+
expect(readme).to include('raider-results/', 'RAIDER_TOKEN', 'RAIDER_ENDPOINT',
|
|
16
|
+
'https://github.com/RaiderHQ/raider_reporter')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'says Allure is still produced' do
|
|
20
|
+
expect(readme).to match(/Allure/)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "with cucumber and #{automation}" do
|
|
25
|
+
it 'has no Reporting section' do
|
|
26
|
+
readme = read_generated("#{FrameworkIndex::CUCUMBER}_#{automation}", 'Readme.md')
|
|
27
|
+
expect(readme).not_to include('RAIDER_TOKEN')
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require_relative 'spec_helper'
|
|
4
4
|
require 'timeout'
|
|
5
5
|
require 'open3'
|
|
6
|
+
require 'json'
|
|
6
7
|
|
|
7
8
|
# End-to-end integration tests that verify generated projects actually work
|
|
8
9
|
# These tests:
|
|
@@ -41,9 +42,19 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
41
42
|
result
|
|
42
43
|
end
|
|
43
44
|
|
|
45
|
+
# The generated Gemfile pins ruby_raider to this gem's major.minor, which may not be
|
|
46
|
+
# published yet (a release candidate branch). Resolve it from this checkout instead;
|
|
47
|
+
# the pin itself is covered by the Gemfile content specs.
|
|
48
|
+
def use_local_ruby_raider(project_name)
|
|
49
|
+
gemfile = File.join(project_name, 'Gemfile')
|
|
50
|
+
root = File.expand_path('../..', __dir__)
|
|
51
|
+
File.write(gemfile, File.read(gemfile).sub(/^gem 'ruby_raider'.*$/, "gem 'ruby_raider', path: '#{root}'"))
|
|
52
|
+
end
|
|
53
|
+
|
|
44
54
|
# Helper to install dependencies
|
|
45
55
|
def bundle_install(project_name)
|
|
46
56
|
puts "\n📦 Installing dependencies for #{project_name}..."
|
|
57
|
+
use_local_ruby_raider(project_name)
|
|
47
58
|
result = run_in_project(project_name, 'bundle install --quiet', timeout: 180)
|
|
48
59
|
|
|
49
60
|
unless result[:success]
|
|
@@ -103,6 +114,25 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
103
114
|
"STDOUT: #{result[:stdout]}\n" \
|
|
104
115
|
"STDERR: #{result[:stderr]}"
|
|
105
116
|
end
|
|
117
|
+
|
|
118
|
+
it 'writes raider-results/run.json listing every example without changing the exit status', :aggregate_failures, :slow do
|
|
119
|
+
skip 'Bundle install failed' unless bundle_install(project)
|
|
120
|
+
|
|
121
|
+
FileUtils.rm_rf(File.join(project, 'raider-results'))
|
|
122
|
+
result = run_rspec(project)
|
|
123
|
+
summary = result[:stdout].match(/(\d+) examples?, (\d+) failures?/)
|
|
124
|
+
expect(summary).not_to be_nil, "No RSpec summary line.\nSTDOUT: #{result[:stdout]}\nSTDERR: #{result[:stderr]}"
|
|
125
|
+
examples = summary[1].to_i
|
|
126
|
+
failures = summary[2].to_i
|
|
127
|
+
|
|
128
|
+
run_file = File.join(project, 'raider-results', 'run.json')
|
|
129
|
+
expect(File).to exist(run_file)
|
|
130
|
+
run = JSON.parse(File.read(run_file))
|
|
131
|
+
expect(run['schema_version']).to eq(1)
|
|
132
|
+
expect(run['results'].size).to eq(examples)
|
|
133
|
+
expect(run['results'].count { |r| r['status'] == 'failed' }).to eq(failures)
|
|
134
|
+
expect(result[:exit_code]).to eq(failures.zero? ? 0 : 1)
|
|
135
|
+
end
|
|
106
136
|
end
|
|
107
137
|
|
|
108
138
|
# Shared example for Cucumber-based projects
|
|
@@ -142,7 +172,6 @@ describe 'End-to-End Project Generation and Execution' do
|
|
|
142
172
|
describe 'Watir + Cucumber' do
|
|
143
173
|
include_examples 'executable cucumber project', 'cucumber_watir'
|
|
144
174
|
end
|
|
145
|
-
|
|
146
175
|
end
|
|
147
176
|
|
|
148
177
|
# Mobile and Visual frameworks require external services, so we only verify structure
|
|
@@ -497,43 +497,6 @@ describe 'Scaffolding E2E' do # rubocop:disable RSpec/DescribeClass
|
|
|
497
497
|
end
|
|
498
498
|
end
|
|
499
499
|
|
|
500
|
-
# ── Relationships ──────────────────────
|
|
501
|
-
|
|
502
|
-
describe 'relationships' do
|
|
503
|
-
before do
|
|
504
|
-
File.write('page_objects/pages/login.rb', "class LoginPage < Page; end\n")
|
|
505
|
-
end
|
|
506
|
-
|
|
507
|
-
after do
|
|
508
|
-
FileUtils.rm_f('page_objects/pages/dashboard.rb')
|
|
509
|
-
FileUtils.rm_f('spec/dashboard_page_spec.rb')
|
|
510
|
-
FileUtils.rm_f('features/dashboard.feature')
|
|
511
|
-
FileUtils.rm_f('features/step_definitions/dashboard_steps.rb')
|
|
512
|
-
FileUtils.rm_f('page_objects/pages/login.rb')
|
|
513
|
-
FileUtils.rm_rf('features') unless framework == 'cucumber'
|
|
514
|
-
FileUtils.rm_rf('spec') unless framework == 'rspec'
|
|
515
|
-
end
|
|
516
|
-
|
|
517
|
-
it 'adds require_relative for dependent page' do
|
|
518
|
-
scaffold.new.invoke(:page, nil, %w[dashboard --uses login])
|
|
519
|
-
content = File.read('page_objects/pages/dashboard.rb')
|
|
520
|
-
expect(content).to include("require_relative 'login'")
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
if style == :spec
|
|
524
|
-
it 'adds dependency to spec let declarations' do
|
|
525
|
-
scaffold.new.invoke(:spec, nil, %w[dashboard --uses login])
|
|
526
|
-
content = File.read('spec/dashboard_page_spec.rb')
|
|
527
|
-
expect(content).to include('LoginPage')
|
|
528
|
-
|
|
529
|
-
case automation
|
|
530
|
-
when 'selenium' then expect(content).to include('LoginPage.new(driver)')
|
|
531
|
-
when 'watir' then expect(content).to include('LoginPage.new(browser)')
|
|
532
|
-
end
|
|
533
|
-
end
|
|
534
|
-
end
|
|
535
|
-
end
|
|
536
|
-
|
|
537
500
|
end
|
|
538
501
|
end
|
|
539
502
|
end
|
|
@@ -93,26 +93,6 @@ RSpec.describe 'Scaffolding features' do
|
|
|
93
93
|
end
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
-
# --- Feature 9: Relationships ---
|
|
97
|
-
|
|
98
|
-
describe 'relationships (--uses)' do
|
|
99
|
-
before do
|
|
100
|
-
File.write('page_objects/pages/login.rb', "class LoginPage < Page; end\n")
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
it 'adds require_relative for dependent pages' do
|
|
104
|
-
scaffold.new.invoke(:page, nil, %w[dashboard --uses login])
|
|
105
|
-
content = File.read('page_objects/pages/dashboard.rb')
|
|
106
|
-
expect(content).to include("require_relative 'login'")
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
it 'adds uses to spec as let declarations' do
|
|
110
|
-
scaffold.new.invoke(:spec, nil, %w[dashboard --uses login])
|
|
111
|
-
content = File.read('spec/dashboard_page_spec.rb')
|
|
112
|
-
expect(content).to include('LoginPage')
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
96
|
# --- Feature 1: Batch scaffold ---
|
|
117
97
|
|
|
118
98
|
describe 'batch scaffolding' do
|
|
@@ -15,6 +15,7 @@ module SystemTestHelper
|
|
|
15
15
|
|
|
16
16
|
Bundler.with_unbundled_env do
|
|
17
17
|
Dir.chdir(project) do
|
|
18
|
+
use_checkout_ruby_raider
|
|
18
19
|
result = run_command('bundle install --quiet')
|
|
19
20
|
return result unless result[:success]
|
|
20
21
|
|
|
@@ -25,6 +26,13 @@ module SystemTestHelper
|
|
|
25
26
|
|
|
26
27
|
private
|
|
27
28
|
|
|
29
|
+
# The generated Gemfile pins ruby_raider to this gem's major.minor, which may not be
|
|
30
|
+
# published yet. Resolve it from this checkout; the pin itself is covered by content specs.
|
|
31
|
+
def use_checkout_ruby_raider(root = File.expand_path('../../..', __dir__))
|
|
32
|
+
gemfile = File.read('Gemfile')
|
|
33
|
+
File.write('Gemfile', gemfile.sub(/^gem 'ruby_raider'.*$/, "gem 'ruby_raider', path: '#{root}'"))
|
|
34
|
+
end
|
|
35
|
+
|
|
28
36
|
def run_command(command, env: {})
|
|
29
37
|
stdout, stderr, status = Open3.capture3(env, command)
|
|
30
38
|
{ success: status.success?, stdout:, stderr: }
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby_raider
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Agustin Pequeno
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-10-11 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rake
|
|
@@ -309,6 +309,7 @@ files:
|
|
|
309
309
|
- spec/integration/content/gemfile_content_spec.rb
|
|
310
310
|
- spec/integration/content/helper_content_spec.rb
|
|
311
311
|
- spec/integration/content/page_content_spec.rb
|
|
312
|
+
- spec/integration/content/readme_content_spec.rb
|
|
312
313
|
- spec/integration/content/syntax_validation_spec.rb
|
|
313
314
|
- spec/integration/content/test_content_spec.rb
|
|
314
315
|
- spec/integration/end_to_end_features_spec.rb
|