ably 0.8.15 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -4
- data/CHANGELOG.md +6 -2
- data/README.md +5 -1
- data/SPEC.md +1473 -852
- data/ably.gemspec +11 -8
- data/lib/ably/auth.rb +90 -53
- data/lib/ably/exceptions.rb +37 -8
- data/lib/ably/logger.rb +10 -1
- data/lib/ably/models/auth_details.rb +42 -0
- data/lib/ably/models/channel_state_change.rb +18 -4
- data/lib/ably/models/connection_details.rb +6 -3
- data/lib/ably/models/connection_state_change.rb +4 -3
- data/lib/ably/models/error_info.rb +1 -1
- data/lib/ably/models/message.rb +17 -1
- data/lib/ably/models/message_encoders/base.rb +103 -82
- data/lib/ably/models/message_encoders/base64.rb +1 -1
- data/lib/ably/models/presence_message.rb +16 -1
- data/lib/ably/models/protocol_message.rb +20 -3
- data/lib/ably/models/token_details.rb +11 -1
- data/lib/ably/models/token_request.rb +16 -6
- data/lib/ably/modules/async_wrapper.rb +7 -3
- data/lib/ably/modules/encodeable.rb +51 -12
- data/lib/ably/modules/enum.rb +17 -7
- data/lib/ably/modules/event_emitter.rb +29 -14
- data/lib/ably/modules/model_common.rb +13 -21
- data/lib/ably/modules/state_emitter.rb +7 -4
- data/lib/ably/modules/state_machine.rb +2 -4
- data/lib/ably/modules/uses_state_machine.rb +7 -3
- data/lib/ably/realtime.rb +2 -0
- data/lib/ably/realtime/auth.rb +102 -42
- data/lib/ably/realtime/channel.rb +68 -26
- data/lib/ably/realtime/channel/channel_manager.rb +154 -65
- data/lib/ably/realtime/channel/channel_state_machine.rb +14 -15
- data/lib/ably/realtime/client.rb +18 -3
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +38 -29
- data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +6 -1
- data/lib/ably/realtime/connection.rb +108 -49
- data/lib/ably/realtime/connection/connection_manager.rb +167 -61
- data/lib/ably/realtime/connection/connection_state_machine.rb +22 -3
- data/lib/ably/realtime/connection/websocket_transport.rb +19 -10
- data/lib/ably/realtime/presence.rb +70 -45
- data/lib/ably/realtime/presence/members_map.rb +201 -36
- data/lib/ably/realtime/presence/presence_manager.rb +30 -6
- data/lib/ably/realtime/presence/presence_state_machine.rb +5 -12
- data/lib/ably/rest.rb +2 -2
- data/lib/ably/rest/channel.rb +5 -5
- data/lib/ably/rest/client.rb +31 -27
- data/lib/ably/rest/middleware/exceptions.rb +1 -3
- data/lib/ably/rest/middleware/logger.rb +2 -2
- data/lib/ably/rest/presence.rb +2 -2
- data/lib/ably/util/pub_sub.rb +1 -1
- data/lib/ably/util/safe_deferrable.rb +26 -0
- data/lib/ably/version.rb +2 -2
- data/spec/acceptance/realtime/auth_spec.rb +470 -111
- data/spec/acceptance/realtime/channel_history_spec.rb +5 -3
- data/spec/acceptance/realtime/channel_spec.rb +1017 -168
- data/spec/acceptance/realtime/client_spec.rb +6 -6
- data/spec/acceptance/realtime/connection_failures_spec.rb +458 -27
- data/spec/acceptance/realtime/connection_spec.rb +424 -105
- data/spec/acceptance/realtime/message_spec.rb +52 -23
- data/spec/acceptance/realtime/presence_history_spec.rb +5 -3
- data/spec/acceptance/realtime/presence_spec.rb +1110 -96
- data/spec/acceptance/rest/auth_spec.rb +222 -59
- data/spec/acceptance/rest/base_spec.rb +1 -1
- data/spec/acceptance/rest/channel_spec.rb +1 -2
- data/spec/acceptance/rest/client_spec.rb +104 -48
- data/spec/acceptance/rest/message_spec.rb +42 -15
- data/spec/acceptance/rest/presence_spec.rb +4 -11
- data/spec/rspec_config.rb +2 -1
- data/spec/shared/client_initializer_behaviour.rb +2 -2
- data/spec/shared/safe_deferrable_behaviour.rb +6 -2
- data/spec/spec_helper.rb +4 -2
- data/spec/support/debug_failure_helper.rb +20 -4
- data/spec/support/event_machine_helper.rb +32 -1
- data/spec/unit/auth_spec.rb +4 -11
- data/spec/unit/logger_spec.rb +28 -2
- data/spec/unit/models/auth_details_spec.rb +49 -0
- data/spec/unit/models/channel_state_change_spec.rb +23 -3
- data/spec/unit/models/connection_details_spec.rb +12 -1
- data/spec/unit/models/connection_state_change_spec.rb +15 -4
- data/spec/unit/models/message_encoders/base64_spec.rb +2 -1
- data/spec/unit/models/message_spec.rb +153 -0
- data/spec/unit/models/presence_message_spec.rb +192 -0
- data/spec/unit/models/protocol_message_spec.rb +64 -6
- data/spec/unit/models/token_details_spec.rb +75 -0
- data/spec/unit/models/token_request_spec.rb +74 -0
- data/spec/unit/modules/async_wrapper_spec.rb +2 -1
- data/spec/unit/modules/enum_spec.rb +69 -0
- data/spec/unit/modules/event_emitter_spec.rb +149 -22
- data/spec/unit/modules/state_emitter_spec.rb +9 -3
- data/spec/unit/realtime/client_spec.rb +1 -1
- data/spec/unit/realtime/connection_spec.rb +8 -5
- data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +1 -1
- data/spec/unit/realtime/presence_spec.rb +4 -3
- data/spec/unit/rest/client_spec.rb +1 -1
- data/spec/unit/util/crypto_spec.rb +3 -3
- metadata +22 -19
@@ -146,4 +146,79 @@ describe Ably::Models::TokenDetails do
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
end
|
149
|
+
|
150
|
+
context 'from_json (#TD7)' do
|
151
|
+
let(:issued_time) { Time.now }
|
152
|
+
let(:expires_time) { Time.now + 24*60*60 }
|
153
|
+
let(:capabilities) { { '*' => ['publish'] } }
|
154
|
+
|
155
|
+
context 'with Ruby idiomatic Hash object' do
|
156
|
+
subject { Ably::Models::TokenDetails.from_json(token_details_object) }
|
157
|
+
|
158
|
+
let(:token_details_object) do
|
159
|
+
{
|
160
|
+
token: 'val1',
|
161
|
+
key_name: 'val2',
|
162
|
+
issued: issued_time.to_i * 1000,
|
163
|
+
expires: expires_time.to_i * 1000,
|
164
|
+
capability: capabilities,
|
165
|
+
client_id: 'val3'
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'returns a valid TokenDetails object' do
|
170
|
+
expect(subject.token).to eql('val1')
|
171
|
+
expect(subject.key_name).to eql('val2')
|
172
|
+
expect(subject.issued.to_f).to be_within(1).of(issued_time.to_f)
|
173
|
+
expect(subject.expires.to_f).to be_within(1).of(expires_time.to_f)
|
174
|
+
expect(subject.capability).to eql(capabilities)
|
175
|
+
expect(subject.client_id).to eql('val3')
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'with JSON-like object' do
|
180
|
+
subject { Ably::Models::TokenDetails.from_json(token_details_object) }
|
181
|
+
|
182
|
+
let(:token_details_object) do
|
183
|
+
{
|
184
|
+
'keyName' => 'val2',
|
185
|
+
'issued' => issued_time.to_i * 1000,
|
186
|
+
'expires' => expires_time.to_i * 1000,
|
187
|
+
'capability' => JSON.dump(capabilities),
|
188
|
+
'clientId' => 'val3'
|
189
|
+
}
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'returns a valid TokenDetails object' do
|
193
|
+
expect(subject.token).to be_nil
|
194
|
+
expect(subject.key_name).to eql('val2')
|
195
|
+
expect(subject.issued.to_f).to be_within(1).of(issued_time.to_f)
|
196
|
+
expect(subject.expires.to_f).to be_within(1).of(expires_time.to_f)
|
197
|
+
expect(subject.capability).to eql(capabilities)
|
198
|
+
expect(subject.client_id).to eql('val3')
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context 'with JSON string' do
|
203
|
+
subject { Ably::Models::TokenDetails.from_json(JSON.dump(token_details_object)) }
|
204
|
+
|
205
|
+
let(:token_details_object) do
|
206
|
+
{
|
207
|
+
'keyName' => 'val2',
|
208
|
+
'issued' => issued_time.to_i * 1000,
|
209
|
+
'expires' => expires_time.to_i * 1000,
|
210
|
+
'clientId' => 'val3'
|
211
|
+
}
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'returns a valid TokenDetails object' do
|
215
|
+
expect(subject.token).to be_nil
|
216
|
+
expect(subject.key_name).to eql('val2')
|
217
|
+
expect(subject.issued.to_f).to be_within(1).of(issued_time.to_f)
|
218
|
+
expect(subject.expires.to_f).to be_within(1).of(expires_time.to_f)
|
219
|
+
expect(subject.capability).to be_nil
|
220
|
+
expect(subject.client_id).to eql('val3')
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
149
224
|
end
|
@@ -107,4 +107,78 @@ describe Ably::Models::TokenRequest do
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
110
|
+
|
111
|
+
context 'from_json (#TE6)' do
|
112
|
+
let(:timestamp) { Time.now }
|
113
|
+
let(:capabilities) { { '*' => ['publish'] } }
|
114
|
+
let(:ttl_seconds) { 60 * 1000 }
|
115
|
+
|
116
|
+
context 'with Ruby idiomatic Hash object' do
|
117
|
+
subject { Ably::Models::TokenRequest.from_json(token_request_object) }
|
118
|
+
|
119
|
+
let(:token_request_object) do
|
120
|
+
{
|
121
|
+
nonce: 'val1',
|
122
|
+
key_name: 'val2',
|
123
|
+
ttl: ttl_seconds * 1000,
|
124
|
+
timestamp: timestamp.to_i * 1000,
|
125
|
+
capability: capabilities,
|
126
|
+
client_id: 'val3'
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'returns a valid TokenRequest object' do
|
131
|
+
expect(subject.nonce).to eql('val1')
|
132
|
+
expect(subject.key_name).to eql('val2')
|
133
|
+
expect(subject.timestamp.to_f).to be_within(1).of(timestamp.to_f)
|
134
|
+
expect(subject.ttl).to eql(ttl_seconds)
|
135
|
+
expect(subject.capability).to eql(capabilities)
|
136
|
+
expect(subject.client_id).to eql('val3')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'with JSON-like object' do
|
141
|
+
subject { Ably::Models::TokenRequest.from_json(token_request_object) }
|
142
|
+
|
143
|
+
let(:token_request_object) do
|
144
|
+
{
|
145
|
+
'keyName' => 'val2',
|
146
|
+
'ttl' => ttl_seconds * 1000,
|
147
|
+
'timestamp' => timestamp.to_i * 1000,
|
148
|
+
'clientId' => 'val3'
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'returns a valid TokenRequest object' do
|
153
|
+
expect { subject.nonce }.to raise_error(Ably::Exceptions::InvalidTokenRequest)
|
154
|
+
expect(subject.key_name).to eql('val2')
|
155
|
+
expect(subject.timestamp.to_f).to be_within(1).of(timestamp.to_f)
|
156
|
+
expect(subject.ttl).to eql(ttl_seconds)
|
157
|
+
expect { subject.capability }.to raise_error(Ably::Exceptions::InvalidTokenRequest)
|
158
|
+
expect(subject.client_id).to eql('val3')
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'with JSON string' do
|
163
|
+
subject { Ably::Models::TokenRequest.from_json(JSON.dump(token_request_object)) }
|
164
|
+
|
165
|
+
let(:token_request_object) do
|
166
|
+
{
|
167
|
+
'nonce' => 'val1',
|
168
|
+
'ttl' => ttl_seconds * 1000,
|
169
|
+
'capability' => JSON.dump(capabilities),
|
170
|
+
'clientId' => 'val3'
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'returns a valid TokenRequest object' do
|
175
|
+
expect(subject.nonce).to eql('val1')
|
176
|
+
expect { subject.key_name }.to raise_error(Ably::Exceptions::InvalidTokenRequest)
|
177
|
+
expect { subject.timestamp }.to raise_error(Ably::Exceptions::InvalidTokenRequest)
|
178
|
+
expect(subject.ttl).to eql(ttl_seconds)
|
179
|
+
expect(subject.capability).to eql(capabilities)
|
180
|
+
expect(subject.client_id).to eql('val3')
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
110
184
|
end
|
@@ -59,7 +59,8 @@ describe Ably::Modules::AsyncWrapper, :api_private do
|
|
59
59
|
subject.operation do |result|
|
60
60
|
raise 'Intentional exception'
|
61
61
|
end
|
62
|
-
expect(subject.logger).to receive(:error)
|
62
|
+
expect(subject.logger).to receive(:error) do |*args, &block|
|
63
|
+
expect(args.concat([block ? block.call : nil]).join(',')).to match(/Intentional exception/)
|
63
64
|
stop_reactor
|
64
65
|
end
|
65
66
|
end
|
@@ -41,6 +41,41 @@ describe Ably::Modules::Enum, :api_private do
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
context 'using include? to compare Enum values' do
|
45
|
+
subject { enum }
|
46
|
+
|
47
|
+
it 'allows same type comparison' do
|
48
|
+
expect([subject.ValueZero].include?(subject.ValueZero)).to eql(true)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'allows different type comparison 1' do
|
52
|
+
expect([subject.ValueZero].include?(:value_zero)).to eql(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'allows different type comparison 2' do
|
56
|
+
skip 'Unless we monkeypath Symbols, the == operator is never invoked'
|
57
|
+
expect([:value_zero].include?(subject.ValueZero)).to eql(true)
|
58
|
+
end
|
59
|
+
|
60
|
+
context '#match_any? replacement for include?' do
|
61
|
+
it 'matches any value in the arguments provided' do
|
62
|
+
expect(subject.ValueZero.match_any?(:value_foo, :value_zero)).to eql(true)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'returns false if there are no matches in any value in the arguments provided' do
|
66
|
+
expect(subject.ValueZero.match_any?(:value_x, :value_y)).to eql(false)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'class method #to_sym_arr' do
|
72
|
+
subject { enum }
|
73
|
+
|
74
|
+
it 'returns all keys as symbols' do
|
75
|
+
expect(enum.to_sym_arr).to contain_exactly(:value_zero, :value_1, :value_snake_case_2, :sentence_case)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
44
79
|
context 'defined Enum from Array class' do
|
45
80
|
subject { enum }
|
46
81
|
|
@@ -212,6 +247,40 @@ describe Ably::Modules::Enum, :api_private do
|
|
212
247
|
end
|
213
248
|
end
|
214
249
|
|
250
|
+
context 'two similar Enums with shared symbol values' do
|
251
|
+
class ExampleEnumOne
|
252
|
+
extend Ably::Modules::Enum
|
253
|
+
ENUMEXAMPLE = ruby_enum('ENUMEXAMPLE', :pear, :orange, :litchi, :apple)
|
254
|
+
end
|
255
|
+
|
256
|
+
class ExampleEnumTwo
|
257
|
+
extend Ably::Modules::Enum
|
258
|
+
ENUMEXAMPLE = ruby_enum('ENUMEXAMPLE', :pear, :grape, :apple)
|
259
|
+
end
|
260
|
+
|
261
|
+
let(:enum_one) { ExampleEnumOne::ENUMEXAMPLE }
|
262
|
+
let(:enum_two) { ExampleEnumTwo::ENUMEXAMPLE }
|
263
|
+
|
264
|
+
it 'provides compatability for the equivalent symbol values' do
|
265
|
+
expect(enum_one.Pear).to eq(enum_two.Pear)
|
266
|
+
expect(enum_two.Pear).to eq(enum_one.Pear)
|
267
|
+
expect(enum_one.Apple).to eq(enum_two.Apple)
|
268
|
+
expect(enum_two.Apple).to eq(enum_one.Apple)
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'does not consider different symbol values the same' do
|
272
|
+
expect(enum_one.Orange).to_not eq(enum_two.Grape)
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'matches symbols when used with a converter method' do
|
276
|
+
expect(ExampleEnumOne::ENUMEXAMPLE(enum_two.Pear)).to eq(:pear)
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'fails to match when using an incompatible method with a converter method' do
|
280
|
+
expect { ExampleEnumOne::ENUMEXAMPLE(enum_two.Grape) }.to raise_error KeyError
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
215
284
|
context 'Enum instance' do
|
216
285
|
context '#==' do
|
217
286
|
subject { enum.get(:value_snake_case_2) }
|
@@ -83,13 +83,13 @@ describe Ably::Modules::EventEmitter do
|
|
83
83
|
allow(obj).to receive(:received_message)
|
84
84
|
end
|
85
85
|
|
86
|
-
it 'is unaffected and processes the prior event callbacks once' do
|
86
|
+
it 'is unaffected and processes the prior event callbacks once (#RTE6b)' do
|
87
87
|
expect(obj).to receive(:received_message).with(msg).twice
|
88
88
|
expect(obj).to_not receive(:received_message_from_new_callbacks).with(msg)
|
89
89
|
subject.emit :message, msg
|
90
90
|
end
|
91
91
|
|
92
|
-
it 'adds them for the next emitted event' do
|
92
|
+
it 'adds them for the next emitted event (#RTE6b)' do
|
93
93
|
expect(obj).to receive(:received_message_from_new_callbacks).with(msg).twice
|
94
94
|
|
95
95
|
# New callbacks are added in this emit
|
@@ -110,12 +110,12 @@ describe Ably::Modules::EventEmitter do
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
-
it 'is unaffected and processes the prior event callbacks once' do
|
113
|
+
it 'is unaffected and processes the prior event callbacks once (#RTE6b)' do
|
114
114
|
expect(obj).to receive(:received_message).with(msg).twice
|
115
115
|
subject.emit :message, msg
|
116
116
|
end
|
117
117
|
|
118
|
-
it 'removes them for the next emitted event' do
|
118
|
+
it 'removes them for the next emitted event (#RTE6b)' do
|
119
119
|
expect(obj).to receive(:received_message).with(msg).twice
|
120
120
|
|
121
121
|
# Callbacks are removed in this emit
|
@@ -127,7 +127,7 @@ describe Ably::Modules::EventEmitter do
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
-
context '#on' do
|
130
|
+
context '#on (#RTE3)' do
|
131
131
|
context 'with event specified' do
|
132
132
|
it 'calls the block every time an event is emitted only' do
|
133
133
|
block_called = 0
|
@@ -137,7 +137,9 @@ describe Ably::Modules::EventEmitter do
|
|
137
137
|
end
|
138
138
|
|
139
139
|
it 'catches exceptions in the provided block, logs the error and continues' do
|
140
|
-
expect(subject.logger).to receive(:error)
|
140
|
+
expect(subject.logger).to receive(:error) do |*args, &block|
|
141
|
+
expect(args.concat([block ? block.call : nil]).join(',')).to match(/Intentional exception/)
|
142
|
+
end
|
141
143
|
subject.on(:event) { raise 'Intentional exception' }
|
142
144
|
subject.emit :event
|
143
145
|
end
|
@@ -152,7 +154,9 @@ describe Ably::Modules::EventEmitter do
|
|
152
154
|
end
|
153
155
|
|
154
156
|
it 'catches exceptions in the provided block, logs the error and continues' do
|
155
|
-
expect(subject.logger).to receive(:error)
|
157
|
+
expect(subject.logger).to receive(:error) do |*args, &block|
|
158
|
+
expect(args.concat([block ? block.call : nil]).join(',')).to match(/Intentional exception/)
|
159
|
+
end
|
156
160
|
subject.on { raise 'Intentional exception' }
|
157
161
|
subject.emit :event
|
158
162
|
end
|
@@ -173,7 +177,7 @@ describe Ably::Modules::EventEmitter do
|
|
173
177
|
end
|
174
178
|
end
|
175
179
|
|
176
|
-
context '#once' do
|
180
|
+
context '#once (#RTE4)' do
|
177
181
|
context 'with event specified' do
|
178
182
|
it 'calls the block the first time an event is emitted only' do
|
179
183
|
block_called = 0
|
@@ -191,7 +195,9 @@ describe Ably::Modules::EventEmitter do
|
|
191
195
|
end
|
192
196
|
|
193
197
|
it 'catches exceptions in the provided block, logs the error and continues' do
|
194
|
-
expect(subject.logger).to receive(:error)
|
198
|
+
expect(subject.logger).to receive(:error) do |*args, &block|
|
199
|
+
expect(args.concat([block ? block.call : nil]).join(',')).to match(/Intentional exception/)
|
200
|
+
end
|
195
201
|
subject.once(:event) { raise 'Intentional exception' }
|
196
202
|
subject.emit :event
|
197
203
|
end
|
@@ -214,7 +220,9 @@ describe Ably::Modules::EventEmitter do
|
|
214
220
|
end
|
215
221
|
|
216
222
|
it 'catches exceptions in the provided block, logs the error and continues' do
|
217
|
-
expect(subject.logger).to receive(:error)
|
223
|
+
expect(subject.logger).to receive(:error) do |*args, &block|
|
224
|
+
expect(args.concat([block ? block.call : nil]).join(',')).to match(/Intentional exception/)
|
225
|
+
end
|
218
226
|
subject.once { raise 'Intentional exception' }
|
219
227
|
subject.emit :event
|
220
228
|
end
|
@@ -248,12 +256,12 @@ describe Ably::Modules::EventEmitter do
|
|
248
256
|
end
|
249
257
|
|
250
258
|
context 'with event names as arguments' do
|
251
|
-
it 'deletes matching callbacks' do
|
259
|
+
it 'deletes matching callbacks when a block is provided' do
|
252
260
|
expect(obj).to_not receive(:received_message).with(msg)
|
253
261
|
subject.off(:message, &callback)
|
254
262
|
end
|
255
263
|
|
256
|
-
it 'deletes all callbacks
|
264
|
+
it 'deletes all matching callbacks when a block is not provided' do
|
257
265
|
expect(obj).to_not receive(:received_message).with(msg)
|
258
266
|
subject.off(:message)
|
259
267
|
end
|
@@ -277,18 +285,137 @@ describe Ably::Modules::EventEmitter do
|
|
277
285
|
end
|
278
286
|
end
|
279
287
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
288
|
+
context 'when on callback is configured for all events' do
|
289
|
+
before do
|
290
|
+
subject.on(&callback)
|
291
|
+
end
|
292
|
+
|
293
|
+
after do
|
294
|
+
subject.emit :message, msg
|
295
|
+
end
|
296
|
+
|
297
|
+
context 'with event names as arguments' do
|
298
|
+
it 'does not remove the all events callback when a block is provided' do
|
299
|
+
expect(obj).to receive(:received_message).with(msg)
|
300
|
+
subject.off(:message, &callback)
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'does not remove the all events callback when a block is not provided' do
|
304
|
+
expect(obj).to receive(:received_message).with(msg)
|
305
|
+
subject.off(:message)
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'does not remove the all events callback when the block does not match' do
|
309
|
+
expect(obj).to receive(:received_message).with(msg)
|
310
|
+
subject.off(:message) { true }
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'without any event names' do
|
315
|
+
it 'deletes all matching callbacks' do
|
316
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
317
|
+
subject.off(&callback)
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'deletes all callbacks if not block given' do
|
321
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
322
|
+
subject.off
|
323
|
+
end
|
324
|
+
end
|
285
325
|
end
|
286
326
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
327
|
+
context 'with unsafe_on subscribers' do
|
328
|
+
before do
|
329
|
+
subject.unsafe_on(&callback)
|
330
|
+
end
|
331
|
+
|
332
|
+
after do
|
333
|
+
subject.emit :message, msg
|
334
|
+
end
|
335
|
+
|
336
|
+
it 'does not deregister them' do
|
337
|
+
expect(obj).to receive(:received_message).with(msg)
|
338
|
+
subject.off
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
context 'with unsafe_once subscribers' do
|
343
|
+
before do
|
344
|
+
subject.unsafe_once(&callback)
|
345
|
+
end
|
346
|
+
|
347
|
+
after do
|
348
|
+
subject.emit :message, msg
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'does not deregister them' do
|
352
|
+
expect(obj).to receive(:received_message).with(msg)
|
353
|
+
subject.off
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
context '#unsafe_off' do
|
359
|
+
let(:callback) { Proc.new { |msg| obj.received_message msg } }
|
360
|
+
|
361
|
+
context 'with unsafe_on subscribers' do
|
362
|
+
before do
|
363
|
+
subject.unsafe_on(&callback)
|
364
|
+
end
|
365
|
+
|
366
|
+
after do
|
367
|
+
subject.emit :message, msg
|
368
|
+
end
|
369
|
+
|
370
|
+
it 'deregisters them' do
|
371
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
372
|
+
subject.unsafe_off
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
context 'with unsafe_once subscribers' do
|
377
|
+
before do
|
378
|
+
subject.unsafe_once(&callback)
|
379
|
+
end
|
380
|
+
|
381
|
+
after do
|
382
|
+
subject.emit :message, msg
|
383
|
+
end
|
384
|
+
|
385
|
+
it 'deregister them' do
|
386
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
387
|
+
subject.unsafe_off
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
context 'with on subscribers' do
|
392
|
+
before do
|
393
|
+
subject.on(&callback)
|
394
|
+
end
|
395
|
+
|
396
|
+
after do
|
397
|
+
subject.emit :message, msg
|
398
|
+
end
|
399
|
+
|
400
|
+
it 'does not deregister them' do
|
401
|
+
expect(obj).to receive(:received_message).with(msg)
|
402
|
+
subject.unsafe_off
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
context 'with once subscribers' do
|
407
|
+
before do
|
408
|
+
subject.once(&callback)
|
409
|
+
end
|
410
|
+
|
411
|
+
after do
|
412
|
+
subject.emit :message, msg
|
413
|
+
end
|
414
|
+
|
415
|
+
it 'does not deregister them' do
|
416
|
+
expect(obj).to receive(:received_message).with(msg)
|
417
|
+
subject.unsafe_off
|
418
|
+
end
|
292
419
|
end
|
293
420
|
end
|
294
421
|
end
|