cranky 1.0.0 → 1.1.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
  SHA1:
3
- metadata.gz: fbcde86a6a73ee0148b12ed591e978d21521f5ba
4
- data.tar.gz: 61a43c0743b8b333f85e3ec26f6604197086741b
3
+ metadata.gz: 42aebc7927e7fc1f29417cb638be0bee94190521
4
+ data.tar.gz: dd1710da521efa26a01615646b5daaa4e98980b7
5
5
  SHA512:
6
- metadata.gz: bf660e5eb16c325dc12f2c6f52839f6b2c5268a0d647729d5cb7b11f5bd9dcd55eb464609d57ffc3ef671b0def15abba10571c141e383e30029d59bd4696e5b6
7
- data.tar.gz: ce11711bca5aa5de02f02d33305074e025147727ef13f425837e0182522cf119330bd38d19eb2e8bd5b46e3a23e44fd1d3a136e9a9b2486fc63bbfcd25848a70
6
+ metadata.gz: e5234e23763c245d614d50dfe44d4e862ad4e236f16fb4eb9f71d5e98bf1899c4b55c4edaec3632b7bd8ea20e16965f0877e6d6e499e8ca3fe5654e3c6ec64e1
7
+ data.tar.gz: 621dcfd64bbdfefddd9e484a3c10e96dbd0f5ebdfe11ba537d7b674973a5ca4b5a77f29eca5416a48e5cab040c4d339213b82b44fd10faa44d4dbfc1a4a5abe3
@@ -1,31 +1,9 @@
1
1
  # Overview of Changes
2
2
 
3
- ## 0.3.1
3
+ ## 1.1.0
4
4
 
5
- * Bugfix, generating a hash of attributes via _attrs did not work with factory methods
6
- that used the inherit method
5
+ * Added before_create, after_build, after_create callbacks (@beorc)
7
6
 
8
- ## 0.3.0
7
+ ## 1.0.0
9
8
 
10
- * Updated README to present the crank syntax as the default
11
-
12
- * Appending the first argument with _attrs will return a hash of attributes rather than
13
- the object, i.e. crank(:user) returns a User instance, and crank(:user_attrs) returns
14
- a hash of valid attributes
15
-
16
- * Factory.attributes_for now returns a hash of attributes rather than an array, this
17
- method is no longer dependent on rails
18
-
19
- * \#3 Factory methods can generate attribute hashes by default by setting :class => Hash in
20
- the define declaration (leemhenson)
21
-
22
- * Factory.debug was broken on ActiveModel based classes, now works with them
23
-
24
- * Attributes can be skipped by setting the value to :skip. e.g. crank(:user, :name => :skip) will
25
- generate a User instance without calling or assigning anything to the name attribute
26
-
27
- * Updated dev environment for latest rspec compatibility (2.6.0)
28
-
29
- ## 0.2.0
30
-
31
- Changes between version prior to this were not tracked here
9
+ * Initial baseline for future change tracking
data/README.md CHANGED
@@ -202,10 +202,12 @@ def user
202
202
  end
203
203
 
204
204
  def apply_trait_admin_to_user(user)
205
+ # the 'options' method is available here
205
206
  user.roles << :admin
206
207
  end
207
208
 
208
209
  def apply_trait_manager_to_user(user)
210
+ # the 'options' method is available here
209
211
  user.roles << :manager
210
212
  end
211
213
  ~~~
@@ -220,6 +222,36 @@ def users_collection
220
222
  end
221
223
  ~~~
222
224
 
225
+ You can inject code using callbacks...
226
+
227
+ ~~~ruby
228
+ # factories/my_factories.rb
229
+ class Cranky::Factory
230
+
231
+ def user
232
+ define name: 'Jimmy'
233
+ end
234
+
235
+ private
236
+
237
+ def after_build_user(user)
238
+ # the 'options' method is available here
239
+ do_something_to(user)
240
+ end
241
+
242
+ def before_create_user(user)
243
+ # the 'options' method is available here
244
+ do_something_to(user)
245
+ end
246
+
247
+ def after_create_user(user)
248
+ # the 'options' method is available here
249
+ do_something_to(user)
250
+ end
251
+
252
+ end
253
+ ~~~
254
+
223
255
  ## Linting Factories
