cypress-on-rails 1.18.0 → 1.19.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/.github/workflows/claude-code-review.yml +57 -0
- data/.github/workflows/claude.yml +50 -0
- data/CHANGELOG.md +319 -98
- data/README.md +93 -1
- data/RELEASING.md +200 -0
- data/Rakefile +1 -4
- data/cypress-on-rails.gemspec +1 -0
- data/docs/BEST_PRACTICES.md +678 -0
- data/docs/DX_IMPROVEMENTS.md +163 -0
- data/docs/PLAYWRIGHT_GUIDE.md +554 -0
- data/docs/RELEASE.md +124 -0
- data/docs/TROUBLESHOOTING.md +351 -0
- data/docs/VCR_GUIDE.md +499 -0
- data/lib/cypress_on_rails/configuration.rb +24 -0
- data/lib/cypress_on_rails/railtie.rb +7 -0
- data/lib/cypress_on_rails/server.rb +197 -0
- data/lib/cypress_on_rails/state_reset_middleware.rb +58 -0
- data/lib/cypress_on_rails/version.rb +1 -1
- data/lib/generators/cypress_on_rails/templates/config/initializers/cypress_on_rails.rb.erb +12 -0
- data/lib/generators/cypress_on_rails/templates/spec/cypress/e2e/rails_examples/using_factory_bot.cy.js +2 -2
- data/lib/generators/cypress_on_rails/templates/spec/cypress/e2e/rails_examples/using_scenarios.cy.js +1 -1
- data/lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js +1 -1
- data/lib/tasks/cypress.rake +33 -0
- data/rakelib/release.rake +80 -0
- data/rakelib/task_helpers.rb +23 -0
- data/rakelib/update_changelog.rake +63 -0
- metadata +31 -2
data/docs/RELEASE.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# Release Process
|
2
|
+
|
3
|
+
This document describes how to release a new version of the `cypress-on-rails` gem.
|
4
|
+
|
5
|
+
## Prerequisites
|
6
|
+
|
7
|
+
1. Install the `gem-release` gem globally:
|
8
|
+
```bash
|
9
|
+
gem install gem-release
|
10
|
+
```
|
11
|
+
|
12
|
+
2. Ensure you have write access to the rubygems.org package
|
13
|
+
|
14
|
+
3. Set up two-factor authentication (2FA) for RubyGems and have your OTP generator ready
|
15
|
+
|
16
|
+
## Release Steps
|
17
|
+
|
18
|
+
### 1. Prepare for Release
|
19
|
+
|
20
|
+
Ensure your working directory is clean:
|
21
|
+
```bash
|
22
|
+
git status
|
23
|
+
```
|
24
|
+
|
25
|
+
If you have uncommitted changes, commit or stash them first.
|
26
|
+
|
27
|
+
### 2. Pull Latest Changes
|
28
|
+
|
29
|
+
```bash
|
30
|
+
git pull --rebase
|
31
|
+
```
|
32
|
+
|
33
|
+
### 3. Run the Release Task
|
34
|
+
|
35
|
+
To release a specific version:
|
36
|
+
```bash
|
37
|
+
rake release[1.19.0]
|
38
|
+
```
|
39
|
+
|
40
|
+
To automatically bump the patch version:
|
41
|
+
```bash
|
42
|
+
rake release
|
43
|
+
```
|
44
|
+
|
45
|
+
To perform a dry run (without actually publishing):
|
46
|
+
```bash
|
47
|
+
rake release[1.19.0,true]
|
48
|
+
```
|
49
|
+
|
50
|
+
### 4. Enter Your OTP
|
51
|
+
|
52
|
+
When prompted, enter your one-time password (OTP) from your authenticator app for RubyGems.
|
53
|
+
|
54
|
+
If you get an error during gem publishing, you can run `gem release` manually to retry.
|
55
|
+
|
56
|
+
### 5. Update the CHANGELOG
|
57
|
+
|
58
|
+
After successfully publishing the gem, update the CHANGELOG:
|
59
|
+
|
60
|
+
```bash
|
61
|
+
bundle exec rake update_changelog
|
62
|
+
# This will:
|
63
|
+
# - Add a new version header with the release date
|
64
|
+
# - Add version comparison links
|
65
|
+
# - Prompt you to move content from [Unreleased] to the new version
|
66
|
+
|
67
|
+
# Edit CHANGELOG.md to move unreleased changes to the new version section
|
68
|
+
git commit -a -m 'Update CHANGELOG.md'
|
69
|
+
git push
|
70
|
+
```
|
71
|
+
|
72
|
+
## Version Numbering
|
73
|
+
|
74
|
+
Follow [Semantic Versioning](https://semver.org/):
|
75
|
+
|
76
|
+
- **Major version** (X.0.0): Breaking changes
|
77
|
+
- **Minor version** (0.X.0): New features, backwards compatible
|
78
|
+
- **Patch version** (0.0.X): Bug fixes, backwards compatible
|
79
|
+
- **Pre-release versions**: Use dot notation, not dashes (e.g., `2.0.0.beta.1`, not `2.0.0-beta.1`)
|
80
|
+
|
81
|
+
## What the Release Task Does
|
82
|
+
|
83
|
+
The release task automates the following steps:
|
84
|
+
|
85
|
+
1. Checks for uncommitted changes (will abort if found)
|
86
|
+
2. Pulls the latest changes from the repository
|
87
|
+
3. Bumps the version number in `lib/cypress_on_rails/version.rb` using `gem bump`
|
88
|
+
4. Creates a git commit with the version bump message
|
89
|
+
5. Creates a git tag for the new version (e.g., `v1.19.0`)
|
90
|
+
6. Pushes the commit to GitHub
|
91
|
+
7. Pushes the tag to GitHub
|
92
|
+
8. Builds the gem
|
93
|
+
9. Publishes the gem to RubyGems (requires OTP)
|
94
|
+
|
95
|
+
## Troubleshooting
|
96
|
+
|
97
|
+
### Authentication Error
|
98
|
+
|
99
|
+
If you get an authentication error with RubyGems:
|
100
|
+
1. Verify your OTP is correct and current
|
101
|
+
2. Ensure your RubyGems API key is valid
|
102
|
+
3. Run `gem release` manually to retry
|
103
|
+
|
104
|
+
### Version Already Exists
|
105
|
+
|
106
|
+
If the version already exists on RubyGems:
|
107
|
+
1. Bump to a higher version number
|
108
|
+
2. Or fix the version in `lib/cypress_on_rails/version.rb` and try again
|
109
|
+
|
110
|
+
### Uncommitted Changes Error
|
111
|
+
|
112
|
+
If you have uncommitted changes:
|
113
|
+
1. Review your changes with `git status`
|
114
|
+
2. Commit them with `git commit -am "Your message"`
|
115
|
+
3. Or stash them with `git stash`
|
116
|
+
4. Then retry the release
|
117
|
+
|
118
|
+
## Post-Release
|
119
|
+
|
120
|
+
After releasing:
|
121
|
+
|
122
|
+
1. Announce the release on relevant channels (Slack, forum, etc.)
|
123
|
+
2. Update any documentation that references version numbers
|
124
|
+
3. Consider creating a GitHub release with release notes
|
@@ -0,0 +1,351 @@
|
|
1
|
+
# Troubleshooting Guide
|
2
|
+
|
3
|
+
This guide addresses common issues and questions when using cypress-playwright-on-rails.
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
- [VCR Integration Issues](#vcr-integration-issues)
|
7
|
+
- [Playwright Support](#playwright-support)
|
8
|
+
- [Test Environment Configuration](#test-environment-configuration)
|
9
|
+
- [Database and Transaction Issues](#database-and-transaction-issues)
|
10
|
+
- [Authentication and Security](#authentication-and-security)
|
11
|
+
- [Performance and Parallel Testing](#performance-and-parallel-testing)
|
12
|
+
- [Common Errors](#common-errors)
|
13
|
+
|
14
|
+
## VCR Integration Issues
|
15
|
+
|
16
|
+
### Issue: "No route matches [POST] '/api/__e2e__/vcr/insert'" (#175)
|
17
|
+
|
18
|
+
**Problem:** VCR middleware is not properly configured or mounted.
|
19
|
+
|
20
|
+
**Solution:**
|
21
|
+
1. Ensure VCR middleware is enabled in `config/initializers/cypress_on_rails.rb`:
|
22
|
+
```ruby
|
23
|
+
CypressOnRails.configure do |c|
|
24
|
+
c.use_vcr_middleware = !Rails.env.production? && ENV['CYPRESS'].present?
|
25
|
+
|
26
|
+
c.vcr_options = {
|
27
|
+
hook_into: :webmock,
|
28
|
+
default_cassette_options: { record: :once },
|
29
|
+
cassette_library_dir: Rails.root.join('spec/fixtures/vcr_cassettes')
|
30
|
+
}
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
2. Add to your `cypress/support/index.js`:
|
35
|
+
```js
|
36
|
+
import 'cypress-on-rails/support/index'
|
37
|
+
```
|
38
|
+
|
39
|
+
3. Make sure your API prefix matches:
|
40
|
+
```ruby
|
41
|
+
c.api_prefix = '/api' # If your app uses /api prefix
|
42
|
+
```
|
43
|
+
|
44
|
+
### Using VCR with GraphQL (#160)
|
45
|
+
|
46
|
+
For GraphQL operations with `use_cassette`:
|
47
|
+
```ruby
|
48
|
+
CypressOnRails.configure do |c|
|
49
|
+
c.use_vcr_use_cassette_middleware = !Rails.env.production? && ENV['CYPRESS'].present?
|
50
|
+
# Note: Don't enable both VCR middlewares simultaneously
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
Add to `cypress/support/commands.js`:
|
55
|
+
```js
|
56
|
+
Cypress.Commands.add('mockGraphQL', () => {
|
57
|
+
cy.on('window:before:load', (win) => {
|
58
|
+
const originalFetch = win.fetch;
|
59
|
+
const fetch = (path, options, ...rest) => {
|
60
|
+
if (options && options.body) {
|
61
|
+
try {
|
62
|
+
const body = JSON.parse(options.body);
|
63
|
+
if (body.operationName) {
|
64
|
+
return originalFetch(`${path}?operation=${body.operationName}`, options, ...rest);
|
65
|
+
}
|
66
|
+
} catch (e) {
|
67
|
+
return originalFetch(path, options, ...rest);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
return originalFetch(path, options, ...rest);
|
71
|
+
};
|
72
|
+
cy.stub(win, 'fetch', fetch);
|
73
|
+
});
|
74
|
+
});
|
75
|
+
```
|
76
|
+
|
77
|
+
## Playwright Support
|
78
|
+
|
79
|
+
### Loading Fixtures in Playwright (#169)
|
80
|
+
|
81
|
+
While Cypress has `cy.appFixtures()`, Playwright requires a different approach:
|
82
|
+
|
83
|
+
**Solution 1: Create helper functions**
|
84
|
+
```js
|
85
|
+
// spec/playwright/support/on-rails.js
|
86
|
+
async function appFixtures() {
|
87
|
+
const response = await page.request.post('/__e2e__/command', {
|
88
|
+
data: {
|
89
|
+
name: 'activerecord_fixtures',
|
90
|
+
options: {}
|
91
|
+
}
|
92
|
+
});
|
93
|
+
return response.json();
|
94
|
+
}
|
95
|
+
|
96
|
+
// Use in tests
|
97
|
+
test('load fixtures', async ({ page }) => {
|
98
|
+
await appFixtures();
|
99
|
+
await page.goto('/');
|
100
|
+
});
|
101
|
+
```
|
102
|
+
|
103
|
+
**Solution 2: Use Factory Bot instead**
|
104
|
+
```js
|
105
|
+
// spec/playwright/support/factories.js
|
106
|
+
async function appFactories(factories) {
|
107
|
+
const response = await page.request.post('/__e2e__/command', {
|
108
|
+
data: {
|
109
|
+
name: 'factory_bot',
|
110
|
+
options: factories
|
111
|
+
}
|
112
|
+
});
|
113
|
+
return response.json();
|
114
|
+
}
|
115
|
+
|
116
|
+
// Use in tests
|
117
|
+
test('create data', async ({ page }) => {
|
118
|
+
await appFactories([
|
119
|
+
['create', 'user', { name: 'Test User' }]
|
120
|
+
]);
|
121
|
+
await page.goto('/users');
|
122
|
+
});
|
123
|
+
```
|
124
|
+
|
125
|
+
## Test Environment Configuration
|
126
|
+
|
127
|
+
### Running Tests in Test Environment with Change Detection (#157)
|
128
|
+
|
129
|
+
**Problem:** Running in development mode has different configuration than test mode.
|
130
|
+
|
131
|
+
**Solution 1: Configure test environment with file watching**
|
132
|
+
```ruby
|
133
|
+
# config/environments/test.rb
|
134
|
+
if ENV['CYPRESS'].present?
|
135
|
+
# Enable file watching in test environment for Cypress
|
136
|
+
config.file_watcher = ActiveSupport::FileUpdateChecker
|
137
|
+
config.cache_classes = false
|
138
|
+
config.reload_classes_only_on_change = true
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
142
|
+
**Solution 2: Use custom environment**
|
143
|
+
```bash
|
144
|
+
# Create config/environments/cypress.rb based on test.rb
|
145
|
+
cp config/environments/test.rb config/environments/cypress.rb
|
146
|
+
|
147
|
+
# Modify cypress.rb to enable reloading
|
148
|
+
# Run with:
|
149
|
+
RAILS_ENV=cypress CYPRESS=1 bin/rails server
|
150
|
+
```
|
151
|
+
|
152
|
+
### Headless Mode Configuration (#118)
|
153
|
+
|
154
|
+
To run Cypress in truly headless mode:
|
155
|
+
```bash
|
156
|
+
# For CI/headless execution
|
157
|
+
bin/rails cypress:run
|
158
|
+
|
159
|
+
# Or manually:
|
160
|
+
CYPRESS=1 bin/rails server -p 5017 &
|
161
|
+
yarn cypress run --headless --project ./e2e
|
162
|
+
```
|
163
|
+
|
164
|
+
## Database and Transaction Issues
|
165
|
+
|
166
|
+
### ApplicationRecord MySQL Error (#155)
|
167
|
+
|
168
|
+
**Problem:** ApplicationRecord being queried as a table.
|
169
|
+
|
170
|
+
**Solution:** Exclude ApplicationRecord from logging:
|
171
|
+
```ruby
|
172
|
+
# spec/e2e/app_commands/log_fail.rb
|
173
|
+
def perform
|
174
|
+
load "#{Rails.root}/db/seeds.rb" if options && options['load_seeds']
|
175
|
+
|
176
|
+
descendants = ActiveRecord::Base.descendants
|
177
|
+
# Exclude abstract classes
|
178
|
+
descendants.reject! { |model| model.abstract_class? || model == ApplicationRecord }
|
179
|
+
|
180
|
+
descendants.each_with_object({}) do |model, result|
|
181
|
+
result[model.name] = model.limit(100).map(&:attributes)
|
182
|
+
rescue => e
|
183
|
+
result[model.name] = { error: e.message }
|
184
|
+
end
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
188
|
+
### Using Rails Transactional Fixtures (#114)
|
189
|
+
|
190
|
+
Instead of database_cleaner, use Rails built-in transactional fixtures:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
# spec/e2e/app_commands/clean.rb
|
194
|
+
require 'active_record/test_fixtures'
|
195
|
+
|
196
|
+
class TransactionalClean
|
197
|
+
include ActiveRecord::TestFixtures
|
198
|
+
|
199
|
+
def perform
|
200
|
+
setup_fixtures
|
201
|
+
yield if block_given?
|
202
|
+
ensure
|
203
|
+
teardown_fixtures
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Use with new rake tasks:
|
208
|
+
CypressOnRails.configure do |c|
|
209
|
+
c.transactional_server = true # Enables automatic rollback
|
210
|
+
end
|
211
|
+
```
|
212
|
+
|
213
|
+
## Authentication and Security
|
214
|
+
|
215
|
+
### Authenticating Commands (#137)
|
216
|
+
|
217
|
+
Protect your commands with authentication:
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
# config/initializers/cypress_on_rails.rb
|
221
|
+
CypressOnRails.configure do |c|
|
222
|
+
c.before_request = lambda { |request|
|
223
|
+
body = JSON.parse(request.body.string)
|
224
|
+
|
225
|
+
# Option 1: Token-based auth
|
226
|
+
if body['cypress_token'] != ENV.fetch('CYPRESS_SECRET_TOKEN')
|
227
|
+
return [401, {}, ['unauthorized']]
|
228
|
+
end
|
229
|
+
|
230
|
+
# Option 2: Warden/Devise auth
|
231
|
+
# if !request.env['warden'].authenticate(:secret_key)
|
232
|
+
# return [403, {}, ['forbidden']]
|
233
|
+
# end
|
234
|
+
|
235
|
+
nil # Continue with command execution
|
236
|
+
}
|
237
|
+
end
|
238
|
+
```
|
239
|
+
|
240
|
+
In Cypress tests:
|
241
|
+
```js
|
242
|
+
Cypress.Commands.overwrite('app', (originalFn, name, options) => {
|
243
|
+
return originalFn(name, {
|
244
|
+
...options,
|
245
|
+
cypress_token: Cypress.env('SECRET_TOKEN')
|
246
|
+
});
|
247
|
+
});
|
248
|
+
```
|
249
|
+
|
250
|
+
## Performance and Parallel Testing
|
251
|
+
|
252
|
+
### Parallel Test Execution (#119)
|
253
|
+
|
254
|
+
While not built-in, you can achieve parallel testing:
|
255
|
+
|
256
|
+
**Option 1: Using cypress-parallel**
|
257
|
+
```bash
|
258
|
+
yarn add -D cypress-parallel
|
259
|
+
|
260
|
+
# In package.json
|
261
|
+
"scripts": {
|
262
|
+
"cy:parallel": "cypress-parallel -s cy:run -t 4"
|
263
|
+
}
|
264
|
+
```
|
265
|
+
|
266
|
+
**Option 2: Database partitioning**
|
267
|
+
```ruby
|
268
|
+
# config/initializers/cypress_on_rails.rb
|
269
|
+
if ENV['CYPRESS_PARALLEL_ID'].present?
|
270
|
+
# Use different database per parallel process
|
271
|
+
config.database_name = "test_cypress_#{ENV['CYPRESS_PARALLEL_ID']}"
|
272
|
+
end
|
273
|
+
```
|
274
|
+
|
275
|
+
**Option 3: CircleCI Parallelization**
|
276
|
+
```yaml
|
277
|
+
# .circleci/config.yml
|
278
|
+
jobs:
|
279
|
+
cypress:
|
280
|
+
parallelism: 4
|
281
|
+
steps:
|
282
|
+
- run:
|
283
|
+
command: |
|
284
|
+
TESTFILES=$(circleci tests glob "e2e/**/*.cy.js" | circleci tests split)
|
285
|
+
yarn cypress run --spec $TESTFILES
|
286
|
+
```
|
287
|
+
|
288
|
+
## Common Errors
|
289
|
+
|
290
|
+
### Webpack Compilation Error (#146)
|
291
|
+
|
292
|
+
**Error:** "Module not found: Error: Can't resolve 'cypress-factory'"
|
293
|
+
|
294
|
+
**Solution:** This is usually a path issue. Check:
|
295
|
+
1. Your support file imports the correct path:
|
296
|
+
```js
|
297
|
+
// cypress/support/index.js
|
298
|
+
import './on-rails' // Not 'cypress-factory'
|
299
|
+
```
|
300
|
+
|
301
|
+
2. Ensure the file exists at the expected location
|
302
|
+
3. Clear Cypress cache if needed:
|
303
|
+
```bash
|
304
|
+
yarn cypress cache clear
|
305
|
+
yarn install
|
306
|
+
```
|
307
|
+
|
308
|
+
### Server Not Starting
|
309
|
+
|
310
|
+
If rake tasks fail to start the server:
|
311
|
+
```ruby
|
312
|
+
# Check for port conflicts
|
313
|
+
lsof -i :3001
|
314
|
+
|
315
|
+
# Use a different port
|
316
|
+
CYPRESS_RAILS_PORT=5017 bin/rails cypress:open
|
317
|
+
|
318
|
+
# Or configure in initializer
|
319
|
+
CypressOnRails.configure do |c|
|
320
|
+
c.server_port = 5017
|
321
|
+
end
|
322
|
+
```
|
323
|
+
|
324
|
+
### State Not Resetting Between Tests
|
325
|
+
|
326
|
+
Ensure clean state:
|
327
|
+
```js
|
328
|
+
// cypress/support/index.js
|
329
|
+
beforeEach(() => {
|
330
|
+
cy.app('clean');
|
331
|
+
cy.app('load_seed'); // Optional
|
332
|
+
});
|
333
|
+
|
334
|
+
// Or use state reset endpoint
|
335
|
+
beforeEach(() => {
|
336
|
+
cy.request('POST', '/cypress_rails_reset_state');
|
337
|
+
});
|
338
|
+
```
|
339
|
+
|
340
|
+
## Getting Help
|
341
|
+
|
342
|
+
If you encounter issues not covered here:
|
343
|
+
|
344
|
+
1. Check existing [GitHub issues](https://github.com/shakacode/cypress-playwright-on-rails/issues)
|
345
|
+
2. Search the [Slack channel](https://join.slack.com/t/reactrails/shared_invite/enQtNjY3NTczMjczNzYxLTlmYjdiZmY3MTVlMzU2YWE0OWM0MzNiZDI0MzdkZGFiZTFkYTFkOGVjODBmOWEyYWQ3MzA2NGE1YWJjNmVlMGE)
|
346
|
+
3. Post in the [forum](https://forum.shakacode.com/c/cypress-on-rails/55)
|
347
|
+
4. Create a new issue with:
|
348
|
+
- Your Rails version
|
349
|
+
- cypress-on-rails version
|
350
|
+
- Minimal reproduction steps
|
351
|
+
- Full error messages and stack traces
|