Search code examples
capybarafactory-botrspec-railsruby-on-rails-5.2

"Ambiguous match, found 2 elements matching visible link" issue


I've looked through a few posts with the same issue, but still feel like mine is a bit different.

viewing_categories_spec.rb

require 'rails_helper'

RSpec.feature 'Users can view categories' do
    scenario 'with the category details' do
        category = FactoryBot.create(:category, name: 'Real Estate')

        visit '/categories'
        click_link('Real Estate')
        expect(page.current_url).to eq category_url(category)
    end
end

category_factory.rb

FactoryBot.define do
    factory :category do
      name {"Computers"}
    end
end

when I run rspec, I'm getting an error:

Failures:

1) Users can view categories with the category details Failure/Error: click_link('Real Estate')

 Capybara::Ambiguous:
   Ambiguous match, found 2 elements matching visible link "Real Estate"
 # ./spec/features/viewing_categories_spec.rb:8:in `block (2 levels) in <main>'

Then I've modified spec by adding match: :first:

require 'rails_helper'

RSpec.feature 'Users can view categories' do
    scenario 'with the category details' do
        category = FactoryBot.create(:category, name: 'Real Estate')

        visit '/categories'
        click_link('Real Estate', match: :first)
        expect(page.current_url).to eq category_url(category)
    end
end

This time I got error:

Failures:

  1) Users can view categories with the category details
     Failure/Error: expect(page.current_url).to eq category_url(category)

       expected: "http://www.example.com/categories/265"
            got: "http://www.example.com/categories/17"

       (compared using ==)
     # ./spec/features/viewing_categories_spec.rb:9:in `block (2 levels) in <main>'

I noticed that sometimes, I'm not seeing the error and sometimes it shown up.

The only thing I see always is "http://www.example.com/categories/17". This part remains same always when I run rspec command.

The full source code is here https://github.com/tenzan/kaganat


Solution

  • The fact that the "http://www.example.com/categories/17" url is constant and that Capybara is seeing two "Real Estate" links on the page when your test appears to only create one leads me to believe that you have some old data left in your test database. By opting to use match: :first you've just covered up the fact that you have more records existing than you expect and that error should have been your first clue (along with just looking at a screenshot of the test running). Something like

    rails db:reset RAILS_ENV=test
    

    will clear out your test database and ensure you don't have old data hanging around. You'll also want to go back to your original click_link('Real Estate') without the :match setting. Additionally, if you want stable tests, you should almost never by using the standard RSpec matchers ('eq', etc) with Capybara returned objects since page load/behavior is an asynchronous thing. Instead you should should the matchers provided by Capybara. In your current example that means instead of writing expect(page.current_url).to eq category_url(category) you should be writing expect(page).to have_current_path(category_url(category))