From a5b2dcaadf53871c811cb57915d976912e85fece Mon Sep 17 00:00:00 2001 From: Aaric Pittman Date: Fri, 1 Sep 2023 18:22:38 -0500 Subject: [PATCH] refactor: BulletTrain::LoadsAndAuthorizesResource#load_team and add tests --- .../loads_and_authorizes_resource.rb | 20 +++-- .../loads_and_authorizes_resource_test.rb | 78 +++++++++++++++++-- .../loads_and_authorizes_resource_test.rb | 2 +- .../test/test_helper.rb | 2 + 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/bullet_train-super_load_and_authorize_resource/app/controllers/concerns/bullet_train/loads_and_authorizes_resource.rb b/bullet_train-super_load_and_authorize_resource/app/controllers/concerns/bullet_train/loads_and_authorizes_resource.rb index 8b9477562..c2d9a2d1e 100644 --- a/bullet_train-super_load_and_authorize_resource/app/controllers/concerns/bullet_train/loads_and_authorizes_resource.rb +++ b/bullet_train-super_load_and_authorize_resource/app/controllers/concerns/bullet_train/loads_and_authorizes_resource.rb @@ -7,10 +7,12 @@ def model_namespace_from_controller_namespace name .gsub(regex_to_remove_controller_namespace || //, "") .split("::") - .slice(0...-1) # drops actual class name + .tap(&:pop) # drops actual class name end def regex_to_remove_controller_namespace + return super if defined?(super) + raise "This is a template method that needs to be implemented by controllers including LoadsAndAuthorizesResource." end @@ -202,17 +204,13 @@ def account_load_and_authorize_resource(model, options, old_options = {}) end def load_team - # Not all objects that need to be authorized belong to a team, - # so we give @team a nil value if no association is found. - begin - # Sometimes `@team` has already been populated by earlier `before_action` steps. - @team ||= @child_object&.team || @parent_object&.team - rescue NoMethodError - @team = nil - end + @team ||= @child_object&.try(:team) || @parent_object&.try(:team) - # Update current attributes. - Current.team = @team + return unless @team + + if defined?(Current) && Current.respond_to?(:team=) + Current.team = @team + end # If the currently loaded team is saved to the database, make that the user's new current team. if @team.try(:persisted?) diff --git a/bullet_train-super_load_and_authorize_resource/test/controllers/concerns/bullet_train/loads_and_authorizes_resource_test.rb b/bullet_train-super_load_and_authorize_resource/test/controllers/concerns/bullet_train/loads_and_authorizes_resource_test.rb index 47106c411..bae4a3cad 100644 --- a/bullet_train-super_load_and_authorize_resource/test/controllers/concerns/bullet_train/loads_and_authorizes_resource_test.rb +++ b/bullet_train-super_load_and_authorize_resource/test/controllers/concerns/bullet_train/loads_and_authorizes_resource_test.rb @@ -1,15 +1,20 @@ require "test_helper" class BulletTrain::LoadsAndAuthorizeResourceTest < ActiveSupport::TestCase - class TestClass + class TestControllerClass < ActionController::Base include BulletTrain::LoadsAndAuthorizesResource + attr_accessor :child_object, :current_user, :parent_object, :team + def self.regex_to_remove_controller_namespace end + + def can?(*args) + end end module Users - class TestClass + class TestControllerClass < ActionController::Base include BulletTrain::LoadsAndAuthorizesResource def self.regex_to_remove_controller_namespace @@ -19,19 +24,78 @@ def self.regex_to_remove_controller_namespace end test "model_namespace_from_controller_namespace returns an array of modules names based on the classes namespace minus regex_to_remove_controller_namespace" do - assert_equal ["BulletTrain", "LoadsAndAuthorizeResourceTest"], TestClass.model_namespace_from_controller_namespace - assert_equal ["Users"], Users::TestClass.model_namespace_from_controller_namespace + assert_equal ["BulletTrain", "LoadsAndAuthorizeResourceTest"], TestControllerClass.model_namespace_from_controller_namespace + assert_equal ["Users"], Users::TestControllerClass.model_namespace_from_controller_namespace end test "it defines .account_load_and_authorize_resource" do - assert TestClass.respond_to?(:account_load_and_authorize_resource) + assert_respond_to TestControllerClass, :account_load_and_authorize_resource end test "it defines .regex_to_remove_controller_namespace" do - assert TestClass.respond_to?(:regex_to_remove_controller_namespace) + assert_respond_to TestControllerClass, :regex_to_remove_controller_namespace end test "it defines #load_team" do - assert TestClass.new.respond_to?(:load_team) + assert_respond_to TestControllerClass.new, :load_team + end + + test "#load_team does not set @team if child_object and parent_object are nil" do + subject = TestControllerClass.new + subject.child_object = nil + subject.parent_object = nil + + assert_nil subject.instance_variable_get(:@team) + end + + test "#load_team sets @team" do + team = OpenStruct.new + subject = TestControllerClass.new + subject.child_object = OpenStruct.new(team: team) + + subject.load_team + + assert_equal team, subject.instance_variable_get(:@team) + end + + test "#load_team sets Current attributes if defined" do + unless defined?(::Current) + temp_current_class = Class.new(ActiveSupport::CurrentAttributes) do + attribute :team + end + Object.const_set(:Current, temp_current_class) + end + + team = OpenStruct.new + subject = TestControllerClass.new + subject.child_object = OpenStruct.new(team: team) + + team.stub(:try, nil) do + subject.load_team + end + + assert_equal team, Current.team + + if temp_current_class + Object.send(:remove_const, :Current) + end + end + + test "#load_team updates current_user's current_team if persisted and can" do + current_user = Minitest::Mock.new + team = OpenStruct.new(id: 1) + subject = TestControllerClass.new + subject.child_object = OpenStruct.new(team: team) + subject.current_user = current_user + + current_user.expect(:update_column, nil, [:current_team_id, team.id]) + + team.stub(:try, true) do + subject.stub(:can?, true) do + subject.load_team + end + end + + current_user.verify end end diff --git a/bullet_train-super_load_and_authorize_resource/test/controllers/concerns/loads_and_authorizes_resource_test.rb b/bullet_train-super_load_and_authorize_resource/test/controllers/concerns/loads_and_authorizes_resource_test.rb index 8255080ae..aa7503632 100644 --- a/bullet_train-super_load_and_authorize_resource/test/controllers/concerns/loads_and_authorizes_resource_test.rb +++ b/bullet_train-super_load_and_authorize_resource/test/controllers/concerns/loads_and_authorizes_resource_test.rb @@ -7,6 +7,6 @@ class TestClass test "includes BulletTrain::LoadsAndAuthorizesResource" do assert TestClass.ancestors.include? BulletTrain::LoadsAndAuthorizesResource - assert TestClass.respond_to?(:account_load_and_authorize_resource) + assert_respond_to TestClass, :account_load_and_authorize_resource end end diff --git a/bullet_train-super_load_and_authorize_resource/test/test_helper.rb b/bullet_train-super_load_and_authorize_resource/test/test_helper.rb index 44d56a045..1224df13c 100644 --- a/bullet_train-super_load_and_authorize_resource/test/test_helper.rb +++ b/bullet_train-super_load_and_authorize_resource/test/test_helper.rb @@ -4,6 +4,8 @@ require_relative "../test/dummy/config/environment" ActiveRecord::Migrator.migrations_paths = [File.expand_path("../test/dummy/db/migrate", __dir__)] require "rails/test_help" +require "minitest/mock" +require "pry" # Load fixtures from the engine if ActiveSupport::TestCase.respond_to?(:fixture_path=)