fabrication 1.1.0 → 1.2.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.
- 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
|