1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
|
RSpec.shared_examples "an observer set" do
let (:observer_set) { described_class.new }
let (:observer) { double('observer') }
let (:another_observer) { double('another observer') }
describe '#add_observer' do
context 'with arguments' do
it 'should return the observer' do
expect(observer_set.add_observer(observer, :a_method)).to eq(observer)
end
end
context 'with a block' do
it 'should return the observer based on a block' do
observer = observer_set.add_observer { :block }
expect(observer.call).to eq(:block)
end
end
end
describe '#notify_observers' do
it 'should return the observer set' do
expect(observer_set.notify_observers).to be(observer_set)
end
context 'with a single observer' do
it 'should update a registered observer without arguments' do
expect(observer).to receive(:update).with(no_args)
observer_set.add_observer(observer)
observer_set.notify_observers
end
it 'should update a registered observer with arguments' do
expect(observer).to receive(:update).with(1, 2, 3)
observer_set.add_observer(observer)
observer_set.notify_observers(1, 2, 3)
end
it 'should notify an observer using the chosen method' do
expect(observer).to receive(:another_method).with('a string arg')
observer_set.add_observer(observer, :another_method)
observer_set.notify_observers('a string arg')
end
it 'should notify an observer once using the last added method' do
expect(observer).to receive(:another_method).with(any_args).never
expect(observer).to receive(:yet_another_method).with('a string arg')
observer_set.add_observer(observer, :another_method)
observer_set.add_observer(observer, :yet_another_method)
observer_set.notify_observers('a string arg')
end
it 'should notify an observer from a block' do
notification = double
expect(notification).to receive(:catch)
observer_set.add_observer {|arg| arg.catch }
observer_set.notify_observers notification
end
it 'can be called many times' do
expect(observer).to receive(:update).with(:an_arg).twice
expect(observer).to receive(:update).with(no_args).once
observer_set.add_observer(observer)
observer_set.notify_observers(:an_arg)
observer_set.notify_observers
observer_set.notify_observers(:an_arg)
end
end
context 'with many observers' do
it 'should notify all observer using the chosen method' do
expect(observer).to receive(:a_method).with(4, 'a')
expect(another_observer).to receive(:update).with(4, 'a')
observer_set.add_observer(observer, :a_method)
observer_set.add_observer(another_observer)
observer_set.notify_observers(4, 'a')
end
end
context 'with a block' do
before(:each) do
allow(observer).to receive(:update).with(any_args)
allow(another_observer).to receive(:update).with(any_args)
end
it 'calls the block once for every observer' do
counter = double('block call counter')
expect(counter).to receive(:called).with(no_args).exactly(2).times
observer_set.add_observer(observer)
observer_set.add_observer(another_observer)
observer_set.notify_observers{ counter.called }
end
it 'passes the block return value to the update method' do
expect(observer).to receive(:update).with(1, 2, 3, 4)
observer_set.add_observer(observer)
observer_set.notify_observers{ [1, 2, 3, 4] }
end
it 'accepts blocks returning a single value' do
expect(observer).to receive(:update).with(:foo)
observer_set.add_observer(observer)
observer_set.notify_observers{ :foo }
end
it 'accepts block return values that include arrays' do
expect(observer).to receive(:update).with(1, [2, 3], 4)
observer_set.add_observer(observer)
observer_set.notify_observers{ [1, [2, 3], 4] }
end
it 'raises an exception if given both arguments and a block' do
observer_set.add_observer(observer)
expect {
observer_set.notify_observers(1, 2, 3, 4){ nil }
}.to raise_error(ArgumentError)
end
end
end
context '#count_observers' do
it 'should be zero after initialization' do
expect(observer_set.count_observers).to eq 0
end
it 'should be 1 after the first observer is added' do
observer_set.add_observer(observer)
expect(observer_set.count_observers).to eq 1
end
it 'should be 1 if the same observer is added many times' do
observer_set.add_observer(observer)
observer_set.add_observer(observer, :another_method)
observer_set.add_observer(observer, :yet_another_method)
expect(observer_set.count_observers).to eq 1
end
it 'should be equal to the number of unique observers' do
observer_set.add_observer(observer)
observer_set.add_observer(another_observer)
observer_set.add_observer(double('observer 3'))
observer_set.add_observer(double('observer 4'))
expect(observer_set.count_observers).to eq 4
end
end
describe '#delete_observer' do
it 'should not notify a deleted observer' do
expect(observer).to receive(:update).never
observer_set.add_observer(observer)
observer_set.delete_observer(observer)
observer_set.notify_observers
end
it 'can delete a non added observer' do
observer_set.delete_observer(observer)
end
it 'should return the observer' do
expect(observer_set.delete_observer(observer)).to be(observer)
end
end
describe '#delete_observers' do
it 'should remove all observers' do
expect(observer).to receive(:update).never
expect(another_observer).to receive(:update).never
observer_set.add_observer(observer)
observer_set.add_observer(another_observer)
observer_set.delete_observers
observer_set.notify_observers
end
it 'should return the observer set' do
expect(observer_set.delete_observers).to be(observer_set)
end
end
describe '#notify_and_delete_observers' do
before(:each) do
observer_set.add_observer(observer, :a_method)
observer_set.add_observer(another_observer)
expect(observer).to receive(:a_method).with('args').once
expect(another_observer).to receive(:update).with('args').once
end
it 'should notify all observers' do
observer_set.notify_and_delete_observers('args')
end
it 'should clear observers' do
observer_set.notify_and_delete_observers('args')
expect(observer_set.count_observers).to eq(0)
end
it 'can be called many times without any other notification' do
observer_set.notify_and_delete_observers('args')
observer_set.notify_and_delete_observers('args')
observer_set.notify_and_delete_observers('args')
end
it 'should return the observer set' do
expect(observer_set.notify_and_delete_observers('args')).to be(observer_set)
end
end
end
|