Back to Repositories

Testing Asynchronous Script Evaluation in Capybara

This test suite validates Capybara’s evaluate_async_script functionality, focusing on asynchronous JavaScript execution in web applications. The tests verify script evaluation, parameter passing, and element handling in async operations.

Test Coverage Overview

The test suite comprehensively covers the evaluate_async_script method in Capybara, examining core async JavaScript functionality.

  • Basic script evaluation and return value handling
  • Complex parameter passing including DOM elements
  • Asynchronous operations with element return values
  • Integration with JavaScript-enabled sessions

Implementation Analysis

The testing approach utilizes Capybara’s session-based testing pattern with RSpec syntax. Tests demonstrate handling of async JavaScript execution through callback patterns and timeout management.

  • Session-based test organization
  • Async JavaScript callback handling
  • Element selector and manipulation testing
  • Timeout and state management verification

Technical Details

  • RSpec testing framework integration
  • Capybara JavaScript driver requirements
  • DOM element selection and manipulation
  • Async execution timing controls
  • Element state verification methods

Best Practices Demonstrated

The test suite exemplifies robust async testing practices with clear separation of concerns and thorough state verification.

  • Explicit wait handling for async operations
  • Proper element presence verification
  • Clear test case isolation
  • Comprehensive error scenarios coverage

teamcapybara/capybara

lib/capybara/spec/session/evaluate_async_script_spec.rb

            
# frozen_string_literal: true

Capybara::SpecHelper.spec '#evaluate_async_script', requires: [:js] do
  it 'should evaluate the given script and return whatever it produces' do
    @session.visit('/with_js')
    expect(@session.evaluate_async_script('arguments[0](4)')).to eq(4)
  end

  it 'should support passing elements as arguments to the script', requires: %i[js es_args] do
    @session.visit('/with_js')
    el = @session.find(:css, '#drag p')
    result = @session.evaluate_async_script('arguments[2]([arguments[0].innerText, arguments[1]])', el, 'Doodle Funk')
    expect(result).to eq ['This is a draggable element.', 'Doodle Funk']
  end

  it 'should support returning elements after asynchronous operation', requires: %i[js es_args] do
    @session.visit('/with_js')
    @session.find(:css, '#change') # ensure page has loaded and element is available
    el = @session.evaluate_async_script("var cb = arguments[0]; setTimeout(function(){ cb(document.getElementById('change')) }, 100)")
    expect(el).to be_instance_of(Capybara::Node::Element)
    expect(el).to eq(@session.find(:css, '#change'))
  end
end