fabrication 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/fabrication/cucumber.rb +104 -0
- data/lib/fabrication/sequencer.rb +9 -3
- data/lib/fabrication/version.rb +1 -1
- data/lib/rails/generators/fabrication/cucumber_steps/templates/fabrication_steps.rb +23 -79
- data/spec/fabrication/cucumber_spec.rb +116 -0
- data/spec/fabrication/sequencer_spec.rb +28 -1
- data/spec/spec_helper.rb +1 -1
- metadata +4 -2
@@ -0,0 +1,104 @@
|
|
1
|
+
module Fabrication
|
2
|
+
module Cucumber
|
3
|
+
class StepFabricator
|
4
|
+
attr_reader :model
|
5
|
+
|
6
|
+
def initialize(model_name, opts ={})
|
7
|
+
@model = dehumanize(model_name)
|
8
|
+
@fabricator = @model.singularize.to_sym
|
9
|
+
@parent_name = opts.delete(:parent)
|
10
|
+
end
|
11
|
+
|
12
|
+
def from_table(table, extra={})
|
13
|
+
hashes = singular? ? [table.rows_hash] : table.hashes
|
14
|
+
hashes.map do |hash|
|
15
|
+
make(parameterize_hash(hash).merge(extra))
|
16
|
+
end.tap {|o| remember(o) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def n(count, attrs={})
|
20
|
+
count.times.map { make(attrs) }.tap {|o| remember(o) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def has_many(children)
|
24
|
+
instance = Fabrications[@fabricator]
|
25
|
+
children = dehumanize(children)
|
26
|
+
[Fabrications[children]].flatten.each do |child|
|
27
|
+
child.send("#{klass.to_s.underscore.downcase}=", instance)
|
28
|
+
child.respond_to?(:save!) && child.save!
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def parent
|
33
|
+
return unless @parent_name
|
34
|
+
Fabrications[dehumanize(@parent_name)]
|
35
|
+
end
|
36
|
+
|
37
|
+
def klass
|
38
|
+
schematic.klass
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def remember(objects)
|
44
|
+
if singular?
|
45
|
+
Fabrications[@fabricator] = objects.last
|
46
|
+
else
|
47
|
+
Fabrications[@model.to_sym] = objects
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def singular?
|
52
|
+
@model == @model.singularize
|
53
|
+
end
|
54
|
+
|
55
|
+
def schematic
|
56
|
+
Fabrication::Fabricator.schematics[@fabricator]
|
57
|
+
end
|
58
|
+
|
59
|
+
def dehumanize(string)
|
60
|
+
string.gsub(/\W+/,'_').downcase
|
61
|
+
end
|
62
|
+
|
63
|
+
def parameterize_hash(hash)
|
64
|
+
hash.inject({}) {|h,(k,v)| h.update(dehumanize(k).to_sym => v)}
|
65
|
+
end
|
66
|
+
|
67
|
+
def make(attrs={})
|
68
|
+
Fabricate(@fabricator, attrs.merge(parentship))
|
69
|
+
end
|
70
|
+
|
71
|
+
def parentship
|
72
|
+
return {} unless parent
|
73
|
+
parent_class_name = parent.class.to_s.underscore
|
74
|
+
|
75
|
+
parent_instance = parent
|
76
|
+
unless klass.new.respond_to?("#{parent_class_name}=")
|
77
|
+
parent_class_name = parent_class_name.pluralize
|
78
|
+
parent_instance = [parent]
|
79
|
+
end
|
80
|
+
|
81
|
+
{ parent_class_name => parent_instance }
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
module Fabrications
|
87
|
+
@@fabrications = {}
|
88
|
+
|
89
|
+
def self.[](fabricator)
|
90
|
+
@@fabrications[fabricator.to_sym]
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.[]=(fabricator, fabrication)
|
94
|
+
@@fabrications[fabricator.to_sym] = fabrication
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
module FabricationMethods
|
101
|
+
def fabrications
|
102
|
+
Fabrication::Cucumber::Fabrications
|
103
|
+
end
|
104
|
+
end
|
@@ -2,10 +2,13 @@ class Fabrication::Sequencer
|
|
2
2
|
|
3
3
|
DEFAULT = :_default
|
4
4
|
|
5
|
-
def self.sequence(name=DEFAULT, start=0)
|
5
|
+
def self.sequence(name=DEFAULT, start=0, &block)
|
6
6
|
idx = sequences[name] ||= start
|
7
|
-
|
8
|
-
|
7
|
+
if block_given?
|
8
|
+
sequence_blocks[name] = block.to_proc
|
9
|
+
else
|
10
|
+
sequence_blocks[name] ||= lambda { |i| i }
|
11
|
+
end.call(idx).tap do
|
9
12
|
sequences[name] += 1
|
10
13
|
end
|
11
14
|
end
|
@@ -14,4 +17,7 @@ class Fabrication::Sequencer
|
|
14
17
|
@sequences ||= {}
|
15
18
|
end
|
16
19
|
|
20
|
+
def self.sequence_blocks
|
21
|
+
@sequence_blocks ||= {}
|
22
|
+
end
|
17
23
|
end
|
data/lib/fabrication/version.rb
CHANGED
@@ -1,103 +1,47 @@
|
|
1
|
-
|
1
|
+
require 'fabrication/cucumber'
|
2
2
|
|
3
|
-
|
4
|
-
model_name = dehumanize(model_name)
|
5
|
-
fabricator_name = generate_fabricator_name(model_name)
|
6
|
-
is_singular = model_name.to_s.singularize == model_name.to_s
|
7
|
-
hashes = is_singular ? [table.rows_hash] : table.hashes
|
8
|
-
@they = hashes.map do |hash|
|
9
|
-
hash = parameterize_hash(hash.merge(extra))
|
10
|
-
Fabricate(fabricator_name, hash)
|
11
|
-
end
|
12
|
-
instantize(fabricator_name, is_singular)
|
13
|
-
end
|
14
|
-
|
15
|
-
def create_with_default_attributes(model_name, count, extra = {})
|
16
|
-
fabricator_name = generate_fabricator_name(dehumanize(model_name))
|
17
|
-
is_singular = count == 1
|
18
|
-
@they = count.times.map { Fabricate(fabricator_name, extra) }
|
19
|
-
instantize(fabricator_name, is_singular)
|
20
|
-
end
|
21
|
-
|
22
|
-
def dehumanize(string)
|
23
|
-
string.gsub(/\W+/,'_').downcase
|
24
|
-
end
|
25
|
-
|
26
|
-
def generate_fabricator_name(model_name)
|
27
|
-
model_name.singularize.to_sym
|
28
|
-
end
|
29
|
-
|
30
|
-
def get_class(model_name)
|
31
|
-
fabricator_name = generate_fabricator_name(model_name)
|
32
|
-
Fabrication::Fabricator.schematics[fabricator_name].klass
|
33
|
-
end
|
34
|
-
|
35
|
-
def instantize(fabricator_name, is_singular)
|
36
|
-
if is_singular
|
37
|
-
@it = @they.last
|
38
|
-
instance_variable_set("@#{fabricator_name}", @it)
|
39
|
-
else
|
40
|
-
instance_variable_set("@#{fabricator_name.to_s.pluralize}", @they)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def parameterize_hash(hash)
|
45
|
-
hash.inject({}) {|h,(k,v)| h.update(dehumanize(k).to_sym => v)}
|
46
|
-
end
|
47
|
-
|
48
|
-
def parentship(parent, child)
|
49
|
-
parent_instance = instance_variable_get("@#{dehumanize(parent)}")
|
50
|
-
parent_class_name = parent_instance.class.to_s.underscore
|
51
|
-
child_class = get_class(dehumanize(child))
|
52
|
-
|
53
|
-
if child_class && !child_class.new.respond_to?("#{parent_class_name}=")
|
54
|
-
parent_class_name = parent_class_name.pluralize
|
55
|
-
parent_instance = [parent_instance]
|
56
|
-
end
|
57
|
-
|
58
|
-
{ parent_class_name => parent_instance }
|
59
|
-
end
|
60
|
-
|
61
|
-
def class_from_model_name(model_name)
|
62
|
-
eval(dehumanize(model_name).singularize.classify)
|
63
|
-
end
|
3
|
+
World(FabricationMethods)
|
64
4
|
|
5
|
+
def with_ivars(fabricator)
|
6
|
+
@they = yield fabricator
|
7
|
+
instance_variable_set("@#{fabricator.model}", @they)
|
65
8
|
end
|
66
9
|
|
67
|
-
World(FabricationMethods)
|
68
|
-
|
69
10
|
Given /^(\d+) ([^"]*)$/ do |count, model_name|
|
70
|
-
|
11
|
+
with_ivars Fabrication::Cucumber::StepFabricator.new(model_name) do |fab|
|
12
|
+
fab.n(count.to_i)
|
13
|
+
end
|
71
14
|
end
|
72
15
|
|
73
16
|
Given /^the following ([^"]*):$/ do |model_name, table|
|
74
|
-
|
17
|
+
with_ivars Fabrication::Cucumber::StepFabricator.new(model_name) do |fab|
|
18
|
+
fab.from_table(table)
|
19
|
+
end
|
75
20
|
end
|
76
21
|
|
77
22
|
Given /^that ([^"]*) has the following ([^"]*):$/ do |parent, child, table|
|
78
|
-
|
23
|
+
with_ivars Fabrication::Cucumber::StepFabricator.new(child, :parent => parent) do |fab|
|
24
|
+
fab.from_table(table)
|
25
|
+
end
|
79
26
|
end
|
80
27
|
|
81
28
|
Given /^that ([^"]*) has (\d+) ([^"]*)$/ do |parent, count, child|
|
82
|
-
|
29
|
+
with_ivars Fabrication::Cucumber::StepFabricator.new(child, :parent => parent) do |fab|
|
30
|
+
fab.n(count.to_i)
|
31
|
+
end
|
83
32
|
end
|
84
33
|
|
85
|
-
Given /^(?:that|those) (.*) belongs? to that (.*)$/ do |
|
86
|
-
|
87
|
-
|
88
|
-
child_or_children = dehumanize(child_or_children)
|
89
|
-
|
90
|
-
child_or_children_instance = instance_variable_get("@#{child_or_children}")
|
91
|
-
[child_or_children_instance].flatten.each do |child_instance|
|
92
|
-
child_instance.send("#{parent}=", parent_instance)
|
93
|
-
child_instance.save
|
34
|
+
Given /^(?:that|those) (.*) belongs? to that (.*)$/ do |children, parent|
|
35
|
+
with_ivars Fabrication::Cucumber::StepFabricator.new(parent) do |fab|
|
36
|
+
fab.has_many(children)
|
94
37
|
end
|
95
38
|
end
|
96
39
|
|
97
40
|
Then /^I should see (\d+) ([^"]*) in the database$/ do |count, model_name|
|
98
|
-
|
41
|
+
Fabrication::Cucumber::StepFabricator.new(model_name).klass.count.should == count.to_i
|
99
42
|
end
|
100
43
|
|
101
44
|
Then /^I should see the following (.*) in the database:$/ do |model_name, table|
|
102
|
-
|
45
|
+
klass = Fabrication::Cucumber::StepFabricator.new(model_name).klass
|
46
|
+
klass.where(table.rows_hash).count.should == 1
|
103
47
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fabrication/cucumber'
|
3
|
+
|
4
|
+
describe Fabrication::Cucumber do
|
5
|
+
include described_class
|
6
|
+
|
7
|
+
let(:name) { 'dogs' }
|
8
|
+
|
9
|
+
describe '#klass' do
|
10
|
+
context 'with a schematic for class "Boom"' do
|
11
|
+
subject { StepFabricator.new(name).klass }
|
12
|
+
let(:fabricator_name) { :dog }
|
13
|
+
|
14
|
+
before do
|
15
|
+
Fabrication::Fabricator.schematics.stub(:[])
|
16
|
+
.with(fabricator_name).and_return(stub(:klass => "Boom"))
|
17
|
+
end
|
18
|
+
|
19
|
+
it { should == "Boom" }
|
20
|
+
|
21
|
+
context "given a human name" do
|
22
|
+
let(:name) { "weiner dogs" }
|
23
|
+
let(:fabricator_name) { :weiner_dog }
|
24
|
+
it { should == "Boom" }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "given a titlecase human name" do
|
28
|
+
let(:name) { "Weiner Dog" }
|
29
|
+
let(:fabricator_name) { :weiner_dog }
|
30
|
+
it { should == "Boom" }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#n" do
|
36
|
+
let(:n) { 3 }
|
37
|
+
let(:fabricator) { StepFabricator.new(name) }
|
38
|
+
|
39
|
+
it "fabricates n times" do
|
40
|
+
Fabrication::Fabricator.should_receive(:generate).with(:dog, anything, {}).exactly(n).times
|
41
|
+
fabricator.n n
|
42
|
+
end
|
43
|
+
|
44
|
+
it "fabricates with attrs" do
|
45
|
+
Fabrication::Fabricator.should_receive(:generate)
|
46
|
+
.with(anything, anything, :collar => 'red').at_least(1)
|
47
|
+
fabricator.n n, :collar => 'red'
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'with a plural subject' do
|
51
|
+
let(:name) { 'dogs' }
|
52
|
+
it 'remembers' do
|
53
|
+
Fabrication::Fabricator.stub(:generate).and_return("dog1", "dog2", "dog3")
|
54
|
+
fabricator.n n
|
55
|
+
Fabrications[name].should == ["dog1", "dog2", "dog3"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'with a singular subject' do
|
60
|
+
let(:name) { 'dog' }
|
61
|
+
it 'remembers' do
|
62
|
+
Fabrication::Fabricator.stub(:generate).and_return("dog1")
|
63
|
+
fabricator.n 1
|
64
|
+
Fabrications[name].should == 'dog1'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#from_table' do
|
71
|
+
it 'maps column names to attribute names' do
|
72
|
+
table = stub(:hashes => [{ 'Favorite Color' => 'pink' }])
|
73
|
+
Fabrication::Fabricator.should_receive(:generate)
|
74
|
+
.with(anything, anything, :favorite_color => 'pink')
|
75
|
+
StepFabricator.new('bears').from_table(table)
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with a plural subject' do
|
79
|
+
let(:table) { double("ASTable", :hashes => hashes) }
|
80
|
+
let(:hashes) do
|
81
|
+
[{'some' => 'thing'},
|
82
|
+
{'some' => 'panother'}]
|
83
|
+
end
|
84
|
+
it 'fabricates with each rows attributes' do
|
85
|
+
Fabrication::Fabricator.should_receive(:generate)
|
86
|
+
.with(:dog, anything, {:some => 'thing'})
|
87
|
+
Fabrication::Fabricator.should_receive(:generate)
|
88
|
+
.with(:dog, anything, {:some => 'panother'})
|
89
|
+
StepFabricator.new(name).from_table(table)
|
90
|
+
end
|
91
|
+
it 'remembers' do
|
92
|
+
Fabrication::Fabricator.stub(:generate).and_return('dog1', 'dog2')
|
93
|
+
StepFabricator.new(name).from_table(table)
|
94
|
+
Fabrications[name].should == ["dog1", "dog2"]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'singular' do
|
99
|
+
let(:name) { 'dog' }
|
100
|
+
let(:table) { double("ASTable", :rows_hash => rows_hash) }
|
101
|
+
let(:rows_hash) do
|
102
|
+
{'some' => 'thing'}
|
103
|
+
end
|
104
|
+
it 'fabricates with each row as an attribute' do
|
105
|
+
Fabrication::Fabricator.should_receive(:generate).with(:dog, anything, {:some => 'thing'})
|
106
|
+
StepFabricator.new(name).from_table(table)
|
107
|
+
end
|
108
|
+
it 'remembers' do
|
109
|
+
Fabrication::Fabricator.stub(:generate).and_return('dog1')
|
110
|
+
StepFabricator.new(name).from_table(table)
|
111
|
+
Fabrications[name].should == "dog1"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -66,6 +66,33 @@ describe Fabrication::Sequencer do
|
|
66
66
|
end.should == "user2@example.com"
|
67
67
|
end
|
68
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
|
69
97
|
end
|
70
|
-
|
71
98
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,6 +7,6 @@ require 'ffaker'
|
|
7
7
|
Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
|
8
8
|
|
9
9
|
RSpec.configure do |config|
|
10
|
-
config.before(:
|
10
|
+
config.before(:all) { TestMigration.up }
|
11
11
|
config.before(:all) { clear_mongodb }
|
12
12
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: fabrication
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.
|
5
|
+
version: 1.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Paul Elliott
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-09-26 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -145,6 +145,7 @@ extra_rdoc_files: []
|
|
145
145
|
files:
|
146
146
|
- lib/fabrication/attribute.rb
|
147
147
|
- lib/fabrication/config.rb
|
148
|
+
- lib/fabrication/cucumber.rb
|
148
149
|
- lib/fabrication/errors/duplicate_fabricator_error.rb
|
149
150
|
- lib/fabrication/errors/unfabricatable_error.rb
|
150
151
|
- lib/fabrication/errors/unknown_fabricator_error.rb
|
@@ -164,6 +165,7 @@ files:
|
|
164
165
|
- lib/rails/generators/fabrication/model/templates/fabricator.rb
|
165
166
|
- spec/fabrication/attribute_spec.rb
|
166
167
|
- spec/fabrication/config_spec.rb
|
168
|
+
- spec/fabrication/cucumber_spec.rb
|
167
169
|
- spec/fabrication/fabricator_spec.rb
|
168
170
|
- spec/fabrication/generator/active_record_spec.rb
|
169
171
|
- spec/fabrication/generator/base_spec.rb
|