cucumber_factory 2.0.0 → 2.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 856fe1922e3b069b305e514911da87b4432acc34c89105b46cbf06d6cdd997be
4
- data.tar.gz: a0f9631996850758343f66f79d96d88a1cf0216c4df464a8132677d462766525
3
+ metadata.gz: 95567d71e09afa59f6db5bb2722ce78eb234b473987025ca3f66b6e181cdac1e
4
+ data.tar.gz: 7b1e046852657282cb2d5b65b714d12bb65c848196c0d6c70c13f3ce231fc684
5
5
  SHA512:
6
- metadata.gz: 31d7825ded3ed0ed9e9c29a490ecbff0028b710cb4f33bddbf1e3846a744444c9ae53a852b37db72284a57f4ef40515e166f8043dbf4d96db5412205a7f3b3c0
7
- data.tar.gz: 71ede7f9b7ae86335fb3eb1cd27ff9c72bd9ec9fbd958585fe4293443c7b6608b3cd0c21ea994971946ac69091722eb2a27714492d34a5e792583068c412b666
6
+ metadata.gz: '083f2675e4b6592ab9ee117b5080fefdeaa06f27abba833f3145b176834f37baf3e40f4ef74e90b9d91558f1034b50c7c6250d2675caeda98d52b8a794d27142'
7
+ data.tar.gz: 392e4121dc98584c1928f2e028964780f079a4a0f74d437fb6595dc6d2b9ecbbb090e9eb97f0361f9fa1059c633fb8a9de8f357d986ad0a3bd5e193e79c20bae
@@ -1,5 +1,4 @@
1
1
  rvm:
2
- - 1.8.7
3
2
  - 2.1.10
4
3
  - 2.5.3
5
4
 
@@ -13,20 +12,10 @@ dist: trusty
13
12
 
14
13
  matrix:
15
14
  exclude:
16
- - gemfile: Gemfile.cucumber-3.1
17
- rvm: 1.8.7
18
15
  - gemfile: Gemfile.cucumber-3.1
19
16
  rvm: 2.1.10 # cucumber 3 wants ruby >= 2.2
20
- - gemfile: Gemfile.cucumber-3.0
21
- rvm: 1.8.7
22
17
  - gemfile: Gemfile.cucumber-3.0
23
18
  rvm: 2.1.10 # cucumber 3 wants ruby >= 2.2
24
- - gemfile: Gemfile.cucumber-2.4
25
- rvm: 1.8.7
26
- - gemfile: Gemfile.cucumber-1.3
27
- rvm: 2.5.3 # doesn't work with old RSpec
28
- - gemfile: Gemfile.cucumber-1.3
29
- rvm: 2.1.10 # doesn't work with old RSpec
30
19
 
31
20
  install:
32
21
  # Replace default Travis CI bundler script with a version that doesn't
@@ -15,6 +15,57 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
15
15
 
16
16
  -
17
17
 