224
256
 
225
257
  Cranky allows for linting known factories:
@@ -235,7 +267,7 @@ Recommended usage of `Factory.lint!` is to run this in a task before your test s
235
267
  Example Rake task:
236
268
 
237
269
  ~~~ruby
238
- # lib/tasks/factory_girl.rake
270
+ # lib/tasks/cranky.rake
239
271
  namespace :cranky do
240
272
  desc "Verify that all factories are valid"
241
273
  task lint: :environment do
@@ -13,18 +13,28 @@ module Cranky
13
13
  end
14
14
 
15
15
  def build(what, overrides={})
16
- crank_it(what, overrides)
16
+ item = crank_it(what, overrides)
17
+ call_after_build(what, item)
18
+
19
+ item
17
20
  end
18
21
 
19
22
  def create(what, overrides={})
20
23
  item = build(what, overrides)
21
- Array(item).each(&:save)
24
+ Array(item).each do |i|
25
+ call_before_create(what, i)
26
+ i.save && call_after_create(what, i)
27
+ end
22
28
  item
23
29
  end
24
30
 
25
31
  def create!(what, overrides={})
26
32
  item = build(what, overrides)
27
- Array(item).each(&:save!)
33
+ Array(item).each do |i|
34
+ call_before_create(what, i)
35
+ i.save!
36
+ call_after_create(what, i)
37
+ end
28
38
  item
29
39
  end
30
40
 
@@ -75,12 +85,13 @@ module Cranky
75
85
  end
76
86
 
77
87
  def factory_names
78
- public_methods(false).reject {|m| TRAIT_METHOD_REGEXP === m }
88
+ public_methods(false).reject {|m| TRAIT_METHOD_REGEXP === m }.sort
79
89
  end
80
90
 
81
91
  def traits_for(factory_name)
82
92
  regexp = /^apply_trait_(\w+)_to_#{factory_name}$/.freeze
83
- trait_methods = public_methods(false).select {|m| regexp === m }
93
+ available_methods = private_methods(false) + public_methods(false)
94
+ trait_methods = available_methods.select {|m| regexp === m }
84
95
  trait_methods.map {|m| regexp.match(m)[1] }
85
96
  end
86
97
 
@@ -94,10 +105,25 @@ module Cranky
94
105
 
95
106
  private
96
107
 
108
+ def call_after_build(what, item)
109
+ method_name = "after_build_#{what}"
110
+ respond_to?(method_name, true) && send(method_name, item)
111
+ end
112
+
113
+ def call_before_create(what, item)
114
+ method_name = "before_create_#{what}"
115
+ respond_to?(method_name, true) && send(method_name, item)
116
+ end
117
+
118
+ def call_after_create(what, item)
119
+ method_name = "after_create_#{what}"
120
+ respond_to?(method_name, true) && send(method_name, item)
121
+ end
122
+
97
123
  def apply_traits(what, item)
98
124
  Array(options[:traits]).each do |t|
99
125
  trait_method_name = "apply_trait_#{t}_to_#{what}"
100
- fail("Invalid trait '#{t}'! No method '#{trait_method_name}' is defined.") unless respond_to?(trait_method_name)
126
+ respond_to?(trait_method_name, true) || fail("Invalid trait '#{t}'! No method '#{trait_method_name}' is defined.")
101
127
  send(trait_method_name, item)
102
128
  end
103
129
 
@@ -6,16 +6,17 @@ module Cranky
6
6
  @factories_to_lint = factories_to_lint
7
7
  @linting_method = "lint_#{linting_strategy}"
8
8
  @invalid_factories = calculate_invalid_factories
9
+ @invalid_callbacks = calculate_invalid_callbacks
9
10
  end
10
11
 
11
12
  def lint!
12
- if invalid_factories.any?
13
+ if invalid_factories.any? || invalid_callbacks.any?
13
14
  raise InvalidFactoryError, error_message
14
15
  end
15
16
  end
16
17
 
