cucumber_factory 1.13.0 → 1.14.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.
@@ -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: