cucumber_factory 1.9.2 → 1.10.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/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
|