acts-as-approvable 0.6.7 → 0.6.8.1

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.
Files changed (64) hide show
  1. data/.gitignore +2 -5
  2. data/.rspec +2 -0
  3. data/.travis.yml +5 -0
  4. data/Appraisals +14 -10
  5. data/CHANGELOG +16 -0
  6. data/Gemfile.lock +60 -20
  7. data/README.md +1 -2
  8. data/Rakefile +44 -16
  9. data/VERSION +1 -1
  10. data/acts-as-approvable.gemspec +21 -11
  11. data/features/create_approval.feature +26 -0
  12. data/features/step_definitions/cucumber_steps.rb +86 -0
  13. data/features/support/env.rb +14 -0
  14. data/features/support/large.txt +29943 -0
  15. data/features/support/second_large.txt +31798 -0
  16. data/features/update_approval.feature +34 -0
  17. data/gemfiles/Gemfile.ci +14 -0
  18. data/gemfiles/Gemfile.ci.lock +98 -0
  19. data/gemfiles/mysql2.gemfile +7 -0
  20. data/gemfiles/mysql2.gemfile.lock +92 -0
  21. data/gemfiles/rails2.gemfile +1 -0
  22. data/gemfiles/rails2.gemfile.lock +59 -17
  23. data/gemfiles/rails30.gemfile +1 -0
  24. data/gemfiles/rails30.gemfile.lock +54 -14
  25. data/gemfiles/rails31.gemfile +1 -0
  26. data/gemfiles/rails31.gemfile.lock +54 -14
  27. data/gemfiles/sqlite.gemfile +7 -0
  28. data/generators/acts_as_approvable/templates/create_approvals.rb +8 -7
  29. data/lib/acts-as-approvable.rb +2 -3
  30. data/lib/acts_as_approvable/approval.rb +3 -2
  31. data/lib/acts_as_approvable/model.rb +55 -0
  32. data/lib/acts_as_approvable/model/class_methods.rb +63 -0
  33. data/lib/acts_as_approvable/model/create_instance_methods.rb +83 -0
  34. data/lib/acts_as_approvable/model/instance_methods.rb +89 -0
  35. data/lib/acts_as_approvable/model/update_instance_methods.rb +61 -0
  36. data/lib/acts_as_approvable/railtie.rb +1 -1
  37. data/lib/generators/acts_as_approvable/templates/create_approvals.rb +8 -7
  38. data/spec/acts_as_approvable/approval_spec.rb +475 -0
  39. data/spec/acts_as_approvable/model/class_methods_spec.rb +219 -0
  40. data/spec/acts_as_approvable/model/create_instance_methods_spec.rb +149 -0
  41. data/spec/acts_as_approvable/model/instance_methods_spec.rb +328 -0
  42. data/spec/acts_as_approvable/model/update_instance_methods_spec.rb +111 -0
  43. data/spec/acts_as_approvable/model_spec.rb +90 -0
  44. data/spec/acts_as_approvable/ownership/class_methods_spec.rb +101 -0
  45. data/spec/acts_as_approvable/ownership/instance_methods_spec.rb +32 -0
  46. data/spec/acts_as_approvable/ownership_spec.rb +51 -0
  47. data/spec/acts_as_approvable_spec.rb +29 -0
  48. data/spec/spec_helper.rb +51 -0
  49. data/spec/support/database.rb +46 -0
  50. data/spec/support/database.yml +12 -0
  51. data/spec/support/matchers.rb +87 -0
  52. data/spec/support/models.rb +60 -0
  53. data/{test → spec/support}/schema.rb +15 -9
  54. metadata +156 -53
  55. data/gemfiles/rails32.gemfile +0 -8
  56. data/gemfiles/rails32.gemfile.lock +0 -99
  57. data/lib/acts_as_approvable/acts_as_approvable.rb +0 -291
  58. data/test/acts_as_approvable_model_test.rb +0 -459
  59. data/test/acts_as_approvable_ownership_test.rb +0 -132
  60. data/test/acts_as_approvable_schema_test.rb +0 -13
  61. data/test/acts_as_approvable_test.rb +0 -8
  62. data/test/database.yml +0 -7
  63. data/test/support.rb +0 -19
  64. data/test/test_helper.rb +0 -62
