fabrication 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/LICENSE +14 -0
  2. data/README.markdown +7 -1
  3. data/Rakefile +19 -0
  4. data/lib/fabrication.rb +11 -0
  5. data/lib/fabrication/config.rb +1 -1
  6. data/lib/fabrication/{cucumber.rb → cucumber/step_fabricator.rb} +2 -7
  7. data/lib/fabrication/fabricator.rb +6 -1
  8. data/lib/fabrication/support.rb +1 -1
  9. data/lib/fabrication/syntax/make.rb +26 -0
  10. data/lib/fabrication/transform.rb +26 -0
  11. data/lib/fabrication/version.rb +1 -1
  12. data/lib/rails/generators/fabrication/cucumber_steps/templates/fabrication_steps.rb +0 -2
  13. data/lib/rails/generators/fabrication/turnip_steps/templates/fabrication_steps.rb +57 -0
  14. data/lib/rails/generators/fabrication/turnip_steps/turnip_steps_generator.rb +21 -0
  15. metadata +156 -135
  16. data/spec/fabrication/attribute_spec.rb +0 -53
  17. data/spec/fabrication/config_spec.rb +0 -32
  18. data/spec/fabrication/cucumber_spec.rb +0 -116
  19. data/spec/fabrication/fabricator_spec.rb +0 -67
  20. data/spec/fabrication/generator/active_record_spec.rb +0 -83
  21. data/spec/fabrication/generator/base_spec.rb +0 -108
  22. data/spec/fabrication/schematic_spec.rb +0 -199
  23. data/spec/fabrication/sequencer_spec.rb +0 -98
  24. data/spec/fabrication/support_spec.rb +0 -54
  25. data/spec/fabrication_spec.rb +0 -329
  26. data/spec/fabricators/active_record_fabricator.rb +0 -21
  27. data/spec/fabricators/cool_object_fabricator.rb +0 -1
  28. data/spec/fabricators/mongoid_fabricator.rb +0 -36
  29. data/spec/fabricators/plain_old_ruby_object_fabricator.rb +0 -51
  30. data/spec/fabricators/sequel_fabricator.rb +0 -15
  31. data/spec/fabricators/sequencer_fabricator.rb +0 -9
  32. data/spec/spec_helper.rb +0 -12
  33. data/spec/support/active_record.rb +0 -65
  34. data/spec/support/mongoid.rb +0 -74
  35. data/spec/support/plain_old_ruby_objects.rb +0 -68
  36. data/spec/support/sequel.rb +0 -22
  37. data/spec/support/sequel_migrations/001_create_tables.rb +0 -23
