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.