Skip to content

Instantly share code, notes, and snippets.

@aamax
Created June 12, 2015 21:38
Show Gist options
  • Save aamax/e769e2d9764fa8e3091f to your computer and use it in GitHub Desktop.
Save aamax/e769e2d9764fa8e3091f to your computer and use it in GitHub Desktop.
class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery with: :exception
protect_from_forgery with: :null_session, :if => Proc.new { |c| c.request.format == 'application/json'}
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
private
def user_not_authorized
flash[:alert] = "You are not authorized to perform this action."
redirect_to(request.referrer || root_path)
end
end
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
raise Pundit::NotAuthorizedError, "must be logged in" unless user
@user = user
@record = record
end
def index?
false
end
def show?
scope.where(:id => record.id).exists?
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
def scope
Pundit.policy_scope!(user, record.class)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope
end
end
end
class PolicyTest < ActiveSupport::TestCase
def assert_permissions(a_user, record, available_actions, permissions_hash = {})
permissions_hash.each do |action, should_be_permitted|
if should_be_permitted
assert_permit a_user, record, action
else
refute_permit a_user, record, action
end
end
# Make sure all available actions were tested
unused_actions = @available_actions - permissions_hash.keys
assert unused_actions.empty?, "The following actions were not tested: #{ unused_actions }"
# Make sure tested actions were in available_actions
unavailable_actions = permissions_hash.keys - @available_actions
assert unavailable_actions.empty?, "The following actions were tested, but not in available_actions: #{ unavailable_actions }"
end
def assert_permit(a_user, record, action)
assert(permit(a_user, record, action), "User #{ a_user.inspect } should be permitted #{ action } on #{ record.inspect }, but isn't permitted")
end
def refute_permit(a_user, record, action)
refute(permit(a_user, record, action), "User #{ a_user.inspect } should NOT be permitted #{ action } on #{ record.inspect }, but is permitted")
end
def permit(a_user, record, action)
self.class.to_s.gsub(/Test/, "").constantize.new(a_user, record).public_send("#{ action.to_s }?")
end
end
I'm trying to test the controller - to make sure that a logged in user who is not an admin user, cannot look at another users show page, and that they can look at their own.
I'm beginning to suspect that this testing is really only relevant inside the policy tests and that I have to assume that the controllers are following the policies as described.
The system uses:
Rails 4.2.1
Minitest
Devise
Pundit
Rolify
Is what I'm trying to do outside the scope of a functional (controller) test? Would it be more realistic to do this as an integration test or an acceptance test or is there a way to get it done here?
Thanks in advance
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/autorun'
# require "minitest/rails"
# require 'minitest/mock'
# require "minitest/rails/capybara"
# require 'minitest/rails'
require 'minitest/reporters'
reporter_options = {color: true }
Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(reporter_options)]
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Add more helper methods to be used by all tests here...
end
class UserPolicy < ApplicationPolicy
attr_reader :user, :record
def show?
@user.has_role?(:admin) || @record == @user
end
end
class UsersController < ApplicationController
before_action :authenticate_user!
# GET /users/1
# GET /users/1.json
def show
set_user
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:email)
end
end
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
include Devise::TestHelpers
def setup
DatabaseCleaner.start
end
def teardown
DatabaseCleaner.clean
end
before do
@work_user = FactoryGirl.create(:user)
@work_user.add_role :user
@other_user = FactoryGirl.create(:user)
@other_user.add_role :user
@admin_user = FactoryGirl.create(:user)
@admin_user.add_role :admin
end
describe 'when user not logged in' do
it 'must not show user data' do
get :show, id: @work_user
response.status.must_equal 302
assert_redirected_to "/users/sign_in"
end
it 'must not index user data' do
get :index
response.status.must_equal 302
assert_redirected_to "/users/sign_in"
end
it 'must not new user data' do
get :new
response.status.must_equal 302
assert_redirected_to "/users/sign_in"
end
it 'must not edit user data' do
get :edit, id: @work_user
response.status.must_equal 302
assert_redirected_to "/users/sign_in"
end
it 'must not index user data' do
delete :destroy, id: @work_user
response.status.must_equal 302
assert_redirected_to "/users/sign_in"
end
end
describe "when basic user logged in" do
def setup
@request.env["devise.mapping"] = Devise.mappings[:admin]
sign_in @work_user
end
it 'must show current user data' do
get(:show, {id: @work_user})
response.status.must_equal 200
end
it 'must NOT show other user data' do
get(:show, {id: @other_user})
# !!!! TEST FAILING!!!! this returns 200 status and it shouldn't... it should raise and exception for unauthorized
response.status.must_equal 302
# TODO check flash message
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment