-
-
Notifications
You must be signed in to change notification settings - Fork 638
Add Playwright E2E testing framework #1836
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
508f061
89d8b53
7f26ca2
f44bd5b
dcabbe1
bdd7003
5ab7dbd
42ef1f4
6a924fc
4d00510
4aaf34e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| name: Playwright E2E Tests | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [master] | ||
|
|
||
| jobs: | ||
| playwright: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: ruby/setup-ruby@v1 | ||
| with: | ||
| ruby-version: '3.3' | ||
| bundler-cache: true | ||
|
|
||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| cache: 'yarn' | ||
|
|
||
| - name: Install yalc globally | ||
| run: npm install -g yalc | ||
|
|
||
| - name: Install root dependencies | ||
| run: yarn install | ||
|
|
||
| - name: Install dummy app dependencies | ||
| working-directory: spec/dummy | ||
| run: | | ||
| bundle install | ||
| yarn install | ||
| - name: Install Playwright browsers | ||
| working-directory: spec/dummy | ||
| run: yarn playwright install --with-deps | ||
|
|
||
| - name: Generate React on Rails packs | ||
| working-directory: spec/dummy | ||
| env: | ||
| RAILS_ENV: test | ||
| run: bundle exec rake react_on_rails:generate_packs | ||
|
|
||
| - name: Build test assets | ||
| working-directory: spec/dummy | ||
| run: yarn build:test | ||
|
|
||
| - name: Run Playwright tests | ||
| working-directory: spec/dummy | ||
| run: yarn test:e2e | ||
|
|
||
| - uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: playwright-report | ||
| path: spec/dummy/e2e/playwright-report/ | ||
| retention-days: 30 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,7 @@ Pre-commit hooks automatically run: | |
| - **Run tests**: | ||
| - Ruby tests: `rake run_rspec` | ||
| - JavaScript tests: `yarn run test` or `rake js_tests` | ||
| - Playwright E2E tests: See Playwright section below | ||
| - All tests: `rake` (default task runs lint and all tests except examples) | ||
| - **Linting** (MANDATORY BEFORE EVERY COMMIT): | ||
| - **REQUIRED**: `bundle exec rubocop` - Must pass with zero offenses | ||
|
|
@@ -233,10 +234,153 @@ rm debug-*.js | |
| - Generated examples are in `gen-examples/` (ignored by git) | ||
| - Only use `yarn` as the JS package manager, never `npm` | ||
|
|
||
| ## Playwright E2E Testing | ||
|
|
||
| ### Overview | ||
| Playwright E2E testing is integrated via the `cypress-on-rails` gem (v1.19+), which provides seamless integration between Playwright and Rails. This allows you to control Rails application state during tests, use factory_bot, and more. | ||
|
|
||
| ### Setup | ||
| The gem and Playwright are already configured. To install Playwright browsers: | ||
|
|
||
| ```bash | ||
| cd spec/dummy | ||
| yarn playwright install --with-deps | ||
| ``` | ||
|
|
||
| ### Running Playwright Tests | ||
|
|
||
| **Note:** Playwright will automatically start the Rails server on port 5017 before running tests. You don't need to manually start the server. | ||
|
|
||
| ```bash | ||
| cd spec/dummy | ||
|
|
||
| # Run all tests (Rails server auto-starts) | ||
| yarn test:e2e | ||
|
|
||
| # Run tests in UI mode (interactive debugging) | ||
| yarn test:e2e:ui | ||
|
|
||
| # Run tests with visible browser | ||
| yarn test:e2e:headed | ||
|
|
||
| # Debug a specific test | ||
| yarn test:e2e:debug | ||
|
|
||
| # View test report | ||
| yarn test:e2e:report | ||
|
|
||
| # Run specific test file | ||
| yarn test:e2e e2e/playwright/e2e/react_on_rails/basic_components.spec.js | ||
| ``` | ||
|
|
||
| ### Writing Tests | ||
|
|
||
| Tests are located in `spec/dummy/e2e/playwright/e2e/`. The gem provides helpful commands for Rails integration: | ||
|
|
||
| ```javascript | ||
| import { test, expect } from "@playwright/test"; | ||
| import { app, appEval, appFactories } from '../../support/on-rails'; | ||
|
|
||
| test.describe("My React Component", () => { | ||
| test.beforeEach(async ({ page }) => { | ||
| // Clean database before each test | ||
| await app('clean'); | ||
| }); | ||
|
|
||
| test("should interact with component", async ({ page }) => { | ||
| // Create test data using factory_bot | ||
| await appFactories([['create', 'user', { name: 'Test User' }]]); | ||
|
|
||
| // Or run arbitrary Ruby code | ||
| await appEval('User.create!(email: "[email protected]")'); | ||
|
|
||
| // Navigate and test | ||
| await page.goto("/"); | ||
| const component = page.locator('#MyComponent-react-component-0'); | ||
| await expect(component).toBeVisible(); | ||
| }); | ||
| }); | ||
| ``` | ||
|
|
||
| ### Available Rails Helpers | ||
|
|
||
| The `cypress-on-rails` gem provides these helpers (imported from `support/on-rails.js`): | ||
|
|
||
| - `app('clean')` - Clean database | ||
| - `appEval(code)` - Run arbitrary Ruby code | ||
| - `appFactories(options)` - Create records via factory_bot | ||
| - `appScenario(name)` - Load predefined scenario | ||
| - See `e2e/playwright/app_commands/` for available commands | ||
|
|
||
| ### Creating App Commands | ||
|
|
||
| Add custom commands in `e2e/playwright/app_commands/`: | ||
|
|
||
| ```ruby | ||
| # e2e/playwright/app_commands/my_command.rb | ||
| CypressOnRails::SmartFactoryWrapper.configure( | ||
| always_reload: !Rails.configuration.cache_classes, | ||
| factory: :factory_bot, | ||
| dir: "{#{FactoryBot.definition_file_paths.join(',')}}" | ||
| ) | ||
|
|
||
| command 'my_command' do |options| | ||
| # Your custom Rails code | ||
| { success: true, data: options } | ||
| end | ||
| ``` | ||
|
|
||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ### Test Organization | ||
|
|
||
| ``` | ||
| spec/dummy/e2e/ | ||
| ├── playwright.config.js # Playwright configuration | ||
| ├── playwright/ | ||
| │ ├── support/ | ||
| │ │ ├── index.js # Test setup | ||
| │ │ └── on-rails.js # Rails helper functions | ||
| │ ├── e2e/ | ||
| │ │ ├── react_on_rails/ # React on Rails specific tests | ||
| │ │ │ └── basic_components.spec.js | ||
| │ │ └── rails_examples/ # Example tests | ||
|
Comment on lines
+272
to
+345
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix Playwright paths/extensions to match the actual test layout. The examples here still point to 🤖 Prompt for AI Agents |
||
| │ │ └── using_scenarios.spec.js | ||
| │ └── app_commands/ # Rails helper commands | ||
| │ ├── clean.rb | ||
| │ ├── factory_bot.rb | ||
| │ ├── eval.rb | ||
| │ └── scenarios/ | ||
| │ └── basic.rb | ||
| ``` | ||
|
Comment on lines
+334
to
+353
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test organization mixes Playwright and Cypress structures. The documented directory structure shows:
This inconsistent structure reflects the broader framework confusion in this PR. The actual directory structure should match whichever framework is genuinely being implemented. Additionally, the path shown at line 268 ( 🧰 Tools🪛 markdownlint-cli2 (0.18.1)330-330: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🤖 Prompt for AI Agents |
||
|
|
||
| ### Best Practices | ||
|
|
||
| - Use `app('clean')` in `beforeEach` to ensure clean state | ||
| - Leverage Rails helpers (`appFactories`, `appEval`) instead of UI setup | ||
| - Test React on Rails specific features: SSR, hydration, component registry | ||
| - Use component IDs like `#ComponentName-react-component-0` for selectors | ||
| - Monitor console errors during tests | ||
| - Test across different browsers with `--project` flag | ||
|
|
||
| ### Debugging | ||
|
|
||
| - Run in UI mode: `yarn test:e2e:ui` | ||
| - Use `page.pause()` to pause execution | ||
| - Check `playwright-report/` for detailed results after test failures | ||
| - Enable debug logging in `playwright.config.js` | ||
|
|
||
| ### CI Integration | ||
|
|
||
| Playwright E2E tests run automatically in CI via GitHub Actions (`.github/workflows/playwright.yml`). The workflow: | ||
| - Runs on all PRs and pushes to master | ||
| - Uses GitHub Actions annotations for test failures | ||
| - Uploads HTML reports as artifacts (available for 30 days) | ||
| - Auto-starts Rails server before running tests | ||
|
|
||
| ## IDE Configuration | ||
|
|
||
| Exclude these directories to prevent IDE slowdowns: | ||
|
|
||
| - `/coverage`, `/tmp`, `/gen-examples`, `/packages/react-on-rails/lib` | ||
| - `/node_modules`, `/spec/dummy/node_modules`, `/spec/dummy/tmp` | ||
| - `/spec/dummy/app/assets/webpack`, `/spec/dummy/log` | ||
| - `/spec/dummy/e2e/playwright-report`, `/spec/dummy/test-results` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| if defined?(CypressOnRails) | ||
| CypressOnRails.configure do |c| | ||
| c.api_prefix = "" | ||
| c.install_folder = File.expand_path("#{__dir__}/../../e2e/playwright") | ||
| # WARNING!! CypressOnRails can execute arbitrary ruby code | ||
| # please use with extra caution if enabling on hosted servers or starting your local server on 0.0.0.0 | ||
| c.use_middleware = !Rails.env.production? | ||
| # c.use_vcr_middleware = !Rails.env.production? | ||
| # # Use this if you want to use use_cassette wrapper instead of manual insert/eject | ||
| # # c.use_vcr_use_cassette_middleware = !Rails.env.production? | ||
| # # Pass custom VCR options | ||
| # c.vcr_options = { | ||
| # hook_into: :webmock, | ||
| # default_cassette_options: { record: :once }, | ||
| # cassette_library_dir: File.expand_path("#{__dir__}/../../e2e/playwright/fixtures/vcr_cassettes") | ||
| # } | ||
| c.logger = Rails.logger | ||
|
|
||
| # Server configuration for rake tasks (cypress:open, cypress:run, playwright:open, playwright:run) | ||
| # c.server_host = 'localhost' # or use ENV['CYPRESS_RAILS_HOST'] | ||
| # c.server_port = 3001 # or use ENV['CYPRESS_RAILS_PORT'] | ||
| # c.transactional_server = true # Enable automatic transaction rollback between tests | ||
|
|
||
| # Server lifecycle hooks for rake tasks | ||
| # c.before_server_start = -> { DatabaseCleaner.clean_with(:truncation) } | ||
| # c.after_server_start = -> { puts "Test server started on port #{CypressOnRails.configuration.server_port}" } | ||
| # c.after_transaction_start = -> { Rails.application.load_seed } | ||
| # c.after_state_reset = -> { Rails.cache.clear } | ||
| # c.before_server_stop = -> { puts "Stopping test server..." } | ||
|
|
||
| # If you want to enable a before_request logic, such as authentication, logging, sending metrics, etc. | ||
| # Refer to https://www.rubydoc.info/gems/rack/Rack/Request for the `request` argument. | ||
| # Return nil to continue through the Cypress command. Return a response [status, header, body] to halt. | ||
| # c.before_request = lambda { |request| | ||
| # unless request.env['warden'].authenticate(:secret_key) | ||
| # return [403, {}, ["forbidden"]] | ||
| # end | ||
| # } | ||
| end | ||
|
|
||
| # # if you compile your asssets on CI | ||
| # if ENV['CYPRESS'].present? && ENV['CI'].present? | ||
| # Rails.application.configure do | ||
| # config.assets.compile = false | ||
| # config.assets.unknown_asset_fallback = false | ||
| # end | ||
| # end | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use Yarn for global tools per repo standards.
Project policy (see CLAUDE.md) forbids
npmcommands; the other workflows install yalc with Yarn. Please switch this step toyarn global add yalc(or equivalent) to stay compliant.🤖 Prompt for AI Agents