@@ -1,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "http://rubygems.org"
4
-
5
- gem "activerecord", "~> 3.2.0"
6
- gem "railties", "~> 3.2.0"
7
-
8
- gemspec :path=>"../"
@@ -1,99 +0,0 @@
1
- PATH
2
- remote: /Users/jlogsdon/Code/acts_as_approvable/acts_as_approvable
3
- specs:
4
- acts-as-approvable (0.6.7)
5
-
6
- GEM
7
- remote: http://rubygems.org/
8
- specs:
9
- actionpack (3.2.1)
10
- activemodel (= 3.2.1)
11
- activesupport (= 3.2.1)
12
- builder (~> 3.0.0)
13
- erubis (~> 2.7.0)
14
- journey (~> 1.0.1)
15
- rack (~> 1.4.0)
16
- rack-cache (~> 1.1)
17
- rack-test (~> 0.6.1)
18
- sprockets (~> 2.1.2)
19
- activemodel (3.2.1)
20
- activesupport (= 3.2.1)
21
- builder (~> 3.0.0)
22
- activerecord (3.2.1)
23
- activemodel (= 3.2.1)
24
- activesupport (= 3.2.1)
25
- arel (~> 3.0.0)
26
- tzinfo (~> 0.3.29)
27
- activesupport (3.2.1)
28
- i18n (~> 0.6)
29
- multi_json (~> 1.0)
30
- appraisal (0.4.1)
31
- bundler
32
- rake
33
- arel (3.0.0)
34
- builder (3.0.0)
35
- coderay (1.0.5)
36
- erubis (2.7.0)
37
- hike (1.2.1)
38
- i18n (0.6.0)
39
- journey (1.0.1)
40
- json (1.6.5)
41
- metaclass (0.0.1)
42
- method_source (0.7.0)
43
- mocha (0.10.4)
44
- metaclass (~> 0.0.1)
45
- multi_json (1.0.4)
46
- pry (0.9.8)
47
- coderay (~> 1.0.5)
48
- method_source (~> 0.7)
49
- slop (>= 2.4.3, < 3)
50
- rack (1.4.1)
51
- rack-cache (1.1)
52
- rack (>= 0.4)
53
- rack-ssl (1.3.2)
54
- rack
55
- rack-test (0.6.1)
56
- rack (>= 1.0)
57
- railties (3.2.1)
58
- actionpack (= 3.2.1)
59
- activesupport (= 3.2.1)
60
- rack-ssl (~> 1.3.2)
61
- rake (>= 0.8.7)
62
- rdoc (~> 3.4)
63
- thor (~> 0.14.6)
64
- rake (0.9.2.2)
65
- rdoc (3.12)
66
- json (~> 1.4)
67
- redcarpet (2.1.0)
68
- shoulda (2.11.3)
69
- simplecov (0.5.4)
70
- multi_json (~> 1.0.3)
71
- simplecov-html (~> 0.5.3)
72
- simplecov-html (0.5.3)
73
- slop (2.4.3)
74
- sprockets (2.1.2)
75
- hike (~> 1.2)
76
- rack (~> 1.0)
77
- tilt (~> 1.1, != 1.3.0)
78
- sqlite3 (1.3.5)
79
- thor (0.14.6)
80
- tilt (1.3.3)
81
- tzinfo (0.3.31)
82
- yard (0.7.5)
83
-
84
- PLATFORMS
85
- ruby
86
-
87
- DEPENDENCIES
88
- activerecord (~> 3.2.0)
89
- acts-as-approvable!
90
- appraisal
91
- mocha
92
- pry
93
- railties (~> 3.2.0)
94
- rake
95
- redcarpet
96
- shoulda
97
- simplecov
98
- sqlite3
99
- yard
@@ -1,291 +0,0 @@
1
- module ActsAsApprovable
2
- ##
3
- # The meat of {ActsAsApprovable}. This applies methods for the configured approval events
4
- # and configures the required relationships.
5
- module Model
6
- def self.included(base)
7
- base.send :extend, ClassMethods
8
- end
9
-
10
- ##
11
- # Class methods added to `ActiveRecord::Base`.
12
- module ClassMethods
13
- # Declare this in your model to require approval on new records or changes to fields.
14
- #
15
- # @param [Hash] options the options for this models approval workflow.
16
- # @option options [Symbol,Array] :on The events to require approval on (`:create` or `:update`).
17
- # @option options [String] :state_field The local field to store `:create` approval state.
18
- # @option options [Array] :ignore A list of fields to ignore. By default we ignore `:created_at`, `:updated_at` and
19
- # the field specified in `:state_field`.
20
- # @option options [Array] :only A list of fields to explicitly require approval on. This list supercedes `:ignore`.
21
- def acts_as_approvable(options = {})
22
- include InstanceMethods
23
-
24
- cattr_accessor :approvable_on
25
- self.approvable_on = Array.wrap(options.delete(:on) { [:create, :update] })
26
-
27
- cattr_accessor :approvable_field
28
- self.approvable_field = options.delete(:state_field)
29
-
30
- cattr_accessor :approvable_ignore
31
- ignores = Array.wrap(options.delete(:ignore) { [] })
32
- ignores.push('created_at', 'updated_at', self.approvable_field)
33
- self.approvable_ignore = ignores.compact.uniq.map(&:to_s)
34
-
35
- cattr_accessor :approvable_only
36
- self.approvable_only = Array.wrap(options.delete(:only) { [] }).uniq.map(&:to_s)
37
-
38
- cattr_accessor :approvals_active
39
- self.approvals_active = true
40
-
41
- has_many :approvals, :as => :item, :dependent => :destroy
42
-
43
- if self.approvable_on.include?(:update)
44
- include UpdateInstanceMethods
45
- before_update :approvable_update, :if => :approvable_update?
46
- end
47
-
48
- if self.approvable_on.include?(:create)
49
- include CreateInstanceMethods
50
- before_create :approvable_create, :if => :approvable_create?
51
- end
52
-
53
- after_save :approvable_save, :if => :approvals_enabled?
54
- end
55
-
56
- ##
57
- # Enable the approval queue for this model.
58
- def approvals_on
59
- self.approvals_active = true
60
- end
61
-
62
- ##
63
- # Disable the approval queue for this model.
64
- def approvals_off
65
- self.approvals_active = false
66
- end
67
-
68
- ##
69
- # Execute a code block while the approval queue is temporarily disabled. The
70
- # queue state will be returned to it's previous value, either on or off.
71
- def without_approval(&block)
72
- enable = self.approvals_active
73
- approvals_off
74
- yield(self)
75
- ensure
76
- approvals_on if enable
77
- end
78
- end
79
-
80
- ##
81
- # Instance methods that apply to the `:create` event specifically.
82
- module CreateInstanceMethods
83
- ##
84
- # Retrieve approval record for the creation event.
85
- #
86
- # @return [Approval]
87
- def approval
88
- approvals.find_by_event('create')
89
- end
90
-
91
- ##
92
- # Get the approval state of the current record from either the local state
93
- # field or, if no state field exists, the creation approval object.
94
- #
95
- # @return [String] one of `'pending'`, `'approved`' or `'rejected'`.
96
- def approval_state
97
- if self.class.approvable_field
98
- send(self.class.approvable_field)
99
- elsif approval.present?
100
- approval.state
101
- end
102
- end
103
-
104
- ##
105
- # Set the records local approval state.
106
- #
107
- # @param [String] state one of `'pending'`, `'approved`' or `'rejected'`.
108
- def set_approval_state(state)
109
- return unless self.class.approvable_field
110
- send("#{self.class.approvable_field}=".to_sym, state)
111
- end
112
-
113
- ##
114
- # Returns true if the record is pending approval.
115
- def pending?
116
- approval_state == 'pending' or approval.try(:pending?)
117
- end
118
-
119
- ##
120
- # Returns true if the record has been approved.
121
- def approved?
122
- approval_state == 'approved' or approval.try(:approved?)
123
- end
124
-
125
- ##
126
- # Returns true if the record has been rejected.
127
- def rejected?
128
- approval_state == 'rejected' or approval.try(:rejected?)
129
- end
130
-
131
- ##
132
- # Approves the record through {Approval#approve!}
133
- #
134
- # @return [Boolean]
135
- def approve!
136
- return unless approvable_on?(:create) && approval.present?
137
- approval.approve!
138
- end
139
-
140
- ##
141
- # Rejects the record through {Approval#reject!}
142
- #
143
- # @return [Boolean]
144
- def reject!
145
- return unless approvable_on?(:create) && approval.present?
146
- approval.reject!
147
- end
148
-
149
- private
150
- def approvable_create?
151
- approvals_enabled? and approvable_on?(:create)
152
- end
153
-
154
- def approvable_create
155
- @approval = approvals.build(:event => 'create', :state => 'pending')
156
- set_approval_state('pending')
157
- end
158
- end
159
-
160
- ##
161
- # Instance methods that apply to the :update event specifically.
162
- module UpdateInstanceMethods
163
- ##
164
- # Retrieve all approval records for `:update` events.
165
- def update_approvals(all = true)
166
- all ? approvals.find_all_by_event('update') : approvals.find_all_by_event_and_state('update', 0)
167
- end
168
-
169
- ##
170
- # Returns true if the record has any `#update_approvals` that are pending
171
- # approval.
172
- def pending_changes?
173
- !update_approvals(false).empty?
174
- end
175
-
176
- ##
177
- # Returns true if any notable (eg. not ignored) fields have been changed.
178
- def changed_notably?
179
- notably_changed.any?
180
- end
181
-
182
- ##
183
- # Returns an array of any notable (eg. not ignored) fields that have not
184
- # been changed.
185
- #
186
- # @return [Array] a list of changed fields.
187
- def notably_changed
188
- unless self.class.approvable_only.empty?
189
- self.class.approvable_only.select { |field| changed.include?(field) }
190
- else
191
- changed - self.class.approvable_ignore
192
- end
193
- end
194
-
195
- private
196
- def approvable_update?
197
- approvals_enabled? and approvable_on?(:update) and changed_notably?
198
- end
199
-
200
- def approvable_update
201
- changed = {}
202
- notably_changed.each do |attr|
203
- original, changed_to = changes[attr]
204
-
205
- write_attribute(attr.to_s, original)
206
- changed[attr] = changed_to
207
- end
208
-
209
- @approval = approvals.build(:event => 'update', :state => 'pending', :object => changed)
210
- end
211
- end
212
-
213
- ##
214
- # Instance methods that apply to both `:update` and `:create` events.
215
- module InstanceMethods
216
- ##
217
- # Returns true if the approval queue is active at both the local and global
218
- # level. Note that the global level supercedes the local level.
219
- def approvals_enabled?
220
- ActsAsApprovable.enabled? and self.class.approvals_active and approvals_on?
221
- end
222
-
223
- ##
224
- # Returns the inverse of `#approvals_enabled?`
225
- def approvals_disabled?
226
- !approvals_enabled?
227
- end
228
-
229
- def approvals_off
230
- @approvals_disabled = true
231
- end
232
-
233
- def approvals_on
234
- @approvals_disabled = false
235
- end
236
-
237
- def approvals_on?
238
- not @approvals_disabled
239
- end
240
-
241
- ##
242
- # Returns true if the model is configured to use the approval queue on the
243
- # given event (`:create` or `:update`).
244
- def approvable_on?(event)
245
- self.class.approvable_on.include?(event)
246
- end
247
-
248
- ##
249
- # A filter that is run before the record can be approved. Returning false
250
- # stops the approval process from completing.
251
- def before_approve(approval); end
252
-
253
- ##
254
- # A filter that is run after the record has been approved.
255
- def after_approve(approval); end
256
-
257
- ##
258
- # A filter that is run before the record can be rejected. Returning false
259
- # stops the rejection process from completing.
260
- def before_reject(approval); end
261
-
262
- ##
263
- # A filter that is run after the record has been rejected.
264
- def after_reject(approval); end
265
-
266
- ##
267
- # Execute a code block while the approval queue is temporarily disabled. The
268
- # queue state will be returned to it's previous value, either on or off.
269
- def without_approval(&block)
270
- enable = approvals_on? # If we use #approvals_enabled? the global state might be incorrectly applied.
271
- approvals_off
272
- yield(self)
273
- ensure
274
- approvals_on if enable
275
- end
276
-
277
- def save_without_approval(*args)
278
- without_approval { |i| save(*args) }
279
- end
280
-
281
- def save_without_approval!(*args)
282
- without_approval { |i| save!(*args) }
283
- end
284
-
285
- private
286
- def approvable_save
287
- @approval.save if @approval.present? && @approval.new_record?
288
- end
289
- end
290
- end
291
- end
@@ -1,459 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ActsAsApprovableModelTest < Test::Unit::TestCase
4
- load_schema
5
-
6
- def teardown
7
- truncate
8
- end
9
-
10
- context 'A record with update only approval' do
11
- context 'and ignored fields' do
12
- setup { @project = Project.create }
13
-
14
- should 'have no approvals' do
15
- assert @project.approvals.empty?
16
- end
17
-
18
- context 'which updates an ignored column' do
19
- setup { @project.update_attribute(:title, 'Ignore Me') }
20
-
21
- should 'not have an approval' do
22
- assert @project.approvals.empty?
23
- end
24
- end
25
-
26
- context 'which updates an ignore column and a non-ignored column' do
27
- setup { @project.update_attributes(:title => 'Ignore Me', :description => 'Must Review') }
28
-
29
- should 'have one approval' do
30
- assert_equal 1, @project.approvals.size
31
- end
32
-
33
- should 'not update the records ignored column' do
34
- assert_equal nil, @project.description
35
- end
36
-
37
- should 'update the records non-ignored columns' do
38
- assert_equal 'Ignore Me', @project.title
39
- end
40
-
41
- should 'have the description on the approval' do
42
- assert @project.approvals.last.object.key?('description')
43
- assert_equal 'Must Review', @project.approvals.last.object['description']
44
- end
45
- end
46
-
47
- context 'that is altered using #without_approval' do
48
- should 'not have an approval object' do
49
- @project.without_approval { |i| i.update_attribute(:description, 'updated') }
50
- assert @project.approvals.empty?
51
- end
52
-
53
- should 'correctly restore approval queue state' do
54
- assert @project.approvals_on?
55
- @project.approvals_off
56
- assert !@project.approvals_on?
57
- @project.without_approval { |i| i.update_attribute(:description, 'updated') }
58
- assert !@project.approvals_on?
59
- end
60
- end
61
- end
62
-
63
- context 'and "only" fields' do
64
- setup { @game = Game.create }
65
-
66
- should 'have no approvals' do
67
- assert @game.approvals.empty?
68
- end
69
-
70
- context 'which updates an only column' do
71
- setup { @game.update_attribute(:title, 'review') }
72
-
73
- should 'have an approval' do
74
- assert_equal 1, @game.approvals.size
75
- end
76
-
77
- should 'have pending changes' do
78
- assert @game.pending_changes?
79
- end
80
- end
81
-
82
- context 'which updates an only column and another column' do
83
- setup { @game.update_attributes(:title => 'review', :description => 'no review') }
84
-
85
- should 'have one approval' do
86
- assert_equal 1, @game.approvals.size
87
- end
88
-
89
- should 'not update the records only column' do
90
- assert_equal nil, @game.title
91
- end
92
-
93
- should 'update the records other fields' do
94
- assert_equal 'no review', @game.description
95
- end
96
-
97
- should 'have the title on the approval' do
98
- assert @game.approvals.last.object.key?('title')
99
- assert_equal 'review', @game.approvals.last.object['title']
100
- end
101
- end
102
-
103
- context 'that has approved, rejected and pending update approvals' do
104
- setup do
105
- @game.update_attributes(:title => 'review1')
106
- @game.update_approvals.last.approve!(true)
107
-
108
- @game.update_attributes(:title => 'review2')
109
- @game.update_approvals.last.reject!
110
-
111
- @game.update_attributes(:title => 'review3')
112
- @game.update_attributes(:title => 'review4')
113
- end
114
-
115
- should 'have #pending_changes?' do
116
- assert @game.pending_changes?
117
- end
118
- end
119
-
120
- context 'that has approved and rejected, but no pending update approvals' do
121
- setup do
122
- @game.update_attributes(:title => 'review1')
123
- @game.update_approvals.last.approve!(true)
124
-
125
- @game.update_attributes(:title => 'review2')
126
- @game.update_approvals.last.reject!
127
- end
128
-
129
- should 'have #pending_changes?' do
130
- assert !@game.pending_changes?
131
- end
132
- end
133
-
134
- context 'that is altered using #without_approval' do
135
- setup { @game.without_approval { |i| i.update_attribute(:title, 'updated') } }
136
-
137
- should 'not have an approval object' do
138
- assert @game.approvals.empty?
139
- end
140
- end
141
-
142
- context 'with approval queue disabled' do
143
- context 'at the record level' do
144
- setup do
145
- @game.approvals_off
146
- @game.update_attributes(:title => 'review')
147
- end
148
-
149
- teardown { @game.approvals_on }
150
-
151
- should 'have approvals off' do
152
- assert @game.approvals_disabled?
153
- end
154
-
155
- should 'not have an approval object' do
156
- assert @game.approvals.empty?
157
- end
158
- end
159
-
160
- context 'at the model level' do
161
- setup do
162
- Game.approvals_off
163
- @game.update_attributes(:title => 'review')
164
- end
165
-
166
- teardown { Game.approvals_on }
167
-
168
- should 'have approvals off' do
169
- assert @game.approvals_disabled?
170
- end
171
-
172
- should 'not have an approval object' do
173
- assert @game.approvals.empty?
174
- end
175
- end
176
-
177
- context 'at the global level' do
178
- setup do
179
- ActsAsApprovable.disable
180
- @game.update_attributes(:title => 'review')
181
- end
182
-
183
- teardown { ActsAsApprovable.enable }
184
-
185
- should 'have approvals off' do
186
- assert @game.approvals_disabled?
187
- end
188
-
189
- should 'not have an approval object' do
190
- assert @game.approvals.empty?
191
- end
192
- end
193
- end
194
- end
195
- end
196
-
197
- context 'An approval record' do
198
- setup do
199
- @project = Project.create
200
- @project.update_attribute(:description, 'review')
201
- @approval = @project.approvals.last
202
- end
203
-
204
- should 'not be locked by default' do
205
- assert @approval.unlocked?
206
- assert !@approval.locked?
207
- end
208
-
209
- should 'be pending' do
210
- assert @approval.pending?
211
- assert !@approval.approved?
212
- assert !@approval.rejected?
213
- end
214
-
215
- should 'check attributes in object' do
216
- @approval.object['foo'] = 'bar'
217
- @approval.approve!
218
- assert_equal @approval.object['description'], @approval.item.description
219
- end
220
-
221
- context 'that is accepted' do
222
- setup { @approval.approve! }
223
-
224
- should 'be locked' do
225
- assert @approval.locked?
226
- assert !@approval.unlocked?
227
- end
228
-
229
- should 'be approved' do
230
- assert @approval.approved?
231
- assert !@approval.rejected?
232
- assert !@approval.pending?
233
- end
234
-
235
- should 'update the target item' do
236
- assert_equal @approval.object['description'], @approval.item.description
237
- end
238
-
239
- should 'raise an error if approved again' do
240
- assert_raise(ActsAsApprovable::Error::Locked) { @approval.approve! }
241
- end
242
-
243
- should 'raise an error if rejected' do
244
- assert_raise(ActsAsApprovable::Error::Locked) { @approval.reject! }
245
- end
246
- end
247
-
248
- context 'that is rejected' do
249
- setup { @approval.reject! }
250
-
251
- should 'be locked' do
252
- assert @approval.locked?
253
- assert !@approval.unlocked?
254
- end
255
-
256
- should 'be rejected' do
257
- assert @approval.rejected?
258
- assert !@approval.approved?
259
- assert !@approval.pending?
260
- end
261
-
262
- should 'not update the target item' do
263
- assert_equal nil, @approval.item.description
264
- end
265
-
266
- should 'raise an error if approved' do
267
- assert_raise(ActsAsApprovable::Error::Locked) { @approval.approve! }
268
- end
269
-
270
- should 'raise an error if rejected again' do
271
- assert_raise(ActsAsApprovable::Error::Locked) { @approval.reject! }
272
- end
273
- end
274
-
275
- context 'that is stale' do
276
- setup { @approval.update_attributes(:created_at => 10.days.ago) }
277
-
278
- should 'be stale' do
279
- assert @approval.stale?
280
- assert !@approval.fresh?
281
- end
282
-
283
- should 'raise an error if approved' do
284
- assert_raise(ActsAsApprovable::Error::Stale) { @approval.approve! }
285
- assert @approval.pending?
286
- end
287
-
288
- should 'not raise an error if rejected' do
289
- assert_nothing_raised { @approval.reject! }
290
- assert @approval.rejected?
291
- end
292
-
293
- should 'allow approval when forced' do
294
- assert_nothing_raised { @approval.approve!(true) }
295
- assert @approval.approved?
296
- end
297
- end
298
- end
299
-
300
- context 'A record with create only approval' do
301
- setup { @user = User.create }
302
-
303
- should 'be pending by default' do
304
- assert @user.pending?
305
- assert !@user.approved?
306
- assert !@user.rejected?
307
- end
308
-
309
- should 'have an approval object' do
310
- assert_equal 1, @user.approvals.size
311
- end
312
-
313
- should 'set the local state' do
314
- assert_equal 'pending', @user.state
315
- end
316
-
317
- context 'when approved' do
318
- setup do
319
- @user.approve!
320
- @user.reload
321
- end
322
-
323
- should 'be approved' do
324
- assert @user.approved?
325
- assert !@user.rejected?
326
- assert !@user.pending?
327
- end
328
-
329
- should 'update the local state' do
330
- assert_equal 'approved', @user.state
331
- end
332
- end
333
-
334
- context 'when rejected' do
335
- setup do
336
- @user.reject!
337
- @user.reload
338
- end
339
-
340
- should 'be rejected' do
341
- assert @user.rejected?
342
- assert !@user.approved?
343
- assert !@user.pending?
344
- end
345
-
346
- should 'update the local state' do
347
- assert_equal 'rejected', @user.state
348
- end
349
- end
350
-
351
- context '.without_approval' do
352
- should 'disable approvals for the given block' do
353
- @user = User.without_approval { |m| m.create }
354
- assert @user.approval.nil?
355
- end
356
- end
357
- end
358
-
359
- context 'A record with default settings' do
360
- setup { @employee = Employee.create }
361
-
362
- should 'be pending by default' do
363
- assert @employee.pending?
364
- assert !@employee.approved?
365
- assert !@employee.rejected?
366
- end
367
-
368
- should 'get the state from the approval record' do
369
- assert_equal @employee.approval_state, @employee.approval.state
370
- end
371
-
372
- context 'when updated' do
373
- setup { @employee.update_attributes(:name => 'John Doe') }
374
-
375
- should 'not update the attribute' do
376
- assert_equal nil, @employee.name
377
- end
378
-
379
- should 'create an approval record' do
380
- assert_equal 1, @employee.update_approvals.size
381
- end
382
- end
383
-
384
- context 'when approving' do
385
- setup { @approval = @employee.approval }
386
-
387
- should 'call before_approve hook' do
388
- @approval.item.expects(:before_approve).once
389
- @approval.approve!
390
- end
391
-
392
- should 'call after_approve hook' do
393
- @approval.item.expects(:after_approve).once
394
- @approval.approve!
395
- end
396
-
397
- should 'halt if before_approve returns false' do
398
- @approval.item.stubs(:before_approve).returns(false)
399
- @approval.approve!
400
- assert @approval.item.pending?
401
- end
402
- end
403
-
404
- context 'when rejecting' do
405
- setup { @approval = @employee.approval }
406
-
407
- should 'call before_reject hook' do
408
- @approval.item.expects(:before_reject).once
409
- @approval.reject!
410
- end
411
-
412
- should 'call after_reject hook' do
413
- @approval.item.expects(:after_reject).once
414
- @approval.reject!
415
- end
416
-
417
- should 'halt if before_reject returns false' do
418
- @approval.item.stubs(:before_reject).returns(false)
419
- @approval.reject!
420
- assert @approval.item.pending?
421
- end
422
- end
423
- end
424
-
425
- context '.options_for_state' do
426
- should 'return an array' do
427
- assert_kind_of Array, Approval.options_for_state
428
- end
429
-
430
- should 'contain our states' do
431
- assert Approval.options_for_state.include?(['All', -1])
432
- assert Approval.options_for_state.include?(['Pending', 0])
433
- assert Approval.options_for_state.include?(['Approved', 1])
434
- assert Approval.options_for_state.include?(['Rejected', 2])
435
- end
436
- end
437
-
438
- context '.options_for_type' do
439
- context 'without approval records' do
440
- should 'be empty' do
441
- assert Approval.options_for_type.empty?
442
- end
443
- end
444
-
445
- context 'with approval records' do
446
- setup do
447
- Project.create.update_attributes(:description => 'review')
448
- Game.create.update_attributes(:title => 'review')
449
- User.create
450
- end
451
-
452
- should 'contain all types with approvals' do
453
- assert Approval.options_for_type.include?('Project')
454
- assert Approval.options_for_type.include?('Game')
455
- assert Approval.options_for_type.include?('User')
456
- end
457
- end
458
- end
459
- end