From e56155ca257ba3e3e9254ff89d8931a3ad573311 Mon Sep 17 00:00:00 2001 From: Steve Brudz Date: Mon, 16 Dec 2024 16:17:47 -0600 Subject: [PATCH 1/4] Customize simplecov config for phoenix --- .simplecov | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.simplecov b/.simplecov index 1071079540..526a82267f 100644 --- a/.simplecov +++ b/.simplecov @@ -1,3 +1,4 @@ SimpleCov.start 'rails' do - # any custom configs like groups and filters can be here at a central place + enable_coverage :branch + add_filter 'phoenix-tests' end From 744b0e577de00b72a731c86945491bc54cabe4c3 Mon Sep 17 00:00:00 2001 From: Steve Brudz Date: Mon, 16 Dec 2024 17:04:09 -0600 Subject: [PATCH 2/4] Use simplecov-json gem instead of simplecov_json_formatter --- .simplecov | 7 +++++++ Gemfile | 1 + Gemfile.lock | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/.simplecov b/.simplecov index 526a82267f..67b86abf8c 100644 --- a/.simplecov +++ b/.simplecov @@ -1,4 +1,11 @@ +require 'simplecov' +require 'simplecov-json' SimpleCov.start 'rails' do + # any custom configs like groups and filters can be here at a central place enable_coverage :branch + formatter SimpleCov::Formatter::MultiFormatter[ + SimpleCov::Formatter::JSONFormatter, + SimpleCov::Formatter::HTMLFormatter + ] add_filter 'phoenix-tests' end diff --git a/Gemfile b/Gemfile index 1744d1218e..1603709196 100644 --- a/Gemfile +++ b/Gemfile @@ -196,6 +196,7 @@ group :test do gem "rails-controller-testing" # Show code coverage. gem 'simplecov' + gem 'simplecov-json' # More concise test ("should") matchers gem 'shoulda-matchers', '~> 6.2' # Mock HTTP requests and ensure they are not called during tests. diff --git a/Gemfile.lock b/Gemfile.lock index 396940a4b6..08d3f4ee84 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -630,6 +630,9 @@ GEM simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) simplecov-html (0.12.3) + simplecov-json (0.2.3) + json + simplecov simplecov_json_formatter (0.1.4) sinatra (3.1.0) mustermann (~> 3.0) @@ -789,6 +792,7 @@ DEPENDENCIES shoulda-matchers (~> 6.2) simple_form simplecov + simplecov-json sprockets (~> 4.2.1) standard (~> 1.40) stimulus-rails From 349c3a701f6e8b3cb7be25836e670895e2aa8082 Mon Sep 17 00:00:00 2001 From: Steve Brudz Date: Tue, 17 Dec 2024 14:41:35 -0600 Subject: [PATCH 3/4] Support use of multiple test databases --- config/database.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/database.yml b/config/database.yml index 0b4fc4bfbd..62f51a4947 100644 --- a/config/database.yml +++ b/config/database.yml @@ -22,7 +22,7 @@ staging: test: <<: *default - database: diaper_test + database: diaper_test<%= ENV['TEST_ENV_NUMBER'] %> timeout: 5000 # These env vars live in Cloud66 application settings. Don't change From 0e28c9619ef7e076dd04fd0daa931dd2d6706115 Mon Sep 17 00:00:00 2001 From: "phoenix[bot]" Date: Thu, 6 Mar 2025 19:52:58 +0000 Subject: [PATCH 4/4] Add generated tests for app/models/partners/*.rb --- .../partners/authorized_family_member_spec.rb | 27 ++ .../tests/app/models/partners/base_spec.rb | 6 + .../partners/child_item_request_spec.rb | 91 ++++++ .../tests/app/models/partners/child_spec.rb | 106 +++++++ .../models/partners/family_request_spec.rb | 174 +++++++++++ .../tests/app/models/partners/family_spec.rb | 258 ++++++++++++++++ .../app/models/partners/item_request_spec.rb | 85 ++++++ .../tests/app/models/partners/profile_spec.rb | 276 ++++++++++++++++++ .../app/models/partners/served_area_spec.rb | 6 + 9 files changed, 1029 insertions(+) create mode 100644 phoenix-tests/unit/tests/app/models/partners/authorized_family_member_spec.rb create mode 100644 phoenix-tests/unit/tests/app/models/partners/base_spec.rb create mode 100644 phoenix-tests/unit/tests/app/models/partners/child_item_request_spec.rb create mode 100644 phoenix-tests/unit/tests/app/models/partners/child_spec.rb create mode 100644 phoenix-tests/unit/tests/app/models/partners/family_request_spec.rb create mode 100644 phoenix-tests/unit/tests/app/models/partners/family_spec.rb create mode 100644 phoenix-tests/unit/tests/app/models/partners/item_request_spec.rb create mode 100644 phoenix-tests/unit/tests/app/models/partners/profile_spec.rb create mode 100644 phoenix-tests/unit/tests/app/models/partners/served_area_spec.rb diff --git a/phoenix-tests/unit/tests/app/models/partners/authorized_family_member_spec.rb b/phoenix-tests/unit/tests/app/models/partners/authorized_family_member_spec.rb new file mode 100644 index 0000000000..ce42ac78ac --- /dev/null +++ b/phoenix-tests/unit/tests/app/models/partners/authorized_family_member_spec.rb @@ -0,0 +1,27 @@ + +require "rails_helper" + +RSpec.describe Partners::AuthorizedFamilyMember do +describe '#display_name', :phoenix do + let(:authorized_family_member_with_full_name) { Partners::AuthorizedFamilyMember.new(first_name: 'John', last_name: 'Doe') } + let(:authorized_family_member_with_first_name_only) { Partners::AuthorizedFamilyMember.new(first_name: 'John', last_name: nil) } + let(:authorized_family_member_with_last_name_only) { Partners::AuthorizedFamilyMember.new(first_name: nil, last_name: 'Doe') } + let(:authorized_family_member_with_no_name) { Partners::AuthorizedFamilyMember.new(first_name: nil, last_name: nil) } + + it 'returns full name when both first_name and last_name are present' do + expect(authorized_family_member_with_full_name.display_name).to eq('John Doe') + end + + it 'returns first_name when last_name is nil' do + expect(authorized_family_member_with_first_name_only.display_name).to eq('John') + end + + it 'returns last_name when first_name is nil' do + expect(authorized_family_member_with_last_name_only.display_name).to eq('Doe') + end + + it 'returns an empty string when both first_name and last_name are nil' do + expect(authorized_family_member_with_no_name.display_name).to eq('') + end +end +end diff --git a/phoenix-tests/unit/tests/app/models/partners/base_spec.rb b/phoenix-tests/unit/tests/app/models/partners/base_spec.rb new file mode 100644 index 0000000000..a8a804350c --- /dev/null +++ b/phoenix-tests/unit/tests/app/models/partners/base_spec.rb @@ -0,0 +1,6 @@ + +require "rails_helper" + +RSpec.describe Partners::Base do + +end diff --git a/phoenix-tests/unit/tests/app/models/partners/child_item_request_spec.rb b/phoenix-tests/unit/tests/app/models/partners/child_item_request_spec.rb new file mode 100644 index 0000000000..70a58a85b2 --- /dev/null +++ b/phoenix-tests/unit/tests/app/models/partners/child_item_request_spec.rb @@ -0,0 +1,91 @@ + +require "rails_helper" + +RSpec.describe Partners::ChildItemRequest do +describe '#quantity', :phoenix do + let(:item_request) { ItemRequest.create(quantity: item_request_quantity) } + let(:children) { Array.new(children_count) { Child.create } } + let(:child_item_request) { Partners::ChildItemRequest.new(item_request: item_request, children: children) } + + context 'when item_request quantity is zero' do + let(:item_request_quantity) { 0 } + let(:children_count) { 1 } + + it 'returns zero' do + expect(child_item_request.quantity).to eq(0) + end + end + + context 'when there are no children' do + let(:item_request_quantity) { 10 } + let(:children_count) { 0 } + + it 'returns zero' do + expect(child_item_request.quantity).to eq(0) + end + end + + context 'when there is one child' do + let(:item_request_quantity) { 10 } + let(:children_count) { 1 } + + it 'returns correct quantity equal to item_request quantity' do + expect(child_item_request.quantity).to eq(10) + end + end + + context 'when there are multiple children' do + let(:item_request_quantity) { 10 } + let(:children_count) { 2 } + + it 'returns correct quantity divided by number of children' do + expect(child_item_request.quantity).to eq(5) + end + end + + context 'when handling division by zero gracefully' do + let(:item_request_quantity) { 10 } + let(:children_count) { 0 } + + it 'returns zero when dividing by zero' do + expect(child_item_request.quantity).to eq(0) + end + end +end +describe '#ordered_item_diaperid', :phoenix do + let(:item_request) { ItemRequest.new(item_id: item_id) } + let(:child_item_request) { Partners::ChildItemRequest.new(item_request: item_request) } + + context 'when item_request is present' do + let(:item_id) { 1 } + + it 'returns the item_id when item_request is present' do + expect(child_item_request.ordered_item_diaperid).to eq(item_id) + end + end + + context 'when item_request is nil' do + let(:item_request) { nil } + + it 'does not raise an error when item_request is nil' do + expect { child_item_request.ordered_item_diaperid }.not_to raise_error + end + end + + context 'when item_id is nil' do + let(:item_id) { nil } + + it 'returns nil when item_id is nil' do + expect(child_item_request.ordered_item_diaperid).to be_nil + end + end + + context 'when item_id is invalid' do + let(:item_id) { 'invalid' } + + it 'returns the invalid item_id as is' do + expect(child_item_request.ordered_item_diaperid).to eq('invalid') + end + end +end +end diff --git a/phoenix-tests/unit/tests/app/models/partners/child_spec.rb b/phoenix-tests/unit/tests/app/models/partners/child_spec.rb new file mode 100644 index 0000000000..a2754ea784 --- /dev/null +++ b/phoenix-tests/unit/tests/app/models/partners/child_spec.rb @@ -0,0 +1,106 @@ + +require "rails_helper" + +RSpec.describe Partners::Child do +describe '#display_name', :phoenix do + let(:child_with_full_name) { build(:partners_child, first_name: 'John', last_name: 'Doe') } + let(:child_with_first_name_only) { build(:partners_child, first_name: 'John', last_name: nil) } + let(:child_with_last_name_only) { build(:partners_child, first_name: nil, last_name: 'Doe') } + let(:child_with_no_name) { build(:partners_child, first_name: nil, last_name: nil) } + + it 'returns full name when both first_name and last_name are present' do + expect(child_with_full_name.display_name).to eq('John Doe') + end + + describe 'when first_name is present but last_name is nil' do + it 'returns only first_name with trailing space' do + expect(child_with_first_name_only.display_name).to eq('John ') + end + end + + describe 'when last_name is present but first_name is nil' do + it 'returns only last_name with leading space' do + expect(child_with_last_name_only.display_name).to eq(' Doe') + end + end + + describe 'when both first_name and last_name are nil' do + it 'returns a single space' do + expect(child_with_no_name.display_name).to eq(' ') + end + end +end +describe '.csv_export_headers', :phoenix do + it 'returns the correct CSV headers' do + expected_headers = %w[ + id first_name last_name date_of_birth gender child_lives_with race agency_child_id + health_insurance comments created_at updated_at guardian_last_name guardian_first_name requested_items active archived + ] + expect(Partners::Child.csv_export_headers).to eq(expected_headers) + end +end +describe '#csv_export_attributes', :phoenix do + let(:family) { build(:partners_family, guardian_first_name: 'John', guardian_last_name: 'Doe') } + let(:requested_item) { build(:item, name: 'Diapers') } + let(:child_with_family) { build(:partners_child, family: family, requested_items: [requested_item]) } + let(:child_without_family) { build(:partners_child, family: nil, requested_items: [requested_item]) } + let(:child_with_no_requested_items) { build(:partners_child, requested_items: []) } + + it 'includes basic attributes' do + expect(child_with_family.csv_export_attributes).to include( + child_with_family.id, + child_with_family.first_name, + child_with_family.last_name, + child_with_family.date_of_birth, + child_with_family.gender, + child_with_family.child_lives_with, + child_with_family.race, + child_with_family.agency_child_id, + child_with_family.health_insurance, + child_with_family.comments, + child_with_family.created_at, + child_with_family.updated_at + ) + end + + describe 'when family association is present' do + it 'includes guardian last name' do + expect(child_with_family.csv_export_attributes).to include(family.guardian_last_name) + end + + it 'includes guardian first name' do + expect(child_with_family.csv_export_attributes).to include(family.guardian_first_name) + end + end + + describe 'when family association is nil' do + it 'handles missing guardian last name gracefully' do + expect(child_without_family.csv_export_attributes).to include(nil) + end + + it 'handles missing guardian first name gracefully' do + expect(child_without_family.csv_export_attributes).to include(nil) + end + end + + describe 'when requested_items are present' do + it 'joins requested item names with a comma' do + expect(child_with_family.csv_export_attributes).to include('Diapers') + end + end + + describe 'when requested_items are empty' do + it 'handles empty requested items gracefully' do + expect(child_with_no_requested_items.csv_export_attributes).to include('') + end + end + + it 'includes active attribute' do + expect(child_with_family.csv_export_attributes).to include(child_with_family.active) + end + + it 'includes archived attribute' do + expect(child_with_family.csv_export_attributes).to include(child_with_family.archived) + end +end +end diff --git a/phoenix-tests/unit/tests/app/models/partners/family_request_spec.rb b/phoenix-tests/unit/tests/app/models/partners/family_request_spec.rb new file mode 100644 index 0000000000..b5dcc219f4 --- /dev/null +++ b/phoenix-tests/unit/tests/app/models/partners/family_request_spec.rb @@ -0,0 +1,174 @@ + +require "rails_helper" + +RSpec.describe Partners::FamilyRequest do +describe '#initialize', :phoenix do + let(:params) { { some_key: 'some_value' } } + let(:partner) { Partner.new(name: 'Test Partner') } + let(:initial_items) { 3 } + + it 'initializes items with the correct size when initial_items is provided' do + family_request = Partners::FamilyRequest.new(params, initial_items: initial_items) + expect(family_request.items.size).to eq(initial_items) + end + + it 'does not initialize items when initial_items is nil' do + family_request = Partners::FamilyRequest.new(params) + expect(family_request.items).to be_nil + end + + it 'assigns the correct partner when partner is provided' do + family_request = Partners::FamilyRequest.new(params, partner: partner) + expect(family_request.partner).to eq(partner) + end + + it 'does not assign a partner when partner is nil' do + family_request = Partners::FamilyRequest.new(params) + expect(family_request.partner).to be_nil + end + + it 'correctly calls super with params' do + family_request = Partners::FamilyRequest.new(params) + expect(family_request.some_key).to eq('some_value') + end +end +describe '#items_attributes=', :phoenix do + let(:valid_attributes) do + { + '0' => { item_id: build(:item).id, person_count: 2 }, + '1' => { item_id: build(:item).id, person_count: 3 } + } + end + + let(:missing_item_id_attributes) do + { + '0' => { person_count: 2 } + } + end + + let(:missing_person_count_attributes) do + { + '0' => { item_id: build(:item).id } + } + end + + let(:additional_keys_attributes) do + { + '0' => { item_id: build(:item).id, person_count: 2, extra_key: 'extra_value' } + } + end + + let(:invalid_item_id_attributes) do + { + '0' => { item_id: 'invalid_id', person_count: 2 } + } + end + + let(:invalid_person_count_attributes) do + { + '0' => { item_id: build(:item).id, person_count: 'invalid_count' } + } + end + + it 'creates the correct number of Item objects with valid attributes' do + family_request = Partners::FamilyRequest.new + family_request.items_attributes = valid_attributes + expect(family_request.instance_variable_get(:@items).size).to eq(2) + end + + it 'creates Item objects with correct attributes' do + family_request = Partners::FamilyRequest.new + family_request.items_attributes = valid_attributes + expect(family_request.instance_variable_get(:@items).first).to have_attributes(item_id: valid_attributes['0'][:item_id], person_count: 2) + end + + describe 'when attributes are missing item_id' do + it 'sets item_id to nil' do + family_request = Partners::FamilyRequest.new + family_request.items_attributes = missing_item_id_attributes + expect(family_request.instance_variable_get(:@items).first).to have_attributes(item_id: nil, person_count: 2) + end + end + + describe 'when attributes are missing person_count' do + it 'sets person_count to nil' do + family_request = Partners::FamilyRequest.new + family_request.items_attributes = missing_person_count_attributes + expect(family_request.instance_variable_get(:@items).first).to have_attributes(item_id: missing_person_count_attributes['0'][:item_id], person_count: nil) + end + end + + describe 'when attributes contain additional keys' do + it 'ignores additional keys and sets correct attributes' do + family_request = Partners::FamilyRequest.new + family_request.items_attributes = additional_keys_attributes + expect(family_request.instance_variable_get(:@items).first).to have_attributes(item_id: additional_keys_attributes['0'][:item_id], person_count: 2) + end + end + + describe 'when attributes have invalid data types' do + it 'handles invalid data types for item_id' do + family_request = Partners::FamilyRequest.new + family_request.items_attributes = invalid_item_id_attributes + expect(family_request.instance_variable_get(:@items).first).to have_attributes(item_id: 'invalid_id', person_count: 2) + end + + it 'handles invalid data types for person_count' do + family_request = Partners::FamilyRequest.new + family_request.items_attributes = invalid_person_count_attributes + expect(family_request.instance_variable_get(:@items).first).to have_attributes(item_id: invalid_person_count_attributes['0'][:item_id], person_count: 'invalid_count') + end + end +end +describe "#new_with_attrs", :phoenix do + let(:empty_attrs) { [] } + let(:multiple_attrs) { [{ key1: 'value1' }, { key2: 'value2' }] } + let(:invalid_attrs) { [{ invalid_key: nil }] } + let(:duplicate_attrs) { [{ key: 'value' }, { key: 'value' }] } + let(:boundary_attrs) { [{ key: '' }, { key: 'a' * 256 }] } + let(:non_array_input) { 'not an array' } + + it "creates a request with no attributes" do + request = Partners::FamilyRequest.new_with_attrs(empty_attrs) + expect(request.items_attributes).to eq({}) + end + + it "creates a request with multiple attributes" do + request = Partners::FamilyRequest.new_with_attrs(multiple_attrs) + expect(request.items_attributes).to eq({0 => { key1: 'value1' }, 1 => { key2: 'value2' }}) + end + + it "creates a request with invalid attributes" do + request = Partners::FamilyRequest.new_with_attrs(invalid_attrs) + expect(request.items_attributes).to eq({0 => { invalid_key: nil }}) + end + + it "creates a request with duplicate attributes" do + request = Partners::FamilyRequest.new_with_attrs(duplicate_attrs) + expect(request.items_attributes).to eq({0 => { key: 'value' }, 1 => { key: 'value' }}) + end + + it "creates a request with boundary values for attributes" do + request = Partners::FamilyRequest.new_with_attrs(boundary_attrs) + expect(request.items_attributes).to eq({0 => { key: '' }, 1 => { key: 'a' * 256 }}) + end + + it "raises an error for non-array input" do + expect { Partners::FamilyRequest.new_with_attrs(non_array_input) }.to raise_error(NoMethodError) + end + + describe "when attributes are empty" do + it "initializes with default item" do + request = Partners::FamilyRequest.new_with_attrs(empty_attrs) + expect(request.items_attributes).to eq({}) + end + end + + describe "when attributes are present" do + it "assigns attributes correctly" do + request = Partners::FamilyRequest.new_with_attrs(multiple_attrs) + expect(request.items_attributes).to eq({0 => { key1: 'value1' }, 1 => { key2: 'value2' }}) + end + end +end +end diff --git a/phoenix-tests/unit/tests/app/models/partners/family_spec.rb b/phoenix-tests/unit/tests/app/models/partners/family_spec.rb new file mode 100644 index 0000000000..59b0f20359 --- /dev/null +++ b/phoenix-tests/unit/tests/app/models/partners/family_spec.rb @@ -0,0 +1,258 @@ + +require "rails_helper" + +RSpec.describe Partners::Family do +describe '#create_authorized', :phoenix do + let(:family) { build(:partners_family, guardian_first_name: guardian_first_name, guardian_last_name: guardian_last_name) } + let(:guardian_first_name) { 'John' } + let(:guardian_last_name) { 'Doe' } + + it 'increments the authorized family members count by 1' do + expect { family.create_authorized }.to change { family.authorized_family_members.count }.by(1) + end + + it 'sets the first name of the authorized family member correctly' do + family.create_authorized + authorized_member = family.authorized_family_members.last + expect(authorized_member.first_name).to eq('John') + end + + it 'sets the last name of the authorized family member correctly' do + family.create_authorized + authorized_member = family.authorized_family_members.last + expect(authorized_member.last_name).to eq('Doe') + end + + context 'when guardian_first_name is missing' do + let(:guardian_first_name) { nil } + + it 'raises a validation error for missing first name' do + expect { family.create_authorized }.to raise_error(ActiveRecord::RecordInvalid, /First name can't be blank/) + end + end + + context 'when guardian_last_name is missing' do + let(:guardian_last_name) { nil } + + it 'raises a validation error for missing last name' do + expect { family.create_authorized }.to raise_error(ActiveRecord::RecordInvalid, /Last name can't be blank/) + end + end +end +describe '#guardian_display_name', :phoenix do + let(:family_with_full_name) { build(:partners_family, guardian_first_name: 'John', guardian_last_name: 'Doe') } + let(:family_with_no_first_name) { build(:partners_family, guardian_first_name: nil, guardian_last_name: 'Doe') } + let(:family_with_no_last_name) { build(:partners_family, guardian_first_name: 'John', guardian_last_name: nil) } + let(:family_with_no_names) { build(:partners_family, guardian_first_name: nil, guardian_last_name: nil) } + let(:family_with_empty_first_name) { build(:partners_family, guardian_first_name: '', guardian_last_name: 'Doe') } + let(:family_with_empty_last_name) { build(:partners_family, guardian_first_name: 'John', guardian_last_name: '') } + let(:family_with_empty_names) { build(:partners_family, guardian_first_name: '', guardian_last_name: '') } + + it 'returns full name when both first and last names are present' do + expect(family_with_full_name.guardian_display_name).to eq('John Doe') + end + + describe 'when first name is missing' do + it 'returns only the last name' do + expect(family_with_no_first_name.guardian_display_name).to eq('Doe') + end + end + + describe 'when last name is missing' do + it 'returns only the first name' do + expect(family_with_no_last_name.guardian_display_name).to eq('John') + end + end + + describe 'when both first and last names are missing' do + it 'returns an empty string' do + expect(family_with_no_names.guardian_display_name).to eq(' ') + end + end + + describe 'when first name is empty' do + it 'returns only the last name' do + expect(family_with_empty_first_name.guardian_display_name).to eq('Doe') + end + end + + describe 'when last name is empty' do + it 'returns only the first name' do + expect(family_with_empty_last_name.guardian_display_name).to eq('John') + end + end + + describe 'when both first and last names are empty' do + it 'returns an empty string' do + expect(family_with_empty_names.guardian_display_name).to eq(' ') + end + end +end +describe '#total_children_count', :phoenix do + let(:family) { build(:partners_family, home_child_count: home_child_count, home_young_child_count: home_young_child_count) } + + context 'when both home_child_count and home_young_child_count are 0' do + let(:home_child_count) { 0 } + let(:home_young_child_count) { 0 } + + it 'returns 0' do + expect(family.total_children_count).to eq(0) + end + end + + context 'when home_child_count is positive and home_young_child_count is 0' do + let(:home_child_count) { 3 } + let(:home_young_child_count) { 0 } + + it 'returns the correct count for positive home_child_count' do + expect(family.total_children_count).to eq(3) + end + end + + context 'when home_child_count is 0 and home_young_child_count is positive' do + let(:home_child_count) { 0 } + let(:home_young_child_count) { 2 } + + it 'returns the correct count for positive home_young_child_count' do + expect(family.total_children_count).to eq(2) + end + end + + context 'when both home_child_count and home_young_child_count are positive' do + let(:home_child_count) { 2 } + let(:home_young_child_count) { 3 } + + it 'returns the sum of both counts' do + expect(family.total_children_count).to eq(5) + end + end + + context 'when handling negative values' do + let(:home_child_count) { -1 } + let(:home_young_child_count) { -1 } + + it 'returns the sum of negative values' do + expect(family.total_children_count).to eq(-2) + end + end + + context 'when handling very large values' do + let(:home_child_count) { 1_000_000 } + let(:home_young_child_count) { 1_000_000 } + + it 'returns the sum of very large values' do + expect(family.total_children_count).to eq(2_000_000) + end + end + + context 'when handling non-integer values' do + let(:home_child_count) { 2.5 } + let(:home_young_child_count) { 3.5 } + + it 'returns the sum of non-integer values' do + expect(family.total_children_count).to eq(6.0) + end + end +end +describe "::csv_export_headers", :phoenix do + let(:expected_headers) do + %w[ + id guardian_first_name guardian_last_name guardian_zip_code guardian_county + guardian_phone case_manager home_adult_count home_child_count home_young_child_count + sources_of_income guardian_employed guardian_employment_type guardian_monthly_pay + guardian_health_insurance comments created_at updated_at partner_id military archived + ] + end + + it "returns the correct headers" do + expect(Partners::Family.csv_export_headers).to eq(expected_headers) + end +end +describe '#csv_export_attributes', :phoenix do + let(:family) { build(:partners_family) } + + it 'includes id' do + expect(family.csv_export_attributes).to include(family.id) + end + + it 'includes guardian_first_name' do + expect(family.csv_export_attributes).to include(family.guardian_first_name) + end + + it 'includes guardian_last_name' do + expect(family.csv_export_attributes).to include(family.guardian_last_name) + end + + it 'includes guardian_zip_code' do + expect(family.csv_export_attributes).to include(family.guardian_zip_code) + end + + it 'includes guardian_county' do + expect(family.csv_export_attributes).to include(family.guardian_county) + end + + it 'includes guardian_phone' do + expect(family.csv_export_attributes).to include(family.guardian_phone) + end + + it 'includes case_manager' do + expect(family.csv_export_attributes).to include(family.case_manager) + end + + it 'includes home_adult_count' do + expect(family.csv_export_attributes).to include(family.home_adult_count) + end + + it 'includes home_child_count' do + expect(family.csv_export_attributes).to include(family.home_child_count) + end + + it 'includes home_young_child_count' do + expect(family.csv_export_attributes).to include(family.home_young_child_count) + end + + it 'includes sources_of_income' do + expect(family.csv_export_attributes).to include(family.sources_of_income) + end + + it 'includes guardian_employed' do + expect(family.csv_export_attributes).to include(family.guardian_employed) + end + + it 'includes guardian_employment_type' do + expect(family.csv_export_attributes).to include(family.guardian_employment_type) + end + + it 'includes guardian_monthly_pay' do + expect(family.csv_export_attributes).to include(family.guardian_monthly_pay) + end + + it 'includes guardian_health_insurance' do + expect(family.csv_export_attributes).to include(family.guardian_health_insurance) + end + + it 'includes comments' do + expect(family.csv_export_attributes).to include(family.comments) + end + + it 'includes created_at' do + expect(family.csv_export_attributes).to include(family.created_at) + end + + it 'includes updated_at' do + expect(family.csv_export_attributes).to include(family.updated_at) + end + + it 'includes partner_id' do + expect(family.csv_export_attributes).to include(family.partner_id) + end + + it 'includes military' do + expect(family.csv_export_attributes).to include(family.military) + end + + it 'includes archived' do + expect(family.csv_export_attributes).to include(family.archived) + end +end +end diff --git a/phoenix-tests/unit/tests/app/models/partners/item_request_spec.rb b/phoenix-tests/unit/tests/app/models/partners/item_request_spec.rb new file mode 100644 index 0000000000..bf60340ed1 --- /dev/null +++ b/phoenix-tests/unit/tests/app/models/partners/item_request_spec.rb @@ -0,0 +1,85 @@ + +require "rails_helper" + +RSpec.describe Partners::ItemRequest do +describe '#request_unit_is_supported', :phoenix do + let(:item) { build(:item, :with_unit, unit: request_unit_name) } + let(:item_request) { build(:item_request, item: item, request_unit: request_unit) } + let(:request_unit_name) { "pack" } + + context 'when request_unit is blank' do + let(:request_unit) { nil } + + it 'returns early if request_unit is blank' do + item_request.request_unit_is_supported + expect(item_request.errors[:request_unit]).to be_empty + end + end + + context 'when request_unit is included in item.request_units' do + let(:request_unit) { request_unit_name } + + it 'does not add any errors' do + item_request.request_unit_is_supported + expect(item_request.errors[:request_unit]).to be_empty + end + end + + context 'when request_unit is not included in item.request_units' do + let(:request_unit) { "unsupported_unit" } + + it 'adds an error to errors' do + item_request.request_unit_is_supported + expect(item_request.errors[:request_unit]).to include("is not supported") + end + end +end +describe '#name_with_unit', :phoenix do + let(:item_request) { build(:item_request, item: item, request_unit: request_unit, quantity: quantity) } + let(:item) { build(:item, name: 'Sample Item') } + let(:request_unit) { nil } + let(:quantity) { 5 } + + context 'when item is nil' do + let(:item) { nil } + + it 'returns nil' do + expect(item_request.name_with_unit).to be_nil + end + end + + context 'when item is present' do + context 'when Flipper feature :enable_packs is enabled and request_unit is present' do + before do + allow(Flipper).to receive(:enabled?).with(:enable_packs).and_return(true) + end + + let(:request_unit) { 'pack' } + + context 'with quantity_override provided' do + let(:quantity_override) { 10 } + + it 'returns name with pluralized request unit based on quantity_override' do + expect(item_request.name_with_unit(quantity_override)).to eq('Sample Item - packs') + end + end + + context 'without quantity_override provided' do + it 'returns name with pluralized request unit based on quantity' do + expect(item_request.name_with_unit).to eq('Sample Item - packs') + end + end + end + + context 'when Flipper feature :enable_packs is not enabled or request_unit is not present' do + before do + allow(Flipper).to receive(:enabled?).with(:enable_packs).and_return(false) + end + + it 'returns just the name' do + expect(item_request.name_with_unit).to eq('Sample Item') + end + end + end +end +end diff --git a/phoenix-tests/unit/tests/app/models/partners/profile_spec.rb b/phoenix-tests/unit/tests/app/models/partners/profile_spec.rb new file mode 100644 index 0000000000..6c15d01033 --- /dev/null +++ b/phoenix-tests/unit/tests/app/models/partners/profile_spec.rb @@ -0,0 +1,276 @@ + +require "rails_helper" + +RSpec.describe Partners::Profile do +describe '#client_share_total', :phoenix do + let(:partner_profile) { create(:partner_profile) } + + context 'when served_areas is empty' do + it 'returns 0' do + allow(partner_profile).to receive(:served_areas).and_return([]) + expect(partner_profile.client_share_total).to eq(0) + end + end + + context 'when all client_share values are nil' do + let!(:served_areas) { build_list(:partners_served_area, 3, partner_profile: partner_profile, client_share: nil) } + + it 'returns 0' do + allow(partner_profile).to receive(:served_areas).and_return(served_areas) + expect(partner_profile.client_share_total).to eq(0) + end + end + + context 'when some client_share values are nil' do + let!(:served_areas) { [build(:partners_served_area, partner_profile: partner_profile, client_share: nil), build(:partners_served_area, partner_profile: partner_profile, client_share: 5), build(:partners_served_area, partner_profile: partner_profile, client_share: 10)] } + + it 'sums non-nil client_share values' do + allow(partner_profile).to receive(:served_areas).and_return(served_areas) + expect(partner_profile.client_share_total).to eq(15) + end + end + + context 'when none of the client_share values are nil' do + let!(:served_areas) { build_list(:partners_served_area, 3, partner_profile: partner_profile, client_share: 5) } + + it 'returns the sum of all client_share values' do + allow(partner_profile).to receive(:served_areas).and_return(served_areas) + expect(partner_profile.client_share_total).to eq(15) + end + end + + context 'when there is a single served_area with a non-nil client_share' do + let!(:served_areas) { [build(:partners_served_area, partner_profile: partner_profile, client_share: 7)] } + + it 'returns the client_share value' do + allow(partner_profile).to receive(:served_areas).and_return(served_areas) + expect(partner_profile.client_share_total).to eq(7) + end + end +end +describe "#split_pick_up_emails", :phoenix do + let(:profile) { build(:partner_profile, pick_up_email: pick_up_email) } + + context "when pick_up_email is nil" do + let(:pick_up_email) { nil } + + it "returns nil" do + expect(profile.split_pick_up_emails).to be_nil + end + end + + context "when emails are separated by commas" do + let(:pick_up_email) { "email1@example.com,email2@example.com" } + + it "splits emails separated by commas" do + expect(profile.split_pick_up_emails).to eq(["email1@example.com", "email2@example.com"]) + end + end + + context "when emails are separated by spaces" do + let(:pick_up_email) { "email1@example.com email2@example.com" } + + it "splits emails separated by spaces" do + expect(profile.split_pick_up_emails).to eq(["email1@example.com", "email2@example.com"]) + end + end + + context "when emails are separated by a mix of commas and spaces" do + let(:pick_up_email) { "email1@example.com, email2@example.com email3@example.com" } + + it "splits emails separated by a mix of commas and spaces" do + expect(profile.split_pick_up_emails).to eq(["email1@example.com", "email2@example.com", "email3@example.com"]) + end + end + + context "when there are extra spaces or empty elements" do + let(:pick_up_email) { "email1@example.com, , email2@example.com " } + + it "removes extra spaces or empty elements" do + expect(profile.split_pick_up_emails).to eq(["email1@example.com", "email2@example.com"]) + end + end +end +describe '#check_social_media', :phoenix do + let(:partner) { create(:partner, partials_to_show: ['media_information']) } + let(:profile_with_website) { build(:partner_profile, website: 'http://example.com', partner: partner) } + let(:profile_with_twitter) { build(:partner_profile, twitter: '@example', partner: partner) } + let(:profile_with_facebook) { build(:partner_profile, facebook: 'facebook.com/example', partner: partner) } + let(:profile_with_instagram) { build(:partner_profile, instagram: '@example', partner: partner) } + let(:profile_without_media_info) { build(:partner_profile, partner: create(:partner, partials_to_show: [])) } + let(:profile_no_social_media_checked) { build(:partner_profile, no_social_media_presence: true, partner: partner) } + let(:profile_no_social_media_unchecked) { build(:partner_profile, no_social_media_presence: false, partner: partner) } + + it 'returns early if website is present' do + profile_with_website.check_social_media + expect(profile_with_website.errors).to be_empty + end + + it 'returns early if twitter is present' do + profile_with_twitter.check_social_media + expect(profile_with_twitter.errors).to be_empty + end + + it 'returns early if facebook is present' do + profile_with_facebook.check_social_media + expect(profile_with_facebook.errors).to be_empty + end + + it 'returns early if instagram is present' do + profile_with_instagram.check_social_media + expect(profile_with_instagram.errors).to be_empty + end + + it 'returns early if partner.partials_to_show does not include "media_information"' do + profile_without_media_info.check_social_media + expect(profile_without_media_info.errors).to be_empty + end + + it 'adds an error if no social media is present and no_social_media_presence is not checked' do + profile_no_social_media_unchecked.check_social_media + expect(profile_no_social_media_unchecked.errors[:no_social_media_presence]).to include("must be checked if you have not provided any of Website, Twitter, Facebook, or Instagram.") + end + + it 'does not add an error if no social media is present and no_social_media_presence is checked' do + profile_no_social_media_checked.check_social_media + expect(profile_no_social_media_checked.errors).to be_empty + end +end +describe '#client_share_is_0_or_100', :phoenix do + let(:partner_profile) { build(:partner_profile, client_share_total: client_share_total) } + + context 'when client_share_total is 0' do + let(:client_share_total) { 0 } + + it 'does not add errors to client_share' do + partner_profile.client_share_is_0_or_100 + expect(partner_profile.errors[:client_share]).to be_empty + end + + it 'does not add errors to base' do + partner_profile.client_share_is_0_or_100 + expect(partner_profile.errors[:base]).to be_empty + end + end + + context 'when client_share_total is 100' do + let(:client_share_total) { 100 } + + it 'does not add errors to client_share' do + partner_profile.client_share_is_0_or_100 + expect(partner_profile.errors[:client_share]).to be_empty + end + + it 'does not add errors to base' do + partner_profile.client_share_is_0_or_100 + expect(partner_profile.errors[:base]).to be_empty + end + end + + describe 'when client_share_total is neither 0 nor 100' do + let(:client_share_total) { 50 } # Example value not 0 or 100 + + context 'when partner_step_form feature is enabled' do + before { allow(Flipper).to receive(:enabled?).with('partner_step_form').and_return(true) } + + it 'adds error to client_share' do + partner_profile.client_share_is_0_or_100 + expect(partner_profile.errors[:client_share]).to include('Total client share must be 0 or 100') + end + end + + context 'when partner_step_form feature is not enabled' do + before { allow(Flipper).to receive(:enabled?).with('partner_step_form').and_return(false) } + + it 'adds error to base' do + partner_profile.client_share_is_0_or_100 + expect(partner_profile.errors[:base]).to include('Total client share must be 0 or 100') + end + end + end +end +describe '#has_at_least_one_request_setting', :phoenix do + let(:partner_profile) { build(:partner_profile, enable_child_based_requests: enable_child_based_requests, enable_individual_requests: enable_individual_requests, enable_quantity_based_requests: enable_quantity_based_requests) } + + before { partner_profile.has_at_least_one_request_setting } + + context 'when all request settings are disabled' do + let(:enable_child_based_requests) { false } + let(:enable_individual_requests) { false } + let(:enable_quantity_based_requests) { false } + + context 'and partner_step_form is enabled' do + before { allow(Flipper).to receive(:enabled?).with('partner_step_form').and_return(true) } + + it 'adds an error to enable_child_based_requests' do + expect(partner_profile.errors[:enable_child_based_requests]).to include('At least one request type must be set') + end + end + + context 'and partner_step_form is disabled' do + before { allow(Flipper).to receive(:enabled?).with('partner_step_form').and_return(false) } + + it 'adds an error to base' do + expect(partner_profile.errors[:base]).to include('At least one request type must be set') + end + end + end + + context 'when at least one request setting is enabled' do + let(:enable_child_based_requests) { true } + let(:enable_individual_requests) { false } + let(:enable_quantity_based_requests) { false } + + it 'does not add any errors' do + expect(partner_profile.errors).to be_empty + end + end +end +describe '#pick_up_email_addresses', :phoenix do + let(:profile) { build(:partner_profile, pick_up_email: pick_up_email) } + + context 'when pick_up_email is nil' do + let(:pick_up_email) { nil } + + it 'returns nil' do + expect(profile.pick_up_email_addresses).to be_nil + end + end + + context 'when there are more than three email addresses' do + let(:pick_up_email) { 'email1@example.com, email2@example.com, email3@example.com, email4@example.com' } + + it 'adds an error for too many email addresses' do + profile.pick_up_email_addresses + expect(profile.errors[:pick_up_email]).to include("can't have more than three email addresses") + end + end + + context 'when there are repeated email addresses' do + let(:pick_up_email) { 'email1@example.com, email1@example.com, email2@example.com' } + + it 'adds an error for repeated email addresses' do + profile.pick_up_email_addresses + expect(profile.errors[:pick_up_email]).to include('should not have repeated email addresses') + end + end + + context 'when there is an invalid email address' do + let(:pick_up_email) { 'invalid-email, email2@example.com, email3@example.com' } + + it 'adds an error for invalid email addresses' do + profile.pick_up_email_addresses + expect(profile.errors[:pick_up_email]).to include('is invalid') + end + end + + context 'when all email addresses are valid and unique' do + let(:pick_up_email) { 'email1@example.com, email2@example.com, email3@example.com' } + + it 'does not add any errors' do + profile.pick_up_email_addresses + expect(profile.errors[:pick_up_email]).to be_empty + end + end +end +end diff --git a/phoenix-tests/unit/tests/app/models/partners/served_area_spec.rb b/phoenix-tests/unit/tests/app/models/partners/served_area_spec.rb new file mode 100644 index 0000000000..258a7c73cb --- /dev/null +++ b/phoenix-tests/unit/tests/app/models/partners/served_area_spec.rb @@ -0,0 +1,6 @@ + +require "rails_helper" + +RSpec.describe Partners::ServedArea do + +end