Back to Repositories

Testing JavaScript Prompt Dialog Handling in Capybara

This test suite validates Capybara’s prompt handling functionality, focusing on the accept_prompt method. It ensures proper interaction with JavaScript prompt dialogs, including accepting prompts with and without custom responses.

Test Coverage Overview

The test suite comprehensively covers prompt dialog interactions in web applications using Capybara.

  • Basic prompt acceptance without messages
  • Handling default values in prompts
  • Custom response submissions
  • Special character handling in responses
  • Message matching validation
  • Error handling for mismatched messages

Implementation Analysis

The testing approach uses RSpec-style syntax with Capybara’s session-based testing pattern. The implementation leverages before hooks for setup and employs expectation matchers to verify prompt interactions and resulting DOM changes.

Key patterns include click-trigger-verify sequences and XPath-based result validation.

Technical Details

  • Framework: Capybara with RSpec
  • Test Scope: Modal dialog handling
  • Dependencies: JavaScript-enabled driver
  • Validation Method: XPath assertions
  • Setup Requirements: :modals capability

Best Practices Demonstrated

The test suite exemplifies robust modal testing practices through isolation of test cases and comprehensive edge case coverage.

  • Isolated test scenarios
  • Consistent setup and teardown
  • Clear expectation definitions
  • Error case handling
  • Special character testing

teamcapybara/capybara

lib/capybara/spec/session/accept_prompt_spec.rb

            
# frozen_string_literal: true

Capybara::SpecHelper.spec '#accept_prompt', requires: [:modals] do
  before do
    @session.visit('/with_js')
  end

  it 'should accept the prompt with no message' do
    @session.accept_prompt do
      @session.click_link('Open prompt')
    end
    expect(@session).to have_xpath("//a[@id='open-prompt' and @response='']")
  end

  it 'should accept the prompt with no message when there is a default' do
    @session.accept_prompt do
      @session.click_link('Open defaulted prompt')
    end
    expect(@session).to have_xpath("//a[@id='open-prompt-with-default' and @response='Default value!']")
  end

  it 'should return the message presented' do
    message = @session.accept_prompt do
      @session.click_link('Open prompt')
    end
    expect(message).to eq('Prompt opened')
  end

  it 'should accept the prompt with a response' do
    @session.accept_prompt with: 'the response' do
      @session.click_link('Open prompt')
    end
    expect(@session).to have_xpath("//a[@id='open-prompt' and @response='the response']")
  end

  it 'should accept the prompt with a response when there is a default' do
    @session.accept_prompt with: 'the response' do
      @session.click_link('Open defaulted prompt')
    end
    expect(@session).to have_xpath("//a[@id='open-prompt-with-default' and @response='the response']")
  end

  it 'should accept the prompt with a blank response when there is a default' do
    @session.accept_prompt with: '' do
      @session.click_link('Open defaulted prompt')
    end
    expect(@session).to have_xpath("//a[@id='open-prompt-with-default' and @response='']")
  end

  it 'should allow special characters in the reponse' do
    @session.accept_prompt with: '\'the\' \b "response"' do
      @session.click_link('Open prompt')
    end
    expect(@session).to have_xpath(%{//a[@id='open-prompt' and @response=concat("'the' ", '\\b "response"')]})
  end

  it 'should accept the prompt if the message matches' do
    @session.accept_prompt 'Prompt opened', with: 'matched' do
      @session.click_link('Open prompt')
    end
    expect(@session).to have_xpath("//a[@id='open-prompt' and @response='matched']")
  end

  it "should not accept the prompt if the message doesn't match" do
    expect do
      @session.accept_prompt 'Incorrect Text', with: 'not matched' do
        @session.click_link('Open prompt')
      end
    end.to raise_error(Capybara::ModalNotFound)
  end

  it 'should return the message presented' do
    message = @session.accept_prompt with: 'the response' do
      @session.click_link('Open prompt')
    end
    expect(message).to eq('Prompt opened')
  end
end