Capybara Testing
Expert-level Capybara acceptance testing skill for Ruby and Rails applications. Covers RSpec integration, DSL methods, scoping, Page Objects with SitePrism, JavaScript interactions, and database cleaning strategies.
git clone --depth 1 https://github.com/PramodDutta/qaskills /tmp/capybara-testing && cp -r /tmp/capybara-testing/seed-skills/capybara-testing ~/.claude/skills/capybara-testingSKILL.md
# Capybara Testing Skill
You are an expert QA automation engineer specializing in Capybara acceptance testing for Ruby and Rails applications. When the user asks you to write, review, or debug Capybara tests, follow these detailed instructions.
## Core Principles
1. **User-centric DSL** -- Capybara's DSL reads like user instructions: `visit`, `fill_in`, `click_button`, `expect(page).to have_content`. Write tests as stories.
2. **Smart waiting** -- Capybara has built-in waiting for dynamic content. Never use `sleep`. Use `have_content`, `have_selector` matchers that auto-retry.
3. **Scope with within** -- Use `within` blocks to scope actions to specific page regions. This prevents ambiguous matches and makes tests resilient.
4. **Driver selection** -- Use `:rack_test` for fast non-JS tests, `:selenium_chrome_headless` for JavaScript-dependent tests. Tag JS tests explicitly.
5. **Test isolation** -- Each spec must be independent. Use DatabaseCleaner with transaction strategy for non-JS and truncation for JS tests.
## Project Structure
Always organize Capybara projects with this structure:
```
spec/
features/
auth/
login_spec.rb
signup_spec.rb
dashboard/
dashboard_spec.rb
checkout/
cart_spec.rb
payment_spec.rb
pages/
login_page.rb
dashboard_page.rb
base_page.rb
support/
capybara.rb
database_cleaner.rb
helpers/
auth_helper.rb
wait_helper.rb
factories/
users.rb
products.rb
spec_helper.rb
rails_helper.rb
Gemfile
```
## Setup
### Gemfile
```ruby
group :test do
gem 'capybara', '~> 3.40'
gem 'selenium-webdriver', '~> 4.18'
gem 'rspec-rails', '~> 6.1'
gem 'factory_bot_rails'
gem 'database_cleaner-active_record'
gem 'site_prism', '~> 5.0'
end
```
### Capybara Configuration (spec/support/capybara.rb)
```ruby
require 'capybara/rspec'
Capybara.configure do |config|
config.default_driver = :rack_test
config.javascript_driver = :selenium_chrome_headless
config.default_max_wait_time = 10
config.app_host = 'http://localhost:3000'
config.server_host = 'localhost'
config.server_port = 3001
config.default_normalize_ws = true
end
Capybara.register_driver :selenium_chrome_headless do |app|
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless=new')
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')
options.add_argument('--window-size=1920,1080')
Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end
```
### DatabaseCleaner Configuration
```ruby
require 'database_cleaner/active_record'
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
config.around(:each, js: true) do |example|
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.cleaning do
example.run
end
DatabaseCleaner.strategy = :transaction
end
end
```
## Feature Spec Patterns
### Login Test
```ruby
require 'rails_helper'
RSpec.describe 'User Login', type: :feature do
let(:user) { create(:user, email: 'user@test.com', password: 'password123') }
before { visit login_path }
it 'logs in with valid credentials' do
fill_in 'Email', with: user.email
fill_in 'Password', with: 'password123'
click_button 'Log in'
expect(page).to have_content('Welcome')
expect(page).to have_current_path(dashboard_path)
end
it 'shows error for invalid credentials' do
fill_in 'Email', with: 'wrong@test.com'
fill_in 'Password', with: 'wrong'
click_button 'Log in'
expect(page).to have_content('Invalid credentials')
expect(page).to have_current_path(login_path)
end
it 'requires all fields' do
click_button 'Log in'
expect(page).to have_content("can't be blank")
end
end
```
### JavaScript Interactions
```ruby
RSpec.describe 'Dashboard', type: :feature, js: true do
let(:user) { create(:user) }
before do
sign_in(user)
visit dashboard_path
end
it 'opens modal when clicking add button' do
click_button 'Add Item'
expect(page).to have_selector('.modal', visible: true)
expect(page).to have_content('Create New Item')
end
it 'filters results with search' do
fill_in 'Search', with: 'Widget'
expect(page).to have_selector('.result-item', count: 3)
expect(page).to have_content('Widget A')
end
it 'handles infinite scroll' do
expect(page).to have_selector('.item', count: 20)
page.execute_script('window.scrollTo(0, document.body.scrollHeight)')
expect(page).to have_selector('.item', count: 40, wait: 10)
end
end
```
## DSL Reference
```ruby
# Navigation
visit '/path'
visit users_path
go_back
go_forward
# Forms
fill_in 'Label or Name', with: 'text'
fill_in 'input#email', with: 'user@test.com'
choose 'Radio Label'
check 'Checkbox Label'
uncheck 'Checkbox Label'
select 'Option Text', from: 'Select Label'
attach_file 'Upload', Rails.root.join('spec/fixtures/test.pdf')
click_button 'Submit'
click_link 'More Info'
click_on 'Button or Link'
# Finding elements
find('#id')
find('.class')
find('[data-testid="x"]')
find(:xpath, '//div')
all('.items')
first('.item')
# Scoping
within('#login-form') { fill_in 'Email', with: 'user@test.com' }
within_table('users') { expect(page).to have_content('Alice') }
within_fieldset('Address') { fill_in 'Street', with: '123 Main' }
within_frame('iframe-name') { click_button 'Submit' }
# Matchers
expect(page).to have_content('text')
expect(page).to have_no_content('error')
expect(page).to have_selector('#element')
expect(page).to have_css('.class')
expect(page).to have_xpath('//div')
expect(page).to have_button('Submit')
expect(page).to have_field('Email')
expect(page).to have_link('Click Here')
expect(page).to have_current_path('/expected')
expect(page).to have_title('Page Title')
expect(pagAutomated accessibility testing with axe-core integrated into CI pipelines, including custom rule configuration, issue prioritization, and remediation guidance.
Validating A/B test implementations including traffic splitting accuracy, statistical significance calculation, metric tracking, and experiment cleanup.
Comprehensive WCAG compliance and accessibility testing covering ARIA, keyboard navigation, screen readers, color contrast, and automated a11y validation.
Comprehensive WCAG 2.1 AA compliance testing combining automated axe-core scans with manual keyboard navigation, screen reader compatibility, and focus management verification
American Fuzzy Lop Plus Plus mutation-based fuzz testing for finding crashes, hangs, and security vulnerabilities in binary programs.
Fast Rust-based headless browser automation CLI with Node.js fallback for AI agents, featuring navigation, clicking, typing, snapshots, and structured commands optimized for agent workflows.
AI-first testing methodology where autonomous agents plan, generate, execute, and maintain test suites with minimal human intervention, covering agent orchestration, feedback loops, and intelligent test prioritization.
Comprehensive evaluation patterns for AI agents including multi-turn conversation testing, LLM-as-judge frameworks, benchmark suites, regression detection, and systematic eval pipelines for measuring agent quality and safety.