Does Ruby on Rails Work With Playwright?
Playwright works seamlessly with Rails as a modern end-to-end testing solution, replacing older tools like Capybara for comprehensive cross-browser testing.
Quick Facts
How Ruby on Rails Works With Playwright
Playwright integrates naturally with Rails through npm/yarn as a standalone testing dependency, requiring no Rails-specific gems or plugins. Unlike Capybara which is Rails-centric, Playwright is framework-agnostic and communicates directly with your running Rails server via HTTP, making it ideal for testing Rails applications in real browser contexts (Chromium, Firefox, WebKit). Rails developers typically run their test server on a dedicated port and point Playwright at it, using familiar patterns like `await page.goto('http://localhost:3000/path')`. The main difference from traditional Rails testing is that Playwright tests live in your `spec/e2e` or `test/e2e` directory as JavaScript/TypeScript files, requiring developers to context-switch languages. However, this isolation is actually beneficial—E2E tests don't need to know about Rails internals, fixtures, or database state management, keeping them focused on user behavior. For screenshot comparisons, accessibility testing, and multi-browser validation, Playwright excels where Capybara falls short.
Best Use Cases
Quick Setup: Rails + Playwright E2E Test
npm install -D @playwright/testimport { test, expect } from '@playwright/test';
test.describe('Rails App E2E', () => {
test.beforeEach(async ({ page }) => {
// Reset database via Rails test route (add to config/routes.rb)
await page.goto('http://localhost:3000/test/reset');
});
test('user can sign up', async ({ page }) => {
await page.goto('http://localhost:3000/signup');
await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'SecurePass123');
// Extract CSRF token
const csrfToken = await page.locator('[name="authenticity_token"]').inputValue();
await page.click('button[type="submit"]');
await expect(page).toHaveURL('http://localhost:3000/dashboard');
await expect(page.locator('h1')).toContainText('Welcome');
});
test('works across browsers', async ({ browser, browserName }) => {
const page = await browser.newPage();
await page.goto('http://localhost:3000');
console.log(`Testing in ${browserName}`);
});
});Known Issues & Gotchas
Rails server must be running before Playwright tests execute; easy to forget in CI/CD pipelines
Fix: Use test fixtures in your GitHub Actions/CI config to start Rails server before running Playwright, or use a process manager like concurrently in npm scripts
Database state is not automatically reset between tests like with Capybara; Playwright can't access Rails test database directly
Fix: Use Rails API endpoints in your E2E tests to seed/reset data, or leverage page.goto() to hit dedicated test reset routes you expose only in test environment
JavaScript/TypeScript tests are less discoverable to Rails developers accustomed to RSpec/Minitest in Ruby
Fix: Document E2E tests separately, consider using Playwright's Python or Java bindings if your team prefers, or use typescript-node for type safety
CSRF token handling requires explicit extraction from page HTML or cookies since Playwright doesn't auto-inject Rails forms
Fix: Extract CSRF tokens via `page.locator('[name="authenticity_token"]').inputValue()` or disable CSRF for test requests
Alternatives
- •Capybara + Selenium: Traditional Rails E2E testing stack with RSpec; mature but slower and less cross-browser support
- •Cypress + Rails: Single-language JavaScript testing with better DX for React/Vue frontends, but requires more server configuration
- •TestCafe + Rails: Another headless browser framework with good multi-browser support; less ecosystem momentum than Playwright
Resources
Related Compatibility Guides
Explore more compatibility guides