Skip to content

Commit d26d966

Browse files
authored
Add cypress-rails compatible rake tasks and server lifecycle hooks (#179)
This PR adds comprehensive test automation support with automatic server lifecycle management, making cypress-on-rails a drop-in replacement for the cypress-rails gem while extending support to Playwright. Key Improvements: * Rake Tasks for Test Execution - Added cypress:open, cypress:run, playwright:open, playwright:run - Automatic Rails server startup/shutdown during test execution - Dynamic port detection to avoid conflicts - Support for CYPRESS_RAILS_HOST and CYPRESS_RAILS_PORT environment variables * Server Lifecycle Hooks - before_server_start: Execute code before Rails server starts - after_server_start: Execute code when server is ready - after_transaction_start: Execute code after database transaction begins - after_state_reset: Execute code after state cleanup (runs AFTER cleanup) - before_server_stop: Execute code before server shutdown * State Reset Functionality - Added /cypress_rails_reset_state endpoint for cypress-rails compatibility - Added /__cypress__/reset_state endpoint for existing users - Automatic database cleanup with referential integrity support - Uses disable_referential_integrity when available - Proper table name quoting with quote_table_name - Rails cache clearing and dependency reset * Transactional Test Mode - Optional automatic database transaction rollback - Configurable via transactional_server option - Faster test execution for compatible test suites * Security Improvements - Refactored shell command execution to prevent injection attacks - Commands passed as argument arrays instead of string interpolation - Uses spawn(*args) and system(*args) for safe execution - Added missing require 'fileutils' dependency * Configuration & Documentation - New configuration initializer template with all hook examples - Comprehensive migration guide from manual server management - Migration guide from cypress-rails gem - Updated README with rake task usage examples Breaking Changes: NONE - This is purely additive functionality. All existing middleware-based usage continues to work unchanged. Impact on Users: New Installations: - Can immediately use rake tasks for automated test execution - No need to manually manage Rails test server - Simplified setup with single-command test execution Existing Installations: - No changes required - existing setup continues to work - Can opt-in to rake tasks for improved workflow - Can gradually adopt lifecycle hooks for custom test setup - State reset endpoint provides backward compatibility Migration from cypress-rails: - Drop-in replacement with same rake task names - Compatible state reset endpoint - Adds Playwright support not available in cypress-rails - More flexible with configurable hooks and options Technical Notes: The implementation uses TCPServer for port detection and spawns the Rails server as a subprocess. Server readiness is verified by attempting TCP connections. State reset uses DatabaseCleaner when available, falling back to manual table truncation with proper referential integrity handling. All shell commands use argument arrays to prevent command injection vulnerabilities. Table names are properly quoted using ActiveRecord's quote_table_name method.
1 parent d50de89 commit d26d966

File tree

8 files changed

+467
-0
lines changed

8 files changed

+467
-0
lines changed

CHANGELOG.md

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

66
---
77

8+
## [Unreleased]
9+
10+
### Added
11+
* **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+
* **Server lifecycle hooks**: Added configuration hooks for test server management:
13+
- `before_server_start`: Run code before Rails server starts
14+
- `after_server_start`: Run code after Rails server is ready
15+
- `after_transaction_start`: Run code after database transaction begins
16+
- `after_state_reset`: Run code after application state is reset
17+
- `before_server_stop`: Run code before Rails server stops
18+
* **State reset endpoint**: Added `/cypress_rails_reset_state` and `/__cypress__/reset_state` endpoints for compatibility with cypress-rails
19+
* **Transactional test mode**: Added support for automatic database transaction rollback between tests
20+
* **Environment configuration**: Support for `CYPRESS_RAILS_HOST` and `CYPRESS_RAILS_PORT` environment variables
21+
* **Automatic server management**: Test server automatically starts and stops with test execution
22+
23+
### Migration Guide
24+
25+
#### From Manual Server Management (Old Way)
26+
If you were previously running tests manually:
27+
28+
**Before (Manual Process):**
29+
```bash
30+
# Terminal 1: Start Rails server
31+
CYPRESS=1 bin/rails server -p 5017
32+
33+
# Terminal 2: Run tests
34+
yarn cypress open --project ./e2e
35+
# or
36+
npx cypress run --project ./e2e
37+
```
38+
39+
**After (Automated with Rake Tasks):**
40+
```bash
41+
# Single command - server managed automatically!
42+
bin/rails cypress:open
43+
# or
44+
bin/rails cypress:run
45+
```
46+
47+
#### From cypress-rails Gem
48+
If migrating from the `cypress-rails` gem:
49+
50+
1. Update your Gemfile:
51+
```ruby
52+
# Remove
53+
gem 'cypress-rails'
54+
55+
# Add
56+
gem 'cypress-on-rails', '~> 1.0'
57+
```
58+
59+
2. Run bundle and generator:
60+
```bash
61+
bundle install
62+
rails g cypress_on_rails:install
63+
```
64+
65+
3. Configure hooks in `config/initializers/cypress_on_rails.rb` (optional):
66+
```ruby
67+
CypressOnRails.configure do |c|
68+
# These hooks match cypress-rails functionality
69+
c.before_server_start = -> { DatabaseCleaner.clean }
70+
c.after_server_start = -> { Rails.application.load_seed }
71+
c.transactional_server = true
72+
end
73+
```
74+
75+
4. Use the same commands you're familiar with:
76+
```bash
77+
bin/rails cypress:open
78+
bin/rails cypress:run
79+
```
80+
81+
---
82+
883
## [1.18.0] — 2025-08-27
984
[Compare]: https://github.com/shakacode/cypress-playwright-on-rails/compare/v1.17.0...v1.18.0
1085

README.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,29 @@ Please use with extra caution if starting your local server on 0.0.0.0 or runnin
143143
144144
Getting started on your local environment
145145
146+
### Using Rake Tasks (Recommended)
147+
148+
The easiest way to run tests is using the provided rake tasks, which automatically manage the Rails server:
149+
150+
```shell
151+
# For Cypress
152+
bin/rails cypress:open # Opens Cypress test runner UI
153+
bin/rails cypress:run # Runs Cypress tests in headless mode
154+
155+
# For Playwright
156+
bin/rails playwright:open # Opens Playwright test runner UI
157+
bin/rails playwright:run # Runs Playwright tests in headless mode
158+
```
159+
160+
These tasks will:
161+
- Start the Rails test server automatically
162+
- Execute your tests
163+
- Stop the server when done
164+
165+
### Manual Server Management
166+
167+
You can also manage the server manually:
168+
146169
```shell
147170
# start rails
148171
CYPRESS=1 bin/rails server -p 5017
@@ -506,6 +529,44 @@ Consider VCR configuration in `cypress_helper.rb` to ignore hosts.
506529
All cassettes will be recorded and saved automatically, using the pattern `<vcs_cassettes_path>/graphql/<operation_name>`
507530

508531

532+
## Server Hooks Configuration
533+
534+
When using the rake tasks (`cypress:open`, `cypress:run`, `playwright:open`, `playwright:run`), you can configure lifecycle hooks to customize test server behavior:
535+
536+
```ruby
537+
CypressOnRails.configure do |c|
538+
# Run code before Rails server starts
539+
c.before_server_start = -> {
540+
puts "Preparing test environment..."
541+
}
542+
543+
# Run code after Rails server is ready
544+
c.after_server_start = -> {
545+
puts "Server is ready for testing!"
546+
}
547+
548+
# Run code after database transaction begins (transactional mode only)
549+
c.after_transaction_start = -> {
550+
# Load seed data that should be rolled back after tests
551+
}
552+
553+
# Run code after application state is reset
554+
c.after_state_reset = -> {
555+
Rails.cache.clear
556+
}
557+
558+
# Run code before Rails server stops
559+
c.before_server_stop = -> {
560+
puts "Cleaning up test environment..."
561+
}
562+
563+
# Configure server settings
564+
c.server_host = 'localhost' # or use ENV['CYPRESS_RAILS_HOST']
565+
c.server_port = 3001 # or use ENV['CYPRESS_RAILS_PORT']
566+
c.transactional_server = true # Enable automatic transaction rollback
567+
end
568+
```
569+
509570
## `before_request` configuration
510571

511572
You may perform any custom action before running a CypressOnRails command, such as authentication, or sending metrics. Please set `before_request` as part of the CypressOnRails configuration.

lib/cypress_on_rails/configuration.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ class Configuration
1010
attr_accessor :before_request
1111
attr_accessor :logger
1212
attr_accessor :vcr_options
13+
14+
# Server hooks for managing test lifecycle
15+
attr_accessor :before_server_start
16+
attr_accessor :after_server_start
17+
attr_accessor :after_transaction_start
18+
attr_accessor :after_state_reset
19+
attr_accessor :before_server_stop
20+
21+
# Server configuration
22+
attr_accessor :server_host
23+
attr_accessor :server_port
24+
attr_accessor :transactional_server
1325

1426
# Attributes for backwards compatibility
1527
def cypress_folder
@@ -38,6 +50,18 @@ def reset
3850
self.before_request = -> (request) {}
3951
self.logger = Logger.new(STDOUT)
4052
self.vcr_options = {}
53+
54+
# Server hooks
55+
self.before_server_start = nil
56+
self.after_server_start = nil
57+
self.after_transaction_start = nil
58+
self.after_state_reset = nil
59+
self.before_server_stop = nil
60+
61+
# Server configuration
62+
self.server_host = ENV.fetch('CYPRESS_RAILS_HOST', 'localhost')
63+
self.server_port = ENV.fetch('CYPRESS_RAILS_PORT', nil)
64+
self.transactional_server = true
4165
end
4266

4367
def tagged_logged

lib/cypress_on_rails/railtie.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@
33

44
module CypressOnRails
55
class Railtie < Rails::Railtie
6+
rake_tasks do
7+
load 'tasks/cypress.rake'
8+
end
69
initializer :setup_cypress_middleware, after: :load_config_initializers do |app|
710
if CypressOnRails.configuration.use_middleware?
811
require 'cypress_on_rails/middleware'
912
app.middleware.use Middleware
13+
14+
# Add state reset middleware for compatibility with cypress-rails
15+
require 'cypress_on_rails/state_reset_middleware'
16+
app.middleware.use StateResetMiddleware
1017
end
1118
if CypressOnRails.configuration.use_vcr_middleware?
1219
require 'cypress_on_rails/vcr/insert_eject_middleware'

0 commit comments

Comments
 (0)