Reputation: 4783
I'm wondering if there are better ways to write controller request specs than how I currently do it. I'm using the devise gem for authentication. This is how I'd test an admin controller:
describe "#index" do
context "when not logged in" do
it "redirects to root page" do
get admin_index_path
expect(response).to redirect_to root_path
end
end
context "when logged in as an user" do
before { sign_in user }
it "redirects to root page" do
get admin_index_path
expect(response).to redirect_to root_path
end
end
context "when logged in as an admin" do
before { sign_in admin }
it "opens the page" do
get admin_index_path
expect(response).to be_success
end
end
end
As you can see there is some "boilerplate" code which repeats over many of my controllers. For controllers which require a user to be logged in, I'd had to write a "not logged in" spec for every controller action. How do you do this? Is there a way to maybe shorten/share the code between the specs? The only thing that changes is the path.
Upvotes: 1
Views: 946
Reputation: 4783
Ok, I came up with this solution. Please let me know if you have any better ideas.
shared_examples "requires user login" do |path|
context "when not logged in" do
it "redirects to root path" do
get public_send(path)
expect(response).to redirect_to root_path
end
end
context "as an user" do
it "redirects to root path" do
sign_in create(:user)
get public_send(path)
expect(response).to redirect_to root_path
end
end
end
shared_examples "requires admin login" do |path|
context "as an user" do
it "redirects to root path" do
sign_in create(:user)
get public_send(path)
expect(response).to redirect_to root_path
end
end
context "as an admin" do
it "gets 200" do
sign_in create(:admin)
get public_send(path)
expect(response).to be_success
end
end
end
To use them:
it_behaves_like "requires user login", "admin_index_path"
or
it_behaves_like "requires admin login", "admin_index_path"
Upvotes: 0
Reputation: 15985
@Linus here is refactored version of your answer
shared_examples "requires login" do |path, user_type|
context "when not logged in" do
it "redirects to root path" do
get public_send("#{path}_path")
expect(response).to redirect_to root_path
end
end
context "as an #{user_type}" do
it "redirects to root path" do
sign_in create(user_type)
get public_send("#{path}_path")
expect(response).to redirect_to root_path
end
end
end
And use it like
it_behaves_like "requires login", "admin_index", :user
for user
it_behaves_like "requires login", "admin_index", :admin
for admin
Upvotes: 4