ably 0.8.15 → 1.0.0
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.
- 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
|