Search code examples
ruby-on-railstestingcapybaraminitest

Check if all (hidden) elements contain a string with Minitest/Capybara


I have a list of elements on a page (cards with comic books) and I want to test if all elements have the title containing a string (let's say "spiderman").

<%= @comics.each do |comic| %>
  <div class="comic-card-text-box">
    <p class="comic-card-title"><%= comic.title %></p>
  </div>
<% end %>

Using Minitest/Capybara/Rails 7, I'm trying to do something like this:

test "displays search results" do
    login_as users(:user1)
    visit root_path

    fill_in "Search...", with: "spiderman"

    assert_selector ".comic-card-title" do |element|
      assert_match element, /spiderman/
    end
  end

And that's the failure I get:

expected to find visible css ".comic-card-title" but there were no matches. Also found "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", which matched the selector but not all filters.

I have 2 issues there that I'm confused about.

  1. I am trying to check if an element contains a substring. What if this element is hidden on the page (only by hovering it will appear)?

  2. How to iterate between these elements to check if all of them have the substring?


Solution

  • Your elements aren't matching either visibility or the filter proc you're passing to assert_selector (don't use assert_match with Capybara elements). If that's because the elements need to be hovered over then you should really just hover over them. Also assert_selector just validates that at least one of the elements will match, not that all of them will. From your questions I'm assuming the comic-card-text-box element is visible on the page (takes up some space) and that the comic-card-title element only becomes visible when you hover over the comic-card-text-box element. If that's the case then you'd want to do something like

    cards = all('.comic-card-text-box', minimum: 1) # specifying count: <expected count> rather than minimum would be better
    cards.each do |card|
      card.hover
      assert_css(card, '.comic-card-title', text: 'spiderman')
    end
    

    If my assumptions about what exactly you're trying to do, and your sites behavior are wrong please clarify in your question.