17
- attr_reader :factories_to_lint, :invalid_factories
18
- private :factories_to_lint, :invalid_factories
18
+ attr_reader :factories_to_lint, :invalid_factories, :invalid_callbacks
19
+ private :factories_to_lint, :invalid_factories, :invalid_callbacks
19
20
 
20
21
  private
21
22
 
@@ -27,6 +28,25 @@ module Cranky
27
28
  end
28
29
  end
29
30
 
31
+ def calculate_invalid_callbacks
32
+ result = []
33
+
34
+ regexp = /^(after_build|before_create|after_create)_(\w+)$/.freeze
35
+ available_methods = @factory.private_methods(false) + @factory.public_methods(false)
36
+ available_methods.select do |m|
37
+ match = regexp.match(m)
38
+ if match
39
+ factory_name = match[2]
40
+
41
+ unless @factory.respond_to?(factory_name)
42
+ result << m
43
+ end
44
+ end
45
+ end
46
+
47
+ result
48
+ end
49
+
30
50
  # Raised when any factory is considered invalid
31
51
  class InvalidFactoryError < RuntimeError; end
32
52
 
@@ -87,15 +107,26 @@ module Cranky
87
107
  end
88
108
 
89
109
  def error_message
110
+ [
111
+ factories_error_message,
112
+ callbacks_error_message
113
+ ].compact.join("\n\n".freeze)
114
+ end
115
+
116
+ def factories_error_message
90
117
  lines = invalid_factories.map do |_factory, exceptions|
91
118
  exceptions.map(&:message)
92
119
  end.flatten
93
120
 
94
- <<-ERROR_MESSAGE.strip
95
- The following factories are invalid:
121
+ return if lines.empty?
122
+
123
+ "The following factories are invalid:\n\n#{lines.join("\n")}"
124
+ end
125
+
126
+ def callbacks_error_message
127
+ return if invalid_callbacks.empty?
96
128
 
97
- #{lines.join("\n")}
98
- ERROR_MESSAGE
129
+ "The following callbacks are invalid:\n\n#{invalid_callbacks.join("\n")}"
99
130
  end
100
131
  end
101
132
  end
@@ -1,3 +1,3 @@
1
1
  module Cranky
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -4,15 +4,17 @@ describe "The Cranky factory" do
4
4
 
5
5
  describe '#factory_names' do
6
6
  it 'returns an array of names of defined factories' do
7
- Factory.factory_names.should eq [:user,
8
- :address,
9
- :users_collection,
10
- :user_manually,
11
- :user_by_define,
12
- :admin_manually,
13
- :admin_by_define,
14
- :user_hash,
15
- :invalid_user]
7
+ Factory.factory_names.should eq %i(
8
+ address
9
+ admin_by_define
10
+ admin_manually
11
+ invalid_user
12
+ user
13
+ user_by_define
14
+ user_hash
15
+ user_manually
16
+ users_collection
17
+ )
16
18
  end
17
19
  end
18
20
 
@@ -144,10 +146,12 @@ describe "The Cranky factory" do
144
146
  it "allows factories to call other factories" do
145
147
  Factory.build(:user_manually).address.city.should == "New York"
146
148
  Factory.create(:user_manually).address.city.should == "New York"
149
+ Factory.create!(:user_manually).address.city.should == "New York"
147
150
  Factory.create(:user_manually).address.saved?.should == false
148
- Factory.build(:user_by_define).address.city.should == "New York"
149
151
  Factory.create(:user_by_define).address.city.should == "New York"
150
152
  Factory.create(:user_by_define).address.saved?.should == true
153
+ Factory.create(:user_by_define).email.should == 'max@home.com'
154
+ Factory.create!(:user_by_define).email.should == 'max@home.com'
151
155
  end
152
156
 
153
157
  it "has its own syntax" do
@@ -184,7 +188,7 @@ describe "The Cranky factory" do
184
188
  end
185
189
 
186
190
  it "returns nothing extra in the attributes" do
187
- crank(:user_attrs).size.should == 6
191
+ crank(:user_attrs).size.should == 4
188
192
  end
189
193
 
190
194
  specify "attributes for works with factory methods using inherit" do
@@ -5,8 +5,12 @@ describe 'Factory.lint' do
5
5
  error_message = <<-ERROR_MESSAGE.strip
