Skip to content

Commit 4e459a7

Browse files
committed
Refactor specs to replace inline parameter class definitions with FactoryBot factories
1 parent 69ab2d5 commit 4e459a7

File tree

2 files changed

+48
-183
lines changed

2 files changed

+48
-183
lines changed

spec/factories/user_parameters.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ class UserParameter < StructuredParams::Params
1919
email { 'tanaka@example.com' }
2020
age { 30 }
2121
address { attributes_for(:address_parameter) }
22-
hobbies { attributes_for_list(:hobby_parameter, 3) }
23-
tags { [] }
22+
hobbies { attributes_for_list(:hobby_parameter, 2) }
23+
tags { %w[Ruby Rails Web] }
2424

2525
initialize_with { new(attributes) }
2626
end

spec/params_spec.rb

Lines changed: 46 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -3,64 +3,10 @@
33
require 'spec_helper'
44

55
RSpec.describe StructuredParams::Params do
6-
# Test parameter class definitions
7-
let(:address_parameter_class) do
8-
Class.new(described_class) do
9-
def self.name
10-
'AddressParameter'
11-
end
12-
13-
attribute :postal_code, :string
14-
attribute :prefecture, :string
15-
attribute :city, :string
16-
attribute :street, :string
17-
18-
validates :postal_code, presence: true, format: { with: /\A\d{3}-\d{4}\z/ }
19-
validates :prefecture, presence: true
20-
validates :city, presence: true
21-
end
22-
end
23-
24-
let(:hobby_parameter_class) do
25-
Class.new(described_class) do
26-
def self.name
27-
'HobbyParameter'
28-
end
29-
30-
attribute :name, :string
31-
attribute :level, :integer
32-
attribute :years_experience, :integer
33-
34-
validates :name, presence: true
35-
validates :level, inclusion: { in: 1..3 }
36-
validates :years_experience, numericality: { greater_than_or_equal_to: 0 }
37-
end
38-
end
39-
40-
let(:user_parameter_class) do
41-
address_class = address_parameter_class
42-
hobby_class = hobby_parameter_class
43-
44-
Class.new(described_class) do
45-
def self.name
46-
'UserParameter'
47-
end
48-
49-
attribute :name, :string
50-
attribute :email, :string
51-
attribute :age, :integer
52-
attribute :address, :object, value_class: address_class
53-
attribute :hobbies, :array, value_class: hobby_class
54-
attribute :tags, :array, value_type: :string
55-
56-
validates :name, presence: true, length: { maximum: 50 }
57-
validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
58-
validates :age, numericality: { greater_than: 0 }
59-
end
60-
end
61-
626
describe '.permit_attribute_names' do
63-
subject(:permit_attribute_names) { user_parameter_class.permit_attribute_names }
7+
subject(:permit_attribute_names) do
8+
UserParameter.permit_attribute_names
9+
end
6410

