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.

See also: Testing your ActiveAdmin controllers with RSpec

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.