Skip to content

Testing your ActiveAdmin controllers with RSpec

Lan edited this page Jul 23, 2020 · 9 revisions

The old content of this page was moved to Testing ActiveAdmin within another gem using RSpec and Combustion

The model

app/models/person.rb

class Person < ApplicationRecord
  validates :first_name, presence: true
end

The admin

app/admin/persons.rb

ActiveAdmin.register Person do

  filter :first_name_or_last_name_cont, label: 'Name'
  filter :email

  index do
    selectable_column
    column :first_name
    column :last_name
    column :email
    actions
  end

  show do
    attributes_table do
      row :first_name
      row :last_name
      row :email
    end
  end

  permit_params :first_name,
                :last_name,
                :email

  form do |f|
    f.semantic_errors *f.object.errors.keys
    f.inputs do
      f.input :first_name
      f.input :last_name
      f.input :email
    end
    f.actions
  end

end

The Controller Tests

You can find your controller classname by running this method call in a console (replacing :admin with the namespace you're using):

ActiveAdmin.application.namespaces[:admin].resources.map(&:c‌​ontroller)

Assuming you use the following gems:

  • rspec
  • capybara
  • shoulda-matchers
  • fabrication

spec/controllers/admin/persons_controller_spec.rb

require 'rails_helper'

RSpec.describe Admin::PersonsController, type: :controller do

  # this lets us inspect the rendered results
  render_views

  let(:page) { Capybara::Node::Simple.new(response.body) } 
  let(:user) { Fabricate :user } 
  before { sign_in user } # if `sign_in` method not exists, please check this document https://github.com/heartcombo/devise#controller-tests.

  let!(:person) { Fabricate :person }

  let(:valid_attributes) do
    Fabricate.attributes_for :person
  end

  let(:invalid_attributes) do
    { first_name: '' }
  end

  describe "GET index" do
    it 'returns http success' do
      get :index
      expect(response).to have_http_status(:success)
    end
    it 'assigns the person' do
      get :index
      expect(assigns(:persons)).to include(person)
    end
    it "should render the expected columns" do
      get :index
      expect(page).to have_content(person.first_name)
      expect(page).to have_content(person.last_name)
      expect(page).to have_content(person.email)
    end
    let(:filters_sidebar) { page.find('#filters_sidebar_section') }
    it "filter Name exists" do
      get :index
      expect(filters_sidebar).to have_css('label[for="q_first_name_or_last_name_cont"]', text: 'Name')
      expect(filters_sidebar).to have_css('input[name="q[first_name_or_last_name_cont]"]')
    end
    it "filter Name works" do
      matching_person = Fabricate :person, first_name: 'ABCDEFG'
      non_matching_person = Fabricate :person, first_name: 'HIJKLMN'

      get :index, params: { q: { first_name_or_last_name_cont: 'BCDEF' } }

      expect(assigns(:persons)).to include(matching_person)
      expect(assigns(:persons)).not_to include(non_matching_person)
    end
  end

  describe "GET new" do
    it 'returns http success' do
      get :new
      expect(response).to have_http_status(:success)
    end
    it 'assigns the person' do
      get :new
      expect(assigns(:person)).to be_a_new(Person)
    end
    it "should render the form elements" do
      get :new
      expect(page).to have_field('First name')
      expect(page).to have_field('Last name')
      expect(page).to have_field('Email')
    end
  end

  describe "POST create" do
    context "with valid params" do
      it "creates a new Person" do
        expect {
          post :create, params: { person: valid_attributes }
        }.to change(Person, :count).by(1)
      end

      it "assigns a newly created person as @person" do
        post :create, params: { person: valid_attributes }
        expect(assigns(:person)).to be_a(Person)
        expect(assigns(:person)).to be_persisted
      end

      it "redirects to the created person" do
        post :create, params: { person: valid_attributes }
        expect(response).to have_http_status(:redirect)
        expect(response).to redirect_to(admin_person_path(Person.last))
      end

      it 'should create the person' do
        post :create, params: { person: valid_attributes }
        person = Person.last

        expect(person.first_name).to eq(valid_attributes[:first_name])
        expect(person.last_name).to  eq(valid_attributes[:last_name])
        expect(person.email).to      eq(valid_attributes[:email])
      end
    end

    context "with invalid params" do
      it 'invalid_attributes return http success' do
        post :create, params: { person: invalid_attributes }
        expect(response).to have_http_status(:success)
      end

      it "assigns a newly created but unsaved person as @person" do
        post :create, params: { person: invalid_attributes }
        expect(assigns(:person)).to be_a_new(Person)
      end

      it 'invalid_attributes do not create a Person' do
        expect do
          post :create, params: { person: invalid_attributes }
        end.not_to change(Person, :count)
      end
    end
  end

  describe "GET edit" do
    before do
      get :edit, params: { id: person.id }
    end
    it 'returns http success' do
      expect(response).to have_http_status(:success)
    end
    it 'assigns the person' do
      expect(assigns(:person)).to eq(person)
    end
    it "should render the form elements" do
      expect(page).to have_field('First name', with: person.first_name)
      expect(page).to have_field('Last name', with: person.last_name)
      expect(page).to have_field('Email', with: person.email)
    end
  end

  describe "PUT update" do
    context 'with valid params' do
      before do
        put :update, params: { id: person.id, person: valid_attributes }
      end
      it 'assigns the person' do
        expect(assigns(:person)).to eq(person)
      end
      it 'returns http redirect' do
        expect(response).to have_http_status(:redirect)
        expect(response).to redirect_to(admin_person_path(person))
      end
      it "should update the person" do
        person.reload

        expect(person.last_name).to  eq(valid_attributes[:last_name])
        expect(person.first_name).to eq(valid_attributes[:first_name])
        expect(person.email).to      eq(valid_attributes[:email])
      end
    end
    context 'with invalid params' do
      it 'returns http success' do
        put :update, params: { id: person.id, person: invalid_attributes }
        expect(response).to have_http_status(:success)
      end
      it 'does not change person' do
        expect do
          put :update, params: { id: person.id, person: invalid_attributes }
        end.not_to change { person.reload.first_name }
      end
    end
  end

  describe "GET show" do
    before do
      get :show, params: { id: person.id }
    end
    it 'returns http success' do
      expect(response).to have_http_status(:success)
    end
    it 'assigns the person' do
      expect(assigns(:person)).to eq(person)
    end
    it "should render the form elements" do
      expect(page).to have_content(person.last_name)
      expect(page).to have_content(person.first_name)
      expect(page).to have_content(person.email)
    end
  end

  describe "DELETE #destroy" do
    it "destroys the requested select_option" do
      expect {
        delete :destroy, params: { id: person.id }
      }.to change(Person, :count).by(-1)
    end

    it "redirects to the field" do
      delete :destroy, params: { id: person.id }
      expect(response).to redirect_to(admin_persons_path)
    end
  end

end
Clone this wiki locally