Skip to content

Commit f9ef376

Browse files
committed
PC-50: Add specs for Item model
1 parent fdde96a commit f9ef376

5 files changed

Lines changed: 230 additions & 7 deletions

File tree

.rubocop.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Layout/LineLength:
5555
- lib/tasks/**/*.rake
5656
- app/admin/**/*.rb
5757
- db/migrate/**/*.rb
58-
- spec/**/*_spec.rb
58+
- spec/**/*.rb
5959
- app/helpers/**/*.rb
6060
- Gemfile
6161
- config/**/*.rb
@@ -68,7 +68,7 @@ Metrics/MethodLength:
6868
- lib/tasks/**/*.rake
6969
- app/admin/**/*.rb
7070
- db/migrate/**/*.rb
71-
- spec/**/*_spec.rb
71+
- spec/**/*.rb
7272
- app/helpers/**/*.rb
7373
- config/**/*.rb
7474

@@ -78,7 +78,7 @@ Metrics/BlockLength:
7878
- lib/tasks/**/*.rake
7979
- app/admin/**/*.rb
8080
- db/migrate/**/*.rb
81-
- spec/**/*_spec.rb
81+
- spec/**/*.rb
8282
- app/helpers/**/*.rb
8383
- config/**/*.rb
8484

@@ -88,7 +88,7 @@ Metrics/AbcSize:
8888
- lib/tasks/**/*.rake
8989
- app/admin/**/*.rb
9090
- db/migrate/**/*.rb
91-
- spec/**/*_spec.rb
91+
- spec/**/*.rb
9292
- app/helpers/**/*.rb
9393
- config/**/*.rb
9494

@@ -98,6 +98,6 @@ Metrics/PerceivedComplexity:
9898
- lib/tasks/**/*.rake
9999
- app/admin/**/*.rb
100100
- db/migrate/**/*.rb
101-
- spec/**/*_spec.rb
101+
- spec/**/*.rb
102102
- app/helpers/**/*.rb
103103
- config/**/*.rb

spec/factories/categories.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,9 @@
33
name { Faker::Team.unique.name }
44
description { Faker::Food.description }
55
is_disabled { false }
6+
7+
trait :disabled do
8+
is_disabled { true }
9+
end
610
end
711
end

spec/factories/items.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
FactoryBot.define do
2+
factory :item do
3+
name { Faker::Commerce.product_name }
4+
description { Faker::Lorem.sentence }
5+
category { association :category }
6+
fixed_parameters { {} }
7+
pricing_options { {} }
8+
is_disabled { false }
9+
is_fixed { false }
10+
is_open { false }
11+
is_selectable_options { false }
12+
open_parameters_label { [] }
13+
formula_parameters { [] }
14+
calculation_formula { nil }
15+
16+
trait :with_fixed_parameters do
17+
fixed_parameters { { "Acquisition" => "2500" } }
18+
is_fixed { true }
19+
formula_parameters { ["Acquisition"] }
20+
calculation_formula { "Acquisition" }
21+
end
22+
23+
trait :with_pricing_options do
24+
pricing_options do
25+
{
26+
"Tier" => {
27+
"1-5" => "100",
28+
"6-15" => "200",
29+
"16+" => "350"
30+
}
31+
}
32+
end
33+
is_selectable_options { true }
34+
formula_parameters { ["Tier"] }
35+
calculation_formula { "Tier" }
36+
end
37+
38+
trait :with_open_parameters do
39+
open_parameters_label { ["Custom"] }
40+
is_open { true }
41+
formula_parameters { ["Custom"] }
42+
calculation_formula { "Custom" }
43+
end
44+
45+
trait :with_invalid_fixed_parameters do
46+
fixed_parameters { { "Acquisition" => "abc" } }
47+
end
48+
49+
trait :with_invalid_pricing_options do
50+
pricing_options { { "Tier" => { "1-5" => "abc" } } }
51+
end
52+
53+
trait :with_disabled_category do
54+
category { association :category, :disabled }
55+
end
56+
57+
trait :without_calculation_formula do
58+
calculation_formula { nil }
59+
end
60+
end
61+
end

spec/models/category_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@
2323
end
2424

2525
it 'allows duplicate names for disabled categories' do
26-
category = create(:category, is_disabled: true)
26+
category = create(:category, :disabled)
2727

2828
2.times do
29-
duplicate_category = build(:category, is_disabled: true, name: category.name)
29+
duplicate_category = build(:category, :disabled, name: category.name)
3030

3131
expect(duplicate_category).to be_valid
3232
expect(duplicate_category.errors[:name]).to be_empty