6
6
  The following factories are invalid:
7
7
 
8
- * user_hash - undefined method `save!' for [:name, "Fred"]:Array (NoMethodError)
9
8
  * invalid_user - Validation failed: {:required_attr=>["can't be blank"]} (RuntimeError)
9
+ * user_hash - undefined method `save!' for [:name, "Fred"]:Array (NoMethodError)
10
+
11
+ The following callbacks are invalid:
12
+
13
+ after_create_not_existing_factory
10
14
  ERROR_MESSAGE
11
15
 
12
16
  expect do
@@ -15,7 +19,14 @@ The following factories are invalid:
15
19
  end
16
20
 
17
21
  it 'does not raise when all factories are valid' do
18
- expect { Factory.lint!(factory_names: [:admin_manually, :address]) }.not_to raise_error
22
+ error_message = <<-ERROR_MESSAGE.strip
23
+ The following callbacks are invalid:
24
+
25
+ after_create_not_existing_factory
26
+ ERROR_MESSAGE
27
+ expect do
28
+ Factory.lint!(factory_names: [:admin_manually, :address])
29
+ end.to raise_error Cranky::Linter::InvalidFactoryError, error_message
19
30
  end
20
31
 
21
32
  describe "trait validation" do
@@ -24,9 +35,13 @@ The following factories are invalid:
24
35
  error_message = <<-ERROR_MESSAGE.strip
25
36
  The following factories are invalid:
26
37
 
38
+ * invalid_user - Validation failed: {:required_attr=>["can't be blank"]} (RuntimeError)
27
39
  * user+invalid - Validation failed: {:required_attr=>["can't be blank"]} (RuntimeError)
28
40
  * user_hash - undefined method `save!' for [:name, "Fred"]:Array (NoMethodError)
29
- * invalid_user - Validation failed: {:required_attr=>["can't be blank"]} (RuntimeError)
41
+
42
+ The following callbacks are invalid:
43
+
44
+ after_create_not_existing_factory
30
45
  ERROR_MESSAGE
31
46
 
32
47
  expect do
@@ -69,8 +69,6 @@ class Cranky::Factory
69
69
  :name => "Fred",
70
70
  :role => :user,
71
71
  :unique => "value#{n}",
72
- :email => "fred@home.com",
73
- :address => Factory.create(:address),
74
72
  :required_attr => true
75
73
  u.argument_received = true if options[:argument_supplied]
76
74
  u
@@ -101,6 +99,12 @@ class Cranky::Factory
101
99
  3.times.map { build(:user) }
102
100
  end
103
101
 
102
+ def invalid_user
103
+ inherit(:user, required_attr: false)
104
+ end
105
+
106
+ private
107
+
104
108
  def apply_trait_manager_to_user_manually(user)
105
109
  user.role = :manager
106
110
  end
@@ -109,7 +113,23 @@ class Cranky::Factory
109
113
  user.required_attr = nil
110
114
  end
111
115
 
112
- def invalid_user
113
- inherit(:user, required_attr: false)
116
+ def after_build_user_by_define(user)
117
+ if user.respond_to?('[]')
118
+ user[:email] = 'fred@home.com'
119
+ else
120
+ user.email = 'fred@home.com'
121
+ end
122
+ end
123
+
124
+ def before_create_user_by_define(user)
125
+ user.address = create!(:address)
126
+ end
127
+
128
+ def after_create_user_by_define(user)
129
+ user.email = 'max@home.com'
130
+ end
131
+
132
+ def after_create_not_existing_factory(user)
133
+ user.address = create!(:address)
114
134
  end
115
135
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cranky
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen McGinty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-06 00:00:00.000000000 Z
11
+ date: 2016-12-28 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A very light yet powerful test factory framework with an extremely clean
14
14
  syntax that makes it very easy to define your factories.
@@ -51,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
51
51
  version: 1.3.4
52
52
  requirements: []
53
53
  rubyforge_project:
54
- rubygems_version: 2.6.7
54
+ rubygems_version: 2.2.5
55
55
  signing_key:
56
56
  specification_version: 4
57
57
  summary: A very light yet powerful test factory framework.