ably-rest 0.7.1 → 0.7.3
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 +13 -5
- data/.gitmodules +1 -1
- data/.rspec +1 -0
- data/.travis.yml +7 -3
- data/SPEC.md +495 -419
- data/ably-rest.gemspec +19 -5
- data/lib/ably-rest.rb +9 -1
- data/lib/submodules/ably-ruby/.gitignore +6 -0
- data/lib/submodules/ably-ruby/.rspec +1 -0
- data/lib/submodules/ably-ruby/.ruby-version.old +1 -0
- data/lib/submodules/ably-ruby/.travis.yml +10 -0
- data/lib/submodules/ably-ruby/Gemfile +4 -0
- data/lib/submodules/ably-ruby/LICENSE.txt +22 -0
- data/lib/submodules/ably-ruby/README.md +122 -0
- data/lib/submodules/ably-ruby/Rakefile +34 -0
- data/lib/submodules/ably-ruby/SPEC.md +1794 -0
- data/lib/submodules/ably-ruby/ably.gemspec +36 -0
- data/lib/submodules/ably-ruby/lib/ably.rb +12 -0
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +438 -0
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +69 -0
- data/lib/submodules/ably-ruby/lib/ably/logger.rb +102 -0
- data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +37 -0
- data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +223 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +132 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/base.rb +108 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/base64.rb +40 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/cipher.rb +83 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/json.rb +34 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/utf8.rb +26 -0
- data/lib/submodules/ably-ruby/lib/ably/models/nil_logger.rb +20 -0
- data/lib/submodules/ably-ruby/lib/ably/models/paginated_resource.rb +173 -0
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +147 -0
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +210 -0
- data/lib/submodules/ably-ruby/lib/ably/models/stat.rb +161 -0
- data/lib/submodules/ably-ruby/lib/ably/models/token.rb +74 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/ably.rb +15 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +62 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/channels_collection.rb +69 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +100 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +69 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/enum.rb +202 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +128 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/event_machine_helpers.rb +26 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/http_helpers.rb +41 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/message_pack.rb +14 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +41 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +153 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +57 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/statesman_monkey_patch.rb +33 -0
- data/lib/submodules/ably-ruby/lib/ably/modules/uses_state_machine.rb +74 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime.rb +64 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +298 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +92 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +69 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channels.rb +50 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +184 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +184 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +70 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +445 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +368 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +91 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +188 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/models/nil_channel.rb +30 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +564 -0
- data/lib/submodules/ably-ruby/lib/ably/rest.rb +43 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +104 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/channels.rb +44 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +396 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/encoder.rb +49 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +41 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/external_exceptions.rb +24 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +17 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/logger.rb +58 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_json.rb +27 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +27 -0
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +92 -0
- data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +105 -0
- data/lib/submodules/ably-ruby/lib/ably/util/pub_sub.rb +43 -0
- data/lib/submodules/ably-ruby/lib/ably/version.rb +3 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +154 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +558 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +119 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +575 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +785 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +457 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +55 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +1001 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/stats_spec.rb +23 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +27 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +564 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +165 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +134 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +41 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +273 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/encoders_spec.rb +185 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +247 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +292 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/stats_spec.rb +172 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +15 -0
- data/lib/submodules/ably-ruby/spec/resources/crypto-data-128.json +56 -0
- data/lib/submodules/ably-ruby/spec/resources/crypto-data-256.json +56 -0
- data/lib/submodules/ably-ruby/spec/rspec_config.rb +57 -0
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +212 -0
- data/lib/submodules/ably-ruby/spec/shared/model_behaviour.rb +86 -0
- data/lib/submodules/ably-ruby/spec/shared/protocol_msgbus_behaviour.rb +36 -0
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +20 -0
- data/lib/submodules/ably-ruby/spec/support/api_helper.rb +60 -0
- data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +104 -0
- data/lib/submodules/ably-ruby/spec/support/markdown_spec_formatter.rb +118 -0
- data/lib/submodules/ably-ruby/spec/support/private_api_formatter.rb +36 -0
- data/lib/submodules/ably-ruby/spec/support/protocol_helper.rb +32 -0
- data/lib/submodules/ably-ruby/spec/support/random_helper.rb +15 -0
- data/lib/submodules/ably-ruby/spec/support/rest_testapp_before_retry.rb +15 -0
- data/lib/submodules/ably-ruby/spec/support/test_app.rb +113 -0
- data/lib/submodules/ably-ruby/spec/unit/auth_spec.rb +68 -0
- data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +146 -0
- data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +18 -0
- data/lib/submodules/ably-ruby/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +349 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/base64_spec.rb +181 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/cipher_spec.rb +260 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/json_spec.rb +135 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/utf8_spec.rb +56 -0
- data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +389 -0
- data/lib/submodules/ably-ruby/spec/unit/models/paginated_resource_spec.rb +288 -0
- data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +386 -0
- data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +315 -0
- data/lib/submodules/ably-ruby/spec/unit/models/stat_spec.rb +113 -0
- data/lib/submodules/ably-ruby/spec/unit/models/token_spec.rb +86 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +124 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/conversions_spec.rb +72 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +272 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +184 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +283 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +206 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/channels_spec.rb +81 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +30 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +33 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/incoming_message_dispatcher_spec.rb +36 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +111 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/realtime_spec.rb +9 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/websocket_transport_spec.rb +25 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +109 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/channels_spec.rb +79 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +53 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/rest_spec.rb +10 -0
- data/lib/submodules/ably-ruby/spec/unit/util/crypto_spec.rb +87 -0
- data/lib/submodules/ably-ruby/spec/unit/util/pub_sub_spec.rb +86 -0
- metadata +182 -27
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ably::Modules::EventEmitter do
|
|
4
|
+
let(:options) { {} }
|
|
5
|
+
let(:klass) do
|
|
6
|
+
callback_opts = options
|
|
7
|
+
Class.new do
|
|
8
|
+
include Ably::Modules::EventEmitter
|
|
9
|
+
configure_event_emitter callback_opts
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
let(:obj) { double('example') }
|
|
13
|
+
let(:msg) { double('message') }
|
|
14
|
+
|
|
15
|
+
subject { klass.new }
|
|
16
|
+
|
|
17
|
+
context '#trigger event fan out' do
|
|
18
|
+
it 'should emit an event for any number of subscribers' do
|
|
19
|
+
2.times do
|
|
20
|
+
subject.on(:message) { |msg| obj.received_message msg }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
expect(obj).to receive(:received_message).with(msg).twice
|
|
24
|
+
subject.trigger :message, msg
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'sends only messages to matching event names' do
|
|
28
|
+
subject.on(:valid) { |msg| obj.received_message msg }
|
|
29
|
+
|
|
30
|
+
expect(obj).to receive(:received_message).with(msg).once
|
|
31
|
+
subject.trigger :valid, msg
|
|
32
|
+
subject.trigger :ignored, msg
|
|
33
|
+
subject.trigger 'valid', msg
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'with coercion', :api_private do
|
|
37
|
+
let(:options) do
|
|
38
|
+
{ coerce_into: Proc.new { |event| String(event) } }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'calls the provided proc to coerce the event name' do
|
|
42
|
+
subject.on('valid') { |msg| obj.received_message msg }
|
|
43
|
+
|
|
44
|
+
expect(obj).to receive(:received_message).with(msg).once
|
|
45
|
+
subject.trigger :valid, msg
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context 'without coercion', :api_private do
|
|
50
|
+
it 'only matches event names on type matches' do
|
|
51
|
+
subject.on('valid') { |msg| obj.received_message msg }
|
|
52
|
+
|
|
53
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
|
54
|
+
subject.trigger :valid, msg
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context '#on subscribe to multiple events' do
|
|
59
|
+
it 'with the same block' do
|
|
60
|
+
subject.on(:click, :hover) { |msg| obj.received_message msg }
|
|
61
|
+
|
|
62
|
+
expect(obj).to receive(:received_message).with(msg).twice
|
|
63
|
+
|
|
64
|
+
subject.trigger :click, msg
|
|
65
|
+
subject.trigger :hover, msg
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context 'event callback changes within the callback block' do
|
|
70
|
+
context 'when new event callbacks are added' do
|
|
71
|
+
before do
|
|
72
|
+
2.times do
|
|
73
|
+
subject.on(:message) do |msg|
|
|
74
|
+
obj.received_message msg
|
|
75
|
+
subject.on(:message) do |msg|
|
|
76
|
+
obj.received_message_from_new_callbacks msg
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
allow(obj).to receive(:received_message)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'is unaffected and processes the prior event callbacks once' do
|
|
84
|
+
expect(obj).to receive(:received_message).with(msg).twice
|
|
85
|
+
expect(obj).to_not receive(:received_message_from_new_callbacks).with(msg)
|
|
86
|
+
subject.trigger :message, msg
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'adds them for the next emitted event' do
|
|
90
|
+
expect(obj).to receive(:received_message_from_new_callbacks).with(msg).twice
|
|
91
|
+
|
|
92
|
+
# New callbacks are added in this trigger
|
|
93
|
+
subject.trigger :message, msg
|
|
94
|
+
|
|
95
|
+
# New callbacks are now called with second event emitted
|
|
96
|
+
subject.trigger :message, msg
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context 'when callbacks are removed' do
|
|
101
|
+
before do
|
|
102
|
+
2.times do
|
|
103
|
+
subject.once(:message) do |msg|
|
|
104
|
+
obj.received_message msg
|
|
105
|
+
subject.off
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'is unaffected and processes the prior event callbacks once' do
|
|
111
|
+
expect(obj).to receive(:received_message).with(msg).twice
|
|
112
|
+
subject.trigger :message, msg
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'removes them for the next emitted event' do
|
|
116
|
+
expect(obj).to receive(:received_message).with(msg).twice
|
|
117
|
+
|
|
118
|
+
# Callbacks are removed in this trigger
|
|
119
|
+
subject.trigger :message, msg
|
|
120
|
+
# No callbacks should exist now
|
|
121
|
+
subject.trigger :message, msg
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context '#once' do
|
|
128
|
+
it 'calls the block the first time an event is emitted only' do
|
|
129
|
+
block_called = 0
|
|
130
|
+
subject.once('event') { block_called += 1 }
|
|
131
|
+
3.times { subject.trigger 'event', 'data' }
|
|
132
|
+
expect(block_called).to eql(1)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it 'does not remove other blocks after it is called' do
|
|
136
|
+
block_called = 0
|
|
137
|
+
subject.once('event') { block_called += 1 }
|
|
138
|
+
subject.on('event') { block_called += 1 }
|
|
139
|
+
3.times { subject.trigger 'event', 'data' }
|
|
140
|
+
expect(block_called).to eql(4)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
context '#off' do
|
|
145
|
+
let(:callback) { Proc.new { |msg| obj.received_message msg } }
|
|
146
|
+
|
|
147
|
+
before do
|
|
148
|
+
subject.on(:message, &callback)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
after do
|
|
152
|
+
subject.trigger :message, msg
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
context 'with event names as arguments' do
|
|
156
|
+
it 'deletes matching callbacks' do
|
|
157
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
|
158
|
+
subject.off(:message, &callback)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'deletes all callbacks if not block given' do
|
|
162
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
|
163
|
+
subject.off(:message)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'continues if the block does not exist' do
|
|
167
|
+
expect(obj).to receive(:received_message).with(msg)
|
|
168
|
+
subject.off(:message) { true }
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
context 'without any event names' do
|
|
173
|
+
it 'deletes all matching callbacks' do
|
|
174
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
|
175
|
+
subject.off(&callback)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it 'deletes all callbacks if not block given' do
|
|
179
|
+
expect(obj).to_not receive(:received_message).with(msg)
|
|
180
|
+
subject.off
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ably::Modules::StateEmitter do
|
|
4
|
+
class ExampleStateWithEventEmitter
|
|
5
|
+
include Ably::Modules::EventEmitter
|
|
6
|
+
extend Ably::Modules::Enum
|
|
7
|
+
|
|
8
|
+
STATE = ruby_enum('STATE',
|
|
9
|
+
:initializing,
|
|
10
|
+
:connecting,
|
|
11
|
+
:connected,
|
|
12
|
+
:disconnected
|
|
13
|
+
)
|
|
14
|
+
include Ably::Modules::StateEmitter
|
|
15
|
+
|
|
16
|
+
def initialize
|
|
17
|
+
@state = :initializing
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
let(:initial_state) { :initializing }
|
|
22
|
+
|
|
23
|
+
subject { ExampleStateWithEventEmitter.new }
|
|
24
|
+
|
|
25
|
+
specify '#state returns current state' do
|
|
26
|
+
expect(subject.state).to eq(:initializing)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
specify '#state= sets current state' do
|
|
30
|
+
expect { subject.state = :connecting }.to change { subject.state }.to(:connecting)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
specify '#change_state sets current state' do
|
|
34
|
+
expect { subject.change_state :connecting }.to change { subject.state }.to(:connecting)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context '#change_state with arguments' do
|
|
38
|
+
let(:args) { [5,3,1] }
|
|
39
|
+
let(:callback_status) { { called: false } }
|
|
40
|
+
|
|
41
|
+
it 'passes the arguments through to the triggered callback' do
|
|
42
|
+
subject.on(:connecting) do |*callback_args|
|
|
43
|
+
expect(callback_args).to eql(args)
|
|
44
|
+
callback_status[:called] = true
|
|
45
|
+
end
|
|
46
|
+
expect { subject.change_state :connecting, *args }.to change { subject.state }.to(:connecting)
|
|
47
|
+
expect(callback_status).to eql(called: true)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context '#state?' do
|
|
52
|
+
it 'returns true if state matches' do
|
|
53
|
+
expect(subject.state?(initial_state)).to eql(true)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'returns false if state does not match' do
|
|
57
|
+
expect(subject.state?(:connecting)).to eql(false)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'and convenience predicates for states' do
|
|
61
|
+
it 'returns true for #initializing? if state matches' do
|
|
62
|
+
expect(subject.initializing?).to eql(true)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'returns false for #connecting? if state does not match' do
|
|
66
|
+
expect(subject.connecting?).to eql(false)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context '#state STATE coercion', :api_private do
|
|
72
|
+
it 'allows valid STATE values' do
|
|
73
|
+
expect { subject.state = :connected }.to_not raise_error
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'prevents invalid STATE values' do
|
|
77
|
+
expect { subject.state = :invalid }.to raise_error KeyError
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context '#once_or_if', :api_private do
|
|
82
|
+
context 'without :else option block' do
|
|
83
|
+
let(:block_calls) { [] }
|
|
84
|
+
let(:block) do
|
|
85
|
+
proc do
|
|
86
|
+
block_calls << Time.now
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'calls the block if in the provided state' do
|
|
91
|
+
subject.once_or_if initial_state, &block
|
|
92
|
+
expect(block_calls.count).to eql(1)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'calls the block when the state is reached' do
|
|
96
|
+
subject.once_or_if :connected, &block
|
|
97
|
+
expect(block_calls.count).to eql(0)
|
|
98
|
+
|
|
99
|
+
subject.change_state :connected
|
|
100
|
+
expect(block_calls.count).to eql(1)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'calls the block only once' do
|
|
104
|
+
subject.once_or_if :connected, &block
|
|
105
|
+
3.times do
|
|
106
|
+
subject.change_state :connected
|
|
107
|
+
subject.change_state :connecting
|
|
108
|
+
end
|
|
109
|
+
expect(block_calls.count).to eql(1)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context 'with an array of targets' do
|
|
114
|
+
let(:block_calls) { [] }
|
|
115
|
+
let(:block) do
|
|
116
|
+
proc do
|
|
117
|
+
block_calls << Time.now
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'calls the block if in the provided state' do
|
|
122
|
+
subject.once_or_if [initial_state, :connecting], &block
|
|
123
|
+
expect(block_calls.count).to eql(1)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'calls the block when one of the states is reached' do
|
|
127
|
+
subject.once_or_if [:connecting, :connected], &block
|
|
128
|
+
expect(block_calls.count).to eql(0)
|
|
129
|
+
|
|
130
|
+
subject.change_state :connected
|
|
131
|
+
expect(block_calls.count).to eql(1)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'calls the block only once' do
|
|
135
|
+
subject.once_or_if [:connecting, :connected], &block
|
|
136
|
+
expect(block_calls.count).to eql(0)
|
|
137
|
+
|
|
138
|
+
3.times do
|
|
139
|
+
subject.change_state :connected
|
|
140
|
+
subject.change_state :connecting
|
|
141
|
+
end
|
|
142
|
+
expect(block_calls.count).to eql(1)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'does not remove all blocks on success' do
|
|
146
|
+
allow(subject).to receive(:off) do |&block|
|
|
147
|
+
raise 'Should not receive a nil block' if block.nil?
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
subject.once_or_if(:connected) { }
|
|
151
|
+
subject.change_state :connected
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
context 'with :else option block', :api_private do
|
|
156
|
+
let(:success_calls) { [] }
|
|
157
|
+
let(:success_block) do
|
|
158
|
+
proc do
|
|
159
|
+
success_calls << Time.now
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
let(:failure_calls) { [] }
|
|
164
|
+
let(:failure_block) do
|
|
165
|
+
proc do |*args|
|
|
166
|
+
failure_calls << args
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
let(:target_state) { :connected }
|
|
171
|
+
|
|
172
|
+
before do
|
|
173
|
+
subject.once_or_if target_state, else: failure_block, &success_block
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
context 'blocks' do
|
|
177
|
+
specify 'are not called if the state does not change' do
|
|
178
|
+
subject.change_state initial_state
|
|
179
|
+
expect(success_calls.count).to eql(0)
|
|
180
|
+
expect(failure_calls.count).to eql(0)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
context 'success block' do
|
|
185
|
+
it 'is called once target_state is reached' do
|
|
186
|
+
subject.change_state target_state
|
|
187
|
+
expect(success_calls.count).to eql(1)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it 'is never called again once target_state is reached' do
|
|
191
|
+
subject.change_state target_state
|
|
192
|
+
subject.change_state :connecting
|
|
193
|
+
subject.change_state target_state
|
|
194
|
+
expect(success_calls.count).to eql(1)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it 'is never called after failure block was called' do
|
|
198
|
+
subject.change_state :connecting
|
|
199
|
+
subject.change_state target_state
|
|
200
|
+
expect(success_calls.count).to eql(0)
|
|
201
|
+
expect(failure_calls.count).to eql(1)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
context 'failure block' do
|
|
206
|
+
it 'is called once a state other than target_state is reached' do
|
|
207
|
+
subject.change_state :connecting
|
|
208
|
+
expect(failure_calls.count).to eql(1)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'is never called again once the block has been called previously' do
|
|
212
|
+
subject.change_state :connecting
|
|
213
|
+
subject.change_state target_state
|
|
214
|
+
subject.change_state :connecting
|
|
215
|
+
expect(failure_calls.count).to eql(1)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it 'is never called after success block was called' do
|
|
219
|
+
subject.change_state target_state
|
|
220
|
+
subject.change_state :connecting
|
|
221
|
+
expect(failure_calls.count).to eql(0)
|
|
222
|
+
expect(success_calls.count).to eql(1)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it 'has arguments from the error state' do
|
|
226
|
+
subject.change_state :disconnected, 1, 2
|
|
227
|
+
expect(failure_calls.count).to eql(1)
|
|
228
|
+
expect(failure_calls.first).to contain_exactly(1, 2)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
context 'state change arguments' do
|
|
234
|
+
let(:arguments) { [1,2,3] }
|
|
235
|
+
|
|
236
|
+
specify 'are passed to success blocks' do
|
|
237
|
+
subject.once_or_if(:connected) do |*arguments|
|
|
238
|
+
expect(arguments).to eql(arguments)
|
|
239
|
+
end
|
|
240
|
+
subject.change_state :connected, *arguments
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
specify 'are passed to else blocks' do
|
|
244
|
+
else_block = proc { |arguments| expect(arguments).to eql(arguments) }
|
|
245
|
+
subject.once_or_if(:connected, else: else_block) do
|
|
246
|
+
raise 'Success should not be called'
|
|
247
|
+
end
|
|
248
|
+
subject.change_state :connecting, *arguments
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
context '#once_state_changed', :api_private do
|
|
254
|
+
let(:block_calls) { [] }
|
|
255
|
+
let(:block) do
|
|
256
|
+
proc do |*args|
|
|
257
|
+
block_calls << args
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it 'is not called if the state does not change' do
|
|
262
|
+
subject.once_state_changed &block
|
|
263
|
+
subject.change_state initial_state
|
|
264
|
+
expect(block_calls.count).to eql(0)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it 'calls the block for any state change once' do
|
|
268
|
+
subject.once_state_changed &block
|
|
269
|
+
3.times do
|
|
270
|
+
subject.change_state :connected
|
|
271
|
+
subject.change_state :connecting
|
|
272
|
+
end
|
|
273
|
+
expect(block_calls.count).to eql(1)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
it 'emits arguments to the block' do
|
|
277
|
+
subject.once_state_changed &block
|
|
278
|
+
subject.change_state :connected, 1, 2
|
|
279
|
+
expect(block_calls.count).to eql(1)
|
|
280
|
+
expect(block_calls.first).to contain_exactly(1, 2)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|