fabrication 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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