Troubleshooting Guide
This guide addresses common issues and questions when using cypress-playwright-on-rails.
Table of Contents
- VCR Integration Issues
- Playwright Support
- Test Environment Configuration
- Database and Transaction Issues
- Authentication and Security
- Performance and Parallel Testing
- Common Errors
VCR Integration Issues
Issue: "No route matches [POST] '/api/e2e/vcr/insert'" (#175)
Problem: VCR middleware is not properly configured or mounted.
Solution:
- Ensure VCR middleware is enabled in
config/initializers/cypress_on_rails.rb:
CypressOnRails.configure do |c|
c.use_vcr_middleware = !Rails.env.production? && ENV['CYPRESS'].present?
c.vcr_options = {
hook_into: :webmock,
default_cassette_options: { record: :once },
cassette_library_dir: Rails.root.join('spec/fixtures/vcr_cassettes')
}
end
- Add to your
cypress/support/index.js:
import 'cypress-on-rails/support/index'
- Make sure your API prefix matches:
c.api_prefix = '/api' # If your app uses /api prefix
Using VCR with GraphQL (#160)
For GraphQL operations with use_cassette:
CypressOnRails.configure do |c|
c.use_vcr_use_cassette_middleware = !Rails.env.production? && ENV['CYPRESS'].present?
# Note: Don't enable both VCR middlewares simultaneously
end
Add to cypress/support/commands.js:
Cypress.Commands.add('mockGraphQL', () => {
cy.on('window:before:load', (win) => {
const originalFetch = win.fetch;
const fetch = (path, options, ...rest) => {
if (options && options.body) {
try {
const body = JSON.parse(options.body);
if (body.operationName) {
return originalFetch(`${path}?operation=${body.operationName}`, options, ...rest);
}
} catch (e) {
return originalFetch(path, options, ...rest);
}
}
return originalFetch(path, options, ...rest);
};
cy.stub(win, 'fetch', fetch);
});
});
Late chunk errors or cascading browser crashes
If errors spill into the next example, check whether teardown kills the origin while streamed requests are still active. Keep Rails and auxiliary services suite-scoped, collect page/console/request failures, and wait for application completion. See Streamed and Multi-process Applications for diagnostics and ordered cleanup.
Playwright Support
Loading Fixtures in Playwright (#169)
While Cypress has cy.appFixtures(), Playwright requires a different approach:
Solution 1: Create helper functions
// spec/playwright/support/on-rails.js
async function appFixtures() {
const response = await page.request.post('/__e2e__/command', {
data: {
name: 'activerecord_fixtures',
options: {}
}
});
return response.json();
}
// Use in tests
test('load fixtures', async ({ page }) => {
await appFixtures();
await page.goto('/');
});
Solution 2: Use Factory Bot instead
// spec/playwright/support/factories.js
async function appFactories(factories) {
const response = await page.request.post('/__e2e__/command', {
data: {
name: 'factory_bot',
options: factories
}
});
return response.json();
}
// Use in tests
test('create data', async ({ page }) => {
await appFactories([
['create', 'user', { name: 'Test User' }]
]);
await page.goto('/users');
});
Test Environment Configuration
Running Tests in Test Environment with Change Detection (#157)
Problem: Running in development mode has different configuration than test mode.
Solution 1: Configure test environment with file watching
# config/environments/test.rb
if ENV['CYPRESS'].present?
# Enable file watching in test environment for Cypress
config.file_watcher = ActiveSupport::FileUpdateChecker
config.cache_classes = false
config.reload_classes_only_on_change = true
end
Solution 2: Use custom environment
# Create config/environments/cypress.rb based on test.rb
cp config/environments/test.rb config/environments/cypress.rb
# Modify cypress.rb to enable reloading
# Run with:
RAILS_ENV=cypress CYPRESS=1 bin/rails server
Headless Mode Configuration (#118)
To run Cypress in truly headless mode:
# For CI/headless execution
bin/rails cypress:run
# Or manually:
CYPRESS=1 bin/rails server -p 5017 &
yarn cypress run --headless --project ./e2e
Database and Transaction Issues
ApplicationRecord MySQL Error (#155)
Problem: ApplicationRecord being queried as a table.
Solution: Exclude ApplicationRecord from logging:
# spec/e2e/app_commands/log_fail.rb
def perform
load "#{Rails.root}/db/seeds.rb" if options && options['load_seeds']
descendants = ActiveRecord::Base.descendants
# Exclude abstract classes
descendants.reject! { |model| model.abstract_class? || model == ApplicationRecord }
descendants.each_with_object({}) do |model, result|
result[model.name] = model.limit(100).map(&:attributes)
rescue => e
result[model.name] = { error: e.message }
end
end
Using Rails Transactional Fixtures (#114)
Instead of database_cleaner, use Rails built-in transactional fixtures:
# spec/e2e/app_commands/clean.rb
require 'active_record/test_fixtures'
class TransactionalClean
include ActiveRecord::TestFixtures
def perform
setup_fixtures
yield if block_given?
ensure
teardown_fixtures
end
end
# Use with new rake tasks:
CypressOnRails.configure do |c|
c.transactional_server = true # Enables automatic rollback
end
Authentication and Security
Authenticating Commands (#137)
Protect your commands with authentication:
# config/initializers/cypress_on_rails.rb
CypressOnRails.configure do |c|
c.before_request = lambda { |request|
body = JSON.parse(request.body.string)
# Option 1: Token-based auth
if body['cypress_token'] != ENV.fetch('CYPRESS_SECRET_TOKEN')
return [401, {}, ['unauthorized']]
end
# Option 2: Warden/Devise auth
# if !request.env['warden'].authenticate(:secret_key)
# return [403, {}, ['forbidden']]
# end
nil # Continue with command execution
}
end
In Cypress tests:
Cypress.Commands.overwrite('app', (originalFn, name, options) => {
return originalFn(name, {
...options,
cypress_token: Cypress.env('SECRET_TOKEN')
});
});
Performance and Parallel Testing
Parallel Test Execution (#119)
While not built-in, you can achieve parallel testing:
Option 1: Using cypress-parallel
yarn add -D cypress-parallel
# In package.json
"scripts": {
"cy:parallel": "cypress-parallel -s cy:run -t 4"
}
Option 2: Database partitioning
# config/initializers/cypress_on_rails.rb
if ENV['CYPRESS_PARALLEL_ID'].present?
# Use different database per parallel process
config.database_name = "test_cypress_#{ENV['CYPRESS_PARALLEL_ID']}"
end
Option 3: CircleCI Parallelization
# .circleci/config.yml
jobs:
cypress:
parallelism: 4
steps:
- run:
command: |
TESTFILES=$(circleci tests glob "e2e/**/*.cy.js" | circleci tests split)
yarn cypress run --spec $TESTFILES
Common Errors
Webpack Compilation Error (#146)
Error: "Module not found: Error: Can't resolve 'cypress-factory'"
Solution: This is usually a path issue. Check:
- Your support file imports the correct path:
// cypress/support/index.js
import './on-rails' // Not 'cypress-factory'
- Ensure the file exists at the expected location
- Clear Cypress cache if needed:
yarn cypress cache clear
yarn install
Server Not Starting
If rake tasks fail to start the server:
# Check for port conflicts
lsof -i :3001
# Use a different port
CYPRESS_RAILS_PORT=5017 bin/rails cypress:open
# Or configure in initializer
CypressOnRails.configure do |c|
c.server_port = 5017
end
State Not Resetting Between Tests
Ensure clean state:
// cypress/support/index.js
beforeEach(() => {
cy.app('clean');
cy.app('load_seed'); // Optional
});
// Or use the state reset endpoint. Use the helper rather than a raw
// cy.request, so the token header is sent when one is configured.
beforeEach(() => {
cy.appResetState();
});
Getting Help
If you encounter issues not covered here:
- Check existing GitHub issues
- Search the Slack channel
- Post in the forum
- Create a new issue with:
- Your Rails version
- cypress-on-rails version
- Minimal reproduction steps
- Full error messages and stack traces