save_queue 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +13 -4
- data/.travis.yml +4 -1
- data/CONTRIBUTING.md +120 -0
- data/HISTORY.md +11 -0
- data/LICENSE +13 -4
- data/README.md +282 -55
- data/Rakefile +10 -3
- data/lib/save_queue/exceptions.rb +13 -0
- data/lib/save_queue/object.rb +41 -18
- data/lib/save_queue/object_queue.rb +87 -0
- data/lib/save_queue/plugins/notification/object.rb +35 -0
- data/lib/save_queue/plugins/notification/queue.rb +25 -0
- data/lib/save_queue/plugins/notification.rb +15 -0
- data/lib/save_queue/plugins/validation/exceptions.rb +12 -0
- data/lib/save_queue/plugins/validation/queue.rb +16 -17
- data/lib/save_queue/plugins/validation.rb +4 -17
- data/lib/save_queue/ruby1.9/observer.rb +204 -0
- data/lib/save_queue/uniq_queue.rb +38 -0
- data/lib/save_queue/version.rb +1 -1
- data/lib/save_queue.rb +1 -0
- data/save_queue.gemspec +4 -3
- data/spec/notification/notification_spec.rb +45 -0
- data/spec/notification/object_spec.rb +54 -0
- data/spec/notification/queue_spec.rb +28 -0
- data/spec/object_queue_spec.rb +155 -0
- data/spec/object_spec.rb +208 -0
- data/spec/save_queue_spec.rb +75 -0
- data/spec/support/object_helpers.rb +10 -0
- data/spec/support/queue_helpers.rb +26 -0
- data/spec/uniq_queue_spec.rb +132 -0
- data/spec/validation/queue_spec.rb +139 -0
- data/spec/validation/validation_spec.rb +42 -0
- metadata +35 -20
- data/lib/save_queue/plugins/validation/object.rb +0 -25
- data/lib/save_queue/queue.rb +0 -45
- data/spec/save_queue_usage_spec.rb +0 -311
- data/spec/support/mock_helpers.rb +0 -17
- data/spec/validation_spec.rb +0 -126
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "save_queue/plugins/notification/object"
|
3
|
+
|
4
|
+
class NotifyObject
|
5
|
+
include SaveQueue
|
6
|
+
include SaveQueue::Plugins::Notification::Object
|
7
|
+
end
|
8
|
+
|
9
|
+
describe SaveQueue::Plugins::Notification::Object do
|
10
|
+
|
11
|
+
it "should register observer on queue to #queue_changed_event method" do
|
12
|
+
NotifyObject.queue_class.any_instance.should_receive(:add_observer).with do |observer, method|
|
13
|
+
observer.is_a?(NotifyObject) and method == :queue_changed_event
|
14
|
+
end
|
15
|
+
NotifyObject.new
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:queue) do
|
19
|
+
queue_class = Class.new
|
20
|
+
queue_class.stub(:include?).with(Hooks).and_return(true)
|
21
|
+
|
22
|
+
queue_class
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should raise an exception if queue does not respond to #add_observer" do
|
26
|
+
queue.any_instance.stub(:respond_to?).with(:add_observer).and_return(false)
|
27
|
+
NotifyObject.queue_class = queue
|
28
|
+
expect { NotifyObject.new }.to raise_error(RuntimeError, /add_observer/)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should not raise an exception if queue respond to #add_observer" do
|
32
|
+
queue.any_instance.stub(:respond_to?).with(:add_observer).and_return(true)
|
33
|
+
queue.any_instance.stub(:add_observer)
|
34
|
+
NotifyObject.queue_class = queue
|
35
|
+
expect { NotifyObject.new }.to_not raise_error
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#queue_changed_event" do
|
39
|
+
let(:object) do
|
40
|
+
NotifyObject.any_instance.stub(:create_queue)
|
41
|
+
NotifyObject.new
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should mark self as changed" do
|
45
|
+
object.should_receive(:mark_as_changed)
|
46
|
+
object.send :queue_changed_event, true, stub(:some_object)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not mark self as changed if result of adding element to a queue was false" do
|
50
|
+
object.should_not_receive(:mark_as_changed)
|
51
|
+
object.send :queue_changed_event, false, stub(:some_object)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "save_queue/plugins/notification/queue"
|
3
|
+
|
4
|
+
class NotifyQueue < SaveQueue::ObjectQueue
|
5
|
+
include SaveQueue::Plugins::Notification::Queue
|
6
|
+
end
|
7
|
+
|
8
|
+
describe SaveQueue::Plugins::Notification::Queue do
|
9
|
+
let(:queue) { NotifyQueue.new }
|
10
|
+
|
11
|
+
[:add, :<<, :push].each do |method|
|
12
|
+
describe "##{method}" do
|
13
|
+
let(:element) { new_element }
|
14
|
+
|
15
|
+
it "should notify observers about change" do
|
16
|
+
queue.should_receive(:changed)
|
17
|
+
queue.should_receive(:notify_observers)
|
18
|
+
queue.send method, element
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should notify observer, provided result of a method call and input object" do
|
22
|
+
queue.should_receive(:changed)
|
23
|
+
queue.should_receive(:notify_observers).with(true, element)
|
24
|
+
queue.send method, element
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "save_queue/object_queue"
|
3
|
+
|
4
|
+
describe SaveQueue::ObjectQueue do
|
5
|
+
let(:queue) { SaveQueue::ObjectQueue.new }
|
6
|
+
let(:element) { new_element(:element) }
|
7
|
+
|
8
|
+
[:add, :<<, :push].each do |method|
|
9
|
+
describe "##{method}" do
|
10
|
+
#it "should add only objects that implement SaveQueue::Object interface" do
|
11
|
+
it "should accept objects that respond to #save and #has_unsaved_changes?" do
|
12
|
+
element = stub(:element, :save => true, :has_unsaved_changes? => true)
|
13
|
+
expect{ queue.send method, element }.not_to raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should not accept objects that does not respond to #save" do
|
17
|
+
element.unstub(:save)
|
18
|
+
expect{ queue.send method, element }.to raise_error ArgumentError, "#{element.inspect} does not respond to #save"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not accept objects that does not respond to #has_unsaved_changes?" do
|
22
|
+
element.unstub(:has_unsaved_changes?)
|
23
|
+
expect{ queue.send method, element }.to raise_error ArgumentError, "#{element.inspect} does not respond to #has_unsaved_changes?"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "#<< method should be able to add objects in chain" do
|
29
|
+
queue << new_element << new_element
|
30
|
+
queue.should have(2).elements
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#save" do
|
34
|
+
it "should save all object in queue" do
|
35
|
+
5.times do
|
36
|
+
element = stub(:element, :has_unsaved_changes? => true)
|
37
|
+
element.should_receive(:save).once
|
38
|
+
queue << element
|
39
|
+
end
|
40
|
+
|
41
|
+
queue.save
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should save an object if it has unsaved changes" do
|
45
|
+
element = stub(:element)
|
46
|
+
element.stub(:has_unsaved_changes?).and_return(true)
|
47
|
+
element.should_receive(:save).once
|
48
|
+
|
49
|
+
queue << element
|
50
|
+
queue.save
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not save an object if it has not been changed" do
|
54
|
+
element = stub(:element)
|
55
|
+
element.stub(:has_unsaved_changes?).and_return(false)
|
56
|
+
element.should_not_receive(:save)
|
57
|
+
|
58
|
+
queue << element
|
59
|
+
queue.save
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should save an object if it has changed state after been added to a queue" do
|
63
|
+
element = new_element(:element, :changed => false, :saved => true)
|
64
|
+
|
65
|
+
queue << element
|
66
|
+
|
67
|
+
element.stub(:has_unsaved_changes?).and_return(true)
|
68
|
+
|
69
|
+
element.should_receive(:save).once.and_return(true)
|
70
|
+
queue.save
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "at least one object in queue was not saved" do
|
75
|
+
before(:each) do
|
76
|
+
@objects ={}
|
77
|
+
queue << @objects[:valid1] = new_element(:valid1)
|
78
|
+
queue << @objects[:valid2] = new_element(:valid2)
|
79
|
+
queue << @objects[:not_changed] = new_element(:not_changed, :changed => false, :saved => true)
|
80
|
+
queue << @objects[:unsaved_but_changed] = new_element(:unsaved_but_changed, :changed => true, :saved => false)
|
81
|
+
queue << @objects[:saved] = new_element(:saved, :changed => true, :saved => true)
|
82
|
+
queue << @objects[:valid3] = new_element(:valid3)
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#save!" do
|
86
|
+
it "should set errors" do
|
87
|
+
expect {queue.save!}.to raise_error
|
88
|
+
|
89
|
+
queue.errors[:save].should_not be_empty
|
90
|
+
queue.errors.should eq :save => { :processed => @objects.values_at(:valid1, :valid2, :not_changed),
|
91
|
+
:saved => @objects.values_at(:valid1, :valid2),
|
92
|
+
:failed => @objects[:unsaved_but_changed],
|
93
|
+
:pending => @objects.values_at(:not_changed, :saved, :valid3) }
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should raise SaveQueue::FailedSaveError" do
|
97
|
+
expect{ queue.save! }.to raise_error(SaveQueue::FailedSaveError) {|error| \
|
98
|
+
error.context.should == { :processed => @objects.values_at(:valid1, :valid2, :not_changed),
|
99
|
+
:saved => @objects.values_at(:valid1, :valid2),
|
100
|
+
:failed => @objects[:unsaved_but_changed],
|
101
|
+
:pending => @objects.values_at(:not_changed, :saved, :valid3) }
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#save" do
|
107
|
+
it "should return false" do
|
108
|
+
queue.save.should be_false
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should set errors" do
|
112
|
+
queue.save
|
113
|
+
|
114
|
+
queue.errors[:save].should_not be_empty
|
115
|
+
queue.errors.should eq :save => { :processed => @objects.values_at(:valid1, :valid2, :not_changed),
|
116
|
+
:saved => @objects.values_at(:valid1, :valid2),
|
117
|
+
:failed => @objects[:unsaved_but_changed],
|
118
|
+
:pending => @objects.values_at(:not_changed, :saved, :valid3) }
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should not raise SaveQueue::FailedSaveError" do
|
122
|
+
expect{ queue.save }.not_to raise_error(SaveQueue::FailedSaveError)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "after fixing all failed objects" do
|
127
|
+
before(:each) do
|
128
|
+
queue.save.should be_false
|
129
|
+
@objects[:unsaved_but_changed].stub(:save).and_return(true)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should save all pending objects" do
|
133
|
+
@objects.values_at(:saved, :valid3).each do |object|
|
134
|
+
object.should_receive(:save).once
|
135
|
+
end
|
136
|
+
|
137
|
+
queue.save.should be_true
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should not save already saved objects" do
|
141
|
+
pending "rewrite this test as integration"
|
142
|
+
@objects.values_at(:valid1, :valid2, :not_changed).each do |object|
|
143
|
+
object.should_not_receive(:save)
|
144
|
+
end
|
145
|
+
|
146
|
+
queue.save.should be_true
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should not have any errors" do
|
150
|
+
queue.save
|
151
|
+
queue.errors.should be_empty
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
data/spec/object_spec.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "save_queue/object"
|
3
|
+
|
4
|
+
describe SaveQueue::Object do
|
5
|
+
let(:object) { new_object }
|
6
|
+
|
7
|
+
describe "#has_unsaved_changes?" do
|
8
|
+
it "should return true for changed object" do
|
9
|
+
object.mark_as_changed
|
10
|
+
object.should have_unsaved_changes
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return false for unchanged object" do
|
14
|
+
object.mark_as_saved
|
15
|
+
object.should_not have_unsaved_changes
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return false for new object" do
|
19
|
+
klass = Class.new
|
20
|
+
klass.send :include, SaveQueue::Object
|
21
|
+
|
22
|
+
klass.new.should_not have_unsaved_changes
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "marks" do
|
27
|
+
it "should change state of an object" do
|
28
|
+
object.mark_as_saved
|
29
|
+
object.should_not have_unsaved_changes
|
30
|
+
object.mark_as_changed
|
31
|
+
object.should have_unsaved_changes
|
32
|
+
object.mark_as_saved
|
33
|
+
object.should_not have_unsaved_changes
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#save!" do
|
38
|
+
it "should delegate to save" do
|
39
|
+
object.save_queue.should_receive(:save!).once
|
40
|
+
object.save!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#save" do
|
45
|
+
it "should save queue" do
|
46
|
+
object.save_queue.should_receive(:save).once
|
47
|
+
object.save
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should save itself" do
|
51
|
+
klass = Class.new do
|
52
|
+
def save
|
53
|
+
"saved!"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
klass.send :include, SaveQueue::Object
|
58
|
+
klass.new.save.should == "saved!"
|
59
|
+
end
|
60
|
+
|
61
|
+
context "object could not be saved" do
|
62
|
+
let(:object) do
|
63
|
+
klass = Class.new do
|
64
|
+
def save
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
klass.send :include, SaveQueue::Object
|
69
|
+
klass.new
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return false" do
|
73
|
+
object.save.should == false
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should not save queue" do
|
77
|
+
object.save_queue.should_not_receive(:save)
|
78
|
+
object.save
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
it "should not circle" do
|
84
|
+
other_object = new_object
|
85
|
+
|
86
|
+
object.mark_as_changed
|
87
|
+
other_object.mark_as_changed
|
88
|
+
|
89
|
+
|
90
|
+
object .save_queue.add other_object
|
91
|
+
other_object.save_queue.add object
|
92
|
+
|
93
|
+
$object_counter = mock :counter
|
94
|
+
$object_counter.should_receive(:increment).once
|
95
|
+
|
96
|
+
def object.save
|
97
|
+
result = super
|
98
|
+
$object_counter.increment
|
99
|
+
|
100
|
+
result
|
101
|
+
end
|
102
|
+
|
103
|
+
$other_object_counter = mock :counter
|
104
|
+
$other_object_counter.should_receive(:increment).once
|
105
|
+
|
106
|
+
def other_object.save
|
107
|
+
result = super
|
108
|
+
$other_object_counter.increment
|
109
|
+
|
110
|
+
result
|
111
|
+
end
|
112
|
+
|
113
|
+
#object.should_receive(:save).once.and_return(true)
|
114
|
+
#@base.should_receive(:save).once.and_return(true)
|
115
|
+
other_object.save.should be_true
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "multiple queues" do
|
119
|
+
let(:other_object) { new_object }
|
120
|
+
|
121
|
+
it "should save object only once" do
|
122
|
+
target = new_object
|
123
|
+
target.mark_as_changed
|
124
|
+
|
125
|
+
object .save_queue.add target
|
126
|
+
other_object.save_queue.add target
|
127
|
+
|
128
|
+
$counter = mock :counter
|
129
|
+
$counter.should_receive(:increment).once
|
130
|
+
|
131
|
+
def target.save
|
132
|
+
result = super
|
133
|
+
$counter.increment
|
134
|
+
|
135
|
+
result
|
136
|
+
end
|
137
|
+
|
138
|
+
#target.should_receive(:save).once.and_return(true)
|
139
|
+
object.save.should be_true
|
140
|
+
other_object.save.should be_true
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "queue" do
|
146
|
+
let(:queue_class) { Class.new(SaveQueue::ObjectQueue) }
|
147
|
+
let(:other_queue_class) { Class.new(SaveQueue::ObjectQueue) }
|
148
|
+
|
149
|
+
it "should mapped to SaveQueue::ObjectQueue by default" do
|
150
|
+
klass = new_class
|
151
|
+
klass.queue_class.should be SaveQueue::ObjectQueue
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "queue class change" do
|
155
|
+
it "before initialization should be possible" do
|
156
|
+
klass = new_class
|
157
|
+
klass.queue_class = other_queue_class
|
158
|
+
klass.new.save_queue.should be_kind_of other_queue_class
|
159
|
+
end
|
160
|
+
|
161
|
+
it "after initialization should not affect already created queue" do
|
162
|
+
klass = new_class
|
163
|
+
klass.queue_class = queue_class
|
164
|
+
object = klass.new
|
165
|
+
|
166
|
+
object.save_queue.should be_a queue_class
|
167
|
+
object.class.queue_class = other_queue_class
|
168
|
+
object.save_queue.should_not be_kind_of other_queue_class
|
169
|
+
object.save_queue.should be_a queue_class
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should check dependencies for Hooks module" do
|
173
|
+
klass = new_class
|
174
|
+
expect{ klass.queue_class = Class.new }.to raise_error(RuntimeError, /Hooks/)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "inheritance" do
|
179
|
+
let(:klass) { new_class }
|
180
|
+
|
181
|
+
it "should inherit settings of parent class" do
|
182
|
+
klass.queue_class = queue_class
|
183
|
+
|
184
|
+
child = Class.new(klass)
|
185
|
+
child.queue_class.should == queue_class
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should not override settings of parent class" do
|
189
|
+
klass.queue_class = queue_class
|
190
|
+
|
191
|
+
child = Class.new(klass)
|
192
|
+
child.queue_class = other_queue_class
|
193
|
+
child.queue_class.should == other_queue_class
|
194
|
+
|
195
|
+
klass.queue_class.should == queue_class
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
it "include SaveQueue::Object should not override settings of parent class" do
|
200
|
+
klass.queue_class = queue_class
|
201
|
+
|
202
|
+
child = Class.new(klass)
|
203
|
+
child.send :include, SaveQueue::Object
|
204
|
+
child.queue_class.should == queue_class
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "save_queue/object"
|
3
|
+
|
4
|
+
describe SaveQueue do
|
5
|
+
describe "#include" do
|
6
|
+
it "should include SaveQueue::Object" do
|
7
|
+
klass = Class.new
|
8
|
+
klass.send :include, SaveQueue
|
9
|
+
|
10
|
+
klass.should include SaveQueue::Object
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "functional" do
|
15
|
+
it "README example should work" do
|
16
|
+
article = Article.new
|
17
|
+
|
18
|
+
tag_objects = []
|
19
|
+
3.times do
|
20
|
+
tag = Tag.new
|
21
|
+
tag.change_attribute :title, "new tag"
|
22
|
+
tag.should_receive(:save).once
|
23
|
+
tag_objects << tag
|
24
|
+
end
|
25
|
+
article.tags = tag_objects
|
26
|
+
|
27
|
+
tag = Tag.new
|
28
|
+
tag.change_attribute :title, "single tag"
|
29
|
+
tag.should_receive(:save).once
|
30
|
+
article.add_tag tag
|
31
|
+
|
32
|
+
# that will save article and all tags in this article if article
|
33
|
+
# and tags are valid, and if article.save and all tag.save returns true
|
34
|
+
# You may also use #save! method, that will trigger save_queue.save! and
|
35
|
+
# raise SaveQueue::FailedSaveError on fail
|
36
|
+
article.save.should be_true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
require 'save_queue'
|
44
|
+
class Article
|
45
|
+
include SaveQueue
|
46
|
+
|
47
|
+
def change_attribute attr, value
|
48
|
+
@attributes ||= {}
|
49
|
+
@attributes[attr] = value
|
50
|
+
mark_as_changed # call this and object will be marked for save
|
51
|
+
end
|
52
|
+
|
53
|
+
def tags= tag_objects
|
54
|
+
@tags = tag_objects
|
55
|
+
mark_as_changed
|
56
|
+
save_queue.add_all tag_objects
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_tag tag
|
60
|
+
@tags ||= []
|
61
|
+
@tags << tag
|
62
|
+
save_queue.add tag # or use <<, push methods
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
class Tag
|
68
|
+
include SaveQueue
|
69
|
+
|
70
|
+
def change_attribute attr, value
|
71
|
+
@attributes ||= {}
|
72
|
+
@attributes[attr] = value
|
73
|
+
mark_as_changed # call this and object will be marked for save
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
def fill_queue
|
2
|
+
5.times do
|
3
|
+
queue << new_element
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
def new_element(name = :element, options = {})
|
8
|
+
element = stub(name)
|
9
|
+
element.stub(:save).and_return(options.has_key?(:saved) ? options[:saved] : true)
|
10
|
+
element.stub(:has_unsaved_changes?).and_return(options.has_key?(:changed) ? options[:changed] : true)
|
11
|
+
|
12
|
+
element
|
13
|
+
end
|
14
|
+
|
15
|
+
def new_velement(options = {:valid => true})
|
16
|
+
object = new_element
|
17
|
+
object.stub(:valid?).and_return(options[:valid])
|
18
|
+
object
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_queue_class(options = {})
|
22
|
+
queue_class = Class.new
|
23
|
+
queue_class.stub(:include?).with(Hooks).and_return(true)
|
24
|
+
|
25
|
+
queue_class
|
26
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "save_queue/uniq_queue"
|
3
|
+
|
4
|
+
describe SaveQueue::UniqQueue do
|
5
|
+
let(:queue) { SaveQueue::UniqQueue.new }
|
6
|
+
#let(:element) { new_element(:element) }
|
7
|
+
|
8
|
+
[:size, :count].each do |method|
|
9
|
+
describe "##{method}" do
|
10
|
+
it "should return 0 for empty queue" do
|
11
|
+
queue.send(method).should be_zero
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should count elements in queue" do
|
15
|
+
3.times do
|
16
|
+
queue << new_element
|
17
|
+
end
|
18
|
+
|
19
|
+
queue.send(method).should == 3
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#new" do
|
25
|
+
it "should be empty queue" do
|
26
|
+
queue.should have(0).elements
|
27
|
+
queue.should be_empty
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
[:add, :<<, :push].each do |method|
|
32
|
+
describe "##{method}" do
|
33
|
+
let(:element) { new_element }
|
34
|
+
it "should add object to a queue" do
|
35
|
+
queue.should be_empty
|
36
|
+
|
37
|
+
queue.send(method, new_element)
|
38
|
+
queue.should_not be_empty
|
39
|
+
queue.should have(1).elements
|
40
|
+
|
41
|
+
queue.send(method, new_element)
|
42
|
+
queue.should_not be_empty
|
43
|
+
queue.should have(2).elements
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should add object to a queue once" do
|
47
|
+
queue.should be_empty
|
48
|
+
|
49
|
+
queue.send(method, element)
|
50
|
+
queue.should have(1).elements
|
51
|
+
|
52
|
+
queue.send(method, element)
|
53
|
+
queue.should have(1).elements
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should return true" do
|
57
|
+
queue.send(method, element).should === true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return false if element was not added" do
|
61
|
+
queue.send(method, element)
|
62
|
+
queue.should have(1).elements
|
63
|
+
|
64
|
+
queue.send(method, element).should === false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#add_all" do
|
70
|
+
it "should delegate to #add" do
|
71
|
+
queue.should_receive(:add).exactly(3).times
|
72
|
+
queue.add_all [1,2,3]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should act as #add if single argument passed" do
|
76
|
+
queue.should_receive(:add).once
|
77
|
+
queue.add_all 1
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
describe "#clear" do
|
83
|
+
it "should clear the queue" do
|
84
|
+
fill_queue
|
85
|
+
#expect{ queue.clear }.to change{ queue.count }.from(5).to(0)
|
86
|
+
queue.should_not be_empty
|
87
|
+
queue.clear
|
88
|
+
queue.should be_empty
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#pop" do
|
93
|
+
it "should remove last element from queue and return it back" do
|
94
|
+
queue << new_element(:first)
|
95
|
+
queue << new_element
|
96
|
+
queue << new_element
|
97
|
+
last = new_element(:last)
|
98
|
+
queue << last
|
99
|
+
|
100
|
+
result = nil
|
101
|
+
expect{ result = queue.pop }.to change{ queue.count }.by(-1)
|
102
|
+
result.should_not be_nil
|
103
|
+
result.should be last
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#shift" do
|
108
|
+
it "should remove first element from queue and return it back" do
|
109
|
+
first = new_element(:first)
|
110
|
+
queue << first
|
111
|
+
queue << new_element
|
112
|
+
queue << new_element
|
113
|
+
queue << new_element(:last)
|
114
|
+
|
115
|
+
result = nil
|
116
|
+
expect{ result = queue.shift }.to change{ queue.count }.by(-1)
|
117
|
+
result.should_not be_nil
|
118
|
+
result.should be first
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "delegates" do
|
123
|
+
let(:queue_var) { queue.instance_variable_get("@queue") }
|
124
|
+
|
125
|
+
SaveQueue::UniqQueue::DELEGATED_METHODS.each do |method|
|
126
|
+
it "##{method}\tshould delegate to @queue##{method}" do
|
127
|
+
queue_var.should_receive(method).once
|
128
|
+
queue.send method
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|