cucumber_factory 1.13.0 → 1.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0fe3dc644f2055470649f9f9c6e4c1daab8ee30b4ad2136cc12011c393404fb9
4
+ data.tar.gz: 7ee265cbb4c3c83752f39ba8f5af0aff938fbee6a83e8fc5b7f4d4d77a2407c6
5
+ SHA512:
6
+ metadata.gz: d37b11bf0e7ac0d9c3103734c102ce88df8eec096d171ebc239ebc9306e0cb767eb75c11a272c10d7a643b7edaa5658475f34884d4ce2e287ccec2c96025dc3c
7
+ data.tar.gz: cfecaf32af5b283cc2f77bba6c69d96bc52bf69a37862e5e2e2562a73a30674842291aa0dbd60f240edf34121cdc251bc9829492ea0f57a809f33bec71afe7d2
data/Gemfile ADDED
@@ -0,0 +1 @@
1
+ ./gemfiles/Gemfile.cucumber-2.4
@@ -0,0 +1 @@
1
+ ./gemfiles/Gemfile.cucumber-2.4.lock
data/README.md CHANGED
@@ -10,20 +10,23 @@ cucumber_factory allows you to create ActiveRecord objects directly from your [C
10
10
  Basic usage
11
11
  -----------
12
12
 
13
- To create a new record with default attributes:
13
+ To create a new record with default attributes, begin any step with `Given there is`:
14
14
 
15
15
  ```cucumber
16
16
  Given there is a movie
17
17
  ```
18
18
 
19
- To create the record, cucumber_factory will call [`Movie.make`](http://github.com/notahat/machinist), [`Factory.create(:movie)`](http://github.com/thoughtbot/factory_bot), [`Movie.create!`](http://apidock.com/rails/ActiveRecord/Persistence/ClassMethods/create%21) or `Movie.new`, depending on what's available.
19
+ To create the record, cucumber_factory will call [`FactoryBot.create(:movie)`](http://github.com/thoughtbot/factory_bot), `FactoryGirl.create(:movie)`, [`Movie.make`](http://github.com/notahat/machinist), [`Movie.create!`](http://apidock.com/rails/ActiveRecord/Persistence/ClassMethods/create%21) or `Movie.new`, depending on what's available.
20
20
 
21
- To create a new record with attributes set, you can say:
21
+ Quoted strings and numbers denote attribute values:
22
22
 
23
23
  ```cucumber
24
- Given there is a movie with the title "Sunshine" and the year "2007"
24
+ Given there is a movie with the title "Sunshine" and the year 2007
25
25
  ```
26
26
 
27
+ Setting boolean attributes
28
+ --------------------------
29
+
27
30
  Boolean attributes can be set by appending `which`, `that` or `who` at the end:
28
31
 
29
32
  ```cucumber
@@ -39,6 +42,10 @@ Given there is a movie which is awesome, popular and successful but not science
39
42
  And there is a director with the income "500000" but with the account balance "-30000"
40
43
  ```
41
44
 
45
+
46
+ Setting many attributes with a table
47
+ ------------------------------------
48
+
42
49
  If you have many attribute assignments you can use doc string or data table:
43
50
 
44
51
  ```cucumber
@@ -102,10 +109,30 @@ Given there is a movie with the prequel above and these attributes:
102
109
  | comedy | false |
103
110
  ```
104
111
 
105
- Support for popular factory gems
106
- --------------------------------
107
112
 
108
- [Machinist blueprints](http://github.com/notahat/machinist) and [factory_bot factories](http://github.com/thoughtbot/factory_bot) will be used when available.
113
+ Setting array attributes or has_many associations
114
+ -------------------------------------------------
115
+
116
+ You can set `has_many` associations by referring to multiple named records in square brackets:
117
+
118
+ ```cucumber
119
+ Given there is a movie with the title "Sunshine"
120
+ And there is a movie with the title "Limitless"
121
+ And there is a movie with the title "Salt"
122
+ And there is a user with the favorite movies ["Sunshine", "Limitless" and "Salt"]
123
+ ```
124
+
125
+ When using [PostgreSQL array columns](https://www.postgresql.org/docs/9.1/static/arrays.html), you can set an array attribute to a value with square brackets:
126
+
127
+ ```cucumber
128
+ Given there is a movie with the tags ["comedy", "drama" and "action"]
129
+ ```
130
+
131
+
132
+
133
+
134
+ Using named factories and traits
135
+ --------------------------------
109
136
 
110
137
  You can use a [FactoryBot child factory](https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#inheritance) or [Machinist named blueprint](https://github.com/notahat/machinist/tree/1.0-maintenance#named-blueprints) by putting the variant name in parentheses:
111
138
 
@@ -120,8 +147,10 @@ Given there is a movie (moody, dark) with the title "Interstellar"
120
147
  ```
121
148
 
122
149
 
150
+
151
+
123
152
  Overriding factory steps
124
- -----------------------
153
+ ------------------------
125
154
 
126
155
  If you want to override a factory step with your own version, just do so:
127
156
 
@@ -2,6 +2,7 @@ require 'cucumber/factory/build_strategy'
2
2
 
3
3
  module Cucumber
4
4
  class Factory
5
+ class Error < StandardError; end
5
6
 
6
7
  ATTRIBUTES_PATTERN = '( with the .+?)?( (?:which|who|that) is .+?)?'
7
8
  TEXT_ATTRIBUTES_PATTERN = ' (?:with|and) these attributes:'
@@ -11,6 +12,14 @@ module Cucumber
11
12
 
12
13
  NAMED_RECORDS_VARIABLE = :'@named_cucumber_factory_records'
13
14
 
15
+ VALUE_INTEGER = /\d+/
16
+ VALUE_DECIMAL = /[\d\.]+/
17
+ VALUE_STRING = /"[^"]*"/
18
+ VALUE_ARRAY = /\[[^\]]*\]/
19
+ VALUE_LAST_RECORD = /\babove\b/
20
+
21
+ VALUE_SCALAR = /#{VALUE_STRING}|#{VALUE_DECIMAL}|#{VALUE_INTEGER}/
22
+
14
23
  CLEAR_NAMED_RECORDS_STEP_DESCRIPTOR = {
15
24
  :kind => :Before,
16
25
  :block => proc { Cucumber::Factory.send(:reset_named_records, self) }
@@ -96,11 +105,10 @@ module Cucumber
96
105
  model_class = build_strategy.model_class
97
106
  attributes = {}
98
107
  if raw_attributes.try(:strip).present?
99
- raw_attributes.scan(/(?:the |and |with |but |,| )+(.*?) ("([^\"]*)"|above)/).each do |fragment|
108
+ raw_attributes.scan(/(?:the |and |with |but |,| )+(.*?) (#{VALUE_SCALAR}|#{VALUE_ARRAY}|#{VALUE_LAST_RECORD})/).each do |fragment|
100
109
  attribute = attribute_name_from_prose(fragment[0])
101
- value_type = fragment[1] # 'above' or a quoted string
102
- value = fragment[2] # the value string without quotes
103
- attributes[attribute] = attribute_value(world, model_class, attribute, value_type, value)
110
+ value = fragment[1]
111
+ attributes[attribute] = attribute_value(world, model_class, attribute, value)
104
112
  end
105
113
  end
106
114
  if raw_boolean_attributes.try(:strip).present?
@@ -131,20 +139,53 @@ module Cucumber
131
139
  record
132
140
  end
133
141
 
134
- def attribute_value(world, model_class, attribute, value_type, value)
142
+ def attribute_value(world, model_class, attribute, value)
135
143
  association = model_class.respond_to?(:reflect_on_association) ? model_class.reflect_on_association(attribute) : nil
136
- if association.present?
137
- if value_type == "above"
138
- value = CucumberFactory::Switcher.find_last(association.klass) or raise "There is no last #{attribute}"
139
- else
144
+
145
+ if matches_fully?(value, VALUE_ARRAY)
146
+ elements_str = unquote(value)
147
+ value = elements_str.scan(VALUE_SCALAR).map { |v| attribute_value(world, model_class, attribute, v) }
148
+ elsif association.present?
149
+ if matches_fully?(value, VALUE_LAST_RECORD)
150
+ value = CucumberFactory::Switcher.find_last(association.klass) or raise Error, "There is no last #{attribute}"
151
+ elsif matches_fully?(value, VALUE_STRING)
152
+ value = unquote(value)
140
153
  value = get_named_record(world, value) || transform_value(world, value)
154
+ else
155
+ raise Error, "Cannot set association #{model_class}##{attribute} to #{value}. To identify a previously created record, use `above` or a quoted string."
141
156
  end
142
157
  else
158
+ value = resolve_scalar_value(world, model_class, attribute, value)
159
+ end
160
+ value
161
+ end
162
+
163
+ def resolve_scalar_value(world, model_class, attribute, value)
164
+ if matches_fully?(value, VALUE_STRING)
165
+ value = unquote(value)
143
166
  value = transform_value(world, value)
167
+ elsif matches_fully?(value, VALUE_INTEGER)
168
+ value = value.to_i
169
+ elsif matches_fully?(value, VALUE_DECIMAL)
170
+ value = BigDecimal(value)
171
+ else
172
+ raise Error, "Cannot set attribute #{model_class}##{attribute} to #{value}."
144
173
  end
145
174
  value
146
175
  end
147
176
 
177
+ def unquote(string)
178
+ string[1, string.length - 2]
179
+ end
180
+
181
+ def full_regexp(partial_regexp)
182
+ Regexp.new("\\A" + partial_regexp.source + "\\z", partial_regexp.options)
183
+ end
184
+
185
+ def matches_fully?(string, partial_regexp)
186
+ string =~ full_regexp(partial_regexp)
187
+ end
188
+
148
189
  def transform_value(world, value)
149
190
  # Transforms were a feature available in Cucumber 1 and 2.
150
191
  # They have been kind-of replaced by ParameterTypes, which don't work with generic steps
@@ -1,3 +1,3 @@
1
1
  module CucumberFactory
2
- VERSION = '1.13.0'
2
+ VERSION = '1.14.0'
3
3
  end
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
-
4
3
  describe 'steps provided by cucumber_factory' do
5
4
 
6
5
  before(:each) do
@@ -198,7 +197,7 @@ describe 'steps provided by cucumber_factory' do
198
197
  it "should raise a proper error if there is no previous record when saying 'above'" do
199
198
  lambda do
200
199
  invoke_cucumber_step('there is a movie with the title "Before Sunset" and the reviewer above and the prequel above')
201
- end.should raise_error(RuntimeError, "There is no last reviewer")
200
+ end.should raise_error(/There is no last reviewer/i)
202
201
  end
203
202
 
204
203
  it "should reload an object assigned to a belongs_to before assigning" do
@@ -274,6 +273,65 @@ describe 'steps provided by cucumber_factory' do
274
273
  user.deleted.should == true
275
274
  end
276
275
 
276
+ it "should allow to set integer attributes without surrounding quotes" do
277
+ invoke_cucumber_step('there is a plain Ruby class with the amount 123 and the total 456')
278
+ obj = PlainRubyClass.last
279
+ obj.attributes[:amount].should == 123
280
+ obj.attributes[:total].should == 456
281
+ end
282
+
283
+ it "should allow to set decimal attributes without surrounding quotes" do
284
+ invoke_cucumber_step('there is a plain Ruby class with the amount 1.23 and the total 45.6')
285
+ obj = PlainRubyClass.last
286
+ obj.attributes[:amount].should be_a(BigDecimal)
287
+ obj.attributes[:amount].to_s.should == "1.23"
288
+ obj.attributes[:total].should be_a(BigDecimal)
289
+ obj.attributes[:total].to_s.should == "45.6"
290
+ end
291
+
292
+ it "should allow set an array of strings with square brackets" do
293
+ invoke_cucumber_step('there is a plain Ruby class with the tags ["foo", "bar"] and the list ["bam", "baz"]')
294
+ obj = PlainRubyClass.last
295
+ obj.attributes[:tags].should == ['foo', 'bar']
296
+ obj.attributes[:list].should == ['bam', 'baz']
297
+ end
298
+
299
+ it "should allow set an array of numbers with square brackets" do
300
+ invoke_cucumber_step('there is a plain Ruby class with the integers [1, 2] and the decimals [3.4, 4.5]')
301
+ obj = PlainRubyClass.last
302
+ obj.attributes[:integers].should == [1, 2]
303
+ obj.attributes[:decimals].should == [BigDecimal('3.4'), BigDecimal('4.5')]
304
+ end
305
+
306
+ it 'should allow to set an empty array' do
307
+ invoke_cucumber_step('there is a plain Ruby class with the tags []')
308
+ obj = PlainRubyClass.last
309
+ obj.attributes[:tags].should == []
310
+ end
311
+
312
+ it 'should allow to separate array values with either a comma or "and"' do
313
+ invoke_cucumber_step('there is a plain Ruby class with the tags ["foo", "bar" and "baz"] and the list ["bam", "baz" and "qux"]')
314
+ obj = PlainRubyClass.last
315
+ obj.attributes[:tags].should == ['foo', 'bar', 'baz']
316
+ obj.attributes[:list].should == ['bam', 'baz', 'qux']
317
+ end
318
+
319
+ it 'should allow to separate array values with an Oxford comma' do
320
+ invoke_cucumber_step('there is a plain Ruby class with the tags ["foo", "bar", and "baz"] and the list ["bam", "baz", and "qux"]')
321
+ obj = PlainRubyClass.last
322
+ obj.attributes[:tags].should == ['foo', 'bar', 'baz']
323
+ obj.attributes[:list].should == ['bam', 'baz', 'qux']
324
+ end
325
+
326
+ it "should allow to set a has_many association by refering to multiple named records in square brackets" do
327
+ invoke_cucumber_step('there is a movie with the title "Sunshine"')
328
+ invoke_cucumber_step('there is a movie with the title "Limitless"')
329
+ invoke_cucumber_step('there is a user with the reviewed movies ["Sunshine" and "Limitless"]')
330
+ user = User.last
331
+ reviewed_movie_titles = user.reviewed_movies.map(&:title)
332
+ reviewed_movie_titles.should =~ ['Sunshine', 'Limitless']
333
+ end
334
+
277
335
  it "should allow attribute names starting with 'the'" do
278
336
  PlainRubyClass.should_receive(:new).with({:theme => 'Sci-fi'})
279
337
  invoke_cucumber_step('there is a plain ruby class with the theme "Sci-fi"')
@@ -9,4 +9,11 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each {|f| require f}
9
9
  Dir["#{File.dirname(__FILE__)}/shared_examples/**/*.rb"].sort.each {|f| require f}
10
10
 
11
11
  Gemika::RSpec.configure_clean_database_before_example
12
+
12
13
  Gemika::RSpec.configure_should_syntax
14
+
15
+ Gemika::RSpec.configure do |config|
16
+ config.before(:each) do
17
+ PlainRubyClass.reset
18
+ end
19
+ end
@@ -1,4 +1,20 @@
1
- class PlainRubyClass
2
- def initialize(options)
3
- end
4
- end
1
+ class PlainRubyClass
2
+ def initialize(attributes)
3
+ @attributes = attributes
4
+ self.class.last = self
5
+ end
6
+
7
+ attr_reader :attributes
8
+
9
+ def self.last
10
+ @last
11
+ end
12
+
13
+ def self.last=(instance)
14
+ @last = instance
15
+ end
16
+
17
+ def self.reset
18
+ @last = nil
19
+ end
20
+ end
@@ -1,3 +1,5 @@
1
- class User < ActiveRecord::Base
2
-
3
- end
1
+ class User < ActiveRecord::Base
2
+
3
+ has_many :reviewed_movies, :class_name => 'Movie', :foreign_key => 'reviewer_id'
4
+
5
+ end
metadata CHANGED
@@ -1,93 +1,82 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: cucumber_factory
3
- version: !ruby/object:Gem::Version
4
- hash: 35
5
- prerelease:
6
- segments:
7
- - 1
8
- - 13
9
- - 0
10
- version: 1.13.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.14.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Henning Koch
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2018-04-26 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2018-10-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: cucumber
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
26
17
  - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
32
20
  type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: activesupport
36
21
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
40
31
  - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
46
34
  type: :runtime
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
49
- name: activerecord
50
35
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
52
- none: false
53
- requirements:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
54
45
  - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 3
57
- segments:
58
- - 0
59
- version: "0"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
60
48
  type: :runtime
61
- version_requirements: *id003
62
- - !ruby/object:Gem::Dependency
63
- name: cucumber_priority
64
49
  prerelease: false
65
- requirement: &id004 !ruby/object:Gem::Requirement
66
- none: false
67
- requirements:
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cucumber_priority
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
68
59
  - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 23
71
- segments:
72
- - 0
73
- - 2
74
- - 0
60
+ - !ruby/object:Gem::Version
75
61
  version: 0.2.0
76
62
  type: :runtime
77
- version_requirements: *id004
78
- description: Cucumber Factory allows you to create ActiveRecord models from your Cucumber features without writing step definitions for each model.
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.2.0
69
+ description: Cucumber Factory allows you to create ActiveRecord models from your Cucumber
70
+ features without writing step definitions for each model.
79
71
  email: github@makandra.de
80
72
  executables: []
81
-
82
73
  extensions: []
83
-
84
74
  extra_rdoc_files: []
85
-
86
- files:
87
- - .gitignore
88
- - .rspec
89
- - .ruby-version
90
- - .travis.yml
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".ruby-version"
79
+ - ".travis.yml"
91
80
  - Gemfile
92
81
  - Gemfile.lock
93
82
  - LICENSE
@@ -109,10 +98,6 @@ files:
109
98
  - lib/cucumber_factory/version.rb
110
99
  - spec/cucumber_factory/factory/build_strategy_spec.rb
111
100
  - spec/cucumber_factory/steps_spec.rb
112
- - spec/rails-2.3/app_root/log/test.log
113
- - spec/rails-3.0/app_root/log/test.log
114
- - spec/rails-3.2/app_root/log/test.log
115
- - spec/rails-4.0/app_root/log/test.log
116
101
  - spec/spec_helper.rb
117
102
  - spec/support/cucumber_helper.rb
118
103
  - spec/support/database.rb
@@ -129,38 +114,27 @@ files:
129
114
  - spec/support/models/user.rb
130
115
  - spec/support/models/uuid_user.rb
131
116
  homepage: http://github.com/makandra/cucumber_factory
132
- licenses:
117
+ licenses:
133
118
  - MIT
119
+ metadata: {}
134
120
  post_install_message:
135
121
  rdoc_options: []
136
-
137
- require_paths:
122
+ require_paths:
138
123
  - lib
139
- required_ruby_version: !ruby/object:Gem::Requirement
140
- none: false
141
- requirements:
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
142
126
  - - ">="
143
- - !ruby/object:Gem::Version
144
- hash: 3
145
- segments:
146
- - 0
147
- version: "0"
148
- required_rubygems_version: !ruby/object:Gem::Requirement
149
- none: false
150
- requirements:
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
151
131
  - - ">="
152
- - !ruby/object:Gem::Version
153
- hash: 3
154
- segments:
155
- - 0
156
- version: "0"
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
157
134
  requirements: []
158
-
159
135
  rubyforge_project:
160
- rubygems_version: 1.8.30
136
+ rubygems_version: 2.7.3
161
137
  signing_key:
162
- specification_version: 3
138
+ specification_version: 4
163
139
  summary: Create records from Cucumber features without writing step definitions.
164
140
  test_files: []
165
-
166
- has_rdoc: