Hello,
How can i test policy scope with rspect? Can anyone have a tutorial or documentation?
Thanks
You can try something like that, but a Matcher will be better...
require 'spec_helper'
describe ConsultationPolicy, focused: true do
let(:consultation) { create :consultation }
context 'scope' do
context 'admin' do
let(:admin) { create :admin }
specify do
expect(
ConsultationPolicy::Scope.new(admin, Consultation).resolve.to_sql
).to eq("SELECT \"consultations\".* FROM \"consultations\" ")
end
end
context 'patient' do
let(:patient) { create :patient }
specify do
expect(
ConsultationPolicy::Scope.new(patient, Consultation).resolve.to_sql
).to eq("SELECT \"consultations\".* FROM \"consultations\" WHERE \"consultations\".\"patient_id\" = #{patient.id}")
end
end
end
end
@joel I wouldn't do that. Testing the generated SQL is super brittle. Just run the query against the DB and see what you get.
Ok, i will try in this way, testing the output.
Thanks joel an jnicklas :).
@jnicklas Yes i'm pretty agree with that and it's strongly coupled to your type of backend, Yes another way is to load one set of data and check what you get.
Here is an example of how I test policy scope:
describe UserPolicy do
describe ".scope" do
before { create_list(:user, 2) } # factory_girl is used here to create test data
it "contains all" do
expect(Pundit.policy_scope(current_user, User.all)).to match_array User.all
end
end
end
Just use change User.all to whatever you need.
Since policies are designed to check which records the user has permission to access, I find a readable solution is to test for individual records included in the output. Here's an example of how I might test that the user can only see posts belonging to them:
let(:current_user) { FactoryGirl.create(:user) }
let(:another_user) { FactoryGirl.create(:user) }
let(:current_users_post) { FactoryGirl.create(:post, user: current_user) }
let(:another_users_post) { FactoryGirl.create(:post, user: another_user) }
it "returns posts in scope that belong to the current user" do
expect(PostPolicy::Scope.new(current_user, Post.all).resolve).to include(current_users_post)
end
it "does not return posts in scope that do not belong to the current user" do
expect(PostPolicy::Scope.new(current_user, Post.all).resolve).not_to include(another_users_post)
end
It may be worth linking to the popular snippet above ( https://github.com/elabs/pundit/issues/123#issuecomment-51412664 ) from #333 -- I would do it but it's locked, so needs to be someone with permissions.
Most helpful comment
Since policies are designed to check which records the user has permission to access, I find a readable solution is to test for individual records included in the output. Here's an example of how I might test that the user can only see posts belonging to them: