acts_as_approvable 0.1.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +5 -0
  4. data/Appraisals +22 -0
  5. data/CHANGELOG +76 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +84 -0
  8. data/MIT-LICENSE +2 -2
  9. data/README.md +146 -0
  10. data/Rakefile +90 -7
  11. data/TODO.md +30 -0
  12. data/VERSION +1 -0
  13. data/acts_as_approvable.gemspec +40 -0
  14. data/features/create_approval.feature +36 -0
  15. data/features/destroy_approval.feature +19 -0
  16. data/features/reset_approval.feature +13 -0
  17. data/features/step_definitions/cucumber_steps.rb +132 -0
  18. data/features/support/env.rb +14 -0
  19. data/features/support/large.txt +29943 -0
  20. data/features/support/second_large.txt +31798 -0
  21. data/features/update_approval.feature +48 -0
  22. data/gemfiles/Gemfile.ci +14 -0
  23. data/gemfiles/Gemfile.ci.lock +98 -0
  24. data/gemfiles/mysql2.gemfile +7 -0
  25. data/gemfiles/mysql2.gemfile.lock +86 -0
  26. data/gemfiles/rails2.gemfile +8 -0
  27. data/gemfiles/rails2.gemfile.lock +86 -0
  28. data/gemfiles/rails30.gemfile +9 -0
  29. data/gemfiles/rails30.gemfile.lock +124 -0
  30. data/gemfiles/rails31.gemfile +9 -0
  31. data/gemfiles/rails31.gemfile.lock +135 -0
  32. data/gemfiles/sqlite.gemfile +7 -0
  33. data/generators/acts_as_approvable/USAGE +3 -0
  34. data/generators/acts_as_approvable/acts_as_approvable_generator.rb +81 -0
  35. data/generators/acts_as_approvable/templates/approvals.js +71 -0
  36. data/generators/acts_as_approvable/templates/approvals_controller.rb +91 -0
  37. data/generators/acts_as_approvable/templates/create_approvals.rb +27 -0
  38. data/generators/acts_as_approvable/templates/initializer.rb +3 -0
  39. data/generators/acts_as_approvable/templates/jquery.form.js +101 -0
  40. data/generators/acts_as_approvable/templates/views/erb/_owner_select.html.erb +4 -0
  41. data/generators/acts_as_approvable/templates/views/erb/_table.html.erb +26 -0
  42. data/generators/acts_as_approvable/templates/views/erb/index.html.erb +17 -0
  43. data/generators/acts_as_approvable/templates/views/haml/_owner_select.html.haml +3 -0
  44. data/generators/acts_as_approvable/templates/views/haml/_table.html.haml +19 -0
  45. data/generators/acts_as_approvable/templates/views/haml/index.html.haml +15 -0
  46. data/init.rb +1 -0
  47. data/lib/acts_as_approvable.rb +96 -2
  48. data/lib/acts_as_approvable/approval.rb +205 -11
  49. data/lib/acts_as_approvable/error.rb +34 -0
  50. data/lib/acts_as_approvable/model.rb +60 -0
  51. data/lib/acts_as_approvable/model/class_methods.rb +63 -0
  52. data/lib/acts_as_approvable/model/create_instance_methods.rb +88 -0
  53. data/lib/acts_as_approvable/model/destroy_instance_methods.rb +38 -0
  54. data/lib/acts_as_approvable/model/instance_methods.rb +107 -0
  55. data/lib/acts_as_approvable/model/update_instance_methods.rb +61 -0
  56. data/lib/acts_as_approvable/ownership.rb +141 -0
  57. data/lib/acts_as_approvable/railtie.rb +7 -0
  58. data/lib/acts_as_approvable/version.rb +1 -8
  59. data/lib/generators/acts_as_approvable/USAGE +1 -0
  60. data/lib/generators/acts_as_approvable/acts_as_approvable_generator.rb +68 -0
  61. data/lib/generators/acts_as_approvable/base.rb +30 -0
  62. data/lib/generators/acts_as_approvable/templates/approvals.js +71 -0
  63. data/lib/generators/acts_as_approvable/templates/approvals_controller.rb +91 -0
  64. data/lib/generators/acts_as_approvable/templates/create_approvals.rb +27 -0
  65. data/lib/generators/acts_as_approvable/templates/jquery.form.js +101 -0
  66. data/lib/generators/erb/acts_as_approvable_generator.rb +33 -0
  67. data/lib/generators/erb/templates/_owner_select.html.erb +4 -0
  68. data/lib/generators/erb/templates/_table.html.erb +26 -0
  69. data/lib/generators/erb/templates/index.html.erb +17 -0
  70. data/lib/generators/haml/acts_as_approvable_generator.rb +33 -0
  71. data/lib/generators/haml/templates/_owner_select.html.haml +3 -0
  72. data/lib/generators/haml/templates/_table.html.haml +19 -0
  73. data/lib/generators/haml/templates/index.html.haml +15 -0
  74. data/lib/tasks/acts_as_approvable.rake +4 -0
  75. data/rails/init.rb +1 -0
  76. data/spec/acts_as_approvable/approval_spec.rb +614 -0
  77. data/spec/acts_as_approvable/model/class_methods_spec.rb +219 -0
  78. data/spec/acts_as_approvable/model/create_instance_methods_spec.rb +169 -0
  79. data/spec/acts_as_approvable/model/destroy_instance_methods_spec.rb +71 -0
  80. data/spec/acts_as_approvable/model/instance_methods_spec.rb +328 -0
  81. data/spec/acts_as_approvable/model/update_instance_methods_spec.rb +111 -0
  82. data/spec/acts_as_approvable/model_spec.rb +113 -0
  83. data/spec/acts_as_approvable/ownership/class_methods_spec.rb +134 -0
  84. data/spec/acts_as_approvable/ownership/instance_methods_spec.rb +32 -0
  85. data/spec/acts_as_approvable/ownership_spec.rb +52 -0
  86. data/spec/acts_as_approvable_spec.rb +31 -0
  87. data/spec/spec_helper.rb +51 -0
  88. data/spec/support/database.rb +49 -0
  89. data/spec/support/database.yml +12 -0
  90. data/spec/support/matchers.rb +87 -0
  91. data/spec/support/models.rb +67 -0
  92. data/spec/support/schema.rb +54 -0
  93. metadata +375 -58
  94. data/README.rdoc +0 -38
  95. data/lib/acts_as_approvable/approver.rb +0 -76
  96. data/lib/generators/acts_as_approvable/install_generator.rb +0 -28
  97. data/lib/generators/acts_as_approvable/templates/install.rb +0 -16