spec/models/item_spec.rb

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
require 'rails_helper'
2+
3+
RSpec.describe Item, type: :model do
4+
describe 'factory' do
5+
it 'has a valid factory' do
6+
expect(build(:item)).to be_valid
7+
end
8+
end
9+
10+
describe 'associations' do
11+
it { is_expected.to belong_to(:category).optional }
12+
end
13+
14+
describe 'validations' do
15+
subject { build(:item) }
16+
17+
describe 'name' do
18+
it { is_expected.to validate_presence_of(:name) }
19+
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:category_id).with_message('Item name must be unique within category') }
20+
21+
it 'allows same name with different categories' do
22+
category1 = create(:category)
23+
category2 = create(:category)
24+
create(:item, name: 'Test Item', category: category1)
25+
item2 = build(:item, name: 'Test Item', category: category2)
26+
expect(item2).to be_valid
27+
end
28+
end
29+
30+
describe 'category_must_be_active' do
31+
it 'is valid with an active category' do
32+
item = build(:item)
33+
expect(item).to be_valid
34+
end
35+
36+
it 'is valid without a category' do
37+
item = build(:item, category: nil)
38+
expect(item).to be_valid
39+
end
40+
41+
it 'is invalid with a disabled category' do
42+
item = build(:item, :with_disabled_category)
43+
expect(item).not_to be_valid
44+
expect(item.errors[:category]).to include('is disabled')
45+
end
46+
end
47+
48+
describe 'calculation_formula' do
49+
context 'when is_fixed is true' do
50+
let(:item) { build(:item, :with_fixed_parameters, :without_calculation_formula) }
51+
52+
it 'requires calculation_formula' do
53+
expect(item).not_to be_valid
54+
expect(item.errors[:calculation_formula]).to include("can't be blank")
55+
end
56+
end
57+
58+
context 'when is_open is true' do
59+
let(:item) { build(:item, :with_open_parameters, :without_calculation_formula) }
60+
61+
it 'requires calculation_formula' do
62+
expect(item).not_to be_valid
63+
expect(item.errors[:calculation_formula]).to include("can't be blank")
64+
end
65+
end
66+
67+
context 'when is_selectable_options is true' do
68+
let(:item) { build(:item, :with_pricing_options, :without_calculation_formula) }
69+
70+
it 'requires calculation_formula' do
71+
expect(item).not_to be_valid
72+
expect(item.errors[:calculation_formula]).to include("can't be blank")
73+
end
74+
end
75+
76+
context 'when multiple flags are true' do
77+
let(:item) do
78+
build(:item,
79+
fixed_parameters: { "Aquisition" => "2500" },
80+
pricing_options: { "Tier" => { "1-5" => "100" } },
81+
is_fixed: true,
82+
is_selectable_options: true,
83+
calculation_formula: nil)
84+
end
85+
86+
it 'requires calculation_formula' do
87+
expect(item).not_to be_valid
88+
expect(item.errors[:calculation_formula]).to include("can't be blank")
89+
end
90+
end
91+
92+
context 'when no flags are true' do
93+
it 'does not require calculation_formula' do
94+
item = build(:item)
95+
expect(item).to be_valid
96+
end
97+
end
98+
end
99+
100+
describe 'fixed_parameters' do
101+
it 'is valid with empty hash' do
102+
item = build(:item, fixed_parameters: {})
103+
expect(item).to be_valid
104+
end
105+
106+
it 'is valid with numeric string values' do
107+
item = build(:item, :with_fixed_parameters)
108+
expect(item).to be_valid
109+
end
110+
111+
it 'is valid with numeric values' do
112+
item = build(:item, fixed_parameters: { "Acquisition" => 2500 })
113+
expect(item).to be_valid
114+
end
115+
116+
it 'is invalid with non-numeric string values' do
117+
item = build(:item, :with_invalid_fixed_parameters)
118+
expect(item).not_to be_valid
119+
expect(item.errors[:fixed_parameters]).to include("value for 'Acquisition' must be a number")
120+
end
121+
122+
it 'is invalid with non-hash values' do
123+
item = build(:item, fixed_parameters: "not_a_hash")
124+
expect(item).not_to be_valid
125+
expect(item.errors[:fixed_parameters]).to include("must be a JSON object")
126+
end
127+
end
128+
129+
describe 'pricing_options' do
130+
it 'is valid with empty hash' do
131+
item = build(:item, pricing_options: {})
132+
expect(item).to be_valid
133+
end
134+
135+
it 'is valid with nested numeric string values' do
136+
item = build(:item, :with_pricing_options)
137+
expect(item).to be_valid
138+
end
139+
140+
it 'is valid with nested numeric values' do
141+
item = build(:item, pricing_options: { "Tier" => { "1-5" => 100 } })
142+
expect(item).to be_valid
143+
end
144+
145+
it 'is invalid with non-numeric nested string values' do
146+
item = build(:item, :with_invalid_pricing_options)
147+
expect(item).not_to be_valid
148+
expect(item.errors[:pricing_options]).to include("value for 'Tier -> 1-5' must be a number")
149+
end
150+
151+
it 'is invalid with non-hash values' do
152+
item = build(:item, pricing_options: "not_a_hash")
153+
expect(item).not_to be_valid
154+
expect(item.errors[:pricing_options]).to include("must be a JSON object")
155+
end
156+
end
157+
end
158+
end

0 commit comments

Comments
 (0)