diff --git a/app/models/unit.rb b/app/models/unit.rb index 6febe7e..96bb91b 100644 --- a/app/models/unit.rb +++ b/app/models/unit.rb @@ -26,10 +26,8 @@ class Unit < ApplicationRecord other_bases_units = arel_table.alias('other_bases_units') sub_units = arel_table.alias('sub_units') - # TODO: move inner 'with' CTE to outer 'with recursive' - it can have multiple - # CTEs, even non recursive ones. Unit.with_recursive(actionable_units: [ - Unit.with(units: self.or(Unit.defaults)).left_joins(:base) + self.or(Unit.defaults).left_joins(:base) .where.not( # Exclude Units that are/have default counterpart Arel::SelectManager.new.project(1).from(other_units) @@ -65,8 +63,14 @@ class Unit < ApplicationRecord ), # Fill base Units to display proper hierarchy. Duplicates will be removed # by final group() - can't be deduplicated with UNION due to 'portable' field. - arel_table.join(actionable_units).on(actionable_units[:base_id].eq(arel_table[:id])) - .project(arel_table[Arel.star], Arel::Nodes.build_quoted(nil).as('portable')) + # Use ActiveRecord::Relation (not a raw SelectManager) so the SQLite Arel + # visitor does not wrap it in parentheses inside the UNION ALL CTE body. + Unit.joins( + arel_table.create_join( + actionable_units, + arel_table.create_on(actionable_units[:base_id].eq(arel_table[:id])) + ) + ).select(arel_table[Arel.star], Arel::Nodes.build_quoted(nil).as('portable')) ]).select(units: [:base_id, :symbol]) .select( units[:id].minimum.as('id'), # can be ANY_VALUE() @@ -74,7 +78,7 @@ class Unit < ApplicationRecord Arel::Nodes.build_quoted(1).as('multiplier'), # disregard multiplier when sorting units[:portable].minimum.as('portable') ) - .from(units).group(:base_id, :symbol) + .from(units).group(units[:base_id], units[:symbol]) } scope :ordered, ->{ left_outer_joins(:base).order(ordering) @@ -83,8 +87,8 @@ class Unit < ApplicationRecord def self.ordering [arel_table.coalesce(Arel::Table.new(:bases_units)[:symbol], arel_table[:symbol]), arel_table[:base_id].not_eq(nil), - :multiplier, - :symbol] + arel_table[:multiplier], + arel_table[:symbol]] end before_destroy do diff --git a/config/environments/test.rb b/config/environments/test.rb index 857297d..b19e889 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -58,4 +58,7 @@ Rails.application.configure do # config.action_view.annotate_rendered_view_with_filenames = true config.log_level = :info + + # Allow the default integration test host. + config.hosts << "www.example.com" end diff --git a/test/controllers/default/units_controller_test.rb b/test/controllers/default/units_controller_test.rb index 2742778..6f8fbf6 100644 --- a/test/controllers/default/units_controller_test.rb +++ b/test/controllers/default/units_controller_test.rb @@ -1,8 +1,12 @@ require "test_helper" class Default::UnitsControllerTest < ActionDispatch::IntegrationTest + setup do + sign_in users(:alice) + end + test "should get index" do - get units_defaults_index_url + get default_units_url assert_response :success end end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index bda70d8..0444788 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb @@ -2,7 +2,9 @@ require "test_helper" class UsersControllerTest < ActionDispatch::IntegrationTest setup do - @user = users(:one) + @admin = users(:admin) + @user = users(:alice) + sign_in @admin end test "should get index" do @@ -10,39 +12,25 @@ class UsersControllerTest < ActionDispatch::IntegrationTest assert_response :success end - test "should get new" do - get new_user_url - assert_response :success - end - - test "should create user" do - assert_difference("User.count") do - post users_url, params: { user: { email: @user.email, status: @user.status } } - end - - assert_redirected_to user_url(User.last) - end - test "should show user" do get user_url(@user) assert_response :success end - test "should get edit" do - get edit_user_url(@user) - assert_response :success - end - test "should update user" do - patch user_url(@user), params: { user: { email: @user.email, status: @user.status } } - assert_redirected_to user_url(@user) + patch user_url(@user), params: { user: { status: :restricted } }, as: :turbo_stream + assert_equal "restricted", @user.reload.status end - test "should destroy user" do - assert_difference("User.count", -1) do - delete user_url(@user) - end + test "should not update self" do + patch user_url(@admin), params: { user: { status: :active } }, as: :turbo_stream, + headers: { "HTTP_REFERER" => users_url } + assert_response :redirect + end - assert_redirected_to users_url + test "should forbid non-admin" do + sign_in @user + get users_url + assert_response :forbidden end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 5362a8d..0d6268a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -2,6 +2,10 @@ ENV["RAILS_ENV"] ||= "test" require_relative "../config/environment" require "rails/test_help" +class ActionDispatch::IntegrationTest + include Devise::Test::IntegrationHelpers +end + class ActiveSupport::TestCase # Run tests in parallel with specified workers parallelize(workers: :number_of_processors)