Dynamically Generate Controller Specs for ActiveAdmin
I use ActiveAdmin (and the arctic_admin theme) to build DocSpring’s internal admin dashboard:
ActiveAdmin has a few quirks and bugs, but I enjoy working with it overall. Some other popular admin frameworks for Rails are Administrate and RailsAdmin.
Whichever framework you’re using, it’s a good idea to write some tests. It’s always frustrating when something crashes, especially when you’re trying to help a customer.
Just like ActiveAdmin automatically generates an admin UI for your models, we can automatically generate some RSpec tests for ActiveAdmin. I use the following code to iterate over ActiveAdmin resources, create models using any FactoryBot factories, and ensure that I can visit the index
and show
routes without crashing:
# frozen_string_literal: true
ActiveAdmin.application.namespaces[:admin].resources.each do |resource|
resource_name = resource.resource_name
resource_title = resource_name.human.titleize
has_factory = FactoryBot.factories.any? do |factory|
factory.name.to_s == resource_name.singular
end
RSpec.describe resource.controller, type: :controller do
let!(:user) { create(:user, :admin) }
let(:page) { Capybara::Node::Simple.new(response.body) }
let!(:model) do
create(resource_name.singular) if has_factory
end
render_views
before(:each) { sign_in user }
it 'renders the index page' do
get :index
expect(page).to have_content(resource_title)
if model
show_path = send("admin_#{resource_name.singular}_path", model)
expect(page).to have_link(model.id, href: show_path)
end
end
if has_factory
it 'renders the show page' do
get :show, params: { id: model.to_param }
expect(page).to have_content("#{resource_title} Details")
expect(page).to have_content(model.name) if model.respond_to?(:name)
end
end
end
end
If you use ActiveAdmin and FactoryBot, you can save this code to spec/controllers/admin/autogenerated_controller_specs.rb
. These specs should pass for most Rails apps, but you might need to make a few changes. If you’ve heavily customized some forms or controller actions, then it might be a good idea to write some tests for those.
While I was working on this, I discovered that some of my FactoryBot factories were crashing, because I had never used them without arguments. I set up a factory_bot:lint
Rake task to make sure that all of my factories can create valid models. I’ve started running this task during my CI build.