From deff429464a95b6551f8da917eae97499881fc4c Mon Sep 17 00:00:00 2001 From: dylangriffinshub Date: Fri, 17 Jul 2026 00:51:05 -0400 Subject: [PATCH] Fix UserParameters#without being a no-op, add real spec coverage #without compared symbol keys (its only caller, CreateCasaAdminService#build, always passes symbols) against ActionController::Parameters#reject!'s string keys, so the block condition was always false and nothing was ever removed. It also didn't return self, breaking the builder chain. This let :active and :type survive into CasaAdmin.new via CreateCasaAdminService#build, letting any authenticated user set active=false on a new admin, or trigger an unrescued ActiveRecord::SubclassNotFound (500) by passing type=. Fixes #7067 Also replaces the pending spec stub in spec/values/user_parameters_spec.rb with real coverage of without, without_type, without_active, with_organization, and with_password. --- app/values/user_parameters.rb | 2 + spec/values/user_parameters_spec.rb | 72 ++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/app/values/user_parameters.rb b/app/values/user_parameters.rb index af24653deb..a672f8981f 100644 --- a/app/values/user_parameters.rb +++ b/app/values/user_parameters.rb @@ -49,7 +49,9 @@ def with_only(*) end def without(*keys) + keys = keys.map(&:to_s) params.reject! { |key| keys.include?(key) } + self end private diff --git a/spec/values/user_parameters_spec.rb b/spec/values/user_parameters_spec.rb index ed802d6e1f..73db21c75d 100644 --- a/spec/values/user_parameters_spec.rb +++ b/spec/values/user_parameters_spec.rb @@ -1,7 +1,75 @@ require "rails_helper" RSpec.describe UserParameters do - # TODO: Add tests for UserParameters + def build_params(attrs) + ActionController::Parameters.new(user: attrs) + end - pending "add some tests for UserParameters" + describe "#without" do + it "removes the given keys and is chainable" do + params = build_params(display_name: "Jane", active: "false", type: "Volunteer") + + result = described_class.new(params).without(:active, :type) + + expect(result).to be_a(described_class) + expect(result.to_h).to eq("display_name" => "Jane") + end + + it "removes keys even when the params only has string keys" do + params = build_params(display_name: "Jane", active: "false") + + result = described_class.new(params).without(:active) + + expect(result.to_h).to eq("display_name" => "Jane") + end + + it "supports further chaining after without" do + params = build_params(display_name: "Jane", active: "false", password: "old") + + result = described_class.new(params).without(:active).with_password("new-password") + + expect(result.to_h).to eq("display_name" => "Jane", "password" => "new-password") + end + end + + describe "#without_type" do + it "removes the type key" do + params = build_params(display_name: "Jane", type: "Volunteer") + + result = described_class.new(params).without_type + + expect(result.to_h).to eq("display_name" => "Jane") + end + end + + describe "#without_active" do + it "removes the active key" do + params = build_params(display_name: "Jane", active: "false") + + result = described_class.new(params).without_active + + expect(result.to_h).to eq("display_name" => "Jane") + end + end + + describe "#with_organization" do + it "sets casa_org_id" do + params = build_params(display_name: "Jane") + organization = create(:casa_org) + + result = described_class.new(params).with_organization(organization) + + expect(result.to_h).to eq("display_name" => "Jane", "casa_org_id" => organization.id) + end + end + + describe "#with_password" do + it "sets password" do + params = build_params(display_name: "Jane") + + result = described_class.new(params).with_password("secret123") + + expect(result.to_h).to eq("display_name" => "Jane", "password" => "secret123") + end + end end