cucumber_factory 2.0.2 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eeed19e5c878629c3f87a038821a955401c40c19ca323577d7e84e3ae019f764
4
- data.tar.gz: 2d3b57e9b739be6e69d28240c7553eec3882b2e200ca64c402a8cc646bcdc169
3
+ metadata.gz: 8f3cf136399f60bcca2308f17e39c1846de1e443157ac433bcdb94f6937a3333
4
+ data.tar.gz: 5983deb45accf5811e0af7f251a15f37062600c7decbf543a021b3338578a9bc
5
5
  SHA512:
6
- metadata.gz: 752a2cbe68fa53254741a792770ab0252f320a218fb3c39fe85679bcf6d8e1289fdee354042bb342d96789266c6f8ac02819393ee375d628def84679de281cad
7
- data.tar.gz: aa2eb84a898e7d52f10b7272ad8f7c04a9d1dea4096d0a7fab04d9158a887f46839e7d36b83f9aec945b13b18f0b4550de19fe9df0897ccc1235f22f990b2b59
6
+ metadata.gz: bb54944c1e92864af9cfcdaca67dfe3988577394907fce3c682b02ea900b50bc89d6d89eb6cdc3cdb90cfc89c199391e02dbfd50ef158ba46f0ccb2129ef8100
7
+ data.tar.gz: 9d90540b249f759377eb7cde97dc567fb61bada43f09c19ad6afaa73fff53e97acfd781ff8014515b9a0b04b8d8772663b8fc367cc9e743e9b61a26f1db839e9
data/.gitignore CHANGED
@@ -6,3 +6,4 @@ pkg
6
6
  .rvmrc
