Skip to content

Commit 884889d

Browse files
justin808claude
andcommitted
Add comprehensive CLAUDE.md guidance file
Created detailed guidance document for Claude Code agents working on cypress-playwright-on-rails gem, covering: - Critical testing and code quality requirements - Common commands for development workflow - Project architecture and request flow patterns - Testing patterns for unit and integration tests - Code style conventions and best practices - Backward compatibility guidelines - Changelog contribution guidelines - Security considerations for E2E testing - Multi-framework support (Cypress and Playwright) - VCR middleware variants and factory patterns - Rails version compatibility notes - Contributing workflow Inspired by ShakaCode's react_on_rails and shakapacker CLAUDE.md files, with specific focus on this gem's unique testing framework integration patterns. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent f57ceb3 commit 884889d

File tree

1 file changed

+371
-0
lines changed

1 file changed

+371
-0
lines changed

CLAUDE.md

Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
# Claude Code Guidelines for cypress-playwright-on-rails
2+
3+
This document provides guidance for Claude Code agents working on the cypress-playwright-on-rails gem.
4+
5+
## ⚠️ Critical Requirements
6+
7+
### Testing Protocol
8+
- **ALWAYS run corresponding RSpec tests when changing source files**
9+
- Changing `lib/cypress_on_rails/middleware.rb`? Run `bundle exec rspec spec/cypress_on_rails/middleware_spec.rb`
10+
- Changing `lib/cypress_on_rails/command_executor.rb`? Run `bundle exec rspec spec/cypress_on_rails/command_executor_spec.rb`
11+
- **Run full test suite before pushing**: `bundle exec rake`
12+
- **Test against multiple Rails versions** when making significant changes:
13+
```bash
14+
./specs_e2e/rails_6_1/test.sh
15+
./specs_e2e/rails_7_2/test.sh
16+
./specs_e2e/rails_8/test.sh
17+
```
18+
19+
### Code Quality
20+
- **ALWAYS use `bundle exec` prefix** when running Ruby tools: `bundle exec rubocop`, `bundle exec rspec`, `bundle exec rake`
21+
- **ALWAYS run `bundle exec rubocop` and fix all violations before committing**
22+
- **NEVER push code that fails RuboCop locally** - if CI fails but local passes, add the exact disable directive CI expects
23+
- **ALWAYS end files with a newline character** - this is mandatory for all files
24+
25+
### Git Workflow
26+
- **NEVER push directly to master** - always create feature branches and use PRs
27+
- **Keep PRs focused and minimal** - one logical change per PR
28+
- **Run `bundle exec rubocop` before every commit**
29+
- **Check CI status after pushing**: `gh pr view --json statusCheckRollup`
30+
31+
## 🚀 Common Commands
32+
33+
### Testing
34+
```bash
35+
# Run all unit tests
36+
bundle exec rspec
37+
38+
# Run specific test file
39+
bundle exec rspec spec/cypress_on_rails/middleware_spec.rb
40+
41+
# Run tests with focus tag
42+
bundle exec rspec --focus
43+
44+
# Run full suite (tests + build gem)
45+
bundle exec rake
46+
47+
# Run integration tests for specific Rails version
48+
./specs_e2e/rails_8/test.sh
49+
```
50+
51+
### Code Quality
52+
```bash
53+
# Run RuboCop (Ruby linter)
54+
bundle exec rubocop
55+
56+
# Auto-fix RuboCop violations
57+
bundle exec rubocop -a
58+
59+
# Check specific file
60+
bundle exec rubocop lib/cypress_on_rails/middleware.rb
61+
```
62+
63+
### Gem Development
64+
```bash
65+
# Install dependencies
66+
bundle install
67+
68+
# Build gem
69+
gem build cypress-on-rails.gemspec
70+
71+
# Install gem locally for testing
72+
gem install cypress-on-rails-*.gem
73+
```
74+
75+
### Generator Testing
76+
```bash
77+
# Test generator in a Rails app
78+
cd /path/to/test/rails/app
79+
bundle exec rails g cypress_on_rails:install
80+
81+
# With options
82+
bundle exec rails g cypress_on_rails:install --framework=playwright
83+
bundle exec rails g cypress_on_rails:install --install_folder=e2e
84+
```
85+
86+
## 📁 Project Architecture
87+
88+
### Core Components
89+
90+
**Middleware Layer** (`lib/cypress_on_rails/middleware.rb`)
91+
- Rack middleware that intercepts `/__e2e__/command` endpoint
92+
- Parses JSON requests and routes to CommandExecutor
93+
- Returns JSON responses with appropriate status codes (201/404/500)
94+
95+
**Command Executor** (`lib/cypress_on_rails/command_executor.rb`)
96+
- Loads `e2e_helper.rb` to set up test environment
97+
- Executes Ruby command files using `eval()` in binding context
98+
- Provides access to Rails, ActiveRecord, factories, and custom app code
99+
100+
**Smart Factory Wrapper** (`lib/cypress_on_rails/smart_factory_wrapper.rb`)
101+
- Abstraction layer over FactoryBot/SimpleRailsFactory
102+
- Auto-reloads factory definitions when files change (mtime tracking)
103+
- Supports: `create()`, `create_list()`, `build()`, `build_list()`
104+
105+
**Configuration** (`lib/cypress_on_rails/configuration.rb`)
106+
- Central configuration: `api_prefix`, `install_folder`, middleware settings
107+
- `before_request` hook for authentication/metrics
108+
- VCR options for HTTP recording/stubbing
109+
110+
**Rails Integration** (`lib/cypress_on_rails/railtie.rb`)
111+
- Automatically injects middleware into Rails stack
112+
- Conditional loading based on configuration
113+
- Supports VCR middleware variants
114+
115+
### Directory Structure
116+
```
117+
lib/cypress_on_rails/
118+
├── middleware.rb # Main HTTP request handler
119+
├── command_executor.rb # Ruby code execution engine
120+
├── smart_factory_wrapper.rb # Factory abstraction with auto-reload
121+
├── simple_rails_factory.rb # Fallback factory implementation
122+
├── configuration.rb # Settings management
123+
├── railtie.rb # Rails auto-integration
124+
├── middleware_config.rb # Shared middleware configuration
125+
└── vcr/ # VCR middleware variants
126+
├── insert_eject_middleware.rb # Manual cassette control
127+
├── use_cassette_middleware.rb # Automatic cassette wrapping
128+
└── middleware_helpers.rb # VCR utilities
129+
130+
lib/generators/cypress_on_rails/
131+
├── install_generator.rb # Rails generator for project setup
132+
└── templates/ # Generated boilerplate files
133+
├── config/initializers/cypress_on_rails.rb.erb
134+
├── spec/e2e/e2e_helper.rb.erb
135+
├── spec/e2e/app_commands/ # Command files
136+
├── spec/cypress/ # Cypress setup
137+
└── spec/playwright/ # Playwright setup
138+
139+
spec/cypress_on_rails/ # Unit tests (RSpec)
140+
specs_e2e/ # Integration tests
141+
├── rails_6_1/ # Rails 6.1 example app
142+
├── rails_7_2/ # Rails 7.2 example app
143+
└── rails_8/ # Rails 8.0 example app
144+
```
145+
146+
## 🔧 Development Patterns
147+
148+
### Request Flow
149+
```
150+
Cypress/Playwright Test
151+
152+
POST /__e2e__/command { name: 'clean', options: {} }
153+
154+
Middleware.call(env)
155+
156+
Configuration.before_request hook (optional auth/metrics)
157+
158+
Parse JSON → Validate command file exists
159+
160+
CommandExecutor.perform(file_path, options)
161+
├─ Load e2e_helper.rb (setup factories, DatabaseCleaner)
162+
└─ eval(file_content) in binding context
163+
164+
Return [status, headers, [json_body]]
165+
```
166+
167+
### Command File Pattern
168+
Command files are plain Ruby evaluated in application context:
169+
170+
```ruby
171+
# spec/e2e/app_commands/clean.rb
172+
DatabaseCleaner.strategy = :truncation
173+
DatabaseCleaner.clean
174+
CypressOnRails::SmartFactoryWrapper.reload
175+
176+
# spec/e2e/app_commands/factory_bot.rb
177+
Array.wrap(command_options).map do |factory_options|
178+
factory_method = factory_options.shift
179+
CypressOnRails::SmartFactoryWrapper.public_send(factory_method, *factory_options)
180+
end
181+
182+
# spec/e2e/app_commands/scenarios/user_with_posts.rb
183+
user = CypressOnRails::SmartFactoryWrapper.create(:user, email: '[email protected]')
184+
CypressOnRails::SmartFactoryWrapper.create_list(:post, 3, author: user)
185+
```
186+
187+
### Testing Patterns
188+
189+
**Unit Tests** - Isolated component testing with doubles/mocks:
190+
```ruby
191+
# spec/cypress_on_rails/middleware_spec.rb
192+
let(:app) { ->(env) { [200, {}, ["app response"]] } }
193+
let(:command_executor) { class_double(CypressOnRails::CommandExecutor) }
194+
let(:file) { class_double(File) }
195+
subject { described_class.new(app, command_executor, file) }
196+
197+
it "parses JSON and calls executor" do
198+
env['rack.input'] = StringIO.new(JSON.generate({name: 'seed'}))
199+
expect(command_executor).to receive(:perform)
200+
subject.call(env)
201+
end
202+
```
203+
204+
**Integration Tests** - Full Rails app with Cypress/Playwright:
205+
```bash
206+
# specs_e2e/rails_8/test.sh
207+
bundle install
208+
bin/rails db:drop db:create db:migrate
209+
bin/rails g cypress_on_rails:install
210+
CYPRESS=1 bin/rails server -p 3001 &
211+
bundle exec cypress run
212+
# or
213+
bundle exec playwright test
214+
```
215+
216+
### Code Style Conventions
217+
218+
**Module Organization**
219+
- Use modules for namespacing: `module CypressOnRails`
220+
- Class methods for singletons: `CommandExecutor.perform`, `SmartFactoryWrapper.create`
221+
222+
**Dependency Injection**
223+
- Middleware accepts dependencies in constructor for testability:
224+
```ruby
225+
def initialize(app, command_executor = CommandExecutor, file = File)
226+
```
227+
228+
**Error Handling**
229+
- Rescue exceptions and log them
230+
- Return appropriate HTTP status codes (404 for missing files, 500 for errors)
231+
- Include error details in JSON response body
232+
233+
**Configuration**
234+
- Centralize settings in `Configuration` class
235+
- Provide sensible defaults
236+
- Document configuration options in initializer template
237+
238+
## 🔄 Backward Compatibility
239+
240+
**Active Deprecations** (maintain compatibility but warn):
241+
1. `cypress_folder``install_folder`
242+
2. `/__cypress__/command``/__e2e__/command`
243+
3. `cypress_helper.rb``e2e_helper.rb`
244+
4. `CypressDev` constant → `CypressOnRails`
245+
246+
**When maintaining backward compatibility:**
247+
- Keep old code paths functional
248+
- Log deprecation warnings via `Configuration.logger.warn`
249+
- Update documentation to recommend new approach
250+
- Provide migration path in CHANGELOG
251+
252+
## 📝 Changelog Guidelines
253+
254+
**What merits a changelog entry:**
255+
- New features or middleware options
256+
- Bug fixes affecting user-facing behavior
257+
- Breaking changes or deprecations
258+
- Performance improvements
259+
- Security fixes
260+
261+
**What doesn't:**
262+
- Internal refactoring
263+
- Test improvements
264+
- Documentation updates (unless user-facing)
265+
- Development tooling changes
266+
267+
**Format:**
268+
```markdown
269+
## [Unreleased]
270+
271+
### Added
272+
- VCR use_cassette middleware for automatic cassette wrapping (#123)
273+
274+
### Changed
275+
- Improved error messages for missing command files (#124)
276+
277+
### Deprecated
278+
- `cypress_folder` configuration option, use `install_folder` instead
279+
280+
### Fixed
281+
- Factory auto-reload not detecting file changes on Windows (#125)
282+
```
283+
284+
## 🔒 Security Considerations
285+
286+
**CRITICAL**: This gem executes arbitrary Ruby code in the application context.
287+
288+
- **NEVER enable in production** (disabled by default via `!Rails.env.production?`)
289+
- **Implement `before_request` hook** for authentication in sensitive environments:
290+
```ruby
291+
c.before_request = lambda { |request|
292+
auth_token = request.env['HTTP_AUTHORIZATION']
293+
raise 'Unauthorized' unless valid_token?(auth_token)
294+
}
295+
```
296+
- **Bind to localhost only** when running Rails server for E2E tests
297+
- **Use in CI/CD pipelines safely** - isolated environments only
298+
299+
## 🎯 cypress-on-rails Specific Considerations
300+
301+
### Multi-Framework Support
302+
The gem supports **both Cypress and Playwright**. When making changes:
303+
- Test generator with both `--framework=cypress` and `--framework=playwright`
304+
- Update both JavaScript support files (`on-rails.js`) when changing API
305+
- Verify examples in both `spec/cypress/` and `spec/playwright/` templates
306+
307+
### VCR Middleware Variants
308+
Two VCR integration modes exist:
309+
1. **Insert/Eject** (`use_vcr_middleware: true`) - Manual cassette control via endpoints
310+
2. **Use Cassette** (`use_vcr_use_cassette_middleware: true`) - Automatic wrapping
311+
312+
When modifying VCR functionality, test both modes.
313+
314+
### Factory Wrapper Intelligence
315+
The `SmartFactoryWrapper` auto-reloads factories when files change:
316+
- Test with file modifications during test runs
317+
- Verify mtime tracking works correctly
318+
- Ensure fallback to `SimpleRailsFactory` when FactoryBot unavailable
319+
320+
### Rails Version Compatibility
321+
This gem targets **Rails 6.1, 7.2, and 8.0+**:
322+
- Test changes against all three versions in `specs_e2e/`
323+
- Be mindful of Rails API changes (e.g., Rails 8.1 delegation requirements)
324+
- Check CI pipeline covers all versions
325+
326+
### Generator Flexibility
327+
The generator supports multiple options:
328+
```bash
329+
--framework=cypress|playwright # Test framework choice
330+
--install_folder=e2e # Custom location
331+
--install_with=yarn|npm|skip # Package manager
332+
--api_prefix=/api # Proxy routing
333+
--experimental # VCR features
334+
```
335+
Test generator combinations when modifying templates.
336+
337+
## 📚 Useful Resources
338+
339+
- **RSpec Documentation**: https://rspec.info/
340+
- **Rack Specification**: https://github.com/rack/rack/blob/main/SPEC.rdoc
341+
- **Cypress Best Practices**: https://docs.cypress.io/guides/references/best-practices
342+
- **Playwright Best Practices**: https://playwright.dev/docs/best-practices
343+
- **FactoryBot Documentation**: https://github.com/thoughtbot/factory_bot
344+
- **VCR Documentation**: https://github.com/vcr/vcr
345+
346+
## 🤝 Contributing Workflow
347+
348+
1. **Create feature branch** from master: `git checkout -b feature/my-feature`
349+
2. **Make focused changes** - one logical change per PR
350+
3. **Write/update tests** for your changes
351+
4. **Run full test suite**: `bundle exec rake`
352+
5. **Run RuboCop**: `bundle exec rubocop`
353+
6. **Update CHANGELOG.md** if user-facing change
354+
7. **Commit with descriptive message**
355+
8. **Push and create PR**: `git push -u origin feature/my-feature && gh pr create`
356+
9. **Address CI failures** immediately - don't wait for merge
357+
358+
## 💡 Tips for Claude Code Agents
359+
360+
- **Read tests first** when understanding a component - they document intended behavior
361+
- **Check `specs_e2e/` examples** to understand real-world usage patterns
362+
- **Use `bundle exec rspec --focus`** to iterate quickly on single test
363+
- **Reference existing middleware** when adding new endpoints
364+
- **Follow Rack middleware conventions** (call next app, return 3-element array)
365+
- **Log liberally** during development - users need debugging info
366+
- **Consider backward compatibility** before changing public APIs
367+
- **Test generator output** by running it in a fresh Rails app
368+
369+
---
370+
371+
**Questions?** Check the README.md, docs/ folder, or existing tests for examples.

0 commit comments

Comments
 (0)