You don't always need a custom matcher to write clean RSpec tests

Updated . Posted . Visible to the public.

When you repeat complex assertions in your tests multiple times, it might be a good idea to extract a custom RSpec matcher. This not only tidies up your own code, but also makes it easier to write future specs.

However, not all situations are well-suited for that. Sometimes the effort isn't worth it, e.g. when your matcher would need too many parameters to be reusable. In those cases, you can also simply extract a private method:

describe `/search` do
  it "doesn't lose the infinite scroll's filter state when navigating backwards" do
    create(:event, :published, name: '1st match', start_date: 1.week.from_now)
    create(:event, :published, name: '2nd match', start_date: 1.week.from_now)
    create(:event, :published, name: 'Discarded', start_date: 2.years.from_now)

    visit(search_path(start_date: 'next_3_months'))

    expect_item_card_to_contain('1st match')
    expect_infinite_scroll_to_be_filtered

    within('.layout--infinite-scroll') do
      click_link('2nd match')
    end

    expect_item_card_to_contain('2nd match')
    expect_infinite_scroll_to_be_filtered

    within('.layout--infinite-scroll') do
      click_link('1st match')
    end

    expect_item_card_to_contain('1st match')
    expect_infinite_scroll_to_be_filtered

    page.go_back

    expect_item_card_to_contain('2nd match')
    expect_infinite_scroll_to_be_filtered

    page.go_back

    expect_item_card_to_contain('1st match')
    expect_infinite_scroll_to_be_filtered
  end

  private

  def expect_infinite_scroll_to_be_filtered
    within('.layout--infinite-scroll') do
      expect(page).to have_text('1st match')
      expect(page).to have_text('2nd match')
      expect(page).not_to have_text('Discarded')
    end
  end

  def expect_item_card_to_contain(text)
    within('.layout--item-card') do
      expect(page).to have_text(text)
    end
  end
end

See also

Klaus Weidinger
Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Klaus Weidinger to makandra dev (2025-07-10 08:58)