7
7
  log/*.log
8
8
  spec/support/database.yml
9
+ uploads/
@@ -13,6 +13,59 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
13
13
 
14
14
  ### Compatible changes
15
15
 
16
+ -
17
+
18
+ ## 2.3.1 - 2020-10-01
19
+
20
+ ### Compatible changes
21
+
22
+ - Lowered the priority of all steps in this gem to avoid issues with overlapping steps.
23
+
24
+ ## 2.3.0 - 2020-09-24
25
+
26
+ ### Compatible changes
27
+
28
+ - Added a step to add file objects to a model:
29
+ ```cucumber
30
+ Given there is a user with the avatar file:"path/to/avatar.jpg"
31
+ ```
32
+ Both single and double quotes are supported.
33
+
34
+ ## 2.2.0 - 2020-09-23
35
+
36
+ ### Compatible changes
37
+
38
+ - A step was added that allows modifying existing records with a similar syntax to creating new records:
39
+ ```cucumber
40
+ (Given "Bob" is a user)
41
+ And "Bob" has the email "foo@bar.com" and is subscribed
42
+ ```
43
+ - This step will also work with doc strings or tables:
44
+ ```cucumber
45
+ (Given "Bob" is a user)
46
+ And the user above has these attributes:
47
+ | name | Bob |
48
+ | email | foo@bar.com |
49
+ ```
50
+
51
+ ## 2.1.1 - 2020-05-20
52
+
53
+ ### Compatible changes
54
+
55
+ - Cucumber 2.1.0 introduced some regressions which are being addressed with this patch:
56
+ - Fix the assignment of polymorphic associations.
57
+ - Restore the support for inherited traits within nested factories.
58
+
59
+ ## 2.1.0 - 2020-03-09
60
+
61
+ ### Compatible changes
62
+
63
+ - 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:
64
+ ```
65
+ Given there is a role
66
+ And there is a user with the role above
67
+ ```
68
+
16
69
  ## 2.0.2 - 2020-03-26
17
70
 
18
71
  ### Compatible changes
@@ -12,5 +12,9 @@ gem 'rake', '>=10.0.4'
12
12
  gem 'database_cleaner', '~>1.0.0'
13
13
  gem 'gemika'
14
14
 
15
+ # Test dependencies
16
+ gem 'factory_bot', '< 5'
17
+ gem 'carrierwave', '~> 1.0'
18
+
15
19
  # Gem under test
16
20
  gem 'cucumber_factory', :path => '.'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cucumber_factory (2.0.2)
4
+ cucumber_factory (2.3.1)
5
5
  activerecord
6
6
  activesupport
7
7
  cucumber
@@ -24,6 +24,10 @@ GEM
24
24
  tzinfo (~> 1.1)
25
25
  arel (6.0.4)
26
26
  builder (3.2.4)
27
+ carrierwave (1.2.3)
28
+ activemodel (>= 4.0.0)
29
+ activesupport (>= 4.0.0)
30
+ mime-types (>= 1.16)
27
31
  concurrent-ruby (1.1.6)
28
32
  cucumber (1.3.20)
29
33
  builder (>= 2.1.2)
@@ -35,11 +39,16 @@ GEM
35
39
  cucumber
36
40
  database_cleaner (1.0.1)
37
41
  diff-lcs (1.3)
42
+ factory_bot (4.11.1)
43
+ activesupport (>= 3.0.0)
38
44
  gemika (0.4.0)
39
45
  gherkin (2.12.2)
40
46
  multi_json (~> 1.3)
41
47
  i18n (0.9.5)
42
48
  concurrent-ruby (~> 1.0)
49
+ mime-types (3.2.2)
50
+ mime-types-data (~> 3.2015)
51
+ mime-types-data (3.2018.0812)
43
52
  minitest (5.12.0)
44
53
  multi_json (1.14.1)
45
54
  multi_test (0.1.2)
@@ -68,9 +77,11 @@ PLATFORMS
68
77
  DEPENDENCIES
69
78
  activerecord (~> 4.2.0)
70
79
  activesupport (~> 4.2.0)
80
+ carrierwave (~> 1.0)
71
81
  cucumber (~> 1.3.20)
72
82
  cucumber_factory!
73
83
  database_cleaner (~> 1.0.0)
84
+ factory_bot (< 5)
74
85
  gemika
75
86
  mysql2
76
87
  rake (>= 10.0.4)
@@ -12,5 +12,9 @@ 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
+ gem 'carrierwave', '~> 1.0' # 2.0 requires Rails >= 5 and Ruby >= 2.2
18
+
15
19
  # Gem under test
16
20
  gem 'cucumber_factory', :path => '.'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cucumber_factory (2.0.2)
4
+ cucumber_factory (2.3.1)
5
5
  activerecord
6
6
  activesupport
7
7
  cucumber
@@ -24,6 +24,10 @@ GEM
24
24
  tzinfo (~> 1.1)
25
25
  arel (6.0.4)
26
26
  builder (3.2.3)
27
+ carrierwave (1.2.3)
28
+ activemodel (>= 4.0.0)
29
+ activesupport (>= 4.0.0)
30
+ mime-types (>= 1.16)
27
31
  concurrent-ruby (1.0.5)
28
32
  cucumber (2.4.0)
29
33
  builder (>= 2.1.2)
@@ -40,10 +44,15 @@ GEM
40
44
  cucumber
41
45
  database_cleaner (1.6.2)
42
46
  diff-lcs (1.3)
47
+ factory_bot (4.11.1)
48
+ activesupport (>= 3.0.0)
43
49
  gemika (0.3.2)
44
50
  gherkin (4.1.3)
45
51
  i18n (0.9.5)
46
52
  concurrent-ruby (~> 1.0)
53
+ mime-types (3.2.2)
54
+ mime-types-data (~> 3.2015)
55
+ mime-types-data (3.2018.0812)
47
56
  minitest (5.11.3)
48
57
  multi_json (1.13.1)
49
58
  multi_test (0.1.2)
@@ -72,9 +81,11 @@ PLATFORMS
72
81
  DEPENDENCIES
73
82
  activerecord (~> 4.2.0)
74
83
  activesupport (~> 4.2.0)
84
+ carrierwave (~> 1.0)
75
85
  cucumber (~> 2.4.0)
76
86
  cucumber_factory!
77
87
  database_cleaner
88
+ factory_bot (< 5)
78
89
  gemika
79
90
  mysql2
80
91
  rake
@@ -12,5 +12,9 @@ gem 'rake'
12
12
  gem 'database_cleaner'
13
13
  gem 'gemika'
14
14
 
15
+ # Test dependencies
16
+ gem 'factory_bot'
17
+ gem 'carrierwave'
18
+
15
19
  # Gem under test
16
20
  gem 'cucumber_factory', :path => '.'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cucumber_factory (2.0.2)
4
+ cucumber_factory (2.3.1)
5
5
  activerecord
6
6
  activesupport
7
7
  cucumber
@@ -24,6 +24,10 @@ GEM
24
24
  arel (7.1.4)
25
25
  backports (3.11.1)
26
26
  builder (3.2.3)
27
+ carrierwave (1.2.3)
28
+ activemodel (>= 4.0.0)
29
+ activesupport (>= 4.0.0)
30
+ mime-types (>= 1.16)
27
31
  concurrent-ruby (1.0.5)
28
32
  cucumber (3.0.2)
29
33
  builder (>= 2.1.2)
@@ -45,10 +49,15 @@ GEM
45
49
  cucumber
46
50
  database_cleaner (1.6.2)
47
51
  diff-lcs (1.3)
52
+ factory_bot (5.1.1)
53
+ activesupport (>= 4.2.0)
48
54
  gemika (0.3.2)
49
55
  gherkin (4.1.3)
50
56
  i18n (0.9.5)
51
57
  concurrent-ruby (~> 1.0)
58
+ mime-types (3.2.2)
59
+ mime-types-data (~> 3.2015)
60
+ mime-types-data (3.2018.0812)
52
61
  minitest (5.11.3)
53
62
  multi_json (1.13.1)
54
63
  multi_test (0.1.2)
@@ -77,9 +86,11 @@ PLATFORMS
77
86
  DEPENDENCIES
78
87
  activerecord (~> 5.0.0)
79
88
  activesupport (~> 5.0.0)
89
+ carrierwave
80
90
  cucumber (~> 3.0.0)
81
91
  cucumber_factory!
82
92
  database_cleaner
93
+ factory_bot
83
94
  gemika
84
95
  mysql2
85
96
  rake
@@ -12,5 +12,9 @@ gem 'rake'
12
12
  gem 'database_cleaner'
13
13
  gem 'gemika'
14
14
 
15
+ # Test dependencies
16
+ gem 'factory_bot'
17
+ gem 'carrierwave'
18
+
15
19
  # Gem under test
16
20
  gem 'cucumber_factory', :path => '.'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cucumber_factory (2.0.2)
4
+ cucumber_factory (2.3.1)
5
5
  activerecord
6
6
  activesupport
7
7
  cucumber
@@ -24,6 +24,10 @@ GEM
24
24
  arel (8.0.0)
25
25
  backports (3.11.1)
26
26
  builder (3.2.3)
27
+ carrierwave (1.2.3)
28
+ activemodel (>= 4.0.0)
29
+ activesupport (>= 4.0.0)
30
+ mime-types (>= 1.16)
27
31
  concurrent-ruby (1.0.5)
28
32
  cucumber (3.1.0)
29
33
  builder (>= 2.1.2)
@@ -45,10 +49,15 @@ GEM
45
49
  cucumber
46
50
  database_cleaner (1.6.2)
47
51
  diff-lcs (1.3)
52
+ factory_bot (5.1.1)
53
+ activesupport (>= 4.2.0)
48
54
  gemika (0.3.2)
49
55
  gherkin (5.0.0)
50
56
  i18n (0.9.5)
51
57
  concurrent-ruby (~> 1.0)
58
+ mime-types (3.2.2)
59
+ mime-types-data (~> 3.2015)
60
+ mime-types-data (3.2018.0812)
52
61
  minitest (5.11.3)
53
62
  multi_json (1.13.1)
54
63
  multi_test (0.1.2)
@@ -77,9 +86,11 @@ PLATFORMS
77
86
  DEPENDENCIES
78
87
  activerecord (~> 5.1.0)
79
88
  activesupport (~> 5.1.0)
89
+ carrierwave
80
90
  cucumber (~> 3.1.0)
81
91
  cucumber_factory!
82
92
  database_cleaner
93
+ factory_bot
83
94
  gemika
84
95
  mysql2
85
96
  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"
@@ -129,7 +151,16 @@ Given there is a movie with the tags ["comedy", "drama" and "action"]
129
151
  ```
130
152
 
131
153
 
154
+ Setting file attributes
155
+ -----------------------
156
+
157
+ You can set an attribute to a file object with the following syntax:
158
+
159
+ ```cucumber
160
+ Given there is a movie with the image file:'path/to/image.jpg'
161
+ ```
132
162
 
163
+ All paths are relative to the project root, absolute paths are not supported. Please note that file attributes must follow the syntax `file:"PATH"`, both single and double quotes are allowed.
133
164
 
134
165
  Using named factories and traits
135
166
  --------------------------------
@@ -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