cucumber_factory 1.4.0 → 1.5.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/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  doc
2
2
  pkg
3
3
  *.gem
4
+ .idea
5
+
data/README.rdoc CHANGED
@@ -43,6 +43,18 @@ You can use named Machinist blueprint such as <tt>Movie.blueprint(:comedy)</tt>
43
43
 
44
44
  Inherited factory_girl factories are not supported yet.
45
45
 
46
+ == Overriding factory steps
47
+
48
+ If you want to override a factory step with your own version, just do so:
49
+
50
+ Given /^there is a movie with good actors$/ do
51
+ movie = Movie.make
52
+ movie.actors << Actor.make(:name => 'Clive Owen')
53
+ movie.actors << Actor.make(:name => 'Denzel Washington')
54
+ end
55
+
56
+ Custom steps will always be preferred over factory steps. Also Cucumber will not raise a warning about ambiguous steps if the only other matching step is a factory step.
57
+
46
58
  === Credits
47
59
 
48
60
  Henning Koch
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ task :default => :spec
8
8
 
9
9
  desc "Run all specs"
10
10
  Spec::Rake::SpecTask.new() do |t|
11
- t.spec_opts = ['--options', "\"spec/spec.opts\""]
11
+ t.spec_opts = ['--options', "\"spec/support/spec.opts\""]
12
12
  t.spec_files = FileList['spec/**/*_spec.rb']
13
13
  end
14
14
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.0
1
+ 1.5.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{cucumber_factory}
8
- s.version = "1.4.0"
8
+ s.version = "1.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Henning Koch"]
12
- s.date = %q{2010-01-28}
12
+ s.date = %q{2010-06-20}
13
13
  s.description = %q{Cucumber Factory allows you to create ActiveRecord models from your Cucumber features without writing step definitions for each model.}
14
14
  s.email = %q{github@makandra.de}
15
15
  s.extra_rdoc_files = [
@@ -22,8 +22,9 @@ Gem::Specification.new do |s|
22
22
  "Rakefile",
23
23
  "VERSION",
24
24
  "cucumber_factory.gemspec",
25
+ "lib/cucumber/factory.rb",
26
+ "lib/cucumber/step_mother_ext.rb",
25
27
  "lib/cucumber_factory.rb",
26
- "lib/cucumber_factory/factory.rb",
27
28
  "spec/app_root/app/controllers/application_controller.rb",
28
29
  "spec/app_root/app/models/job_offer.rb",
29
30
  "spec/app_root/app/models/machinist_model.rb",
@@ -48,38 +49,42 @@ Gem::Specification.new do |s|
48
49
  "spec/app_root/log/.gitignore",
49
50
  "spec/app_root/script/console",
50
51
  "spec/factory_spec.rb",
51
- "spec/rcov.opts",
52
- "spec/spec.opts",
53
- "spec/spec_helper.rb"
52
+ "spec/spec_helper.rb",
53
+ "spec/step_mother_ext_spec.rb",
54
+ "spec/steps_spec.rb",
55
+ "spec/support/rcov.opts",
56
+ "spec/support/spec.opts"
54
57
  ]
