capybara-playwright-driver

repository·main·Indexed 42 days ago

https://github.com/yusukeiwaki/capybara-playwright-driver

A Playwright driver for Capybara that integrates Playwright into Rails applications for modern browser automation. It allows developers to use the standard Capybara DSL while providing access to native Playwright locators, actions, and tracing via methods like `with_playwright_page` and `with_playwright_element_handle`.

Tokens
5.1K
Snippets
22
Records
30
Agent score
54%

What's inside capybara-playwright-driver

  1. Configure the Playwright driver for Capybara

    main

    To use Playwright, register the :playwright driver within your Capybara configuration. You can specify the browser_type (e.g., :firefox) and whether to run in headless mode. It is also recommended to set Capybara.default_max_wait_time and a Capybara.save_path for screenshots/logs.

    require 'capybara-playwright-driver'
    
    Capybara.register_driver(:playwright) do |app|
      Capybara::Playwright::Driver.new(app, browser_type: :firefox, headless: false)
    end
    
    Capybara.default_max_wait_time = 15
    Capybara.default_driver = :playwright
    Capybara.save_path = 'tmp/capybara'
    require 'capybara-playwright-driver'
    
    # setup
    Capybara.register_driver(:playwright) do |app|
      Capybara::Playwright::Driver.new(app, browser_type: :firefox, headless: false)
    end
    Capybara.default_max_wait_time = 15
    Capybara.default_driver = :playwright
    Capybara.save_path = 'tmp/capybara'
  2. Optimize text input performance with Playwright's `fill`

    main

    Capybara's fill_in uses Playwright's typing behavior, sending individual keyboard events for every character. This is slower for large values. For better performance when input speed matters more than individual keyboard events, use Playwright's native fill method via with_playwright_page.

    page.driver.with_playwright_page { |playwright_page| playwright_page.get_by_label('Body').fill(large_value) }
  3. Manage caret behavior in contenteditable elements

    main

    This driver delegates keyboard focus and caret behavior to Playwright. If a contenteditable element loses focus between send_keys calls, the caret position might differ from Selenium. To ensure reliability, specify caret movement explicitly.

    editor.send_keys(:end, '@') # The page moves focus to an autocomplete control.
    editor.send_keys(:end, 'alice')
  4. Set up the development environment for Playwright

    main

    To prepare your environment for running tests, you must install the correct version of Playwright via npm and its dependencies.

    bundle install
    export PLAYWRIGHT_CLI_VERSION=$(bundle exec ruby -e 'require "playwright"; puts Playwright::COMPATIBLE_PLAYWRIGHT_VERSION.strip')
    npm install playwright@${PLAYWRIGHT_CLI_VERSION}
    ./node_modules/.bin/playwright install --with-deps
  5. Manage screenshots and video recordings during reset!

    main

    When calling reset! on the driver, certain side effects occur regarding media capture:

    • Screenshots: If callback_on_save_screenshot? is true, the driver attempts to capture a raw screenshot via @browser.raw_screenshot and passes it to callback_on_save_screenshot(raw_screenshot) before the page is cleared.
    • Videos: The video path is retrieved via @browser.video_path. If a path exists, it is passed to callback_on_save_screenrecord(video_path).

    Note on Lifecycle:

    • Screenshots are only available before closing the page.
    • Video paths can only be acquired before closing the context.
    • Videos are only completely saved after closing the context.
  6. Use Playwright-native selectors and actions via Capybara

    main

    While you can use the standard Capybara DSL, you can also access the underlying Playwright page and element handles directly to use Playwright's native locators (like get_by_label) and actions (like press).

    Use page.driver.with_playwright_page to access the Playwright page object, and element.with_playwright_element_handle to access a Playwright element_handle from a Capybara element.

    # Using Playwright-native page methods
    page.driver.with_playwright_page do |page|
      page.get_by_label('Search or jump to', exact: true).press('Enter')
    end
    
    # Using Playwright-native element methods
    all('[data-testid="results-list"] h3').each do |li|
      puts "#{li.with_playwright_element_handle { |handle| handle.text_content }} by Playwright"
    end
    # search_field.send_keys(:enter)
    page.driver.with_playwright_page do |page|
      page.get_by_label('Search or jump to', exact: true).press('Enter')
    end
    
    all('[data-testid="results-list"] h3').each do |li|
      #puts "#{li.all('a').first.text} by Capybara"
      puts "#{li.with_playwright_element_handle { |handle| handle.text_content }} by Playwright"
    end
  7. Configure Playwright browser launch parameters

    main

    When configuring the Capybara Playwright driver, you can pass a hash of options to control how the browser is launched. The driver filters these options against a set of allowed LAUNCH_PARAMS.

    Supported keys include:

    • args: Command line arguments for the browser.
    • channel: The browser channel to use (e.g., 'chrome', 'msedge').
    • chromiumSandbox: Boolean to enable/disable the Chromium sandbox.
    • devtools: Boolean to enable DevTools.
    • downloadsPath: Path where downloads should be saved.
    • env: Environment variables for the browser process.
    • executablePath: Path to a specific browser executable.
    • firefoxUserPrefs: Firefox-specific user preferences.
    • handleSIGHUP: Boolean to handle SIGHUP signals.
    • handleSIGINT: Boolean to handle SIGINT signals.
    • handleSIGTERM: Boolean to handle SIGTERM signals.
    • headless: Boolean to run the browser in headless mode.
    • ignoreDefaultArgs: Boolean to ignore default browser arguments.
    • proxy: Proxy configuration.
    • slowMo: Delay (in milliseconds) between actions to slow down execution.
    • tracesDir: Directory where Playwright traces should be saved.
    # Example of passing launch parameters (conceptually)
    Capybara.register_driver :playwright do |app| 
      # The driver uses these keys to configure the browser launch
      options = {
        headless: true,
        slowMo: 50,
        channel: 'chrome'
      }
      # ... driver initialization logic ...
    end
  8. Handle Selenium compatibility and whitespace differences

    main

    The Playwright driver uses innerText behavior for visible text, which may differ from Selenium's text algorithm regarding paragraph and rich-text-editor boundaries. If your assertions fail due to whitespace differences, use Capybara's normalize_ws: true option.

    expect(message).to have_text('Hello Regards', normalize_ws: true)
  9. Check element state with Node methods

    main

    The Capybara::Playwright::Node class provides several methods to query the state of an element using Playwright's evaluation capabilities. These methods are useful for assertions in your Capybara tests.

    • checked?: Returns true if the element is checked.
    • selected?: Returns true if the element is selected.
    • disabled?: Returns true if the element is disabled or if its parent/ancestor (like an optgroup, select, or fieldset) is disabled.
    • readonly?: Returns true if the element is not editable.
    • multiple?: Returns true if the element allows multiple selections.