@@ -1,199 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Fabrication::Schematic do
4
-
5
- let(:schematic) do
6
- Fabrication::Schematic.new(OpenStruct) do
7
- name "Orgasmo"
8
- something(:param => 2) { "hi!" }
9
- another_thing { 25 }
10
- end
11
- end
12
-
13
- describe "generator selection" do
14
- context "for an activerecord object" do
15
- it "uses the activerecord generator" do
16
- Fabrication::Schematic.new(Division).generator.should == Fabrication::Generator::ActiveRecord
17
- end
18
- end
19
- context "for a mongoid object" do
20
- it "uses the base generator" do
21
- Fabrication::Schematic.new(Author).generator.should == Fabrication::Generator::Mongoid
22
- end
23
- end
24
- context "for a sequel object" do
25
- it "uses the base generator" do
26
- Fabrication::Schematic.new(ParentSequelModel).generator.should == Fabrication::Generator::Sequel
27
- end
28
- end
29
- end
30
-
31
- describe ".new" do
32
- it "stores the klass" do
33
- schematic.klass.should == OpenStruct
34
- end
35
- it "stores the generator" do
36
- schematic.generator.should == Fabrication::Generator::Base
37
- end
38
- it "stores the attributes" do
39
- schematic.attributes.size.should == 3
40
- end
41
- end
42
-
43
- describe "#attribute" do
44
- it "returns the requested attribute if it exists" do
45
- schematic.attribute(:name).name.should == :name
46
- end
47
- it "returns nil if it does not exist" do
48
- schematic.attribute(:not_there).should be_nil
49
- end
50
- end
51
-
52
- describe "#attributes" do
53
- it "always returns an empty array" do
54
- schematic.attributes = nil
55
- schematic.attributes.should == []
56
- end
57
- end
58
-
59
- describe "#generate" do
60
-
61
- context "an instance" do
62
-
63
- it "generates a new instance" do
64
- schematic.generate.should be_kind_of(OpenStruct)
65
- end
66
-
67
- end
68
-
69
- context "an attributes hash" do
70
-
71
- let(:hash) { schematic.generate(:attributes => true) }
72
-
73
- it "generates a hash with the object's attributes" do
74
- hash.should be_kind_of(Hash)
75
- end
76
-
77
- it "has the correct attributes" do
78
- hash.size.should == 3
79
- hash[:name].should == 'Orgasmo'
80
- hash[:something].should == "hi!"
81
- hash[:another_thing].should == 25
82
- end
83
-
84
- end
85
-
86
- end
87
-
88
- describe "#merge" do
89
-
90
- context "without inheritance" do
91
-
92
- subject { schematic }
93
-
94
- it "stored 'name' correctly" do
95
- attribute = subject.attribute(:name)
96
- attribute.name.should == :name
97
- attribute.params.should == {}
98
- attribute.value.should == "Orgasmo"
99
- end
100
-
101
- it "stored 'something' correctly" do
102
- attribute = subject.attribute(:something)
103
- attribute.name.should == :something
104
- attribute.params.should == { :param => 2 }
105
- Proc.should === attribute.value
106
- attribute.value.call.should == "hi!"
107
- end
108
-
109
- it "stored 'another_thing' correctly" do
110
- attribute = subject.attribute(:another_thing)
111
- attribute.name.should == :another_thing
112
- attribute.params.should == {}
113
- Proc.should === attribute.value
114
- attribute.value.call.should == 25
115
- end
116
-
117
- end
118
-
119
- context "with inheritance" do
120
-
121
- subject do
122
- schematic.merge do
123
- name { "Willis" }
124
- something "Else!"
125
- another_thing(:thats_what => 'she_said') { "Boo-ya!" }
126
- end
127
- end
128
-
129
- it "stored 'name' correctly" do
130
- attribute = subject.attribute(:name)
131
- attribute.name.should == :name
132
- attribute.params.should == {}
133
- Proc.should === attribute.value
134
- attribute.value.call.should == "Willis"
135
- end
136
-
137
- it "stored 'something' correctly" do
138
- attribute = subject.attribute(:something)
139
- attribute.name.should == :something
140
- attribute.params.should == {}
141
- attribute.value.should == "Else!"
142
- end
143
-
144
- it "stored 'another_thing' correctly" do
145
- attribute = subject.attribute(:another_thing)
146
- attribute.name.should == :another_thing
147
- attribute.params.should == { :thats_what => 'she_said' }
148
- Proc.should === attribute.value
149
- attribute.value.call.should == "Boo-ya!"
150
- end
151
-
152
- end
153
-
154
- end
155
-
156
- describe "#on_init" do
157
- let(:init_block) { lambda {} }
158
- let(:init_schematic) do
159
- block = init_block
160
- Fabrication::Schematic.new(OpenStruct) do
161
- on_init &block
162
- end
163
- end
164
-
165
- it "stores the on_init callback" do
166
- init_schematic.callbacks[:on_init].should == init_block
167
- end
168
-
169
- context "with inheritance" do
170
- let(:child_block) { lambda {} }
171
- let(:child_schematic) do
172
- block = child_block
173
- init_schematic.merge do
174
- on_init &block
175
- end
176
- end
177
-
178
- it "overwrites the on_init callback" do
179
- child_schematic.callbacks[:on_init].should == child_block
180
- end
181
- end
182
- end
183
-
184
- context "when overriding" do
185
- let(:address) { Address.new }
186
-
187
- it "symbolizes attribute keys" do
188
- Fabricator(:address) do
189
- city { raise 'should not be called' }
190
- end
191
- Fabricator(:contact) do
192
- address
193
- end
194
- lambda do
195
- Fabricate(:contact, 'address' => address)
196
- end.should_not raise_error(RuntimeError)
197
- end
198
- end
199
- end
@@ -1,98 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Fabrication::Sequencer do
4
-
5
- context 'with no arguments' do
6
- subject { Fabrication::Sequencer.sequence }
7
-
8
- it { should == 0 }
9
- it 'creates a default sequencer' do
10
- Fabrication::Sequencer.sequences[:_default].should == 1
11
- end
12
- end
13
-
14
- context 'with only a name' do
15
-
16
- it 'starts with 0' do
17
- Fabricate.sequence(:incr).should == 0
18
- end
19
-
20
- it 'increments by one with each call' do
21
- Fabricate.sequence(:incr).should == 1
22
- Fabricate.sequence(:incr).should == 2
23
- Fabricate.sequence(:incr).should == 3
24
- Fabricate.sequence(:incr).should == 4
25
- end
26
-
27
- it 'increments counters separately' do
28
- Fabricate.sequence(:number).should == 0
29
- Fabricate.sequence(:number).should == 1
30
- Fabricate.sequence(:number).should == 2
31
- Fabricate.sequence(:number).should == 3
32
- end
33
-
34
- end
35
-
36
- context 'with a name and starting number' do
37
-
38
- it 'starts with the number provided' do
39
- Fabricate.sequence(:higher, 69).should == 69
40
- end
41
-
42
- it 'increments by one with each call' do
43
- Fabricate.sequence(:higher).should == 70
44
- Fabricate.sequence(:higher, 69).should == 71
45
- Fabricate.sequence(:higher).should == 72
46
- Fabricate.sequence(:higher).should == 73
47
- end
48
-
49
- end
50
-
51
- context 'with a block' do
52
-
53
- it 'yields the number to the block and returns the value' do
54
- Fabricate.sequence(:email) do |i|
55
- "user#{i}@example.com"
56
- end.should == "user0@example.com"
57
- end
58
-
59
- it 'increments by one with each call' do
60
- Fabricate.sequence(:email) do |i|
61
- "user#{i}@example.com"
62
- end.should == "user1@example.com"
63
-
64
- Fabricate.sequence(:email) do |i|
65
- "user#{i}@example.com"
66
- end.should == "user2@example.com"
67
- end
68
-
69
- context 'and then without a block' do
70
- it 'remembers the original block' do
71
- Fabricate.sequence :ordinal, &:ordinalize
72
- Fabricate.sequence(:ordinal).should == "1st"
73
- end
74
- context 'and then with a new block' do
75
- it 'evaluates the new block' do
76
- Fabricate.sequence(:ordinal) do |i|
77
- i ** 2
78
- end.should == 4
79
- end
80
- it 'remembers the new block' do
81
- Fabricate.sequence(:ordinal).should == 9
82
- end
83
- end
84
- end
85
- end
86
- context 'with two sequences declared with blocks' do
87
- it 'remembers both blocks' do
88
- Fabricate.sequence(:shapes) do |i|
89
- %w[square circle rectangle][i % 3]
90
- end
91
- Fabricate.sequence(:colors) do |i|
92
- %w[red green blue][i % 3]
93
- end
94
- Fabricate.sequence(:shapes).should == 'circle'
95
- Fabricate.sequence(:colors).should == 'green'
96
- end
97
- end
98
- end
@@ -1,54 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Fabrication::Support do
4
-
5
- describe ".class_for" do
6
-
7
- context "with a class that exists" do
8
-
9
- it "returns the class for a class" do
10
- Fabrication::Support.class_for(Object).should == Object
11
- end
12
-
13
- it "returns the class for a class name string" do
14
- Fabrication::Support.class_for('object').should == Object
15
- end
16
-
17
- it "returns the class for a class name symbol" do
18
- Fabrication::Support.class_for(:object).should == Object
19
- end
20
-
21
- end
22
-
23
- context "with a class that doesn't exist" do
24
-
25
- it "returns nil for a class name string" do
26
- Fabrication::Support.class_for('your_mom').should be_nil
27
- end
28
-
29
- it "returns nil for a class name symbol" do
30
- Fabrication::Support.class_for(:your_mom).should be_nil
31
- end
32
-
33
- end
34
-
35
- end
36
-
37
- describe ".find_definitions" do
38
-
39
- before(:all) do
40
- Fabrication.clear_definitions
41
- Fabrication::Support.find_definitions
42
- end
43
-
44
- it "has an awesome object" do
45
- Fabrication::Fabricator.schematics[:awesome_object].should be
46
- end
47
-
48
- it "has a cool object" do
49
- Fabrication::Fabricator.schematics[:cool_object].should be
50
- end
51
-
52
- end
53
-
54
- end
@@ -1,329 +0,0 @@
1
- require 'spec_helper'
2
-
3
- shared_examples 'something fabricatable' do
4
- subject { Fabricate(fabricator_name) }
5
-
6
- context 'defaults from fabricator' do
7
- its(:dynamic_field) { should == 'dynamic content' }
8
- its(:nil_field) { should be_nil }
9
- its(:number_field) { should == 5 }
10
- its(:string_field) { should == 'content' }
11
- end
12
-
13
- context 'model callbacks are fired' do
14
- its(:before_save_value) { should == 11 }
15
- end
16
-
17
- context 'overriding at fabricate time' do
18
- subject do
19
- Fabricate(
20
- fabricator_name,
21
- :string_field => 'new content',
22
- :number_field => 10,
23
- :nil_field => nil
24
- ) do
25
- dynamic_field { 'new dynamic content' }
26
- end
27
- end
28
- its('collection_field.size') { should == 2 }
29
- its('collection_field.first.number_field') { should == 10 }
30
- its('collection_field.last.number_field') { should == 10 }
31
- its(:dynamic_field) { should == 'new dynamic content' }
32
- its(:nil_field) { should be_nil }
33
- its(:number_field) { should == 10 }
34
- its(:string_field) { should == 'new content' }
35
- end
36
-
37
- context 'state of the object' do
38
- it 'generates a fresh object every time' do
39
- Fabricate(fabricator_name).should_not == subject
40
- end
41
-
42
- it { should be_persisted }
43
- its('collection_field.first') { should be_persisted }
44
- its('collection_field.last') { should be_persisted }
45
- end
46
-
47
- context 'attributes for' do
48
- subject { Fabricate.attributes_for(fabricator_name) }
49
- it { should be_kind_of(HashWithIndifferentAccess) }
50
- it 'serializes the attributes' do
51
- should include({
52
- :dynamic_field => 'dynamic content',
53
- :nil_field => nil,
54
- :number_field => 5,
55
- :string_field => 'content'
56
- })
57
- end
58
- end
59
- end
60
-
61
- describe Fabrication do
62
-
63
- context 'plain old ruby objects' do
64
- let(:fabricator_name) { :parent_ruby_object }
65
- it_should_behave_like 'something fabricatable'
66
- end
67
-
68
- context 'active_record models' do
69
- let(:fabricator_name) { :parent_active_record_model }
70
- it_should_behave_like 'something fabricatable'
71
- end
72
-
73
- context 'mongoid documents' do
74
- let(:fabricator_name) { :parent_mongoid_document }
75
- it_should_behave_like 'something fabricatable'
76
- end
77
-
78
- context 'sequel models' do
79
- let(:fabricator_name) { :parent_sequel_model }
80
- it_should_behave_like 'something fabricatable'
81
- end
82
-
83
- context 'when the class requires a constructor' do
84
- subject do
85
- Fabricate(:city) do
86
- on_init { init_with('Jacksonville Beach', 'FL') }
87
- end
88
- end
89
-
90
- its(:city) { should == 'Jacksonville Beach' }
91
- its(:state) { should == 'FL' }
92
- end
93
-
94
- context 'with a class in a module' do
95
- subject { Fabricate("Something::Amazing", :stuff => "things") }
96
- its(:stuff) { should == "things" }
97
- end
98
-
99
- context 'with the generation parameter' do
100
-
101
- let(:person) do
102
- Fabricate(:person, :first_name => "Paul") do
103
- last_name { |person| "#{person.first_name}#{person.age}" }
104
- age 50
105
- end
106
- end
107
-
108
- it 'evaluates the fields in order of declaration' do
109
- person.last_name.should == "Paul"
110
- end
111
-
112
- end
113
-
114
- context 'multiple instance' do
115
-
116
- let(:person1) { Fabricate(:person, :first_name => 'Jane') }
117
- let(:person2) { Fabricate(:person, :first_name => 'John') }
118
-
119
- it 'person1 is named Jane' do
120
- person1.first_name.should == 'Jane'
121
- end
122
-
123
- it 'person2 is named John' do
124
- person2.first_name.should == 'John'
125
- end
126
-
127
- it 'they have different last names' do
128
- person1.last_name.should_not == person2.last_name
129
- end
130
-
131
- end
132
-
133
- context 'with a specified class name' do
134
-
135
- let(:someone) { Fabricate(:someone) }
136
-
137
- before do
138
- Fabricator(:someone, :class_name => :person) do
139
- first_name "Paul"
140
- end
141
- end
142
-
143
- it 'generates the person as someone' do
144
- someone.first_name.should == "Paul"
145
- end
146
-
147
- end
148
-
149
- context 'with an active record object' do
150
-
151
- before { TestMigration.up }
152
- after { TestMigration.down }
153
-
154
- before(:all) do
155
- Fabricator(:main_company, :from => :company) do
156
- name { Faker::Company.name }
157
- divisions!(:count => 4)
158
- non_field { "hi" }
159
- after_create { |o| o.update_attribute(:city, "Jacksonville Beach") }
160
- end
161
-
162
- Fabricator(:other_company, :from => :main_company) do
163
- divisions(:count => 2)
164
- after_build { |o| o.name = "Crazysauce" }
165
- end
166
- end
167
-
168
- let(:company) { Fabricate(:main_company, :name => "Hashrocket") }
169
- let(:other_company) { Fabricate(:other_company) }
170
-
171
- it 'generates field blocks immediately' do
172
- company.name.should == "Hashrocket"
173
- end
174
-
175
- it 'generates associations immediately when forced' do
176
- Division.find_all_by_company_id(company.id).count.should == 4
177
- end
178
-
179
- it 'generates non-database backed fields immediately' do
180
- company.instance_variable_get(:@non_field).should == 'hi'
181
- end
182
-
183
- it 'executes after build blocks' do
184
- other_company.name.should == 'Crazysauce'
185
- end
186
-
187
- it 'executes after create blocks' do
188
- company.city.should == 'Jacksonville Beach'
189
- end
190
-
191
- it 'overrides associations' do
192
- Fabricate(:company, :divisions => []).divisions.should == []
193
- end
194
-
195
- it 'overrides inherited associations' do
196
- other_company.divisions.count.should == 2
197
- Division.count.should == 2
198
- end
199
-
200
- end
201
-
202
- context 'with a mongoid document' do
203
-
204
- let(:author) { Fabricate(:author) }
205
-
206
- it "sets the author name" do
207
- author.name.should == "George Orwell"
208
- end
209
-
210
- it 'generates four books' do
211
- author.books.map(&:title).should == (1..4).map { |i| "book title #{i}" }
212
- end
213
-
214
- it "sets dynamic fields" do
215
- Fabricate(:special_author).mongoid_dynamic_field.should == 50
216
- end
217
-
218
- it "sets lazy dynamic fields" do
219
- Fabricate(:special_author).lazy_dynamic_field.should == "foo"
220
- end
221
- end
222
-
223
- context 'with multiple callbacks' do
224
- let(:child) { Fabricate(:child) }
225
-
226
- it "runs the first callback" do
227
- child.first_name.should == "Johnny"
228
- end
229
-
230
- it "runs the second callback" do
231
- child.age.should == 10
232
- end
233
- end
234
-
235
- context 'with multiple, inherited callbacks' do
236
- let(:senior) { Fabricate(:senior) }
237
-
238
- it "runs the parent callbacks first" do
239
- senior.age.should == 70
240
- end
241
- end
242
-
243
- context 'with a parent fabricator' do
244
-
245
- context 'and a previously defined parent' do
246
-
247
- let(:ernie) { Fabricate(:hemingway) }
248
-
249
- it 'has the values from the parent' do
250
- ernie.books.count.should == 4
251
- end
252
-
253
- it 'overrides specified values from the parent' do
254
- ernie.name.should == 'Ernest Hemingway'
255
- end
256
-
257
- end
258
-
259
- context 'and a class name as a parent' do
260
-
261
- let(:greyhound) { Fabricate(:greyhound) }
262
-
263
- it 'has the breed defined' do
264
- greyhound.breed.should == 'greyhound'
265
- end
266
-
267
- it 'does not have a name' do
268
- greyhound.name.should be_nil
269
- end
270
-
271
- end
272
-
273
- end
274
-
275
- describe '.clear_definitions' do
276
- before { Fabrication.clear_definitions }
277
- after { Fabrication::Support.find_definitions }
278
-
279
- it 'should not generate authors' do
280
- Fabrication::Fabricator.schematics.has_key?(:author).should be_false
281
- end
282
- end
283
-
284
- context 'when defining a fabricator twice' do
285
- it 'throws an error' do
286
- lambda { Fabricator(:author) {} }.should raise_error(Fabrication::DuplicateFabricatorError)
287
- end
288
- end
289
-
290
- context "when defining a fabricator for a class that doesn't exist" do
291
- it 'throws an error' do
292
- lambda { Fabricator(:your_mom) }.should raise_error(Fabrication::UnfabricatableError)
293
- end
294
- end
295
-
296
- context 'when generating from a non-existant fabricator' do
297
- it 'throws an error' do
298
- lambda { Fabricate(:your_mom) }.should raise_error(Fabrication::UnknownFabricatorError)
299
- end
300
- end
301
-
302
- context 'defining a fabricator without a block' do
303
-
304
- before(:all) do
305
- class Widget; end
306
- Fabricator(:widget)
307
- end
308
-
309
- it 'works fine' do
310
- Fabricate(:widget).should be
311
- end
312
-
313
- end
314
-
315
- describe "Fabricate with a sequence" do
316
- subject { Fabricate(:sequencer) }
317
-
318
- its(:simple_iterator) { should == 0 }
319
- its(:param_iterator) { should == 10 }
320
- its(:block_iterator) { should == "block2" }
321
-
322
- context "when namespaced" do
323
- subject { Fabricate("Sequencer::Namespaced") }
324
-
325
- its(:iterator) { should == 0 }
326
- end
327
- end
328
-
329
- end