Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions phoenix-tests/unit/tests/app/models/product_drive_participant_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
require "rails_helper"

RSpec.describe ProductDriveParticipant, type: :model do
let(:organization) { Organization.create!(name: "Test Org") }
let(:product_drive_participant) { described_class.new(organization: organization) }

describe "associations" do
it "has many donations" do
association = described_class.reflect_on_association(:donations)
expect(association.macro).to eq(:has_many)
expect(association.options[:inverse_of]).to eq(:product_drive_participant)
expect(association.options[:dependent]).to eq(:destroy)
end
end

describe "validations" do
context "when phone is blank" do
it "validates presence of email" do
product_drive_participant.phone = nil
product_drive_participant.email = nil
product_drive_participant.valid?
expect(product_drive_participant.errors[:email]).to include("Must provide a phone or an e-mail")
end
end

context "when email is blank" do
it "validates presence of phone" do
product_drive_participant.email = nil
product_drive_participant.phone = nil
product_drive_participant.valid?
expect(product_drive_participant.errors[:phone]).to include("Must provide a phone or an e-mail")
end
end

context "when contact_name is blank" do
it "validates presence of business_name" do
product_drive_participant.contact_name = nil
product_drive_participant.business_name = nil
product_drive_participant.valid?
expect(product_drive_participant.errors[:business_name]).to include("Must provide a name or a business name")
end
end

context "when business_name is blank" do
it "validates presence of contact_name" do
product_drive_participant.business_name = nil
product_drive_participant.contact_name = nil
product_drive_participant.valid?
expect(product_drive_participant.errors[:contact_name]).to include("Must provide a name or a business name")
end
end

it "validates length of comment" do
product_drive_participant.comment = "a" * 501
product_drive_participant.valid?
expect(product_drive_participant.errors[:comment]).to include("is too long (maximum is 500 characters)")
end
end

describe "scopes" do
describe ".alphabetized" do
it "orders by contact_name" do
participant1 = ProductDriveParticipant.create!(contact_name: "Zeta", email: "zeta@example.com", organization: organization)
participant2 = ProductDriveParticipant.create!(contact_name: "Alpha", email: "alpha@example.com", organization: organization)
expect(ProductDriveParticipant.alphabetized).to eq([participant2, participant1])
end
end
end

describe "#volume" do
it "calculates total volume of donations" do
donation1 = double("Donation", line_items: double("LineItems", total: 10))
donation2 = double("Donation", line_items: double("LineItems", total: 20))
allow(product_drive_participant).to receive(:donations).and_return([donation1, donation2])
expect(product_drive_participant.volume).to eq(30)
end
end

describe "#volume_by_product_drive" do
it "calculates total volume of donations for a specific product drive" do
product_drive_id = 1
donation1 = double("Donation", line_items: double("LineItems", total: 10))
donation2 = double("Donation", line_items: double("LineItems", total: 20))
allow(product_drive_participant).to receive_message_chain(:donations, :by_product_drive).with(product_drive_id).and_return([donation1, donation2])
expect(product_drive_participant.volume_by_product_drive(product_drive_id)).to eq(30)
end
end

describe "#donation_source_view" do
context "when contact_name is present" do
it "returns the contact name with participant label" do
product_drive_participant.contact_name = "John Doe"
expect(product_drive_participant.donation_source_view).to eq("John Doe (participant)")
end
end

context "when contact_name is blank" do
it "returns nil" do
product_drive_participant.contact_name = nil
expect(product_drive_participant.donation_source_view).to be_nil
end
end
end
end
168 changes: 168 additions & 0 deletions phoenix-tests/unit/tests/app/models/product_drive_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
require "rails_helper"

RSpec.describe ProductDrive, type: :model do
let(:organization) { create(:organization) }
let(:product_drive) { create(:product_drive, organization: organization) }
let(:donation) { create(:donation, product_drive: product_drive) }
let(:line_item) { create(:line_item, itemizable: donation) }

describe "associations" do
it "belongs to organization" do
expect(product_drive.organization).to eq(organization)
end

it "has many donations" do
expect(product_drive.donations).to include(donation)
end

it "has many product_drive_participants through donations" do
participant = create(:product_drive_participant, donations: [donation])
expect(product_drive.product_drive_participants).to include(participant)
end
end

