Back to Repositories

Testing Link Detection and Validation Workflows in Capybara

This test suite validates Capybara’s link detection capabilities through the #has_link? and #has_no_link? methods. It ensures proper functionality for finding and verifying HTML links with various attributes and states.

Test Coverage Overview

The test suite provides comprehensive coverage of link detection scenarios in web pages.

Key areas tested include:
  • Basic link text matching
  • href attribute validation
  • Target attribute verification
  • Link focus state testing
  • Negative testing scenarios

Implementation Analysis

The implementation uses RSpec-style expectations to verify link presence and attributes. The testing approach employs both positive and negative assertions to ensure robust link detection, with particular attention to edge cases and attribute matching patterns.

Key patterns include:
  • Before block setup for consistent test environment
  • Regular expression matching for href attributes
  • Focus state validation
  • Invalid option handling

Technical Details

Testing tools and configuration:
  • Capybara test framework
  • RSpec expectation syntax
  • Custom SpecHelper implementation
  • Active element support for focus testing
  • Mock warning handling for invalid locators

Best Practices Demonstrated

The test suite exemplifies several testing best practices including isolated test cases, clear test descriptions, and comprehensive edge case coverage.

Notable practices:
  • Consistent test structure
  • Explicit error validation
  • Feature-specific context blocks
  • Comprehensive attribute testing
  • Clear separation of positive and negative test cases

teamcapybara/capybara

lib/capybara/spec/session/has_link_spec.rb

            
# frozen_string_literal: true

Capybara::SpecHelper.spec '#has_link?' do
  before do
    @session.visit('/with_html')
  end

  it 'should be true if the given link is on the page' do
    expect(@session).to have_link('foo')
    expect(@session).to have_link('awesome title')
    expect(@session).to have_link('A link', href: '/with_simple_html')
    expect(@session).to have_link(:'A link', href: :'/with_simple_html')
    expect(@session).to have_link('A link', href: %r{/with_simple_html})
    expect(@session).to have_link('labore', target: '_self')
  end

  it 'should be false if the given link is not on the page' do
    expect(@session).not_to have_link('monkey')
    expect(@session).not_to have_link('A link', href: '/nonexistent-href')
    expect(@session).not_to have_link('A link', href: /nonexistent/)
    expect(@session).not_to have_link('labore', target: '_blank')
  end

  it 'should notify if an invalid locator is specified' do
    allow(Capybara::Helpers).to receive(:warn).and_return(nil)
    @session.has_link?(@session)
    expect(Capybara::Helpers).to have_received(:warn).with(/Called from: .+/)
  end

  context 'with focused:', requires: [:active_element] do
    it 'should be true if the given link is on the page and has focus' do
      @session.send_keys(:tab)

      expect(@session).to have_link('labore', focused: true)
    end

    it 'should be false if the given link is on the page and does not have focus' do
      expect(@session).to have_link('labore', focused: false)
    end
  end

  it 'should raise an error if an invalid option is passed' do
    expect do
      expect(@session).to have_link('labore', invalid: true)
    end.to raise_error(ArgumentError, 'Invalid option(s) :invalid, should be one of :above, :below, :left_of, :right_of, :near, :count, :minimum, :maximum, :between, :text, :id, :class, :style, :visible, :obscured, :exact, :exact_text, :normalize_ws, :match, :wait, :filter_set, :focused, :href, :alt, :title, :target, :download')
  end
end

Capybara::SpecHelper.spec '#has_no_link?' do
  before do
    @session.visit('/with_html')
  end

  it 'should be false if the given link is on the page' do
    expect(@session).not_to have_no_link('foo')
    expect(@session).not_to have_no_link('awesome title')
    expect(@session).not_to have_no_link('A link', href: '/with_simple_html')
    expect(@session).not_to have_no_link('labore', target: '_self')
  end

  it 'should be true if the given link is not on the page' do
    expect(@session).to have_no_link('monkey')
    expect(@session).to have_no_link('A link', href: '/nonexistent-href')
    expect(@session).to have_no_link('A link', href: %r{/nonexistent-href})
    expect(@session).to have_no_link('labore', target: '_blank')
  end

  context 'with focused:', requires: [:active_element] do
    it 'should be true if the given link is on the page and has focus' do
      expect(@session).to have_no_link('labore', focused: true)
    end

    it 'should be false if the given link is on the page and does not have focus' do
      @session.send_keys(:tab)

      expect(@session).to have_no_link('labore', focused: false)
    end
  end
end