Skip to content

Commit 73961af

Browse files
authored
Fix generator folder structure for install (#201) (#203)
Why Generator placed e2e_helper.rb in framework subdirectory, breaking middleware file discovery and Cypress config location. Summary Moved e2e_helper.rb and app_commands to install_folder root instead of framework subdirectory. Added 20 tests, migration guide, and backward-compatible fallback loading. Key improvements - Backward compatible fallback loads from old location with warning - Comprehensive test coverage including negative assertions - CHANGELOG migration guide with three upgrade paths Impact - Existing: Files must migrate or fallback loads with warning - New: Correct structure created, both frameworks share helpers Risks - Breaking: Old structure deprecated, migration required for clean setup
1 parent f4a7768 commit 73961af

File tree

6 files changed

+374
-17
lines changed

6 files changed

+374
-17
lines changed

CHANGELOG.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,82 @@ This project adheres to [Semantic Versioning](https://semver.org/).
77

88
## [Unreleased]
99

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+
1086
## [1.19.0] - 2025-10-01
1187

1288
### Added
@@ -436,6 +512,7 @@ If migrating from the `cypress-rails` gem:
436512
[PR 27]: https://github.com/shakacode/cypress-playwright-on-rails/pull/27
437513
[PR 31]: https://github.com/shakacode/cypress-playwright-on-rails/pull/31
438514
[PR 18]: https://github.com/shakacode/cypress-playwright-on-rails/pull/18
515+
[#201]: https://github.com/shakacode/cypress-playwright-on-rails/issues/201
439516

440517
<!-- Version diff reference list -->
441518
[1.19.0]: https://github.com/shakacode/cypress-playwright-on-rails/compare/v1.18.0...v1.19.0

README.md

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,52 @@ bin/rails g cypress_on_rails:install --install_with=skip
134134
bin/rails g cypress_on_rails:install --install_with=skip
135135
```
136136

137-
The generator modifies/adds the following files/directory in your application:
138-
* `config/initializers/cypress_on_rails.rb` used to configure Cypress on Rails
139-
* `e2e/cypress/integration/` contains your cypress tests
140-
* `e2e/cypress/support/on-rails.js` contains Cypress on Rails support code
141-
* `e2e/cypress/e2e_helper.rb` contains helper code to require libraries like factory_bot
142-
* `e2e/cypress/app_commands/` contains your scenario definitions
143-
* `e2e/playwright/e2e/` contains your playwright tests
144-
* `e2e/playwright/support/on-rails.js` contains Playwright on Rails support code
145-
146-
If you are not using `database_cleaner` look at `e2e/cypress/app_commands/clean.rb`.
147-
If you are not using `factory_bot` look at `e2e/cypress/app_commands/factory_bot.rb`.
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`.
148183

149184
Now you can create scenarios and commands that are plain Ruby files that get loaded through middleware, the ruby sky is your limit.
150185

@@ -448,8 +483,7 @@ Add your VCR configuration to your `config/cypress_on_rails.rb`
448483
c.vcr_options = {
449484
hook_into: :webmock,
450485
default_cassette_options: { record: :once },
451-
# It's possible to override cassette_library_dir using install_folder
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")
453487
}
454488
```
455489

lib/cypress_on_rails/command_executor.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,35 @@ def self.perform(file,command_options = nil)
1616
def self.load_e2e_helper
1717
e2e_helper_file = "#{configuration.install_folder}/e2e_helper.rb"
1818
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
1925
if File.exist?(e2e_helper_file)
2026
Kernel.require e2e_helper_file
2127
elsif File.exist?(cypress_helper_file)
2228
Kernel.require cypress_helper_file
2329
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
2448
else
2549
logger.warn "could not find #{e2e_helper_file} nor #{cypress_helper_file}"
2650
end

lib/generators/cypress_on_rails/install_generator.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ def install_framework
4242

4343
def add_initial_files
4444
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}/#{options.framework}/e2e_helper.rb"
46-
directory 'spec/e2e/app_commands', "#{options.install_folder}/#{options.framework}/app_commands"
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"
4747
if options.framework == 'cypress'
4848
copy_file "spec/cypress/support/on-rails.js", "#{options.install_folder}/cypress/support/on-rails.js"
4949
directory 'spec/cypress/e2e/rails_examples', "#{options.install_folder}/cypress/e2e/rails_examples"

lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
if defined?(CypressOnRails)
22
CypressOnRails.configure do |c|
33
c.api_prefix = "<%= options.api_prefix %>"
4-
c.install_folder = File.expand_path("#{__dir__}/../../<%= options.install_folder %>/<%= options.framework %>")
4+
c.install_folder = File.expand_path("#{__dir__}/../../<%= options.install_folder %>")
55
# WARNING!! CypressOnRails can execute arbitrary ruby code
66
# please use with extra caution if enabling on hosted servers or starting your local server on 0.0.0.0
77
c.use_middleware = !Rails.env.production?
@@ -12,7 +12,7 @@ if defined?(CypressOnRails)
1212
<% unless options.experimental %># <% end %> c.vcr_options = {
1313
<% unless options.experimental %># <% end %> hook_into: :webmock,
1414
<% unless options.experimental %># <% end %> default_cassette_options: { record: :once },
15-
<% unless options.experimental %># <% end %> cassette_library_dir: File.expand_path("#{__dir__}/../../<%= options.install_folder %>/<%= options.framework %>/fixtures/vcr_cassettes")
15+
<% unless options.experimental %># <% end %> cassette_library_dir: File.expand_path("#{__dir__}/../../<%= options.install_folder %>/fixtures/vcr_cassettes")
1616
<% unless options.experimental %># <% end %> }
1717
c.logger = Rails.logger
1818

0 commit comments

Comments
 (0)