describe "validations" do
it "validates presence of name" do
product_drive.name = nil
expect(product_drive).not_to be_valid
expect(product_drive.errors[:name]).to include("A name must be chosen.")
end

it "validates presence of start_date" do
product_drive.start_date = nil
expect(product_drive).not_to be_valid
expect(product_drive.errors[:start_date]).to include("Please enter a start date.")
end

it "validates end_date is after start_date" do
product_drive.start_date = Date.today
product_drive.end_date = Date.yesterday
expect(product_drive).not_to be_valid
expect(product_drive.errors[:end_date]).to include("End date must be after the start date")
end
end

describe "scopes" do
describe ".by_name" do
it "filters by name" do
create(:product_drive, name: "Drive A")
create(:product_drive, name: "Drive B")
expect(ProductDrive.by_name("Drive A").count).to eq(1)
end
end

describe ".by_item_category_id" do
it "filters by item category id" do
item_category = create(:item_category)
item = create(:item, item_category: item_category)
line_item.update(item: item)
expect(ProductDrive.by_item_category_id(item_category.id)).to include(product_drive)
end
end

describe ".within_date_range" do
it "filters by date range" do
create(:product_drive, start_date: Date.today - 5, end_date: Date.today + 5)
create(:product_drive, start_date: Date.today + 10, end_date: Date.today + 15)
expect(ProductDrive.within_date_range("#{Date.today - 1} - #{Date.today + 1}").count).to eq(1)
end
end

describe ".alphabetized" do
it "orders by name" do
drive_a = create(:product_drive, name: "Drive A")
drive_b = create(:product_drive, name: "Drive B")
expect(ProductDrive.alphabetized).to eq([drive_a, drive_b])
end
end
end

describe "instance methods" do
describe "#end_date_is_bigger_of_end_date" do
it "adds error if end_date is before start_date" do
product_drive.start_date = Date.today
product_drive.end_date = Date.yesterday
product_drive.valid?
expect(product_drive.errors[:end_date]).to include("End date must be after the start date")
end
end

describe "#donation_quantity" do
it "calculates total donation quantity" do
line_item.update(quantity: 5)
expect(product_drive.donation_quantity).to eq(5)
end
end

describe "#distinct_items_count" do
it "counts distinct items" do
item2 = create(:item)
create(:line_item, itemizable: donation, item: item2)
expect(product_drive.distinct_items_count).to eq(2)
end
end

describe "#in_kind_value" do
it "calculates in-kind value" do
allow(donation).to receive(:value_per_itemizable).and_return(100)
expect(product_drive.in_kind_value).to eq(100)
end
end

describe "#donation_source_view" do
it "returns formatted donation source view" do
expect(product_drive.donation_source_view).to eq("#{product_drive.name} (product drive)")
end
end

describe "#item_quantities_by_name_and_date" do
it "returns item quantities filtered by date and sorted by name" do
item = create(:item, organization: organization, name: "Item A")
line_item.update(item: item, quantity: 10)
expect(product_drive.item_quantities_by_name_and_date(Date.today..Date.today)).to eq([10])
end
end

describe "#donation_quantity_by_date" do
it "calculates donation quantity by date" do
line_item.update(quantity: 5)
expect(product_drive.donation_quantity_by_date(Date.today..Date.today)).to eq(5)
end

context "with item_category_id" do
it "filters donation quantity by item category" do
item_category = create(:item_category)
item = create(:item, item_category: item_category)
line_item.update(item: item, quantity: 5)
expect(product_drive.donation_quantity_by_date(Date.today..Date.today, item_category.id)).to eq(5)
end
end
end

describe "#distinct_items_count_by_date" do
it "counts distinct items by date" do
item2 = create(:item)
create(:line_item, itemizable: donation, item: item2)
expect(product_drive.distinct_items_count_by_date(Date.today..Date.today)).to eq(2)
end

context "with item_category_id" do
it "filters distinct items count by item category" do
item_category = create(:item_category)
item = create(:item, item_category: item_category)
line_item.update(item: item)
expect(product_drive.distinct_items_count_by_date(Date.today..Date.today, item_category.id)).to eq(1)
end
end
end
end

describe "class methods" do
describe ".search_date_range" do
it "parses date range from string" do
result = ProductDrive.search_date_range("2023-01-01 - 2023-12-31")
expect(result).to eq({ start_date: "2023-01-01", end_date: "2023-12-31" })
end
end
end
end