cypress-on-rails 1.19.0 → 1.20.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/CHANGELOG.md +80 -0
- data/README.md +47 -19
- data/cypress-on-rails.gemspec +2 -2
- data/lib/cypress_on_rails/command_executor.rb +24 -0
- data/lib/cypress_on_rails/configuration.rb +8 -0
- data/lib/cypress_on_rails/server.rb +73 -12
- data/lib/cypress_on_rails/version.rb +1 -1
- data/lib/generators/cypress_on_rails/install_generator.rb +2 -2
- data/lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb +2 -2
- data/spec/cypress_on_rails/configuration_spec.rb +6 -0
- data/spec/generators/install_generator_spec.rb +222 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c135e18e23ddeea1d0d2bbd246de9147b9ce42969bd862e51f1e3dec39abbe0
|
4
|
+
data.tar.gz: a295806731243324fbfda475ec6be6a6c4bce60651755b278431afd722501cab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 501aebab098ec19fbec53e3f7ea0ef8adc966c0d4ec2d60a0c424c45e369ad652899270b5e411376f5e582ef8a29acc3d02814cccee85654fe989bdc0aad9c1f
|
7
|
+
data.tar.gz: f833268a8c93e4853fbb28d5b26f653ae741817c4314756975ebd46cac69b6791ca0d436a1d4ab20c9f0be88d4e14b4e399d3d59326cbaf01fb4f2d0b57f24d4
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,84 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
### Fixed
|
11
|
+
* **BREAKING: Generator folder structure**: Fixed install generator to create `e2e_helper.rb` and `app_commands/` at the install folder root (e.g., `e2e/`) instead of inside the framework subdirectory (e.g., `e2e/cypress/`). This ensures compatibility between Cypress/Playwright config file location and middleware expectations. [#201]
|
12
|
+
|
13
|
+
### Migration Guide for Folder Structure Change
|
14
|
+
|
15
|
+
#### Breaking Change Notice
|
16
|
+
If you previously ran the install generator (versions prior to 1.20.0), the file structure created was incorrect. The generator placed helper and command files in the framework subdirectory when they should be at the install folder root.
|
17
|
+
|
18
|
+
**Old (Incorrect) Structure:**
|
19
|
+
```
|
20
|
+
e2e/
|
21
|
+
cypress.config.js
|
22
|
+
cypress/
|
23
|
+
e2e_helper.rb ← Wrong location
|
24
|
+
app_commands/ ← Wrong location
|
25
|
+
support/
|
26
|
+
e2e/
|
27
|
+
```
|
28
|
+
|
29
|
+
**New (Correct) Structure:**
|
30
|
+
```
|
31
|
+
e2e/
|
32
|
+
cypress.config.js
|
33
|
+
e2e_helper.rb ← Correct location
|
34
|
+
app_commands/ ← Correct location
|
35
|
+
fixtures/
|
36
|
+
vcr_cassettes/ ← VCR cassettes also at root
|
37
|
+
cypress/
|
38
|
+
support/
|
39
|
+
e2e/
|
40
|
+
```
|
41
|
+
|
42
|
+
#### How to Migrate
|
43
|
+
|
44
|
+
**Option 1: Fresh Installation (Recommended for new projects)**
|
45
|
+
```bash
|
46
|
+
# Remove old structure
|
47
|
+
rm -rf e2e/
|
48
|
+
|
49
|
+
# Re-run generator
|
50
|
+
bin/rails g cypress_on_rails:install --force
|
51
|
+
```
|
52
|
+
|
53
|
+
**Option 2: Manual Migration (For existing projects with custom code)**
|
54
|
+
```bash
|
55
|
+
# Move files to correct location
|
56
|
+
mv e2e/cypress/e2e_helper.rb e2e/
|
57
|
+
mv e2e/cypress/app_commands e2e/
|
58
|
+
|
59
|
+
# Update VCR cassettes path if using VCR
|
60
|
+
mv e2e/cypress/fixtures e2e/
|
61
|
+
|
62
|
+
# Verify your initializer has the correct path
|
63
|
+
# Should be: c.install_folder = File.expand_path("#{__dir__}/../../e2e")
|
64
|
+
# Not: c.install_folder = File.expand_path("#{__dir__}/../../e2e/cypress")
|
65
|
+
```
|
66
|
+
|
67
|
+
**Option 3: Update Initializer Only (Quick fix, not recommended)**
|
68
|
+
If you cannot migrate files immediately, you can temporarily update your initializer:
|
69
|
+
```ruby
|
70
|
+
# config/initializers/cypress_on_rails.rb
|
71
|
+
c.install_folder = File.expand_path("#{__dir__}/../../e2e/cypress")
|
72
|
+
```
|
73
|
+
However, this means Cypress may have issues finding config files. We recommend migrating to the correct structure.
|
74
|
+
|
75
|
+
#### Why This Change?
|
76
|
+
The middleware expects to find `e2e_helper.rb` at `#{install_folder}/e2e_helper.rb` and commands at `#{install_folder}/app_commands/`. Meanwhile, Cypress/Playwright expect config files at the install_folder root when using `--project` flag. The previous structure created a conflict where these requirements couldn't both be satisfied.
|
77
|
+
|
78
|
+
#### Testing Your Migration
|
79
|
+
After migrating, verify:
|
80
|
+
1. Run `bin/rails cypress:open` or `bin/rails playwright:open` - should open successfully
|
81
|
+
2. Run a test that uses app commands - should execute without "file not found" errors
|
82
|
+
3. Check that VCR cassettes (if used) are being created/loaded correctly
|
83
|
+
|
84
|
+
---
|
85
|
+
|
86
|
+
## [1.19.0] - 2025-10-01
|
87
|
+
|
10
88
|
### Added
|
11
89
|
* **Rake tasks for test execution**: Added `cypress:open` and `cypress:run` rake tasks for seamless test execution, similar to cypress-rails functionality. Also added `playwright:open` and `playwright:run` tasks.
|
12
90
|
* **Server lifecycle hooks**: Added configuration hooks for test server management:
|
@@ -434,8 +512,10 @@ If migrating from the `cypress-rails` gem:
|
|
434
512
|
[PR 27]: https://github.com/shakacode/cypress-playwright-on-rails/pull/27
|
435
513
|
[PR 31]: https://github.com/shakacode/cypress-playwright-on-rails/pull/31
|
436
514
|
[PR 18]: https://github.com/shakacode/cypress-playwright-on-rails/pull/18
|
515
|
+
[#201]: https://github.com/shakacode/cypress-playwright-on-rails/issues/201
|
437
516
|
|
438
517
|
<!-- Version diff reference list -->
|
518
|
+
[1.19.0]: https://github.com/shakacode/cypress-playwright-on-rails/compare/v1.18.0...v1.19.0
|
439
519
|
[1.18.0]: https://github.com/shakacode/cypress-playwright-on-rails/compare/v1.17.0...v1.18.0
|
440
520
|
[1.17.0]: https://github.com/shakacode/cypress-playwright-on-rails/compare/v1.16.0...v1.17.0
|
441
521
|
[1.16.0]: https://github.com/shakacode/cypress-playwright-on-rails/compare/v1.15.1...v1.16.0
|
data/README.md
CHANGED
@@ -134,17 +134,52 @@ bin/rails g cypress_on_rails:install --install_with=skip
|
|
134
134
|
bin/rails g cypress_on_rails:install --install_with=skip
|
135
135
|
```
|
136
136
|
|
137
|
-
The generator
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
137
|
+
The generator creates the following structure in your application:
|
138
|
+
|
139
|
+
**For Cypress:**
|
140
|
+
```
|
141
|
+
e2e/
|
142
|
+
cypress.config.js # Cypress configuration
|
143
|
+
e2e_helper.rb # Helper code for factory_bot, database_cleaner, etc.
|
144
|
+
app_commands/ # Your custom commands and scenarios
|
145
|
+
clean.rb
|
146
|
+
factory_bot.rb
|
147
|
+
scenarios/
|
148
|
+
basic.rb
|
149
|
+
fixtures/
|
150
|
+
vcr_cassettes/ # VCR recordings (if using VCR)
|
151
|
+
cypress/
|
152
|
+
support/
|
153
|
+
index.js
|
154
|
+
commands.js
|
155
|
+
on-rails.js # Cypress on Rails support code
|
156
|
+
e2e/
|
157
|
+
rails_examples/ # Example tests
|
158
|
+
```
|
159
|
+
|
160
|
+
**For Playwright:**
|
161
|
+
```
|
162
|
+
e2e/
|
163
|
+
playwright.config.js # Playwright configuration
|
164
|
+
e2e_helper.rb # Helper code for factory_bot, database_cleaner, etc.
|
165
|
+
app_commands/ # Your custom commands and scenarios (shared with Cypress)
|
166
|
+
fixtures/
|
167
|
+
vcr_cassettes/ # VCR recordings (if using VCR)
|
168
|
+
playwright/
|
169
|
+
support/
|
170
|
+
index.js
|
171
|
+
on-rails.js # Playwright on Rails support code
|
172
|
+
e2e/
|
173
|
+
rails_examples/ # Example tests
|
174
|
+
```
|
175
|
+
|
176
|
+
**Additional files:**
|
177
|
+
* `config/initializers/cypress_on_rails.rb` - Configuration for Cypress on Rails
|
178
|
+
|
179
|
+
**Important:** Note that `e2e_helper.rb` and `app_commands/` are at the root of the install folder (e.g., `e2e/`), NOT inside the framework subdirectory (e.g., `e2e/cypress/`). This allows both Cypress and Playwright to share the same commands and helpers when using both frameworks.
|
180
|
+
|
181
|
+
If you are not using `database_cleaner` look at `e2e/app_commands/clean.rb`.
|
182
|
+
If you are not using `factory_bot` look at `e2e/app_commands/factory_bot.rb`.
|
148
183
|
|
149
184
|
Now you can create scenarios and commands that are plain Ruby files that get loaded through middleware, the ruby sky is your limit.
|
150
185
|
|
@@ -448,8 +483,7 @@ Add your VCR configuration to your `config/cypress_on_rails.rb`
|
|
448
483
|
c.vcr_options = {
|
449
484
|
hook_into: :webmock,
|
450
485
|
default_cassette_options: { record: :once },
|
451
|
-
|
452
|
-
cassette_library_dir: File.expand_path("#{__dir__}/../../spec/cypress/fixtures/vcr_cassettes")
|
486
|
+
cassette_library_dir: File.expand_path("#{__dir__}/../../e2e/fixtures/vcr_cassettes")
|
453
487
|
}
|
454
488
|
```
|
455
489
|
|
@@ -777,15 +811,9 @@ In `config/initializers/cypress_on_rails.rb`, add this line:
|
|
777
811
|
<img alt="BrowserStack" src="https://user-images.githubusercontent.com/4244251/184881129-e1edf4b7-3ae1-4ea8-9e6d-3595cf01609e.png" height="55px">
|
778
812
|
</picture>
|
779
813
|
</a>
|
780
|
-
<a href="https://railsautoscale.com">
|
781
|
-
<img src="https://user-images.githubusercontent.com/4244251/184881144-95c2c25c-9879-4069-864d-4e67d6ed39d2.png" alt="Rails Autoscale" height="55px">
|
782
|
-
</a>
|
783
814
|
<a href="https://www.honeybadger.io">
|
784
815
|
<img src="https://user-images.githubusercontent.com/4244251/184881133-79ee9c3c-8165-4852-958e-31687b9536f4.png" alt="Honeybadger" height="55px">
|
785
816
|
</a>
|
786
|
-
<a href="https://reviewable.io">
|
787
|
-
<img src="https://user-images.githubusercontent.com/20628911/230848305-c94510a4-82d7-468f-bf9f-eeb81d3f2ce0.png" alt="Reviewable" height="55px">
|
788
|
-
</a>
|
789
817
|
|
790
818
|
<br />
|
791
819
|
<br />
|
data/cypress-on-rails.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.author = ["miceportal team", 'Grant Petersen-Speelman']
|
9
9
|
s.email = ["info@miceportal.de", 'grantspeelman@gmail.com']
|
10
10
|
s.homepage = "http://github.com/shakacode/cypress-on-rails"
|
11
|
-
s.summary = "Integrates
|
12
|
-
s.description = "Integrates
|
11
|
+
s.summary = "Integrates Cypress and Playwright with Rails or Rack applications"
|
12
|
+
s.description = "Integrates Cypress and Playwright with Rails or Rack applications"
|
13
13
|
s.post_install_message = 'The CypressDev constant is being deprecated and will be completely removed and replaced with CypressOnRails.'
|
14
14
|
s.files = `git ls-files`.split("\n")
|
15
15
|
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
@@ -16,11 +16,35 @@ module CypressOnRails
|
|
16
16
|
def self.load_e2e_helper
|
17
17
|
e2e_helper_file = "#{configuration.install_folder}/e2e_helper.rb"
|
18
18
|
cypress_helper_file = "#{configuration.install_folder}/cypress_helper.rb"
|
19
|
+
|
20
|
+
# Check for old structure (files in framework subdirectory)
|
21
|
+
old_cypress_location = "#{configuration.install_folder}/cypress/e2e_helper.rb"
|
22
|
+
old_playwright_location = "#{configuration.install_folder}/playwright/e2e_helper.rb"
|
23
|
+
|
24
|
+
# Try to load from the correct location first
|
19
25
|
if File.exist?(e2e_helper_file)
|
20
26
|
Kernel.require e2e_helper_file
|
21
27
|
elsif File.exist?(cypress_helper_file)
|
22
28
|
Kernel.require cypress_helper_file
|
23
29
|
warn "cypress_helper.rb is deprecated, please rename the file to e2e_helper.rb"
|
30
|
+
# Fallback: load from old location if new location doesn't exist
|
31
|
+
elsif File.exist?(old_cypress_location) || File.exist?(old_playwright_location)
|
32
|
+
old_location = File.exist?(old_cypress_location) ? old_cypress_location : old_playwright_location
|
33
|
+
logger.warn "=" * 80
|
34
|
+
logger.warn "DEPRECATION WARNING: Old folder structure detected!"
|
35
|
+
logger.warn "Found e2e_helper.rb at: #{old_location}"
|
36
|
+
logger.warn "This file should be at: #{e2e_helper_file}"
|
37
|
+
logger.warn ""
|
38
|
+
logger.warn "Loading from old location for now, but this will stop working in a future version."
|
39
|
+
logger.warn "The generator now creates e2e_helper.rb and app_commands/ at the install_folder"
|
40
|
+
logger.warn "root, not inside the framework subdirectory."
|
41
|
+
logger.warn ""
|
42
|
+
logger.warn "To fix this, run: mv #{old_location} #{e2e_helper_file}"
|
43
|
+
logger.warn "Also move app_commands: mv #{File.dirname(old_location)}/app_commands #{configuration.install_folder}/"
|
44
|
+
logger.warn "See CHANGELOG.md for full migration guide."
|
45
|
+
logger.warn "=" * 80
|
46
|
+
# Load from old location as fallback
|
47
|
+
Kernel.require old_location
|
24
48
|
else
|
25
49
|
logger.warn "could not find #{e2e_helper_file} nor #{cypress_helper_file}"
|
26
50
|
end
|
@@ -22,6 +22,12 @@ module CypressOnRails
|
|
22
22
|
attr_accessor :server_host
|
23
23
|
attr_accessor :server_port
|
24
24
|
attr_accessor :transactional_server
|
25
|
+
# HTTP path to check for server readiness (default: '/')
|
26
|
+
# Can be set via CYPRESS_RAILS_READINESS_PATH environment variable
|
27
|
+
attr_accessor :server_readiness_path
|
28
|
+
# Timeout in seconds for individual HTTP readiness checks (default: 5)
|
29
|
+
# Can be set via CYPRESS_RAILS_READINESS_TIMEOUT environment variable
|
30
|
+
attr_accessor :server_readiness_timeout
|
25
31
|
|
26
32
|
# Attributes for backwards compatibility
|
27
33
|
def cypress_folder
|
@@ -62,6 +68,8 @@ module CypressOnRails
|
|
62
68
|
self.server_host = ENV.fetch('CYPRESS_RAILS_HOST', 'localhost')
|
63
69
|
self.server_port = ENV.fetch('CYPRESS_RAILS_PORT', nil)
|
64
70
|
self.transactional_server = true
|
71
|
+
self.server_readiness_path = ENV.fetch('CYPRESS_RAILS_READINESS_PATH', '/')
|
72
|
+
self.server_readiness_timeout = ENV.fetch('CYPRESS_RAILS_READINESS_TIMEOUT', '5').to_i
|
65
73
|
end
|
66
74
|
|
67
75
|
def tagged_logged
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'socket'
|
2
2
|
require 'timeout'
|
3
3
|
require 'fileutils'
|
4
|
+
require 'net/http'
|
4
5
|
require 'cypress_on_rails/configuration'
|
5
6
|
|
6
7
|
module CypressOnRails
|
@@ -9,13 +10,16 @@ module CypressOnRails
|
|
9
10
|
|
10
11
|
def initialize(options = {})
|
11
12
|
config = CypressOnRails.configuration
|
12
|
-
|
13
|
+
|
13
14
|
@framework = options[:framework] || :cypress
|
14
15
|
@host = options[:host] || config.server_host
|
15
16
|
@port = options[:port] || config.server_port || find_available_port
|
16
17
|
@port = @port.to_i if @port
|
17
18
|
@install_folder = options[:install_folder] || config.install_folder || detect_install_folder
|
18
19
|
@transactional = options.fetch(:transactional, config.transactional_server)
|
20
|
+
# Process management: track PID and process group for proper cleanup
|
21
|
+
@server_pid = nil
|
22
|
+
@server_pgid = nil
|
19
23
|
end
|
20
24
|
|
21
25
|
def open
|
@@ -105,34 +109,91 @@ module CypressOnRails
|
|
105
109
|
|
106
110
|
puts "Starting Rails server: #{server_args.join(' ')}"
|
107
111
|
|
108
|
-
spawn(*server_args, out: $stdout, err: $stderr)
|
112
|
+
@server_pid = spawn(*server_args, out: $stdout, err: $stderr, pgroup: true)
|
113
|
+
begin
|
114
|
+
@server_pgid = Process.getpgid(@server_pid)
|
115
|
+
rescue Errno::ESRCH => e
|
116
|
+
# Edge case: process terminated before we could get pgid
|
117
|
+
# This is OK - send_term_signal will fall back to single-process kill
|
118
|
+
CypressOnRails.configuration.logger.warn("Process #{@server_pid} terminated immediately after spawn: #{e.message}")
|
119
|
+
@server_pgid = nil
|
120
|
+
end
|
121
|
+
@server_pid
|
109
122
|
end
|
110
123
|
|
111
124
|
def wait_for_server(timeout = 30)
|
112
125
|
Timeout.timeout(timeout) do
|
113
126
|
loop do
|
114
|
-
|
115
|
-
|
116
|
-
break
|
117
|
-
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
118
|
-
sleep 0.1
|
119
|
-
end
|
127
|
+
break if server_responding?
|
128
|
+
sleep 0.1
|
120
129
|
end
|
121
130
|
end
|
122
131
|
rescue Timeout::Error
|
123
132
|
raise "Rails server failed to start on #{host}:#{port} after #{timeout} seconds"
|
124
133
|
end
|
125
134
|
|
135
|
+
def server_responding?
|
136
|
+
config = CypressOnRails.configuration
|
137
|
+
readiness_path = config.server_readiness_path || '/'
|
138
|
+
timeout = config.server_readiness_timeout || 5
|
139
|
+
uri = URI("http://#{host}:#{port}#{readiness_path}")
|
140
|
+
|
141
|
+
response = Net::HTTP.start(uri.host, uri.port, open_timeout: timeout, read_timeout: timeout) do |http|
|
142
|
+
http.get(uri.path)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Accept 200-399 (success and redirects), reject 404 and 5xx
|
146
|
+
# 3xx redirects are considered "ready" because the server is responding correctly
|
147
|
+
(200..399).cover?(response.code.to_i)
|
148
|
+
rescue Errno::ECONNREFUSED, Errno::EADDRNOTAVAIL, Errno::ETIMEDOUT, SocketError,
|
149
|
+
Net::OpenTimeout, Net::ReadTimeout, Net::HTTPBadResponse
|
150
|
+
false
|
151
|
+
end
|
152
|
+
|
126
153
|
def stop_server(pid)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
154
|
+
return unless pid
|
155
|
+
|
156
|
+
puts "Stopping Rails server (PID: #{pid})"
|
157
|
+
send_term_signal(pid)
|
158
|
+
|
159
|
+
begin
|
160
|
+
Timeout.timeout(10) do
|
161
|
+
Process.wait(pid)
|
162
|
+
end
|
163
|
+
rescue Timeout::Error
|
164
|
+
CypressOnRails.configuration.logger.warn("Server did not terminate after TERM signal, sending KILL")
|
165
|
+
safe_kill_process('KILL', pid)
|
166
|
+
Process.wait(pid) rescue Errno::ESRCH
|
131
167
|
end
|
132
168
|
rescue Errno::ESRCH
|
133
169
|
# Process already terminated
|
134
170
|
end
|
135
171
|
|
172
|
+
def send_term_signal(pid)
|
173
|
+
if @server_pgid && process_exists?(pid)
|
174
|
+
Process.kill('TERM', -@server_pgid)
|
175
|
+
else
|
176
|
+
safe_kill_process('TERM', pid)
|
177
|
+
end
|
178
|
+
rescue Errno::ESRCH, Errno::EPERM => e
|
179
|
+
CypressOnRails.configuration.logger.warn("Failed to kill process group #{@server_pgid}: #{e.message}, trying single process")
|
180
|
+
safe_kill_process('TERM', pid)
|
181
|
+
end
|
182
|
+
|
183
|
+
def process_exists?(pid)
|
184
|
+
return false unless pid
|
185
|
+
Process.kill(0, pid)
|
186
|
+
true
|
187
|
+
rescue Errno::ESRCH, Errno::EPERM
|
188
|
+
false
|
189
|
+
end
|
190
|
+
|
191
|
+
def safe_kill_process(signal, pid)
|
192
|
+
Process.kill(signal, pid) if pid
|
193
|
+
rescue Errno::ESRCH, Errno::EPERM
|
194
|
+
# Process already terminated or permission denied
|
195
|
+
end
|
196
|
+
|
136
197
|
def base_url
|
137
198
|
"http://#{host}:#{port}"
|
138
199
|
end
|
@@ -42,8 +42,8 @@ module CypressOnRails
|
|
42
42
|
|
43
43
|
def add_initial_files
|
44
44
|
template "config/initializers/cypress_on_rails.rb.erb", "config/initializers/cypress_on_rails.rb"
|
45
|
-
template "spec/e2e/e2e_helper.rb.erb", "#{options.install_folder}
|
46
|
-
directory 'spec/e2e/app_commands', "#{options.install_folder}
|
45
|
+
template "spec/e2e/e2e_helper.rb.erb", "#{options.install_folder}/e2e_helper.rb"
|
46
|
+
directory 'spec/e2e/app_commands', "#{options.install_folder}/app_commands"
|
47
47
|
if options.framework == 'cypress'
|
48
48
|
copy_file "spec/cypress/support/on-rails.js", "#{options.install_folder}/cypress/support/on-rails.js"
|
49
49
|
directory 'spec/cypress/e2e/rails_examples', "#{options.install_folder}/cypress/e2e/rails_examples"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
if defined?(CypressOnRails)
|
2
2
|
CypressOnRails.configure do |c|
|
3
3
|
c.api_prefix = "<%= options.api_prefix %>"
|
4
|
-
c.install_folder = File.expand_path("#{__dir__}/../../<%= options.install_folder
|
4
|
+
c.install_folder = File.expand_path("#{__dir__}/../../<%= options.install_folder %>")
|
5
5
|
# WARNING!! CypressOnRails can execute arbitrary ruby code
|
6
6
|
# please use with extra caution if enabling on hosted servers or starting your local server on 0.0.0.0
|
7
7
|
c.use_middleware = !Rails.env.production?
|
@@ -12,7 +12,7 @@ if defined?(CypressOnRails)
|
|
12
12
|
<% unless options.experimental %># <% end %> c.vcr_options = {
|
13
13
|
<% unless options.experimental %># <% end %> hook_into: :webmock,
|
14
14
|
<% unless options.experimental %># <% end %> default_cassette_options: { record: :once },
|
15
|
-
<% unless options.experimental %># <% end %> cassette_library_dir: File.expand_path("#{__dir__}/../../<%= options.install_folder
|
15
|
+
<% unless options.experimental %># <% end %> cassette_library_dir: File.expand_path("#{__dir__}/../../<%= options.install_folder %>/fixtures/vcr_cassettes")
|
16
16
|
<% unless options.experimental %># <% end %> }
|
17
17
|
c.logger = Rails.logger
|
18
18
|
|
@@ -10,6 +10,8 @@ RSpec.describe CypressOnRails::Configuration do
|
|
10
10
|
expect(CypressOnRails.configuration.logger).to_not be_nil
|
11
11
|
expect(CypressOnRails.configuration.before_request).to_not be_nil
|
12
12
|
expect(CypressOnRails.configuration.vcr_options).to eq({})
|
13
|
+
expect(CypressOnRails.configuration.server_readiness_path).to eq('/')
|
14
|
+
expect(CypressOnRails.configuration.server_readiness_timeout).to eq(5)
|
13
15
|
end
|
14
16
|
|
15
17
|
it 'can be configured' do
|
@@ -22,6 +24,8 @@ RSpec.describe CypressOnRails::Configuration do
|
|
22
24
|
config.logger = my_logger
|
23
25
|
config.before_request = before_request_lambda
|
24
26
|
config.vcr_options = { hook_into: :webmock }
|
27
|
+
config.server_readiness_path = '/health'
|
28
|
+
config.server_readiness_timeout = 10
|
25
29
|
end
|
26
30
|
expect(CypressOnRails.configuration.api_prefix).to eq('/api')
|
27
31
|
expect(CypressOnRails.configuration.install_folder).to eq('my/path')
|
@@ -29,5 +33,7 @@ RSpec.describe CypressOnRails::Configuration do
|
|
29
33
|
expect(CypressOnRails.configuration.logger).to eq(my_logger)
|
30
34
|
expect(CypressOnRails.configuration.before_request).to eq(before_request_lambda)
|
31
35
|
expect(CypressOnRails.configuration.vcr_options).to eq(hook_into: :webmock)
|
36
|
+
expect(CypressOnRails.configuration.server_readiness_path).to eq('/health')
|
37
|
+
expect(CypressOnRails.configuration.server_readiness_timeout).to eq(10)
|
32
38
|
end
|
33
39
|
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rails/generators'
|
3
|
+
require 'generators/cypress_on_rails/install_generator'
|
4
|
+
require 'tmpdir'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
RSpec.describe CypressOnRails::InstallGenerator, type: :generator do
|
8
|
+
let(:destination_root) { Dir.mktmpdir }
|
9
|
+
|
10
|
+
before do
|
11
|
+
# Set up a minimal Rails app structure
|
12
|
+
FileUtils.mkdir_p(File.join(destination_root, 'config', 'initializers'))
|
13
|
+
FileUtils.mkdir_p(File.join(destination_root, 'bin'))
|
14
|
+
|
15
|
+
# Mock the generator's destination_root
|
16
|
+
allow(Dir).to receive(:pwd).and_return(destination_root)
|
17
|
+
|
18
|
+
# Prevent actual npm/yarn installation in tests
|
19
|
+
# Mock only package manager commands, let file operations through
|
20
|
+
allow_any_instance_of(CypressOnRails::InstallGenerator).to receive(:system) do |_, command|
|
21
|
+
# Return true for yarn/npm install commands to skip actual installation
|
22
|
+
command.to_s.match?(/yarn|npm/)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
after do
|
27
|
+
FileUtils.rm_rf(destination_root)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'with default options (cypress framework, e2e folder)' do
|
31
|
+
let(:args) { [] }
|
32
|
+
let(:options) { {} }
|
33
|
+
|
34
|
+
before do
|
35
|
+
run_generator(args, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'creates the initializer with correct install_folder path' do
|
39
|
+
initializer_path = File.join(destination_root, 'config', 'initializers', 'cypress_on_rails.rb')
|
40
|
+
expect(File).to exist(initializer_path)
|
41
|
+
|
42
|
+
content = File.read(initializer_path)
|
43
|
+
# Should point to e2e, not e2e/cypress
|
44
|
+
expect(content).to include('c.install_folder = File.expand_path("#{__dir__}/../../e2e")')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'creates cypress config at install_folder root' do
|
48
|
+
config_path = File.join(destination_root, 'e2e', 'cypress.config.js')
|
49
|
+
expect(File).to exist(config_path)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'creates e2e_helper.rb at install_folder root' do
|
53
|
+
helper_path = File.join(destination_root, 'e2e', 'e2e_helper.rb')
|
54
|
+
expect(File).to exist(helper_path)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'creates app_commands directory at install_folder root' do
|
58
|
+
commands_path = File.join(destination_root, 'e2e', 'app_commands')
|
59
|
+
expect(File).to be_directory(commands_path)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'creates cypress support files in framework subdirectory' do
|
63
|
+
support_path = File.join(destination_root, 'e2e', 'cypress', 'support', 'index.js')
|
64
|
+
expect(File).to exist(support_path)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'creates cypress examples in framework subdirectory' do
|
68
|
+
examples_path = File.join(destination_root, 'e2e', 'cypress', 'e2e', 'rails_examples')
|
69
|
+
expect(File).to be_directory(examples_path)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'with playwright framework' do
|
74
|
+
let(:args) { [] }
|
75
|
+
let(:options) { { framework: 'playwright' } }
|
76
|
+
|
77
|
+
before do
|
78
|
+
run_generator(args, options)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'creates the initializer with correct install_folder path' do
|
82
|
+
initializer_path = File.join(destination_root, 'config', 'initializers', 'cypress_on_rails.rb')
|
83
|
+
expect(File).to exist(initializer_path)
|
84
|
+
|
85
|
+
content = File.read(initializer_path)
|
86
|
+
# Should point to e2e, not e2e/playwright
|
87
|
+
expect(content).to include('c.install_folder = File.expand_path("#{__dir__}/../../e2e")')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'creates playwright config at install_folder root' do
|
91
|
+
config_path = File.join(destination_root, 'e2e', 'playwright.config.js')
|
92
|
+
expect(File).to exist(config_path)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'creates e2e_helper.rb at install_folder root' do
|
96
|
+
helper_path = File.join(destination_root, 'e2e', 'e2e_helper.rb')
|
97
|
+
expect(File).to exist(helper_path)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'creates app_commands directory at install_folder root' do
|
101
|
+
commands_path = File.join(destination_root, 'e2e', 'app_commands')
|
102
|
+
expect(File).to be_directory(commands_path)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'creates playwright support files in framework subdirectory' do
|
106
|
+
support_path = File.join(destination_root, 'e2e', 'playwright', 'support', 'index.js')
|
107
|
+
expect(File).to exist(support_path)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'creates playwright examples in framework subdirectory' do
|
111
|
+
examples_path = File.join(destination_root, 'e2e', 'playwright', 'e2e', 'rails_examples')
|
112
|
+
expect(File).to be_directory(examples_path)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'with custom install_folder' do
|
117
|
+
let(:args) { [] }
|
118
|
+
let(:options) { { install_folder: 'spec/system' } }
|
119
|
+
|
120
|
+
before do
|
121
|
+
run_generator(args, options)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'creates files in the custom folder' do
|
125
|
+
helper_path = File.join(destination_root, 'spec', 'system', 'e2e_helper.rb')
|
126
|
+
expect(File).to exist(helper_path)
|
127
|
+
|
128
|
+
commands_path = File.join(destination_root, 'spec', 'system', 'app_commands')
|
129
|
+
expect(File).to be_directory(commands_path)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'sets the correct install_folder in the initializer' do
|
133
|
+
initializer_path = File.join(destination_root, 'config', 'initializers', 'cypress_on_rails.rb')
|
134
|
+
content = File.read(initializer_path)
|
135
|
+
expect(content).to include('c.install_folder = File.expand_path("#{__dir__}/../../spec/system")')
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe 'file structure ensures middleware and framework compatibility' do
|
140
|
+
let(:args) { [] }
|
141
|
+
let(:options) { {} }
|
142
|
+
|
143
|
+
before do
|
144
|
+
run_generator(args, options)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'does not create e2e_helper.rb in old location (framework subdirectory)' do
|
148
|
+
old_cypress_path = File.join(destination_root, 'e2e', 'cypress', 'e2e_helper.rb')
|
149
|
+
old_playwright_path = File.join(destination_root, 'e2e', 'playwright', 'e2e_helper.rb')
|
150
|
+
expect(File).not_to exist(old_cypress_path)
|
151
|
+
expect(File).not_to exist(old_playwright_path)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'does not create app_commands in old location (framework subdirectory)' do
|
155
|
+
old_cypress_path = File.join(destination_root, 'e2e', 'cypress', 'app_commands')
|
156
|
+
old_playwright_path = File.join(destination_root, 'e2e', 'playwright', 'app_commands')
|
157
|
+
expect(File).not_to exist(old_cypress_path)
|
158
|
+
expect(File).not_to exist(old_playwright_path)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'places e2e_helper.rb where middleware expects it (install_folder/e2e_helper.rb)' do
|
162
|
+
# Middleware looks for #{install_folder}/e2e_helper.rb
|
163
|
+
helper_path = File.join(destination_root, 'e2e', 'e2e_helper.rb')
|
164
|
+
expect(File).to exist(helper_path)
|
165
|
+
expect(File.read(helper_path)).to include('CypressOnRails')
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'places app_commands where middleware expects it (install_folder/app_commands)' do
|
169
|
+
# Middleware looks for #{install_folder}/app_commands/#{command}.rb
|
170
|
+
commands_path = File.join(destination_root, 'e2e', 'app_commands')
|
171
|
+
expect(File).to be_directory(commands_path)
|
172
|
+
|
173
|
+
# Check that command files exist
|
174
|
+
clean_cmd = File.join(commands_path, 'clean.rb')
|
175
|
+
expect(File).to exist(clean_cmd)
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'places cypress.config.js where cypress --project flag expects it' do
|
179
|
+
# Cypress runs with --project install_folder, expects config at that level
|
180
|
+
config_path = File.join(destination_root, 'e2e', 'cypress.config.js')
|
181
|
+
expect(File).to exist(config_path)
|
182
|
+
|
183
|
+
# Verify the config references the correct relative path for support files
|
184
|
+
content = File.read(config_path)
|
185
|
+
expect(content).to include('cypress/support/index.js')
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'creates a valid directory structure' do
|
189
|
+
# The expected structure:
|
190
|
+
# e2e/
|
191
|
+
# cypress.config.js <- Config at root of install_folder
|
192
|
+
# e2e_helper.rb <- Helper at root of install_folder
|
193
|
+
# app_commands/ <- Commands at root of install_folder
|
194
|
+
# cypress/ <- Framework-specific subdirectory
|
195
|
+
# support/
|
196
|
+
# e2e/
|
197
|
+
|
198
|
+
expect(File).to exist(File.join(destination_root, 'e2e', 'cypress.config.js'))
|
199
|
+
expect(File).to exist(File.join(destination_root, 'e2e', 'e2e_helper.rb'))
|
200
|
+
expect(File).to be_directory(File.join(destination_root, 'e2e', 'app_commands'))
|
201
|
+
expect(File).to be_directory(File.join(destination_root, 'e2e', 'cypress'))
|
202
|
+
expect(File).to be_directory(File.join(destination_root, 'e2e', 'cypress', 'support'))
|
203
|
+
expect(File).to be_directory(File.join(destination_root, 'e2e', 'cypress', 'e2e'))
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def run_generator(args, options)
|
208
|
+
generator_options = []
|
209
|
+
options.each do |key, value|
|
210
|
+
generator_options << "--#{key}=#{value}"
|
211
|
+
end
|
212
|
+
|
213
|
+
CypressOnRails::InstallGenerator.start(
|
214
|
+
args + generator_options,
|
215
|
+
{
|
216
|
+
destination_root: destination_root,
|
217
|
+
shell: Thor::Shell::Basic.new,
|
218
|
+
behavior: :invoke
|
219
|
+
}
|
220
|
+
)
|
221
|
+
end
|
222
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cypress-on-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- miceportal team
|
@@ -108,7 +108,7 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
-
description: Integrates
|
111
|
+
description: Integrates Cypress and Playwright with Rails or Rack applications
|
112
112
|
email:
|
113
113
|
- info@miceportal.de
|
114
114
|
- grantspeelman@gmail.com
|
@@ -197,6 +197,7 @@ files:
|
|
197
197
|
- spec/cypress_on_rails/smart_factory_wrapper_spec.rb
|
198
198
|
- spec/cypress_on_rails/vcr/insert_eject_middleware_spec.rb
|
199
199
|
- spec/cypress_on_rails/vcr/use_cassette_middleware_spec.rb
|
200
|
+
- spec/generators/install_generator_spec.rb
|
200
201
|
- spec/spec_helper.rb
|
201
202
|
- specs_e2e/cypress.config.js
|
202
203
|
- specs_e2e/playwright.config.js
|
@@ -436,5 +437,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
436
437
|
requirements: []
|
437
438
|
rubygems_version: 3.6.7
|
438
439
|
specification_version: 4
|
439
|
-
summary: Integrates
|
440
|
+
summary: Integrates Cypress and Playwright with Rails or Rack applications
|
440
441
|
test_files: []
|