cucumber_factory 1.9.2 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/cucumber/factory.rb +5 -32
- data/lib/cucumber/factory/build_strategy.rb +90 -0
- data/lib/cucumber_factory/version.rb +1 -1
- data/spec/shared/cucumber_factory/factory/build_strategy_spec.rb +51 -0
- data/spec/shared/cucumber_factory/steps_spec.rb +10 -9
- data/spec/shared/support/factory_girl_mock.rb +17 -0
- metadata +7 -4
- data/spec/shared/cucumber_factory/factory_spec.rb +0 -29
data/lib/cucumber/factory.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'cucumber/factory/build_strategy'
|
2
|
+
|
1
3
|
module Cucumber
|
2
4
|
class Factory
|
3
5
|
|
@@ -58,7 +60,8 @@ module Cucumber
|
|
58
60
|
end
|
59
61
|
|
60
62
|
def parse_creation(world, raw_model, raw_variant, raw_attributes, raw_boolean_attributes)
|
61
|
-
|
63
|
+
build_strategy = BuildStrategy.from_prose(raw_model, raw_variant)
|
64
|
+
model_class = build_strategy.model_class
|
62
65
|
attributes = {}
|
63
66
|
if raw_attributes.try(:strip).present?
|
64
67
|
raw_attributes.scan(/(?:the|and|with|but|,| )+(.*?) ("([^\"]*)"|above)/).each do |fragment|
|
@@ -75,8 +78,7 @@ module Cucumber
|
|
75
78
|
attributes[attribute] = flag
|
76
79
|
end
|
77
80
|
end
|
78
|
-
|
79
|
-
record = create_record(model_class, variant, attributes)
|
81
|
+
record = build_strategy.create_record(attributes)
|
80
82
|
remember_record_names(world, record, attributes)
|
81
83
|
record
|
82
84
|
end
|
@@ -99,35 +101,6 @@ module Cucumber
|
|
99
101
|
prose.downcase.gsub(" ", "_").to_sym
|
100
102
|
end
|
101
103
|
|
102
|
-
def model_class_from_prose(prose)
|
103
|
-
# don't use \w which depends on the system locale
|
104
|
-
prose.gsub(/[^A-Za-z0-9_\/]+/, "_").camelize.constantize
|
105
|
-
end
|
106
|
-
|
107
|
-
def factory_girl_factory_name(name)
|
108
|
-
name.to_s.underscore.gsub('/', '_').to_sym
|
109
|
-
end
|
110
|
-
|
111
|
-
def create_record(model_class, variant, attributes)
|
112
|
-
fg_factory_name = factory_girl_factory_name(variant || model_class)
|
113
|
-
if defined?(::FactoryGirl) && factory = ::FactoryGirl.factories[fg_factory_name]
|
114
|
-
::FactoryGirl.create(fg_factory_name, attributes)
|
115
|
-
elsif model_class.respond_to?(:make) # Machinist blueprint
|
116
|
-
if variant.present?
|
117
|
-
model_class.make(variant.to_sym, attributes)
|
118
|
-
else
|
119
|
-
model_class.make(attributes)
|
120
|
-
end
|
121
|
-
elsif model_class.respond_to?(:create!) # Plain ActiveRecord
|
122
|
-
model = model_class.new
|
123
|
-
CucumberFactory::Switcher.assign_attributes(model, attributes)
|
124
|
-
model.save!
|
125
|
-
model
|
126
|
-
else
|
127
|
-
model_class.new(attributes)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
104
|
def remember_record_names(world, record, attributes)
|
132
105
|
string_values = attributes.values.select { |v| v.is_a?(String) }
|
133
106
|
for string_value in string_values
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Cucumber
|
2
|
+
class Factory
|
3
|
+
|
4
|
+
# wraps machinist / factory_girl / ruby object logic
|
5
|
+
|
6
|
+
class BuildStrategy
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def from_prose(model_prose, variant_prose)
|
11
|
+
# don't use \w which depends on the system locale
|
12
|
+
underscored_model_name = model_prose.gsub(/[^A-Za-z0-9_\/]+/, "_")
|
13
|
+
variant = variant_prose.present? && /\((.*?)\)/.match(variant_prose)[1].downcase.gsub(" ", "_")
|
14
|
+
|
15
|
+
if factory_girl_strategy = factory_girl_strategy(variant || underscored_model_name)
|
16
|
+
factory_girl_strategy
|
17
|
+
else
|
18
|
+
model_class = underscored_model_name.camelize.constantize
|
19
|
+
machinist_strategy(model_class, variant) ||
|
20
|
+
active_record_strategy(model_class) ||
|
21
|
+
ruby_object_strategy(model_class)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def factory_girl_strategy(factory_name)
|
28
|
+
return unless defined?(::FactoryGirl)
|
29
|
+
|
30
|
+
factory_name = factory_name.to_s.underscore.gsub('/', '_').to_sym
|
31
|
+
if factory = ::FactoryGirl.factories[factory_name]
|
32
|
+
|
33
|
+
new(factory.build_class) do |attributes|
|
34
|
+
::FactoryGirl.create(factory.name, attributes)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def machinist_strategy(model_class, variant)
|
41
|
+
if model_class.respond_to?(:make)
|
42
|
+
|
43
|
+
new(model_class) do |attributes|
|
44
|
+
if variant.present?
|
45
|
+
model_class.make(variant.to_sym, attributes)
|
46
|
+
else
|
47
|
+
model_class.make(attributes)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def active_record_strategy(model_class)
|
55
|
+
if model_class.respond_to?(:create!)
|
56
|
+
|
57
|
+
new(model_class) do |attributes|
|
58
|
+
model = model_class.new
|
59
|
+
CucumberFactory::Switcher.assign_attributes(model, attributes)
|
60
|
+
model.save!
|
61
|
+
model
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def ruby_object_strategy(model_class)
|
68
|
+
new(model_class) do |attributes|
|
69
|
+
model_class.new(attributes)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
attr_reader :model_class
|
77
|
+
|
78
|
+
def initialize(model_class, &block)
|
79
|
+
@model_class = model_class
|
80
|
+
@create_proc = block
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_record(attributes)
|
84
|
+
@create_proc.call(attributes)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative '../../support/factory_girl_mock'
|
3
|
+
|
4
|
+
describe Cucumber::Factory::BuildStrategy do
|
5
|
+
|
6
|
+
subject { Cucumber::Factory::BuildStrategy }
|
7
|
+
|
8
|
+
# most of the behaviour is integration tested in steps_spec.rb
|
9
|
+
|
10
|
+
describe '.from_prose' do
|
11
|
+
|
12
|
+
context 'when describing a factory girl factory' do
|
13
|
+
|
14
|
+
it 'returns a strategy corresponding to the factories model' do
|
15
|
+
FactoryGirl.stub_factories :job_offer => JobOffer
|
16
|
+
strategy = subject.from_prose('job offer', nil)
|
17
|
+
|
18
|
+
strategy.should be_a(described_class)
|
19
|
+
strategy.model_class.should == JobOffer
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'uses the variant for the factory name if present' do
|
23
|
+
FactoryGirl.stub_factories :job_offer => JobOffer
|
24
|
+
strategy = subject.from_prose('foo', '(job offer)')
|
25
|
+
|
26
|
+
strategy.should be_a(described_class)
|
27
|
+
strategy.model_class.should == JobOffer
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when describing a non factory girl model' do
|
33
|
+
|
34
|
+
it "should return a strategy for the class matching a natural language expression" do
|
35
|
+
subject.from_prose("movie", nil).model_class.should == Movie
|
36
|
+
subject.from_prose("job offer", nil).model_class.should == JobOffer
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should ignore variants for the class name" do
|
40
|
+
subject.from_prose("movie", "(job offer)").model_class.should == Movie
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should allow namespaced models" do
|
44
|
+
subject.from_prose("people/actor", nil).model_class.should == People::Actor
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -3,12 +3,7 @@ require 'spec_helper'
|
|
3
3
|
require_relative 'cucumber_helper'
|
4
4
|
require 'cucumber'
|
5
5
|
require 'cucumber/rb_support/rb_language'
|
6
|
-
|
7
|
-
class FactoryGirl # for factory_girl compatibility spec
|
8
|
-
def self.factories
|
9
|
-
{}
|
10
|
-
end
|
11
|
-
end
|
6
|
+
require_relative '../support/factory_girl_mock'
|
12
7
|
|
13
8
|
describe 'steps provided by cucumber_factory' do
|
14
9
|
|
@@ -39,17 +34,23 @@ describe 'steps provided by cucumber_factory' do
|
|
39
34
|
end
|
40
35
|
|
41
36
|
it "should create models that have a factory_girl factory by calling #FactoryGirl.create(:model_name)" do
|
42
|
-
FactoryGirl.
|
37
|
+
FactoryGirl.stub_factories :job_offer => JobOffer
|
43
38
|
FactoryGirl.should_receive(:create).with(:job_offer, { :title => "Awesome job" })
|
44
39
|
invoke_cucumber_step('there is a job offer with the title "Awesome job"')
|
45
40
|
end
|
46
41
|
|
47
|
-
it "should create model variants that have a factory_girl factory by calling #FactoryGirl.create(:
|
48
|
-
FactoryGirl.
|
42
|
+
it "should create model variants that have a factory_girl factory by calling #FactoryGirl.create(:variant)" do
|
43
|
+
FactoryGirl.stub_factories :tempting_job_offer => JobOffer
|
49
44
|
FactoryGirl.should_receive(:create).with(:tempting_job_offer, { :title => "Awesomafiablyfantasmic job" })
|
50
45
|
invoke_cucumber_step('there is a job offer (tempting job offer) with the title "Awesomafiablyfantasmic job"')
|
51
46
|
end
|
52
47
|
|
48
|
+
it "should create model variants that have a factory_girl factory by using the model name as a factory name" do
|
49
|
+
FactoryGirl.stub_factories :tempting_job_offer => JobOffer
|
50
|
+
FactoryGirl.should_receive(:create).with(:tempting_job_offer, { :title => "Awesomafiablyfantasmic job" })
|
51
|
+
invoke_cucumber_step('there is a tempting job offer with the title "Awesomafiablyfantasmic job"')
|
52
|
+
end
|
53
|
+
|
53
54
|
it "should instantiate plain ruby classes by calling #new" do
|
54
55
|
PlainRubyClass.should_receive(:new).with({})
|
55
56
|
invoke_cucumber_step("there is a plain ruby class")
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class FactoryGirl # for factory_girl compatibility spec
|
2
|
+
|
3
|
+
def self.factories
|
4
|
+
{}
|
5
|
+
end
|
6
|
+
|
7
|
+
Factory = Struct.new(:name, :build_class)
|
8
|
+
|
9
|
+
def self.stub_factories(hash)
|
10
|
+
factories = {}
|
11
|
+
hash.each do |name, build_class|
|
12
|
+
factories[name] = Factory.new(name, build_class)
|
13
|
+
end
|
14
|
+
FactoryGirl.stub :factories => factories
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber_factory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-02-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- Rakefile
|
122
122
|
- cucumber_factory.gemspec
|
123
123
|
- lib/cucumber/factory.rb
|
124
|
+
- lib/cucumber/factory/build_strategy.rb
|
124
125
|
- lib/cucumber/runtime_ext.rb
|
125
126
|
- lib/cucumber_factory.rb
|
126
127
|
- lib/cucumber_factory/switcher.rb
|
@@ -207,9 +208,10 @@ files:
|
|
207
208
|
- spec/shared/app_root/db/migrate/003_create_payments.rb
|
208
209
|
- spec/shared/app_root/db/migrate/004_create_actors.rb
|
209
210
|
- spec/shared/cucumber_factory/cucumber_helper.rb
|
210
|
-
- spec/shared/cucumber_factory/
|
211
|
+
- spec/shared/cucumber_factory/factory/build_strategy_spec.rb
|
211
212
|
- spec/shared/cucumber_factory/runtime_ext_spec.rb
|
212
213
|
- spec/shared/cucumber_factory/steps_spec.rb
|
214
|
+
- spec/shared/support/factory_girl_mock.rb
|
213
215
|
homepage: http://github.com/makandra/cucumber_factory
|
214
216
|
licenses:
|
215
217
|
- MIT
|
@@ -231,8 +233,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
231
233
|
version: '0'
|
232
234
|
requirements: []
|
233
235
|
rubyforge_project:
|
234
|
-
rubygems_version: 1.8.
|
236
|
+
rubygems_version: 1.8.25
|
235
237
|
signing_key:
|
236
238
|
specification_version: 3
|
237
239
|
summary: Create records from Cucumber features without writing step definitions.
|
238
240
|
test_files: []
|
241
|
+
has_rdoc:
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Cucumber::Factory do
|
4
|
-
|
5
|
-
subject { Cucumber::Factory }
|
6
|
-
|
7
|
-
describe 'model_class_from_prose' do
|
8
|
-
|
9
|
-
it "should return the class matching a natural language expression" do
|
10
|
-
subject.send(:model_class_from_prose, "movie").should == Movie
|
11
|
-
subject.send(:model_class_from_prose, "job offer").should == JobOffer
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should allow namespaced models" do
|
15
|
-
subject.send(:model_class_from_prose, "people/actor").should == People::Actor
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
describe 'factory_girl_factory_name' do
|
21
|
-
|
22
|
-
it "should underscorize everything" do
|
23
|
-
subject.send(:factory_girl_factory_name, People::Actor).should == :people_actor
|
24
|
-
subject.send(:factory_girl_factory_name, JobOffer).should == :job_offer
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|