6511
it {
6612
expect(permit_attribute_names).to eq([:name, :email, :age,
@@ -84,14 +30,14 @@ def self.name
8430
},
8531
hobbies: [
8632
{ name: 'programming', level: 3, years_experience: 10 },
87-
{ name: '読書', level: 2, years_experience: 5 }
33+
{ name: 'Web', level: 2, years_experience: 5 }
8834
],
89-
tags: %w[Ruby Rails 技術書]
35+
tags: %w[Ruby Rails Web]
9036
}
9137
end
9238

9339
context 'with valid parameters' do
94-
subject(:user_param) { user_parameter_class.new(valid_params) }
40+
subject(:user_param) { build(:user_parameter, **valid_params) }
9541

9642
it {
9743
expect(user_param).to have_attributes(
@@ -104,7 +50,7 @@ def self.name
10450
context 'with object parameters' do
10551
subject(:address) { user_param.address }
10652

107-
it { is_expected.to be_instance_of(address_parameter_class) }
53+
it { is_expected.to be_instance_of(AddressParameter) }
10854

10955
it {
11056
expect(address).to have_attributes(
@@ -120,20 +66,20 @@ def self.name
12066
subject(:hobbies) { user_param.hobbies }
12167

12268
it { is_expected.to be_an(Array) }
123-
it { is_expected.to contain_exactly(hobby_parameter_class, hobby_parameter_class) }
69+
it { is_expected.to contain_exactly(HobbyParameter, HobbyParameter) }
12470
it { expect(hobbies[0]).to have_attributes(name: 'programming', level: 3, years_experience: 10) }
125-
it { expect(hobbies[1]).to have_attributes(name: '読書', level: 2, years_experience: 5) }
71+
it { expect(hobbies[1]).to have_attributes(name: 'Web', level: 2, years_experience: 5) }
12672
end
12773

12874
context 'with array of strings' do
12975
subject { user_param.tags }
13076

131-
it { is_expected.to eq(%w[Ruby Rails 技術書]) }
77+
it { is_expected.to eq(%w[Ruby Rails Web]) }
13278
end
13379
end
13480

13581
context 'with ActionController::Parameters' do
136-
subject(:user_param) { user_parameter_class.new(action_controller_params) }
82+
subject(:user_param) { UserParameter.new(action_controller_params) }
13783

13884
let(:action_controller_params) do
13985
ActionController::Parameters.new(valid_params.merge(unpermitted: 'value'))
@@ -147,50 +93,24 @@ def self.name
14793

14894
context 'with invalid parameter type' do
14995
it 'raises ArgumentError' do
150-
expect { user_parameter_class.new('invalid') }.to raise_error(ArgumentError)
96+
expect { UserParameter.new('invalid') }.to raise_error(ArgumentError)
15197
end
15298
end
15399
end
154100

155101
describe '#valid?' do
156102
context 'with valid object parameters' do
157-
subject(:user_param) { user_parameter_class.new(valid_params) }
158-
159-
let(:valid_params) do
160-
{
161-
name: 'Tanaka Taro',
162-
email: 'tanaka@example.com',
163-
age: 30,
164-
address: {
165-
postal_code: '123-4567',
166-
prefecture: 'Tokyo',
167-
city: 'Shibuya-ku',
168-
street: 'Saka 1-2-3'
169-
},
170-
hobbies: [
171-
{ name: 'programming', level: 3, years_experience: 10 }
172-
]
173-
}
174-
end
103+
subject(:user_param) { build(:user_parameter) }
175104

176105
it { is_expected.to be_valid }
177106
end
178107

179108
context 'with invalid parent parameters' do
180-
subject(:user_param) { user_parameter_class.new(invalid_parent_params) }
181-
182-
let(:invalid_parent_params) do
183-
{
184-
name: '', # invalid
185-
email: 'invalid-email', # invalid
186-
age: -1, # invalid
187-
address: {
188-
postal_code: '123-4567',
189-
prefecture: 'Tokyo',
190-
city: 'Shibuya-ku',
191-
street: 'Saka 1-2-3'
192-
}
193-
}
109+
subject(:user_param) do
110+
build(:user_parameter,
111+
name: '',
112+
email: 'invalid-email',
113+
age: -1)
194114
end
195115

196116
it 'returns false and includes parent validation errors' do
@@ -202,20 +122,15 @@ def self.name
202122
end
203123

204124
context 'with invalid object single object' do
205-
subject(:user_param) { user_parameter_class.new(invalid_address_params) }
206-
207-
let(:invalid_address_params) do
208-
{
209-
name: '', # invalid
210-
email: 'tanaka@example.com',
211-
age: 30,
212-
address: {
213-
postal_code: 'invalid', # invalid format
214-
prefecture: '', # blank
215-
city: 'Shibuya-ku',
216-
street: 'Saka 1-2-3'
217-
}
218-
}
125+
subject(:user_param) do
126+
build(:user_parameter,
127+
name: '', # blank
128+
address: {
129+
postal_code: 'invalid', # invalid format
130+
prefecture: '', # blank
131+
city: 'Shibuya-ku',
132+
street: 'Saka 1-2-3'
133+
})
219134
end
220135

221136
it 'returns false and includes object validation errors' do
@@ -227,94 +142,46 @@ def self.name
227142
end
228143

229144
context 'with invalid object array objects' do
230-
subject(:user_param) { user_parameter_class.new(invalid_hobbies_params) }
231-
232-
let(:invalid_hobbies_params) do
233-
{
234-
name: 'Tanaka Taro',
235-
email: 'tanaka@example.com',
236-
age: 30,
237-
hobbies: [
238-
{ name: '', level: 5, years_experience: -1 }, # all invalid
239-
{ name: 'valid hobby', level: 2, years_experience: 3 } # valid
240-
]
241-
}
145+
subject(:user_param) do
146+
build(:user_parameter,
147+
hobbies: [
148+
{ name: '', level: 5, years_experience: -1 }, # all invalid
149+
{ name: 'valid hobby', level: 2, years_experience: 3 } # valid
150+
])
242151
end
243152

244153
it 'returns false and includes array validation errors with index' do
245154
expect(user_param).not_to be_valid
246-
expect(user_param.errors['hobbies.0.name']).to include("can't be blank")
247-
expect(user_param.errors['hobbies.0.level']).to include('is not included in the list')
248-
expect(user_param.errors['hobbies.0.years_experience']).to include('must be greater than or equal to 0')
155+
expect(user_param.errors[:'hobbies.0.name']).to include("can't be blank")
156+
expect(user_param.errors[:'hobbies.0.level']).to include('is not included in the list')
157+
expect(user_param.errors[:'hobbies.0.years_experience']).to include('must be greater than or equal to 0')
249158
end
250159
end
251160
end
252161

253162
describe '#attributes' do
254-
subject(:attributes) { user_parameter_class.new(params).attributes(symbolize: symbolize) }
163+
subject(:attributes) { build(:user_parameter, **user_param_attributes).attributes(symbolize: symbolize) }
255164

256-
let(:symbolize) { false }
165+
let(:user_param_attributes) { attributes_for(:user_parameter) }
257166

258-
let(:params) do
259-
{
260-
name: 'Tanaka Taro',
261-
email: 'tanaka@example.com',
262-
age: 30,
263-
address: {
264-
postal_code: '123-4567',
265-
prefecture: 'Tokyo',
266-
city: 'Shibuya-ku',
267-
street: 'Saka 1-2-3'
268-
},
269-
hobbies: [
270-
{ name: 'programming', level: 3, years_experience: 10 }
271-
],
272-
tags: %w[Ruby Rails]
273-
}
274-
end
167+
context 'when symbolize: false' do
168+
let(:symbolize) { false }
275169

276-
it 'returns attributes with objects converted to hashes' do
277-
expect(attributes).to include(
278-
'name' => 'Tanaka Taro',
279-
'address' => hash_including(
280-
'postal_code' => '123-4567',
281-
'prefecture' => 'Tokyo',
282-
'city' => 'Shibuya-ku',
283-
'street' => 'Saka 1-2-3'
284-
),
285-
'hobbies' => array_including(
286-
hash_including('name' => 'programming', 'level' => 3, 'years_experience' => 10)
287-
),
288-
'tags' => %w[Ruby Rails]
289-
)
170+
it { is_expected.to eq user_param_attributes.deep_stringify_keys }
290171
end
291172

292173
context 'with symbolize: true' do
293174
let(:symbolize) { true }
294175

295-
it 'returns symbolized attributes' do
296-
expect(attributes).to include(
297-
name: 'Tanaka Taro',
298-
address: hash_including(
299-
postal_code: '123-4567',
300-
prefecture: 'Tokyo',
301-
city: 'Shibuya-ku',
302-
street: 'Saka 1-2-3'
303-
),
304-
hobbies: array_including(
305-
hash_including(name: 'programming', level: 3, years_experience: 10)
306-
),
307-
tags: %w[Ruby Rails]
308-
)
309-
end
176+
it { is_expected.to eq user_param_attributes.deep_symbolize_keys }
310177
end
311178
end
312179

313180
describe 'edge cases' do
314-
context 'with nil object values' do
315-
subject(:user_param) { user_parameter_class.new(params_with_nil) }
181+
subject(:user_param) { build(:user_parameter, **params) }
316182

317-
let(:params_with_nil) do
183+
context 'with nil object values' do
184+
let(:params) do
318185
{
319186
name: 'Tanaka Taro',
320187
email: 'tanaka@example.com',
@@ -335,9 +202,7 @@ def self.name
335202
end
336203

337204
context 'with empty arrays' do
338-
subject(:user_param) { user_parameter_class.new(params_with_empty_arrays) }
339-
340-
let(:params_with_empty_arrays) do
205+
let(:params) do
341206
{
342207
name: 'Tanaka Taro',
343208
email: 'tanaka@example.com',

0 commit comments

Comments
 (0)