55
58
  s.homepage = %q{http://github.com/makandra/cucumber_factory}
56
59
  s.rdoc_options = ["--charset=UTF-8"]
57
60
  s.require_paths = ["lib"]
58
- s.rubygems_version = %q{1.3.5}
61
+ s.rubygems_version = %q{1.3.6}
59
62
  s.summary = %q{Create records from Cucumber features without writing step definitions.}
60
63
  s.test_files = [
61
- "spec/app_root/app/models/opera.rb",
62
- "spec/app_root/app/models/movie.rb",
64
+ "spec/app_root/app/controllers/application_controller.rb",
63
65
  "spec/app_root/app/models/job_offer.rb",
64
- "spec/app_root/app/models/payment.rb",
65
66
  "spec/app_root/app/models/machinist_model.rb",
67
+ "spec/app_root/app/models/movie.rb",
68
+ "spec/app_root/app/models/opera.rb",
69
+ "spec/app_root/app/models/payment.rb",
66
70
  "spec/app_root/app/models/plain_ruby_class.rb",
67
71
  "spec/app_root/app/models/user.rb",
68
- "spec/app_root/app/controllers/application_controller.rb",
72
+ "spec/app_root/config/boot.rb",
69
73
  "spec/app_root/config/environment.rb",
74
+ "spec/app_root/config/environments/in_memory.rb",
70
75
  "spec/app_root/config/environments/mysql.rb",
71
76
  "spec/app_root/config/environments/postgresql.rb",
72
- "spec/app_root/config/environments/sqlite3.rb",
73
- "spec/app_root/config/environments/in_memory.rb",
74
77
  "spec/app_root/config/environments/sqlite.rb",
75
- "spec/app_root/config/boot.rb",
78
+ "spec/app_root/config/environments/sqlite3.rb",
76
79
  "spec/app_root/config/routes.rb",
77
- "spec/app_root/db/migrate/002_create_users.rb",
78
80
  "spec/app_root/db/migrate/001_create_movies.rb",
81
+ "spec/app_root/db/migrate/002_create_users.rb",
79
82
  "spec/app_root/db/migrate/003_create_payments.rb",
80
83
  "spec/app_root/lib/console_with_fixtures.rb",
81
- "spec/factory_spec.rb",
82
- "spec/spec_helper.rb"
84
+ "spec/spec_helper.rb",
85
+ "spec/step_mother_ext_spec.rb",
86
+ "spec/steps_spec.rb",
87
+ "spec/factory_spec.rb"
83
88
  ]
84
89
 
85
90
  if s.respond_to? :specification_version then
@@ -0,0 +1,109 @@
1
+ module Cucumber
2
+ module Factory
3
+ class << self
4
+
5
+ # List of Cucumber step definitions created by #add_steps
6
+ attr_reader :step_definitions
7
+
8
+ def add_steps(dsl)
9
+ @step_definitions = []
10
+ steps.each do |step|
11
+ @step_definitions << (dsl.instance_eval do
12
+ Given(step[:pattern], &step[:action])
13
+ end)
14
+ end
15
+ end
16
+
17
+ def steps
18
+ [ { :pattern => /^"([^\"]*)" is an? (.+?)( \(.+?\))?( with the .+?)?$/,
19
+ :action => lambda { |name, raw_model, raw_variant, raw_attributes| Cucumber::Factory.parse_named_creation(self, name, raw_model, raw_variant, raw_attributes) } },
20
+ { :pattern => /^there is an? (.+?)( \(.+?\))?( with the .+?)?$/,
21
+ :action => lambda { |raw_model, raw_variant, raw_attributes| Cucumber::Factory.parse_creation(self, raw_model, raw_variant, raw_attributes) } } ]
22
+ end
23
+
24
+ # # Emulate Cucumber step matching for specs
25
+ # def parse(world, command)
26
+ # command = command.sub(/^When |Given |Then /, "")
27
+ # steps.each do |step|
28
+ # match = step[:pattern].match(command)
29
+ # if match
30
+ # step[:action].bind(world).call(*match.captures)
31
+ # return
32
+ # end
33
+ # end
34
+ # raise "No step definition for: #{command}"
35
+ # end
36
+
37
+ def parse_named_creation(world, name, raw_model, raw_variant, raw_attributes)
38
+ record = parse_creation(world, raw_model, raw_variant, raw_attributes)
39
+ variable = variable_name_from_prose(name)
40
+ world.instance_variable_set variable, record
41
+ end
42
+
43
+ def parse_creation(world, raw_model, raw_variant, raw_attributes)
44
+ model_class = model_class_from_prose(raw_model)
45
+ attributes = {}
46
+ if raw_attributes.present? && raw_attributes.strip.present?
47
+ raw_attributes.scan(/(the|and|with| )+(.*?) ("([^\"]*)"|above)/).each do |fragment|
48
+ value = nil
49
+ attribute = fragment[1].downcase.gsub(" ", "_").to_sym
50
+ value_type = fragment[2] # 'above' or a quoted string
51
+ value = fragment[3]
52
+ association = model_class.reflect_on_association(attribute) if model_class.respond_to?(:reflect_on_association)
53
+ if association.present?
54
+ if value_type == "above"
55
+ # Don't use class.last, in sqlite that is not always the last inserted element
56
+ value = association.klass.find(:last, :order => "id") or raise "There is no last #{attribute}"
57
+ else
58
+ value = world.instance_variable_get(variable_name_from_prose(value))
59
+ end
60
+ end
61
+ attributes[attribute] = value
62
+ end
63
+ end
64
+ variant = raw_variant.present? && /\((.*?)\)/.match(raw_variant)[1].downcase.gsub(" ", "_")
65
+ create_record(model_class, variant, attributes)
66
+ end
67
+
68
+ def model_class_from_prose(prose)
69
+ # don't use \w which depends on the system locale
70
+ prose.gsub(/[^A-Za-z0-9_]+/, "_").camelize.constantize
71
+ end
72
+
73
+ def variable_name_from_prose(prose)
74
+ # don't use \w which depends on the system locale
75
+ name = prose.downcase.gsub(/[^A-Za-z0-9_]+/, '_')
76
+ name = name.gsub(/^_+/, '').gsub(/_+$/, '')
77
+ name = "_#{name}" unless name.length >= 0 && name =~ /^[a-z]/
78
+ :"@#{name}"
79
+ end
80
+
81
+ private
82
+
83
+ def factory_girl_factory_name(model_class)
84
+ model_class.to_s.underscore.to_sym
85
+ end
86
+
87
+ def create_record(model_class, variant, attributes)
88
+ factory_name = factory_girl_factory_name(model_class)
89
+ if defined?(::Factory) && factory = ::Factory.factories[factory_name]
90
+ ::Factory.create(factory_name, attributes)
91
+ elsif model_class.respond_to?(:make) # Machinist blueprint
92
+ if variant.present?
93
+ model_class.make(variant.to_sym, attributes)
94
+ else
95
+ model_class.make(attributes)
96
+ end
97
+ elsif model_class.respond_to?(:create!) # Plain ActiveRecord
98
+ model = model_class.new
99
+ model.send(:attributes=, attributes, false) # ignore attr_accessible
100
+ model.save!
101
+ model
102
+ else
103
+ model_class.new(attributes)
104
+ end
105
+ end
106
+
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,36 @@
1
+ require 'cucumber/step_mother'
2
+
3
+ module Cucumber
4
+
5
+ class Ambiguous
6
+
7
+ attr_reader :matches
8
+
9
+ def initialize_with_remembering_matches(step_name, matches, *args)
10
+ @matches = matches
11
+ initialize_without_remembering_matches(step_name, matches, *args)
12
+ end
13
+
14
+ alias_method_chain :initialize, :remembering_matches
15
+
16
+ end
17
+
18
+ class StepMother
19
+
20
+ def step_match_with_factory_priority(*args)
21
+ step_match_without_factory_priority(*args)
22
+ rescue Ambiguous => e
23
+ matched_definitions = e.matches.collect(&:step_definition)
24
+ if matched_definitions.size == 2 && (Cucumber::Factory.step_definitions & matched_definitions).any?
25
+ (matched_definitions - Cucumber::Factory.step_definitions).first
26
+ else
27
+ raise
28
+ end
29
+ end
30
+
31
+ alias_method_chain :step_match, :factory_priority
32
+
33
+ end
34
+
35
+ end
36
+
@@ -1,2 +1,2 @@
1
- # Include hook code here
2
- require 'cucumber_factory/factory'
1
+ require 'cucumber/factory'
2
+ require 'cucumber/step_mother_ext'
data/spec/factory_spec.rb CHANGED
@@ -1,11 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
- class Factory # for factory_girl compatibility spec
4
- def self.factories
5
- {}
6
- end
7
- end
8
-
9
3
  describe Cucumber::Factory do
10
4
 
11
5
  describe 'add_steps' do
@@ -40,110 +34,5 @@ describe Cucumber::Factory do
40
34
  end
41
35
 
42
36
  end
43
-
44
- describe 'parse' do
45
-
46
- before(:each) do
47
- @world = Object.new
48
- end
49
-
50
- it "should create ActiveRecord models by calling #new and #save!" do
51
- movie = Movie.new
52
- Movie.should_receive(:new).with().and_return(movie)
53
- movie.should_receive(:save!)
54
- Cucumber::Factory.parse(@world, "Given there is a movie")
55
- end
56
-
57
- it "should create models that have a machinist blueprint by calling #make" do
58
- MachinistModel.should_receive(:make).with({ :attribute => "foo"})
59
- Cucumber::Factory.parse(@world, 'Given there is a machinist model with the attribute "foo"')
60
- end
61
-
62
- it "should be able to invoke machinist blueprint variants" do
63
- MachinistModel.should_receive(:make).with(:variant, { :attribute => "foo"})
64
- Cucumber::Factory.parse(@world, 'Given there is a machinist model (variant) with the attribute "foo"')
65
- end
66
-
67
- it "should be able to invoke machinist blueprint variants containing spaces or uppercase characters in prose" do
68
- MachinistModel.should_receive(:make).with(:variant_mark_two, { :attribute => "foo"})
69
- Cucumber::Factory.parse(@world, 'Given there is a machinist model (Variant Mark Two) with the attribute "foo"')
70
- end
71
-
72
- it "should create models that have a factory_girl factory by calling #Factory.make(:model_name)" do
73
- Factory.should_receive(:factories).with().and_return({ :job_offer => :job_offer_factory }) # Fake factory look up in factory_girl
74
- Factory.should_receive(:create).with(:job_offer, { :title => "Awesome job" })
75
- Cucumber::Factory.parse(@world, 'Given there is a job offer with the title "Awesome job"')
76
- end
77
-
78
- it "should instantiate plain ruby classes by calling #new" do
79
- PlainRubyClass.should_receive(:new).with({})
80
- Cucumber::Factory.parse(@world, "Given there is a plain ruby class")
81
- end
82
-
83
- it "should instantiate classes with multiple words in their name" do
84
- JobOffer.should_receive(:new).with({})
85
- Cucumber::Factory.parse(@world, "Given there is a job offer")
86
- end
87
-
88
- it "should instantiate classes with uppercase characters in their name" do
89
- user = User.new
90
- User.should_receive(:new).and_return(user)
91
- Cucumber::Factory.parse(@world, "Given there is a User")
92
- end
93
-
94
- it "should allow either 'a' or 'an' for the article" do
95
- Opera.should_receive(:new).with({})
96
- Cucumber::Factory.parse(@world, "Given there is an opera")
97
- end
98
-
99
- it "should create records with attributes" do
100
- movie = Movie.new
101
- Movie.stub(:new => movie)
102
- movie.should_receive(:"attributes=").with({ :title => "Sunshine", :year => "2007" }, false)
103
- Cucumber::Factory.parse(@world, 'Given there is a movie with the title "Sunshine" and the year "2007"')
104
- end
105
-
106
- it "should create records with attributes containing spaces" do
107
- movie = Movie.new
108
- Movie.stub(:new => movie)
109
- movie.should_receive(:"attributes=").with({ :box_office_result => "99999999" }, false)
110
- Cucumber::Factory.parse(@world, 'Given there is a movie with the box office result "99999999"')
111
- end
112
-
113
- it "should create records with attributes containing uppercase characters" do
114
- user = User.new
115
- User.stub(:new => user)
116
- user.should_receive(:"attributes=").with({ :name => "Susanne" }, false)
117
- Cucumber::Factory.parse(@world, 'Given there is a User with the Name "Susanne"')
118
- end
119
-
120
- it "should override attr_accessible protection" do
121
- Cucumber::Factory.parse(@world, 'Given there is a payment with the amount "120" and the comment "Thanks for lending"')
122
- payment = Payment.last
123
- payment.amount.should == 120
124
- payment.comment.should == 'Thanks for lending'
125
- end
126
-
127
- it "should set instance variables in the world" do
128
- Cucumber::Factory.parse(@world, 'Given "Sunshine" is a movie with the title "Sunshine" and the year "2007"')
129
- @world.instance_variable_get(:'@sunshine').title.should == "Sunshine"
130
- end
131
-
132
- it "should understand pointers to instance variables" do
133
- Cucumber::Factory.parse(@world, 'Given "Before Sunrise" is a movie with the title "Before Sunrise"')
134
- Cucumber::Factory.parse(@world, 'Given "Before Sunset" is a movie with the title "Before Sunset" and the prequel "Before Sunrise"')
135
- @world.instance_variable_get(:'@before_sunset').prequel.title.should == "Before Sunrise"
136
- end
137
-
138
- it "should allow to point to a previously created record through 'above'" do
139
- Cucumber::Factory.parse(@world, 'Given there is a user with the name "Jane"')
140
- Cucumber::Factory.parse(@world, 'Given there is a movie with the title "Before Sunrise"')
141
- Cucumber::Factory.parse(@world, 'Given there is a movie with the title "Before Sunset" and the reviewer above and the prequel above')
142
- @before_sunset = Movie.find_by_title!("Before Sunset")
143
- @before_sunset.prequel.title.should == "Before Sunrise"
144
- @before_sunset.reviewer.name.should == "Jane"
145
- end
146
-
147
- end
148
37
 
149
38
  end
data/spec/spec_helper.rb CHANGED
@@ -1,8 +1,4 @@
1
1
  $: << File.join(File.dirname(__FILE__), "/../lib" )
2
- #require 'lib/cucumber_factory'
3
- # Dir["spec/fixtures/**/*.rb"].each {|f| require f}
4
-
5
-
6
2
 
7
3
  # Set the default environment to sqlite3's in_memory database
8
4
  ENV['RAILS_ENV'] ||= 'in_memory'
@@ -23,55 +19,10 @@ Spec::Runner.configure do |config|
23
19
  config.use_instantiated_fixtures = false
24
20
  end
25
21
 
26
-
27
- ## This file is copied to ~/spec when you run 'ruby script/generate rspec'
28
- ## from the project root directory.
29
- #ENV["RAILS_ENV"] ||= 'test'
30
- #require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
31
- #require 'spec/autorun'
32
- #require 'spec/rails'
33
- #
34
- ## Requires supporting files with custom matchers and macros, etc,
35
- ## in ./support/ and its subdirectories.
36
- #Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
37
- #
38
- #Spec::Runner.configure do |config|
39
- # # If you're not using ActiveRecord you should remove these
40
- # # lines, delete config/database.yml and disable :active_record
41
- # # in your config/boot.rb
42
- # config.use_transactional_fixtures = true
43
- # config.use_instantiated_fixtures = false
44
- # config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
45
- #
46
- # # == Fixtures
47
- # #
48
- # # You can declare fixtures for each example_group like this:
49
- # # describe "...." do
50
- # # fixtures :table_a, :table_b
51
- # #
52
- # # Alternatively, if you prefer to declare them only once, you can
53
- # # do so right here. Just uncomment the next line and replace the fixture
54
- # # names with your fixtures.
55
- # #
56
- # # config.global_fixtures = :table_a, :table_b
57
- # #
58
- # # If you declare global fixtures, be aware that they will be declared
59
- # # for all of your examples, even those that don't use them.
60
- # #
61
- # # You can also declare which fixtures to use (for example fixtures for test/fixtures):
62
- # #
63
- # # config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
64
- # #
65
- # # == Mock Framework
66
- # #
67
- # # RSpec uses it's own mocking framework by default. If you prefer to
68
- # # use mocha, flexmock or RR, uncomment the appropriate line:
69
- # #
70
- # # config.mock_with :mocha
71
- # # config.mock_with :flexmock
72
- # # config.mock_with :rr
73
- # #
74
- # # == Notes
75
- # #
76
- # # For more information take a look at Spec::Runner::Configuration and Spec::Runner
77
- #end
22
+ def prepare_cucumber_example
23
+ @step_mother = Cucumber::StepMother.new
24
+ @language = @step_mother.load_programming_language('rb')
25
+ @dsl = Object.new
26
+ @dsl.extend(Cucumber::RbSupport::RbDsl)
27
+ Cucumber::Factory.add_steps(@dsl)
28
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ require 'cucumber'
4
+ require 'cucumber/rb_support/rb_language'
5
+
6
+ describe Cucumber::StepMother, 'extended with cucumber_factory' do
7
+
8
+ before(:each) do
9
+ prepare_cucumber_example
10
+ end
11
+
12
+ describe 'step_match' do
13
+
14
+ it "should not raise an ambiguous step error and return the user step if the only other matching step is a factory step" do
15
+ user_step = @dsl.Given(/^there is a movie with a funny tone/){}
16
+ @step_mother.step_match('there is a movie with a funny tone').should == user_step
17
+ end
18
+
19
+ it "should still raise an ambiguous step error if more than two non-factory steps match" do
20
+ @dsl.Given(/^there is a movie with (.*?) tone/){}
21
+ @dsl.Given(/^there is a movie with a funny tone/){}
22
+ expect do
23
+ @step_mother.step_match('there is a movie with a funny tone')
24
+ end.to raise_error(Cucumber::Ambiguous)
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,115 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ require 'cucumber'
4
+ require 'cucumber/rb_support/rb_language'
5
+
6
+ class Factory # for factory_girl compatibility spec
7
+ def self.factories
8
+ {}
9
+ end
10
+ end
11
+
12
+ describe 'steps provided by cucumber_factory' do
13
+
14
+ before(:each) do
15
+ prepare_cucumber_example
16
+ end
17
+
18
+ it "should create ActiveRecord models by calling #new and #save!" do
19
+ movie = Movie.new
20
+ Movie.should_receive(:new).with().and_return(movie)
21
+ movie.should_receive(:save!)
22
+ @step_mother.invoke("there is a movie")
23
+ end
24
+
25
+ it "should create models that have a machinist blueprint by calling #make" do
26
+ MachinistModel.should_receive(:make).with({ :attribute => "foo"})
27
+ @step_mother.invoke('there is a machinist model with the attribute "foo"')
28
+ end
29
+
30
+ it "should be able to invoke machinist blueprint variants" do
31
+ MachinistModel.should_receive(:make).with(:variant, { :attribute => "foo"})
32
+ @step_mother.invoke('there is a machinist model (variant) with the attribute "foo"')
33
+ end
34
+
35
+ it "should be able to invoke machinist blueprint variants containing spaces or uppercase characters in prose" do
36
+ MachinistModel.should_receive(:make).with(:variant_mark_two, { :attribute => "foo"})
37
+ @step_mother.invoke('there is a machinist model (Variant Mark Two) with the attribute "foo"')
38
+ end
39
+
40
+ it "should create models that have a factory_girl factory by calling #Factory.make(:model_name)" do
41
+ Factory.should_receive(:factories).with().and_return({ :job_offer => :job_offer_factory }) # Fake factory look up in factory_girl
42
+ Factory.should_receive(:create).with(:job_offer, { :title => "Awesome job" })
43
+ @step_mother.invoke('there is a job offer with the title "Awesome job"')
44
+ end
45
+
46
+ it "should instantiate plain ruby classes by calling #new" do
47
+ PlainRubyClass.should_receive(:new).with({})
48
+ @step_mother.invoke("there is a plain ruby class")
49
+ end
50
+
51
+ it "should instantiate classes with multiple words in their name" do
52
+ JobOffer.should_receive(:new).with({})
53
+ @step_mother.invoke("there is a job offer")
54
+ end
55
+
56
+ it "should instantiate classes with uppercase characters in their name" do
57
+ user = User.new
58
+ User.should_receive(:new).and_return(user)
59
+ @step_mother.invoke("there is a User")
60
+ end
61
+
62
+ it "should allow either 'a' or 'an' for the article" do
63
+ Opera.should_receive(:new).with({})
64
+ @step_mother.invoke("there is an opera")
65
+ end
66
+
67
+ it "should create records with attributes" do
68
+ movie = Movie.new
69
+ Movie.stub(:new => movie)
70
+ movie.should_receive(:"attributes=").with({ :title => "Sunshine", :year => "2007" }, false)
71
+ @step_mother.invoke('there is a movie with the title "Sunshine" and the year "2007"')
72
+ end
73
+
74
+ it "should create records with attributes containing spaces" do
75
+ movie = Movie.new
76
+ Movie.stub(:new => movie)
77
+ movie.should_receive(:"attributes=").with({ :box_office_result => "99999999" }, false)
78
+ @step_mother.invoke('there is a movie with the box office result "99999999"')
79
+ end
80
+
81
+ it "should create records with attributes containing uppercase characters" do
82
+ user = User.new
83
+ User.stub(:new => user)
84
+ user.should_receive(:"attributes=").with({ :name => "Susanne" }, false)
85
+ @step_mother.invoke('there is a User with the Name "Susanne"')
86
+ end
87
+
88
+ it "should override attr_accessible protection" do
89
+ @step_mother.invoke('there is a payment with the amount "120" and the comment "Thanks for lending"')
90
+ payment = Payment.last
91
+ payment.amount.should == 120
92
+ payment.comment.should == 'Thanks for lending'
93
+ end
94
+
95
+ it "should set instance variables in the world" do
96
+ @step_mother.invoke('"Sunshine" is a movie with the title "Sunshine" and the year "2007"')
97
+ @language.current_world.instance_variable_get(:'@sunshine').title.should == "Sunshine"
98
+ end
99
+
100
+ it "should understand pointers to instance variables" do
101
+ @step_mother.invoke('"Before Sunrise" is a movie with the title "Before Sunrise"')
102
+ @step_mother.invoke('"Before Sunset" is a movie with the title "Before Sunset" and the prequel "Before Sunrise"')
103
+ @language.current_world.instance_variable_get(:'@before_sunset').prequel.title.should == "Before Sunrise"
104
+ end
105
+
106
+ it "should allow to point to a previously created record through 'above'" do
107
+ @step_mother.invoke('there is a user with the name "Jane"')
108
+ @step_mother.invoke('there is a movie with the title "Before Sunrise"')
109
+ @step_mother.invoke('there is a movie with the title "Before Sunset" and the reviewer above and the prequel above')
110
+ @before_sunset = Movie.find_by_title!("Before Sunset")
111
+ @before_sunset.prequel.title.should == "Before Sunrise"
112
+ @before_sunset.reviewer.name.should == "Jane"
113
+ end
114
+
115
+ end
File without changes
File without changes
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber_factory
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 5
8
+ - 0
9
+ version: 1.5.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Henning Koch
@@ -9,7 +14,7 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-01-28 00:00:00 +01:00
17
+ date: 2010-06-20 00:00:00 +02:00
13
18
  default_executable:
14
19
  dependencies: []
15
20
 
@@ -28,8 +33,9 @@ files:
28
33
  - Rakefile
29
34
  - VERSION
30
35
  - cucumber_factory.gemspec
36
+ - lib/cucumber/factory.rb
37
+ - lib/cucumber/step_mother_ext.rb
31
38
  - lib/cucumber_factory.rb
32
- - lib/cucumber_factory/factory.rb
33
39
  - spec/app_root/app/controllers/application_controller.rb
34
40
  - spec/app_root/app/models/job_offer.rb
35
41
  - spec/app_root/app/models/machinist_model.rb
@@ -54,9 +60,11 @@ files:
54
60
  - spec/app_root/log/.gitignore
55
61
  - spec/app_root/script/console
56
62
  - spec/factory_spec.rb
57
- - spec/rcov.opts
58
- - spec/spec.opts
59
63
  - spec/spec_helper.rb
64
+ - spec/step_mother_ext_spec.rb
65
+ - spec/steps_spec.rb
66
+ - spec/support/rcov.opts
67
+ - spec/support/spec.opts
60
68
  has_rdoc: true
61
69
  homepage: http://github.com/makandra/cucumber_factory
62
70
  licenses: []
@@ -70,41 +78,45 @@ required_ruby_version: !ruby/object:Gem::Requirement
70
78
  requirements:
71
79
  - - ">="
72
80
  - !ruby/object:Gem::Version
81
+ segments:
82
+ - 0
73
83
  version: "0"
74
- version:
75
84
  required_rubygems_version: !ruby/object:Gem::Requirement
76
85
  requirements:
77
86
  - - ">="
78
87
  - !ruby/object:Gem::Version
88
+ segments:
89
+ - 0
79
90
  version: "0"
80
- version:
81
91
  requirements: []
82
92
 
83
93
  rubyforge_project:
84
- rubygems_version: 1.3.5
94
+ rubygems_version: 1.3.6
85
95
  signing_key:
86
96
  specification_version: 3
87
97
  summary: Create records from Cucumber features without writing step definitions.
88
98
  test_files:
89
- - spec/app_root/app/models/opera.rb
90
- - spec/app_root/app/models/movie.rb
99
+ - spec/app_root/app/controllers/application_controller.rb
91
100
  - spec/app_root/app/models/job_offer.rb
92
- - spec/app_root/app/models/payment.rb
93
101
  - spec/app_root/app/models/machinist_model.rb
102
+ - spec/app_root/app/models/movie.rb
103
+ - spec/app_root/app/models/opera.rb
104
+ - spec/app_root/app/models/payment.rb
94
105
  - spec/app_root/app/models/plain_ruby_class.rb
95
106
  - spec/app_root/app/models/user.rb
96
- - spec/app_root/app/controllers/application_controller.rb
107
+ - spec/app_root/config/boot.rb
97
108
  - spec/app_root/config/environment.rb
109
+ - spec/app_root/config/environments/in_memory.rb
98
110
  - spec/app_root/config/environments/mysql.rb
99
111
  - spec/app_root/config/environments/postgresql.rb
100
- - spec/app_root/config/environments/sqlite3.rb
101
- - spec/app_root/config/environments/in_memory.rb
102
112
  - spec/app_root/config/environments/sqlite.rb
103
- - spec/app_root/config/boot.rb
113
+ - spec/app_root/config/environments/sqlite3.rb
104
114
  - spec/app_root/config/routes.rb
105
- - spec/app_root/db/migrate/002_create_users.rb
106
115
  - spec/app_root/db/migrate/001_create_movies.rb
116
+ - spec/app_root/db/migrate/002_create_users.rb
107
117
  - spec/app_root/db/migrate/003_create_payments.rb
108
118
  - spec/app_root/lib/console_with_fixtures.rb
109
- - spec/factory_spec.rb
110
119
  - spec/spec_helper.rb
120
+ - spec/step_mother_ext_spec.rb
121
+ - spec/steps_spec.rb
122
+ - spec/factory_spec.rb
@@ -1,108 +0,0 @@
1
- module Cucumber
2
- module Factory
3
-
4
- def self.add_steps(world)
5
- steps.each do |step|
6
- world.instance_eval do
7
- Given(step[0], &step[1].bind(world))
8
- end
9
- end
10
- end
11
-
12
- def self.steps
13
- [
14
- [
15
- /^"([^\"]*)" is an? (.+?)( \(.+?\))?( with the .+?)?$/,
16
- lambda { |name, raw_model, raw_variant, raw_attributes| Cucumber::Factory.parse_named_creation(self, name, raw_model, raw_variant, raw_attributes) }
17
- ],
18
- [
19
- /^there is an? (.+?)( \(.+?\))?( with the .+?)?$/,
20
- lambda { |raw_model, raw_variant, raw_attributes| Cucumber::Factory.parse_creation(self, raw_model, raw_variant, raw_attributes) }
21
- ]
22
- ]
23
- end
24
-
25
- def self.parse(world, command)
26
- command = command.sub(/^When |Given |Then /, "")
27
- steps.each do |step|
28
- match = step[0].match(command)
29
- if match
30
- step[1].bind(world).call(*match.captures)
31
- return
32
- end
33
- end
34
- raise "No step definition for: #{command}"
35
- end
36
-
37
- def self.parse_named_creation(world, name, raw_model, raw_variant, raw_attributes)
38
- record = parse_creation(world, raw_model, raw_variant, raw_attributes)
39
- variable = variable_name_from_prose(name)
40
- world.instance_variable_set variable, record
41
- end
42
-
43
- def self.parse_creation(world, raw_model, raw_variant, raw_attributes)
44
- model_class = model_class_from_prose(raw_model)
45
- attributes = {}
46
- if raw_attributes.present? && raw_attributes.strip.present?
47
- raw_attributes.scan(/(the|and|with| )+(.*?) ("([^\"]*)"|above)/).each do |fragment|
48
- value = nil
49
- attribute = fragment[1].downcase.gsub(" ", "_").to_sym
50
- value_type = fragment[2] # 'above' or a quoted string
51
- value = fragment[3]
52
- association = model_class.reflect_on_association(attribute) if model_class.respond_to?(:reflect_on_association)
53
- if association.present?
54
- if value_type == "above"
55
- # Don't use class.last, in sqlite that is not always the last inserted element
56
- value = association.klass.find(:last, :order => "id") or raise "There is no last #{attribute}"
57
- else
58
- value = world.instance_variable_get(variable_name_from_prose(value))
59
- end
60
- end
61
- attributes[attribute] = value
62
- end
63
- end
64
- variant = raw_variant.present? && /\((.*?)\)/.match(raw_variant)[1].downcase.gsub(" ", "_")
65
- create_record(model_class, variant, attributes)
66
- end
67
-
68
- def self.model_class_from_prose(prose)
69
- # don't use \w which depends on the system locale
70
- prose.gsub(/[^A-Za-z0-9_]+/, "_").camelize.constantize
71
- end
72
-
73
- def self.variable_name_from_prose(prose)
74
- # don't use \w which depends on the system locale
75
- name = prose.downcase.gsub(/[^A-Za-z0-9_]+/, '_')
76
- name = name.gsub(/^_+/, '').gsub(/_+$/, '')
77
- name = "_#{name}" unless name.length >= 0 && name =~ /^[a-z]/
78
- :"@#{name}"
79
- end
80
-
81
- private
82
-
83
- def self.factory_girl_factory_name(model_class)
84
- model_class.to_s.underscore.to_sym
85
- end
86
-
87
- def self.create_record(model_class, variant, attributes)
88
- factory_name = factory_girl_factory_name(model_class)
89
- if defined?(::Factory) && factory = ::Factory.factories[factory_name]
90
- ::Factory.create(factory_name, attributes)
91
- elsif model_class.respond_to?(:make) # Machinist blueprint
92
- if variant.present?
93
- model_class.make(variant.to_sym, attributes)
94
- else
95
- model_class.make(attributes)
96
- end
97
- elsif model_class.respond_to?(:create!) # Plain ActiveRecord
98
- model = model_class.new
99
- model.send(:attributes=, attributes, false) # ignore attr_accessible
100
- model.save!
101
- model
102
- else
103
- model_class.new(attributes)
104
- end
105
- end
106
-
107
- end
108
- end