FreeAgent makes use of the RSpec and ViewComponent frameworks for unit testing and reusable front-end components respectively.
Since FreeAgent is a Ruby on Rails application, we’ll often want to write unit tests for our Rails view templates, using RSpec, i.e., a view spec.
When rendering our reusable view components in our view templates, especially complex ones, testing can get a bit confusing, especially if the template is dependent on being rendered within the context of a view component.
E.g., suppose you want to write a view spec for _row.html.erb
, which is rendered in another view below.
<% # _table.html.erb %> <%= render TableComponent.new do |table| %> <% @employees.each do |employee| %> <% table.with_row do |row| %> <%= render "row", employee: employee, row: row %> <% end %> <% end %> <% end %> <% # _row.html.erb %> <% row.with_cell do %> <div data-testid="employee_1"> <p>Some content</p> </div> <% end %>
It turns out that in the view spec, you can include ViewComponent::TestHelpers
to get access to view component helpers, e.g., render_inline
which is useful for setting up a test case.
RSpec.describe "_row", type: :view do include ViewComponent::TestHelpers let(:employee) { build_stubbed(:employee) } subject do render_inline(Table::RowComponent.new(context: :tbody, position: 1)) do |row| render partial: "employees/_row", locals: { employee:, row: } end end it { is_expected.to have_content "Some content" } end
An extra tip: to avoid testing the wrapping components, scoping the tested content using an attribute like testid
can be helpful.
subject do row = render_inline(Table::RowComponent.new(context: :tbody, position: 1)) do |row| render partial: "employees/_row", locals: { employee:, row: } end row.find "[data-testid='employee_#{employee.id}']" end
So there you have it! Next time you’re trying to write view specs for your components, consider adding the TestHelpers
module.