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.
- data/.gitignore +2 -5
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Appraisals +14 -10
- data/CHANGELOG +16 -0
- data/Gemfile.lock +60 -20
- data/README.md +1 -2
- data/Rakefile +44 -16
- data/VERSION +1 -1
- data/acts-as-approvable.gemspec +21 -11
- data/features/create_approval.feature +26 -0
- data/features/step_definitions/cucumber_steps.rb +86 -0
- data/features/support/env.rb +14 -0
- data/features/support/large.txt +29943 -0
- data/features/support/second_large.txt +31798 -0
- data/features/update_approval.feature +34 -0
- data/gemfiles/Gemfile.ci +14 -0
- data/gemfiles/Gemfile.ci.lock +98 -0
- data/gemfiles/mysql2.gemfile +7 -0
- data/gemfiles/mysql2.gemfile.lock +92 -0
- data/gemfiles/rails2.gemfile +1 -0
- data/gemfiles/rails2.gemfile.lock +59 -17
- data/gemfiles/rails30.gemfile +1 -0
- data/gemfiles/rails30.gemfile.lock +54 -14
- data/gemfiles/rails31.gemfile +1 -0
- data/gemfiles/rails31.gemfile.lock +54 -14
- data/gemfiles/sqlite.gemfile +7 -0
- data/generators/acts_as_approvable/templates/create_approvals.rb +8 -7
- data/lib/acts-as-approvable.rb +2 -3
- data/lib/acts_as_approvable/approval.rb +3 -2
- data/lib/acts_as_approvable/model.rb +55 -0
- data/lib/acts_as_approvable/model/class_methods.rb +63 -0
- data/lib/acts_as_approvable/model/create_instance_methods.rb +83 -0
- data/lib/acts_as_approvable/model/instance_methods.rb +89 -0
- data/lib/acts_as_approvable/model/update_instance_methods.rb +61 -0
- data/lib/acts_as_approvable/railtie.rb +1 -1
- data/lib/generators/acts_as_approvable/templates/create_approvals.rb +8 -7
- data/spec/acts_as_approvable/approval_spec.rb +475 -0
- data/spec/acts_as_approvable/model/class_methods_spec.rb +219 -0
- data/spec/acts_as_approvable/model/create_instance_methods_spec.rb +149 -0
- data/spec/acts_as_approvable/model/instance_methods_spec.rb +328 -0
- data/spec/acts_as_approvable/model/update_instance_methods_spec.rb +111 -0
- data/spec/acts_as_approvable/model_spec.rb +90 -0
- data/spec/acts_as_approvable/ownership/class_methods_spec.rb +101 -0
- data/spec/acts_as_approvable/ownership/instance_methods_spec.rb +32 -0
- data/spec/acts_as_approvable/ownership_spec.rb +51 -0
- data/spec/acts_as_approvable_spec.rb +29 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/support/database.rb +46 -0
- data/spec/support/database.yml +12 -0
- data/spec/support/matchers.rb +87 -0
- data/spec/support/models.rb +60 -0
- data/{test → spec/support}/schema.rb +15 -9
- metadata +156 -53
- data/gemfiles/rails32.gemfile +0 -8
- data/gemfiles/rails32.gemfile.lock +0 -99
- data/lib/acts_as_approvable/acts_as_approvable.rb +0 -291
- data/test/acts_as_approvable_model_test.rb +0 -459
- data/test/acts_as_approvable_ownership_test.rb +0 -132
- data/test/acts_as_approvable_schema_test.rb +0 -13
- data/test/acts_as_approvable_test.rb +0 -8
- data/test/database.yml +0 -7
- data/test/support.rb +0 -19
- 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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|