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
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsApprovable::Model::UpdateInstanceMethods do
4
+ subject { UpdatesApprovable.create }
5
+
6
+ describe '#update_approvals' do
7
+ before(:each) do
8
+ subject.update_attributes(:title => 'review')
9
+ @approval1 = subject.approvals.last
10
+ @approval1.approve!
11
+
12
+ subject.update_attributes(:title => 'review2')
13
+ @approval2 = subject.approvals.last
14
+ end
15
+
16
+ it 'retreives all :update approvals' do
17
+ subject.update_approvals.should == [@approval1, @approval2]
18
+ end
19
+
20
+ context 'when requesting only pending records' do
21
+ it 'retreives pending :update approvals' do
22
+ subject.update_approvals(false).should == [@approval2]
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '#pending_changes?' do
28
+ it 'returns false with no pending approvals' do
29
+ subject.should_not be_pending_changes
30
+ end
31
+
32
+ context 'with pending approvals' do
33
+ before(:each) do
34
+ subject.update_attributes(:title => 'review')
35
+ end
36
+
37
+ it 'returns true' do
38
+ subject.should be_pending_changes
39
+ end
40
+ end
41
+
42
+ context 'with approved and rejected approvals' do
43
+ before(:each) do
44
+ subject.update_attributes(:title => 'review')
45
+ subject.approvals.last.approve!
46
+
47
+ subject.update_attributes(:title => 'review')
48
+ subject.approvals.last.reject!
49
+ end
50
+
51
+ it 'returns false' do
52
+ subject.should_not be_pending_changes
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#changed_notably?' do
58
+ it 'returns true if #notably_changed returns values' do
59
+ subject.stub(:notably_changed => [1])
60
+ subject.should be_changed_notably
61
+ end
62
+
63
+ it 'returns false if #notably_changed does not return values' do
64
+ subject.stub(:notably_changed => [])
65
+ subject.should_not be_changed_notably
66
+ end
67
+ end
68
+
69
+ describe '#notably_changed' do
70
+ before(:each) do
71
+ subject.title = 'review'
72
+ subject.updated_at += 60
73
+ end
74
+
75
+ it 'includes fields that should be approved' do
76
+ subject.changed.should include('title')
77
+ subject.notably_changed.should include('title')
78
+ end
79
+
80
+ it 'does not include fields that should be ignored' do
81
+ subject.changed.should include('updated_at')
82
+ subject.notably_changed.should_not include('updated_at')
83
+ end
84
+
85
+ it 'gets a list of approvable fields from #approvable_fields' do
86
+ subject.should_receive(:approvable_fields).and_return([])
87
+ subject.notably_changed
88
+ end
89
+ end
90
+
91
+ describe '#approvable_fields' do
92
+ it 'proxies to the class level' do
93
+ subject.class.should_receive(:approvable_fields)
94
+ subject.approvable_fields
95
+ end
96
+ end
97
+
98
+ context 'when a record is updated' do
99
+ before(:each) do
100
+ subject.update_attribute(:body, 'updated')
101
+ end
102
+
103
+ it 'saves the updated values to the approval record' do
104
+ subject.update_approvals.last.object.should == {'body' => 'updated'}
105
+ end
106
+
107
+ it 'saves the original values to the approval record' do
108
+ subject.update_approvals.last.original.should == {'body' => nil}
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsApprovable::Model do
4
+ context 'when acts_as_approvable is not configured' do
5
+ subject { NotApprovable }
6
+
7
+ it { subject.new.should_not have_many(:approvals) }
8
+
9
+ it { should_not extend(ActsAsApprovable::Model::ClassMethods) }
10
+ it { should_not extend(ActsAsApprovable::Model::InstanceMethods) }
11
+ it { should_not extend(ActsAsApprovable::Model::CreateInstanceMethods) }
12
+ it { should_not extend(ActsAsApprovable::Model::UpdateInstanceMethods) }
13
+ end
14
+
15
+ context 'with default configuration options' do
16
+ subject { DefaultApprovable }
17
+
18
+ it { should be_approvable_on(:create) }
19
+ it { should be_approvable_on(:update) }
20
+ it { should be_approvals_enabled }
21
+ it { subject.new.should have_many(:approvals) }
22
+
23
+ it { should extend(ActsAsApprovable::Model::ClassMethods) }
24
+ it { should extend(ActsAsApprovable::Model::InstanceMethods) }
25
+ it { should extend(ActsAsApprovable::Model::CreateInstanceMethods) }
26
+ it { should extend(ActsAsApprovable::Model::UpdateInstanceMethods) }
27
+
28
+ it 'has no approvable_field' do
29
+ subject.approvable_field.should_not be
30
+ end
31
+
32
+ it 'ignores timestamps' do
33
+ subject.approvable_ignore.should include('created_at')
34
+ subject.approvable_ignore.should include('updated_at')
35
+ end
36
+
37
+ it 'ignores the primary key' do
38
+ subject.approvable_ignore.should include(subject.primary_key)
39
+ end
40
+ end
41
+
42
+ context 'with :create as the only event' do
43
+ context 'and no other options' do
44
+ subject { CreatesApprovable }
45
+
46
+ it { should be_approvable_on(:create) }
47
+ it { should_not be_approvable_on(:update) }
48
+
49
+ it { should extend(ActsAsApprovable::Model::ClassMethods) }
50
+ it { should extend(ActsAsApprovable::Model::InstanceMethods) }
51
+ it { should extend(ActsAsApprovable::Model::CreateInstanceMethods) }
52
+ it { should_not extend(ActsAsApprovable::Model::UpdateInstanceMethods) }
53
+ end
54
+
55
+ context 'and a :state_field' do
56
+ subject { CreatesWithStateApprovable }
57
+
58
+ it 'has an approvable_field' do
59
+ subject.approvable_field.should be
60
+ end
61
+
62
+ it 'ignores the approvable_field' do
63
+ subject.approvable_ignore.should include(subject.approvable_field.to_s)
64
+ end
65
+
66
+ it 'ignores timestamps' do
67
+ subject.approvable_ignore.should include('created_at')
68
+ subject.approvable_ignore.should include('updated_at')
69
+ end
70
+
71
+ it 'ignores the primary key' do
72
+ subject.approvable_ignore.should include(subject.primary_key)
73
+ end
74
+ end
75
+ end
76
+
77
+ context 'with :update as the only event' do
78
+ context 'and no other options' do
79
+ subject { UpdatesApprovable }
80
+
81
+ it { should be_approvable_on(:update) }
82
+ it { should_not be_approvable_on(:create) }
83
+
84
+ it { should extend(ActsAsApprovable::Model::ClassMethods) }
85
+ it { should extend(ActsAsApprovable::Model::InstanceMethods) }
86
+ it { should extend(ActsAsApprovable::Model::UpdateInstanceMethods) }
87
+ it { should_not extend(ActsAsApprovable::Model::CreateInstanceMethods) }
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsApprovable::Ownership::ClassMethods do
4
+ before(:all) do
5
+ ActsAsApprovable::Ownership.configure
6
+ end
7
+
8
+ before(:each) do
9
+ @user1 = User.create
10
+ @user2 = User.create
11
+ end
12
+
13
+ subject { Approval }
14
+
15
+ describe '.owner_class' do
16
+ it 'proxies to ActsAsApprovable' do
17
+ ActsAsApprovable.should_receive(:owner_class)
18
+ subject.owner_class
19
+ end
20
+ end
21
+
22
+ describe '.available_owners' do
23
+ it 'selects all records from #owner_class' do
24
+ subject.available_owners.should include(@user1)
25
+ subject.available_owners.should include(@user2)
26
+ end
27
+ end
28
+
29
+ describe '.options_for_available_owners' do
30
+ it 'returns an array usable by #options_for_select' do
31
+ subject.options_for_available_owners.should be_an_options_array
32
+ end
33
+
34
+ it 'uses .available_owners as its source' do
35
+ subject.should_receive(:available_owners).and_return([])
36
+ subject.options_for_available_owners
37
+ end
38
+
39
+ it 'uses .options_for_owner to format each record' do
40
+ subject.should_receive(:option_for_owner).with(@user1).once
41
+ subject.should_receive(:option_for_owner).with(@user2).once
42
+ subject.options_for_available_owners
43
+ end
44
+
45
+ it 'includes a prompt if requested' do
46
+ subject.options_for_available_owners(true).should include(['(none)', nil])
47
+ end
48
+
49
+ it 'does not includes a prompt by default' do
50
+ subject.options_for_available_owners.should_not include(['(none)', nil])
51
+ end
52
+ end
53
+
54
+ context 'when no users are assigned' do
55
+ describe '.assigned_owners' do
56
+ it 'should be empty' do
57
+ subject.assigned_owners.should be_empty
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'when some users are assigned' do
63
+ before(:each) do
64
+ CreatesApprovable.create.approval.update_attribute(:owner_id, @user1.id)
65
+ end
66
+
67
+ describe '.assigned_owners' do
68
+ it 'selects all owners with an assigned approval' do
69
+ subject.assigned_owners.should include(@user1)
70
+ end
71
+
72
+ it 'does not include owners without an assignment' do
73
+ subject.assigned_owners.should_not include(@user2)
74
+ end
75
+ end
76
+
77
+ describe '.options_for_assigned_owners' do
78
+ it 'returns an array usable by #options_for_select' do
79
+ subject.options_for_assigned_owners.should be_an_options_array
80
+ end
81
+
82
+ it 'uses .assigned_owners as its source' do
83
+ subject.should_receive(:assigned_owners).and_return([@user1])
84
+ subject.options_for_assigned_owners
85
+ end
86
+
87
+ it 'uses .options_for_owner to format each record' do
88
+ subject.should_receive(:option_for_owner).with(@user1)
89
+ subject.options_for_assigned_owners
90
+ end
91
+
92
+ it 'includes a prompt if requested' do
93
+ subject.options_for_assigned_owners(true).should include(['All Users', nil])
94
+ end
95
+
96
+ it 'does not includes a prompt by default' do
97
+ subject.options_for_assigned_owners.should_not include(['All Users', nil])
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsApprovable::Ownership::InstanceMethods do
4
+ before(:all) do
5
+ ActsAsApprovable::Ownership.configure
6
+ end
7
+
8
+ before(:each) do
9
+ @user1 = User.create
10
+ @user2 = User.new
11
+ subject.stub(:save => true)
12
+ end
13
+
14
+ subject { Approval.new }
15
+
16
+ describe '#assign' do
17
+ it 'sets the owner' do
18
+ expect { subject.assign(@user1) }.to change{subject.owner}.from(nil).to(@user1)
19
+ end
20
+
21
+ it 'raises an InvalidOwner error if the owner is not valid' do
22
+ expect { subject.assign(@user2) }.to raise_error(ActsAsApprovable::Error::InvalidOwner)
23
+ end
24
+ end
25
+
26
+ describe '#unassign' do
27
+ it 'removes the assigned owner' do
28
+ subject.owner = @user1
29
+ expect { subject.unassign }.to change{subject.owner}.from(@user1).to(nil)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsApprovable::Ownership do
4
+ describe '.configure' do
5
+ it 'defaults to Approval as the approval model' do
6
+ Approval.should_receive(:include).with(ActsAsApprovable::Ownership)
7
+ subject.configure
8
+ end
9
+
10
+ it 'defaults to User as the owner model' do
11
+ ActsAsApprovable.should_receive(:owner_class=).with(User)
12
+ subject.configure
13
+ end
14
+
15
+ it 'adds a belongs_to(:owner) association' do
16
+ subject.configure
17
+ Approval.new.should belong_to(:owner)
18
+ end
19
+
20
+ it 'uses the given approval :model' do
21
+ class FakeApproval < ActiveRecord::Base; end
22
+ FakeApproval.should_receive(:include).with(ActsAsApprovable::Ownership)
23
+ subject.configure(:model => FakeApproval)
24
+ end
25
+
26
+ it 'uses the given :owner' do
27
+ class FakeUser; end
28
+ ActsAsApprovable.should_receive(:owner_class=).with(FakeUser)
29
+ subject.configure(:owner => FakeUser)
30
+ end
31
+
32
+ it 'applies the provided block' do
33
+ Approval.should_receive(:class_exec)
34
+ subject.configure {}
35
+ end
36
+ end
37
+
38
+ describe '.included' do
39
+ before(:all) do
40
+ class IncludedOwnership; include ActsAsApprovable::Ownership; end
41
+ end
42
+
43
+ it 'should extend ClassMethods' do
44
+ IncludedOwnership.should extend(ActsAsApprovable::Ownership::ClassMethods)
45
+ end
46
+
47
+ it 'should extend InstanceMethods' do
48
+ IncludedOwnership.should extend(ActsAsApprovable::Ownership::InstanceMethods)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsApprovable do
4
+ it { should respond_to(:owner_class) }
5
+ it { should respond_to(:owner_class=) }
6
+ it { should respond_to(:view_language) }
7
+ it { should respond_to(:view_language=) }
8
+
9
+ describe '.enabled?' do
10
+ it 'returns true by default' do
11
+ subject.enabled?.should be_true
12
+ end
13
+ end
14
+
15
+ describe '.disable' do
16
+ it 'disables the approval queue' do
17
+ subject.disable
18
+ subject.enabled?.should be_false
19
+ end
20
+ end
21
+
22
+ describe '.enable' do
23
+ it 'enables the approval queue' do
24
+ subject.enable
25
+ subject.enabled?.should be_true
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,51 @@
1
+ if RUBY_VERSION =~ /^1\.9/
2
+ begin
3
+ require 'simplecov'
4
+ SimpleCov.start do
5
+ add_filter '/spec/'
6
+ end if ENV['COVERAGE']
7
+ rescue LoadError
8
+ end
9
+ end
10
+
11
+ ENV['RAILS_ENV'] = 'test'
12
+ ENV['RAILS_ROOT'] ||= File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..'))
13
+
14
+ require 'rspec'
15
+ require 'shoulda'
16
+ require 'timecop'
17
+ require 'active_record'
18
+
19
+ begin
20
+ require 'plymouth'
21
+ rescue LoadError
22
+ end
23
+
24
+ require File.expand_path('../lib/acts-as-approvable', File.dirname(__FILE__))
25
+
26
+ require File.expand_path('support/database', File.dirname(__FILE__))
27
+ require File.expand_path('support/models', File.dirname(__FILE__))
28
+ require File.expand_path('support/matchers', File.dirname(__FILE__))
29
+
30
+ RSpec.configure do |config|
31
+ config.before(:suite) do
32
+ LOGGER = Support::Database.setup_log unless defined?(LOGGER)
33
+ Support::Database.load_schema
34
+ end
35
+
36
+ config.before(:each) do
37
+ Object.send(:remove_const, :CleanApprovable) if defined?(CleanApprovable)
38
+ class CleanApprovable < ActiveRecord::Base
39
+ def self.table_name; 'nots'; end
40
+ def self.primary_key; 'id'; end
41
+ end
42
+
43
+ freeze_at = Time.parse('2012-01-01')
44
+ Timecop.freeze(freeze_at)
45
+ end
46
+
47
+ config.after(:each) do
48
+ Timecop.return
49
+ Support::Database.truncate
50
+ end
51
+ end