18
+ ## 2.2.0 - 2020-09-23
19
+
20
+ ### Compatible changes
21
+
22
+ - A step was added that allows modifying existing records with a similar syntax to creating new records:
23
+ ```cucumber
24
+ (Given "Bob" is a user)
25
+ And "Bob" has the email "foo@bar.com" and is subscribed
26
+ ```
27
+ - This step will also work with doc strings or tables:
28
+ ```cucumber
29
+ (Given "Bob" is a user)
30
+ And the user above has these attributes:
31
+ | name | Bob |
32
+ | email | foo@bar.com |
33
+ ```
34
+
35
+ ## 2.1.1 - 2020-05-20
36
+
37
+ ### Compatible changes
38
+
39
+ - Cucumber 2.1.0 introduced some regressions which are being addressed with this patch:
40
+ - Fix the assignment of polymorphic associations.
41
+ - Restore the support for inherited traits within nested factories.
42
+
43
+ ## 2.1.0 - 2020-03-09
44
+
45
+ ### Compatible changes
46
+
47
+ - Allow associations to be set for [transient attributes](https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#transient-attributes) if they are named after the model. For example, when there is a `Role` model and the`user` factory has a transient attribute `role`, the following steps are now valid:
48
+ ```
49
+ Given there is a role
50
+ And there is a user with the role above
51
+ ```
52
+
53
+ ## 2.0.2 - 2020-03-26
54
+
55
+ ### Compatible changes
56
+
57
+ - Removed development and test support for Ruby 1.8. Closes #32.
58
+
59
+ ## 2.0.1 - 2020-02-27
60
+
61
+ ### Compatible changes
62
+
63
+ - Fix a bug that prevented created records to be named when using multiline attribute assignments
64
+ ```
65
+ Given "Bob" is a user with these attributes:
66
+ | email | foo@bar.com |
67
+ ```
68
+
18
69
  ## 2.0.0 - 2020-02-10
19
70
 
20
71
  ### Breaking changes
@@ -2,16 +2,18 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Runtime dependencies
4
4
  gem 'cucumber', '~> 1.3.20'
5
- gem 'activesupport', '~> 2.3.0'
6
- gem 'activerecord', '~> 2.3.0'
7
- gem 'mysql2', '= 0.2.20'
8
- gem 'i18n', '=0.6.11' # 0.7 no longer builds for Ruby 1.8.7
5
+ gem 'activesupport', '~> 4.2.0'
6
+ gem 'activerecord', '~> 4.2.0'
7
+ gem 'mysql2'
9
8
 
10
9
  # Development dependencies
11
- gem 'rspec', '~> 1.0'
12
- gem 'rake', '=10.0.4'
10
+ gem 'rspec', '> 3.0'
11
+ gem 'rake', '>=10.0.4'
13
12
  gem 'database_cleaner', '~>1.0.0'
14
13
  gem 'gemika'
15
14
 
15
+ # Test dependencies
16
+ gem 'factory_bot', '< 5'
17
+
16
18
  # Gem under test
17
19
  gem 'cucumber_factory', :path => '.'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cucumber_factory (1.15.0)
4
+ cucumber_factory (2.2.0)
5
5
  activerecord
6
6
  activesupport
7
7
  cucumber
@@ -10,10 +10,21 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- activerecord (2.3.18)
14
- activesupport (= 2.3.18)
15
- activesupport (2.3.18)
16
- builder (3.2.2)
13
+ activemodel (4.2.11.1)
14
+ activesupport (= 4.2.11.1)
15
+ builder (~> 3.1)
16
+ activerecord (4.2.11.1)
17
+ activemodel (= 4.2.11.1)
18
+ activesupport (= 4.2.11.1)
19
+ arel (~> 6.0)
20
+ activesupport (4.2.11.1)
21
+ i18n (~> 0.7)
22
+ minitest (~> 5.1)
23
+ thread_safe (~> 0.3, >= 0.3.4)
24
+ tzinfo (~> 1.1)
25
+ arel (6.0.4)
26
+ builder (3.2.4)
27
+ concurrent-ruby (1.1.6)
17
28
  cucumber (1.3.20)
18
29
  builder (>= 2.1.2)
19
30
  diff-lcs (>= 1.1.3)
@@ -23,31 +34,50 @@ GEM
23
34
  cucumber_priority (0.3.2)
24
35
  cucumber
25
36
  database_cleaner (1.0.1)
26
- diff-lcs (1.2.5)
27
- gemika (0.3.2)
37
+ diff-lcs (1.3)
38
+ factory_bot (4.11.1)
39
+ activesupport (>= 3.0.0)
40
+ gemika (0.4.0)
28
41
  gherkin (2.12.2)
29
42
  multi_json (~> 1.3)
30
- i18n (0.6.11)
31
- multi_json (1.11.2)
43
+ i18n (0.9.5)
44
+ concurrent-ruby (~> 1.0)
45
+ minitest (5.12.0)
46
+ multi_json (1.14.1)
32
47
  multi_test (0.1.2)
33
- mysql2 (0.2.20)
34
- rake (10.0.4)
35
- rspec (1.3.2)
48
+ mysql2 (0.5.3)
49
+ rake (12.3.3)
50
+ rspec (3.9.0)
51
+ rspec-core (~> 3.9.0)
52
+ rspec-expectations (~> 3.9.0)
53
+ rspec-mocks (~> 3.9.0)
54
+ rspec-core (3.9.1)
55
+ rspec-support (~> 3.9.1)
56
+ rspec-expectations (3.9.0)
57
+ diff-lcs (>= 1.2.0, < 2.0)
58
+ rspec-support (~> 3.9.0)
59
+ rspec-mocks (3.9.1)
60
+ diff-lcs (>= 1.2.0, < 2.0)
61
+ rspec-support (~> 3.9.0)
62
+ rspec-support (3.9.2)
63
+ thread_safe (0.3.6)
64
+ tzinfo (1.2.6)
65
+ thread_safe (~> 0.1)
36
66
 
37
67
  PLATFORMS
38
68
  ruby
39
69
 
40
70
  DEPENDENCIES
41
- activerecord (~> 2.3.0)
42
- activesupport (~> 2.3.0)
71
+ activerecord (~> 4.2.0)
72
+ activesupport (~> 4.2.0)
43
73
  cucumber (~> 1.3.20)
44
74
  cucumber_factory!
45
75
  database_cleaner (~> 1.0.0)
76
+ factory_bot (< 5)
46
77
  gemika
47
- i18n (= 0.6.11)
48
- mysql2 (= 0.2.20)
49
- rake (= 10.0.4)
50
- rspec (~> 1.0)
78
+ mysql2
79
+ rake (>= 10.0.4)
80
+ rspec (> 3.0)
51
81
 
52
82
  BUNDLED WITH
53
- 1.17.1
83
+ 1.17.3
@@ -12,5 +12,8 @@ gem 'rake'
12
12
  gem 'database_cleaner'
13
13
  gem 'gemika'
14
14
 
15
+ # Test dependencies
16
+ gem 'factory_bot', '< 5' # 5.0 requires Ruby >= 2.3
17
+
15
18
  # Gem under test
16
19
  gem 'cucumber_factory', :path => '.'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cucumber_factory (2.0.0)
4
+ cucumber_factory (2.2.0)
5
5
  activerecord
6
6
  activesupport
7
7
  cucumber
@@ -40,6 +40,8 @@ GEM
40
40
  cucumber
41
41
  database_cleaner (1.6.2)
42
42
  diff-lcs (1.3)
43
+ factory_bot (4.11.1)
44
+ activesupport (>= 3.0.0)
43
45
  gemika (0.3.2)
44
46
  gherkin (4.1.3)
45
47
  i18n (0.9.5)
@@ -75,6 +77,7 @@ DEPENDENCIES
75
77
  cucumber (~> 2.4.0)
76
78
  cucumber_factory!
77
79
  database_cleaner
80
+ factory_bot (< 5)
78
81
  gemika
79
82
  mysql2
80
83
  rake
@@ -12,5 +12,8 @@ gem 'rake'
12
12
  gem 'database_cleaner'
13
13
  gem 'gemika'
14
14
 
15
+ # Test dependencies
16
+ gem 'factory_bot'
17
+
15
18
  # Gem under test
16
19
  gem 'cucumber_factory', :path => '.'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cucumber_factory (2.0.0)
4
+ cucumber_factory (2.2.0)
5
5
  activerecord
6
6
  activesupport
7
7
  cucumber
@@ -45,6 +45,8 @@ GEM
45
45
  cucumber
46
46
  database_cleaner (1.6.2)
47
47
  diff-lcs (1.3)
48
+ factory_bot (5.1.1)
49
+ activesupport (>= 4.2.0)
48
50
  gemika (0.3.2)
49
51
  gherkin (4.1.3)
50
52
  i18n (0.9.5)
@@ -80,6 +82,7 @@ DEPENDENCIES
80
82
  cucumber (~> 3.0.0)
81
83
  cucumber_factory!
82
84
  database_cleaner
85
+ factory_bot
83
86
  gemika
84
87
  mysql2
85
88
  rake
@@ -12,5 +12,8 @@ gem 'rake'
12
12
  gem 'database_cleaner'
13
13
  gem 'gemika'
14
14
 
15
+ # Test dependencies
16
+ gem 'factory_bot'
17
+
15
18
  # Gem under test
16
19
  gem 'cucumber_factory', :path => '.'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cucumber_factory (2.0.0)
4
+ cucumber_factory (2.2.0)
5
5
  activerecord
6
6
  activesupport
7
7
  cucumber
@@ -45,6 +45,8 @@ GEM
45
45
  cucumber
46
46
  database_cleaner (1.6.2)
47
47
  diff-lcs (1.3)
48
+ factory_bot (5.1.1)
49
+ activesupport (>= 4.2.0)
48
50
  gemika (0.3.2)
49
51
  gherkin (5.0.0)
50
52
  i18n (0.9.5)
@@ -80,6 +82,7 @@ DEPENDENCIES
80
82
  cucumber (~> 3.1.0)
81
83
  cucumber_factory!
82
84
  database_cleaner
85
+ factory_bot
83
86
  gemika
84
87
  mysql2
85
88
  rake
data/README.md CHANGED
@@ -24,6 +24,13 @@ Quoted strings and numbers denote attribute values:
24
24
  Given there is a movie with the title "Sunshine" and the year 2007
25
25
  ```
26
26
 
27
+ To update an existing record, specify the record and the changes:
28
+ ```
29
+ Given the movie above has the title "Sunset" and the year 2008
30
+ Given the movie "Sunrise" has the year 2009
31
+ ```
32
+ A record can be specified by the `above` keyword, which uses the last created record of this class, or by any string that was used during its creation.
33
+
27
34
  Setting boolean attributes
28
35
  --------------------------
29
36
 
@@ -42,6 +49,13 @@ Given there is a movie which is awesome, popular and successful but not science
42
49
  And there is a director with the income "500000" but with the account balance "-30000"
43
50
  ```
44
51
 
52
+ To update boolean attributes use the keyword `is`:
53
+
54
+ ```cucumber
55
+ Given the movie above is awesome but not popular
56
+ Given the movie above has the year 1979 but is not science fiction
57
+ ```
58
+
45
59
 
46
60
  Setting many attributes with a table
47
61
  ------------------------------------
@@ -62,10 +76,18 @@ Given there is a movie with these attributes:
62
76
  | comedy | false |
63
77
  ```
64
78
 
79
+ ```cucumber
80
+ Given the movie above has these attributes:
81
+ """
82
+ name: Sunshine
83
+ comedy: false
84
+ """
85
+ ```
86
+
65
87
  Setting associations
66
88
  --------------------
67
89
 
68
- You can set `belongs_to` associations by referring to the last created record of as `above`:
90
+ You can set `belongs_to` and `transient` associations by referring to the last created record of as `above`:
69
91
 
70
92
  ```cucumber
71
93
  Given there is a movie with the title "Before Sunrise"
@@ -13,6 +13,7 @@ require 'cucumber_priority'
13
13
 
14
14
  # Gem
15
15
  require 'cucumber_factory/build_strategy'
16
+ require 'cucumber_factory/update_strategy'
16
17
  require 'cucumber_factory/factory'
17
18
  require 'cucumber_factory/switcher'
18
19
 
@@ -7,79 +7,115 @@ module CucumberFactory
7
7
  class << self
8
8
 
9
9
  def from_prose(model_prose, variant_prose)
10
- # don't use \w which depends on the system locale
11
- underscored_model_name = model_prose.gsub(/[^A-Za-z0-9_\/]+/, "_")
12
- if variant_prose.present?
13
- variants = /\((.*?)\)/.match(variant_prose)[1].split(/\s*,\s*/)
14
- variants = variants.collect { |variant| variant.downcase.gsub(" ", "_") }
10
+ variants = variants_from_prose(variant_prose)
11
+ factory = factory_bot_factory(model_prose, variants)
12
+
13
+ if factory
14
+ factory.compile # Required to load inherited traits!
15
+ strategy = factory_bot_strategy(factory, model_prose, variants)
16
+ transient_attributes = factory_bot_transient_attributes(factory, variants)
15
17
  else
16
- variants = []
18
+ strategy = alternative_strategy(model_prose, variants)
19
+ transient_attributes = []
17
20
  end
18
21
 
19
- if factory_bot_strategy = factory_bot_strategy(underscored_model_name, variants)
20
- factory_bot_strategy
22
+ [strategy, transient_attributes]
23
+ end
24
+
25
+ def parse_model_class(model_prose)
26
+ underscored_model_name(model_prose).camelize.constantize
27
+ end
28
+
29
+ private
30
+
31
+ def variants_from_prose(variant_prose)
32
+ if variant_prose.present?
33
+ variants = /\((.*?)\)/.match(variant_prose)[1].split(/\s*,\s*/)
34
+ variants.collect { |variant| variant.downcase.gsub(" ", "_").to_sym }
21
35
  else
22
- model_class = underscored_model_name.camelize.constantize
23
- machinist_strategy(model_class, variants) ||
24
- active_record_strategy(model_class) ||
25
- ruby_object_strategy(model_class)
36
+ []
26
37
  end
27
38
  end
28
39
 
29
- private
40
+ def factory_bot_factory(model_prose, variants)
41
+ return unless factory_bot_class
30
42
 
31
- def factory_bot_strategy(factory_name, variants)
32
- factory_class = ::FactoryBot if defined?(FactoryBot)
33
- factory_class ||= ::FactoryGirl if defined?(FactoryGirl)
34
- return unless factory_class
43
+ factory_name = factory_name_from_prose(model_prose)
44
+ factory = factory_bot_class.factories[factory_name]
35
45
 
36
- variants = variants.map(&:to_sym)
37
- factory_name = factory_name.to_s.underscore.gsub('/', '_').to_sym
46
+ if factory.nil? && variants.present?
47
+ factory = factory_bot_class.factories[variants[0]]
48
+ end
38
49
 
39
- factory = factory_class.factories[factory_name]
50
+ factory
51
+ end
40
52
 
41
- if factory.nil? && variants.present? && factory = factory_class.factories[variants[0]]
53
+ def factory_bot_strategy(factory, model_prose, variants)
54
+ return unless factory
55
+
56
+ factory_name = factory_name_from_prose(model_prose)
57
+ if factory_bot_class.factories[factory_name].nil? && variants.present?
42
58
  factory_name, *variants = variants
43
59
  end
44
60
 
45
- if factory
46
- new(factory.build_class) do |attributes|
47
- # Cannot have additional scalar args after a varargs
48
- # argument in Ruby 1.8 and 1.9
49
- args = []
50
- args += variants
51
- args << attributes
52
- factory_class.create(factory_name, *args)
53
- end
61
+ new(factory.build_class) do |attributes|
62
+ # Cannot have additional scalar args after a varargs
63
+ # argument in Ruby 1.8 and 1.9
64
+ args = []
65
+ args += variants
66
+ args << attributes
67
+ factory_bot_class.create(factory_name, *args)
68
+ end
69
+ end
70
+
71
+ def factory_bot_transient_attributes(factory, variants)
72
+ return [] unless factory
73
+
74
+ factory_attributes = factory_bot_attributes(factory, variants)
75
+ class_attributes = factory.build_class.attribute_names.map(&:to_sym)
76
+
77
+ factory_attributes - class_attributes
78
+ end
79
+
80
+ def factory_bot_attributes(factory, variants)
81
+ traits = factory_bot_traits(factory, variants)
82
+ factory.with_traits(traits.map(&:name)).definition.attributes.names
83
+ end
84
+
85
+ def factory_bot_traits(factory, variants)
86
+ factory.definition.defined_traits.select do |trait|
87
+ variants.include?(trait.name.to_sym)
54
88
  end
89
+ end
55
90
 
91
+ def alternative_strategy(model_prose, variants)
92
+ model_class = parse_model_class(model_prose)
93
+ machinist_strategy(model_class, variants) ||
94
+ active_record_strategy(model_class) ||
95
+ ruby_object_strategy(model_class)
56
96
  end
57
97
 
58
98
  def machinist_strategy(model_class, variants)
59
- if model_class.respond_to?(:make)
60
-
61
- new(model_class) do |attributes|
62
- if variants.present?
63
- variants.size == 1 or raise 'Machinist only supports a single variant per blueprint'
64
- model_class.make(variants.first.to_sym, attributes)
65
- else
66
- model_class.make(attributes)
67
- end
68
- end
99
+ return unless model_class.respond_to?(:make)
69
100
 
101
+ new(model_class) do |attributes|
102
+ if variants.present?
103
+ variants.size == 1 or raise 'Machinist only supports a single variant per blueprint'
104
+ model_class.make(variants.first, attributes)
105
+ else
106
+ model_class.make(attributes)
107
+ end
70
108
  end
71
109
  end
72
110
 
73
111
  def active_record_strategy(model_class)
74
- if model_class.respond_to?(:create!)
75
-
76
- new(model_class) do |attributes|
77
- model = model_class.new
78
- CucumberFactory::Switcher.assign_attributes(model, attributes)
79
- model.save!
80
- model
81
- end
112
+ return unless model_class.respond_to?(:create!)
82
113
 
114
+ new(model_class) do |attributes|
115
+ model = model_class.new
116
+ CucumberFactory::Switcher.assign_attributes(model, attributes)
117
+ model.save!
118
+ model
83
119
  end
84
120
  end
85
121
 
@@ -89,6 +125,21 @@ module CucumberFactory
89
125
  end
90
126
  end
91
127
 
128
+ def factory_bot_class
129
+ factory_class = ::FactoryBot if defined?(FactoryBot)
130
+ factory_class ||= ::FactoryGirl if defined?(FactoryGirl)
131
+ factory_class
132
+ end
133
+
134
+ def factory_name_from_prose(model_prose)
135
+ underscored_model_name(model_prose).to_s.underscore.gsub('/', '_').to_sym
136
+ end
137
+
138
+ def underscored_model_name(model_prose)
139
+ # don't use \w which depends on the system locale
140
+ model_prose.gsub(/[^A-Za-z0-9_\/]+/, "_")
141
+ end
142
+
92
143
  end
93
144
 
94
145