@@ -0,0 +1,219 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsApprovable::Model::ClassMethods do
4
+ subject { DefaultApprovable }
5
+
6
+ describe '.acts_as_approvable' do
7
+ subject { CleanApprovable }
8
+
9
+ it 'includes InstanceMethods into the class' do
10
+ subject.should_not extend(ActsAsApprovable::Model::InstanceMethods)
11
+ subject.acts_as_approvable
12
+ subject.should extend(ActsAsApprovable::Model::InstanceMethods)
13
+ end
14
+
15
+ it 'includes ClassMethods into the class' do
16
+ subject.should_not extend(ActsAsApprovable::Model::ClassMethods)
17
+ subject.acts_as_approvable
18
+ subject.should extend(ActsAsApprovable::Model::ClassMethods)
19
+ end
20
+ end
21
+
22
+ describe '.approvals_enabled?' do
23
+ before(:each) do
24
+ subject.stub(:global_approvals_on? => true)
25
+ subject.stub(:approvals_on? => true)
26
+ end
27
+
28
+ context 'when approvals are globally disabled' do
29
+ before(:each) do
30
+ subject.stub(:global_approvals_on? => false)
31
+ end
32
+
33
+ it 'returns false' do
34
+ subject.approvals_enabled?.should be_false
35
+ end
36
+
37
+ it 'checks the global status' do
38
+ subject.should_receive(:global_approvals_on?).and_return(false)
39
+ subject.approvals_enabled?
40
+ end
41
+
42
+ it 'does not check the model status' do
43
+ subject.should_not_receive(:approvals_on?)
44
+ subject.approvals_enabled?
45
+ end
46
+ end
47
+
48
+ context 'when approvals are disabled for the Model' do
49
+ before(:each) do
50
+ subject.stub(:approvals_on? => false)
51
+ end
52
+
53
+ it 'returns false' do
54
+ subject.approvals_enabled?.should be_false
55
+ end
56
+
57
+ it 'checks the global status' do
58
+ subject.should_receive(:global_approvals_on?).and_return(true)
59
+ subject.approvals_enabled?
60
+ end
61
+
62
+ it 'checks the model status' do
63
+ subject.should_receive(:approvals_on?).and_return(false)
64
+ subject.approvals_enabled?
65
+ end
66
+ end
67
+ end
68
+
69
+ describe '.approvals_disabled?' do
70
+ before(:each) do
71
+ subject.stub(:approvals_enabled? => true)
72
+ end
73
+
74
+ it 'returns the inverse of the approval queue status' do
75
+ subject.approvals_disabled?.should == !subject.approvals_enabled?
76
+ end
77
+
78
+ it 'calls .approvals_enabled? for the status' do
79
+ subject.should_receive(:approvals_enabled?).and_return(true)
80
+ subject.approvals_disabled?
81
+ end
82
+ end
83
+
84
+ describe '.approvals_off' do
85
+ before(:each) do
86
+ subject.approvals_off
87
+ end
88
+
89
+ it 'disables the model level approval queue' do
90
+ subject.approvals_on?.should be_false
91
+ end
92
+ end
93
+
94
+ describe '.approvals_on' do
95
+ before(:each) do
96
+ subject.approvals_on
97
+ end
98
+
99
+ it 'enables the model level approval queue' do
100
+ subject.approvals_on?.should be_true
101
+ end
102
+ end
103
+
104
+ describe '.approvals_on?' do
105
+ context 'when approval queues are enabled locally' do
106
+ before(:each) do
107
+ subject.approvals_disabled = false
108
+ end
109
+
110
+ it 'returns true' do
111
+ subject.approvals_on?.should be_true
112
+ end
113
+
114
+ it 'ignores the global level status' do
115
+ subject.stub(:global_approvals_on? => false)
116
+ subject.approvals_on?.should be_true
117
+ end
118
+ end
119
+
120
+ context 'when approval queues are disabled locally' do
121
+ before(:each) do
122
+ subject.approvals_disabled = true
123
+ end
124
+
125
+ it 'returns false' do
126
+ subject.approvals_on?.should be_false
127
+ end
128
+
129
+ it 'ignores the global level status' do
130
+ subject.stub(:global_approvals_on? => true)
131
+ subject.approvals_on?.should be_false
132
+ end
133
+ end
134
+ end
135
+
136
+ describe '.global_approvals_on?' do
137
+ it 'checks the global approval status' do
138
+ ActsAsApprovable.should_receive(:enabled?)
139
+ subject.global_approvals_on?
140
+ end
141
+ end
142
+
143
+ describe '.approvable_on?' do
144
+ it { should be_approvable_on(:create) }
145
+ it { should be_approvable_on(:update) }
146
+
147
+ context 'when the model is approvable on :create events' do
148
+ subject { CreatesApprovable }
149
+
150
+ it { should be_approvable_on(:create) }
151
+ it { should_not be_approvable_on(:update) }
152
+ end
153
+
154
+ context 'when the model is approvable on :update events' do
155
+ subject { UpdatesApprovable }
156
+
157
+ it { should be_approvable_on(:update) }
158
+ it { should_not be_approvable_on(:create) }
159
+ end
160
+ end
161
+
162
+ describe '.approvable_fields' do
163
+ subject { CleanApprovable }
164
+
165
+ context 'with :only fields configured' do
166
+ before(:each) do
167
+ subject.acts_as_approvable :only => [:body, :extra]
168
+ end
169
+
170
+ it 'returns the configured fields' do
171
+ subject.approvable_fields.should == ['body', 'extra']
172
+ end
173
+ end
174
+
175
+ context 'with :ignore fields configured' do
176
+ before(:each) do
177
+ subject.acts_as_approvable :ignore => [:title, :extra]
178
+ end
179
+
180
+ it 'returns the available fields minus whats ignored' do
181
+ subject.approvable_fields.should include('body')
182
+ end
183
+
184
+ it 'ignores timestamps' do
185
+ subject.approvable_fields.should_not include('created_at')
186
+ subject.approvable_fields.should_not include('updated_at')
187
+ end
188
+
189
+ it 'ignores primary keys' do
190
+ subject.approvable_fields.should_not include(subject.primary_key)
191
+ end
192
+ end
193
+ end
194
+
195
+ describe '.without_approval' do
196
+ around(:each) do |example|
197
+ subject.approvals_on
198
+ example.run
199
+ subject.approvals_on
200
+ end
201
+
202
+ it 'disables approval queues' do
203
+ @record = subject.without_approval { |m| m.create(:title => 'title', :body => 'the body') }
204
+ @record.approval.should_not be
205
+ end
206
+
207
+ it 'enables the approval queue after running' do
208
+ subject.should be_approvals_on
209
+ subject.without_approval { |m| m.create(:title => 'title', :body => 'the body') }
210
+ subject.should be_approvals_on
211
+ end
212
+
213
+ it 'returns the approval queue to the previous state' do
214
+ subject.approvals_off
215
+ subject.without_approval { |m| m.create(:title => 'title', :body => 'the body') }
216
+ subject.should_not be_approvals_on
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,169 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsApprovable::Model::CreateInstanceMethods do
4
+ subject { CreatesApprovable.create }
5
+
6
+ describe '#approval' do
7
+ subject { CreatesApprovable.create } # Reverse the mocking for #approval
8
+
9
+ it 'returns a :create approval' do
10
+ subject.approval.event == :create
11
+ end
12
+
13
+ it 'returns the first :create approval' do
14
+ duplicate = Approval.create(:item_id => subject.id, :item_type => 'CreatesApprovable', :event => 'create')
15
+ subject.approval != duplicate
16
+ end
17
+ end
18
+
19
+ context do
20
+ before(:each) do
21
+ @approval = subject.approvals.first
22
+ subject.stub(:approval => @approval)
23
+ end
24
+
25
+ describe '#approval_state' do
26
+ it 'gets the state from the approval record' do
27
+ @approval.should_receive(:state)
28
+ subject.approval_state
29
+ end
30
+
31
+ context 'when a :state_field is configured' do
32
+ subject { CreatesWithStateApprovable.create }
33
+
34
+ it 'gets the state from the configured field' do
35
+ subject.should_receive(:state)
36
+ subject.approval_state
37
+ end
38
+
39
+ it 'does not get the state from the approval record' do
40
+ subject.should_not_receive(:approval)
41
+ subject.approval_state
42
+ end
43
+ end
44
+ end
45
+
46
+ describe '#set_approval_state' do
47
+ it 'does nothing if no :state_field is configured' do
48
+ subject.should_not_receive(:state=)
49
+ subject.set_approval_state('pending')
50
+ end
51
+
52
+ context 'when a :state_field is configured' do
53
+ subject { CreatesWithStateApprovable.create }
54
+
55
+ it 'sets the configured field' do
56
+ subject.should_receive(:state=)
57
+ subject.set_approval_state('pending')
58
+ end
59
+ end
60
+ end
61
+
62
+ describe '#pending?' do
63
+ it 'gets the status from the approval record' do
64
+ subject.should_receive(:approval)
65
+ subject.pending?
66
+ end
67
+
68
+ context 'when a :state_field is configured' do
69
+ subject { CreatesWithStateApprovable.create }
70
+
71
+ it 'gets the state from the configured field' do
72
+ subject.should_receive(:state)
73
+ subject.pending?
74
+ end
75
+
76
+ it 'does not get the state from the approval record' do
77
+ subject.should_not_receive(:approval)
78
+ subject.pending?
79
+ end
80
+ end
81
+ end
82
+
83
+ describe '#approved?' do
84
+ it 'gets the status from the approval record' do
85
+ subject.should_receive(:approval)
86
+ subject.approved?
87
+ end
88
+
89
+ context 'when a :state_field is configured' do
90
+ subject { CreatesWithStateApprovable.create }
91
+
92
+ it 'gets the state from the configured field' do
93
+ subject.should_receive(:state)
94
+ subject.approved?
95
+ end
96
+
97
+ it 'does not get the state from the approval record' do
98
+ subject.should_not_receive(:approval)
99
+ subject.approved?
100
+ end
101
+ end
102
+ end
103
+
104
+ describe '#rejected?' do
105
+ it 'gets the status from the approval record' do
106
+ subject.should_receive(:approval)
107
+ subject.rejected?
108
+ end
109
+
110
+ context 'when a :state_field is configured' do
111
+ subject { CreatesWithStateApprovable.create }
112
+
113
+ it 'gets the state from the configured field' do
114
+ subject.should_receive(:state)
115
+ subject.rejected?
116
+ end
117
+
118
+ it 'does not get the state from the approval record' do
119
+ subject.should_not_receive(:approval)
120
+ subject.rejected?
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '#approve!' do
126
+ it 'approves the record' do
127
+ subject.approve!
128
+ subject.should be_approved
129
+ end
130
+
131
+ it 'proxies to the approval record for approval' do
132
+ subject.should_receive(:approval)
133
+ subject.approve!
134
+ end
135
+ end
136
+
137
+ describe '#reject!' do
138
+ it 'rejects the record' do
139
+ subject.reject!
140
+ subject.should be_rejected
141
+ end
142
+
143
+ it 'proxies to the approval record for approval' do
144
+ subject.should_receive(:approval)
145
+ subject.reject!
146
+ end
147
+ end
148
+
149
+ describe '#reset!' do
150
+ it 'proxies to the approval record for approval' do
151
+ subject.should_receive(:approval)
152
+ subject.reset!
153
+ end
154
+
155
+ context 'when the approval is stale' do
156
+ before(:each) do
157
+ subject.approval.class.record_timestamps = false
158
+ subject.approval.update_attribute(:updated_at, subject.approval.updated_at - 1)
159
+ subject.approval.class.record_timestamps = true
160
+ end
161
+
162
+ it 'puts the approval back to fresh' do
163
+ subject.reset!
164
+ subject.approval.should be_fresh
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsApprovable::Model::DestroyInstanceMethods do
4
+ subject { DestroysApprovable.create }
5
+
6
+ describe '#destroy_approvals' do
7
+ before(:each) do
8
+ subject.destroy
9
+ @approval1 = subject.approvals.last
10
+ @approval1.reject!
11
+
12
+ subject.destroy
13
+ @approval2 = subject.approvals.last
14
+ end
15
+
16
+ it 'retreives all :destroy approvals' do
17
+ subject.destroy_approvals.should == [@approval1, @approval2]
18
+ end
19
+
20
+ context 'when requesting only pending records' do
21
+ it 'retreives pending :destroy approvals' do
22
+ subject.destroy_approvals(false).should == [@approval2]
23
+ end
24
+ end
25
+
26
+ context 'with other event records' do
27
+ subject { DefaultApprovable.create }
28
+
29
+ before(:each) do
30
+ @approval3 = subject.approval
31
+
32
+ subject.update_attribute(:title, 'review')
33
+ @approval4 = subject.approvals.last
34
+ @approval4.approve!
35
+ end
36
+
37
+ it 'retreives only :destroy approvals' do
38
+ subject.destroy_approvals.should == [@approval1, @approval2]
39
+ end
40
+
41
+ context 'when requesting only pending records' do
42
+ it 'retreives only pending :destroy approvals' do
43
+ subject.destroy_approvals(false).should == [@approval2]
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#pending_destruction?' do
50
+ context 'with pending approvals' do
51
+ it { should_not be_pending_destruction }
52
+ end
53
+
54
+ context 'with pending approvals' do
55
+ before(:each) do
56
+ subject.destroy
57
+ end
58
+
59
+ it { should be_pending_destruction }
60
+ end
61
+
62
+ context 'with rejected approvals' do
63
+ before(:each) do
64
+ subject.destroy
65
+ subject.approvals.last.reject!
66
+ end
67
+
68
+ it { should_not be_pending_destruction }
69
+ end
70
+ end
71
+ end