ably 0.1.5 → 0.1.6
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/README.md +11 -1
- data/ably.gemspec +4 -3
- data/lib/ably.rb +6 -2
- data/lib/ably/auth.rb +24 -16
- data/lib/ably/exceptions.rb +16 -5
- data/lib/ably/{realtime/models → models}/error_info.rb +9 -11
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +57 -26
- data/lib/ably/{realtime/models → models}/message.rb +45 -38
- data/lib/ably/{realtime/models → models}/nil_channel.rb +4 -4
- data/lib/ably/{rest/models/paged_resource.rb → models/paginated_resource.rb} +21 -10
- data/lib/ably/models/presence_message.rb +126 -0
- data/lib/ably/{realtime/models → models}/protocol_message.rb +76 -38
- data/lib/ably/models/token.rb +74 -0
- data/lib/ably/modules/channels_collection.rb +49 -0
- data/lib/ably/modules/conversions.rb +2 -0
- data/lib/ably/modules/event_emitter.rb +43 -8
- data/lib/ably/modules/event_machine_helpers.rb +1 -0
- data/lib/ably/modules/http_helpers.rb +9 -2
- data/lib/ably/modules/message_pack.rb +14 -0
- data/lib/ably/modules/model_common.rb +29 -0
- data/lib/ably/modules/{state.rb → state_emitter.rb} +8 -7
- data/lib/ably/realtime.rb +37 -7
- data/lib/ably/realtime/channel.rb +154 -31
- data/lib/ably/realtime/channels.rb +47 -0
- data/lib/ably/realtime/client.rb +39 -33
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +50 -21
- data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +9 -11
- data/lib/ably/realtime/connection.rb +148 -79
- data/lib/ably/realtime/connection/connection_state_machine.rb +111 -0
- data/lib/ably/realtime/connection/websocket_transport.rb +161 -0
- data/lib/ably/realtime/presence.rb +270 -0
- data/lib/ably/rest.rb +14 -3
- data/lib/ably/rest/channel.rb +3 -3
- data/lib/ably/rest/channels.rb +26 -12
- data/lib/ably/rest/client.rb +42 -25
- data/lib/ably/rest/middleware/exceptions.rb +21 -23
- data/lib/ably/rest/middleware/external_exceptions.rb +8 -10
- data/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +17 -0
- data/lib/ably/rest/middleware/parse_json.rb +9 -2
- data/lib/ably/rest/middleware/parse_message_pack.rb +6 -2
- data/lib/ably/rest/presence.rb +4 -4
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_history_spec.rb +125 -0
- data/spec/acceptance/realtime/channel_spec.rb +135 -63
- data/spec/acceptance/realtime/connection_spec.rb +86 -0
- data/spec/acceptance/realtime/message_spec.rb +116 -94
- data/spec/acceptance/realtime/presence_history_spec.rb +0 -0
- data/spec/acceptance/realtime/presence_spec.rb +277 -0
- data/spec/acceptance/rest/auth_spec.rb +351 -347
- data/spec/acceptance/rest/base_spec.rb +43 -26
- data/spec/acceptance/rest/channel_spec.rb +88 -83
- data/spec/acceptance/rest/channels_spec.rb +32 -28
- data/spec/acceptance/rest/presence_spec.rb +83 -63
- data/spec/acceptance/rest/stats_spec.rb +38 -37
- data/spec/acceptance/rest/time_spec.rb +10 -6
- data/spec/integration/modules/{state_spec.rb → state_emitter_spec.rb} +16 -2
- data/spec/spec_helper.rb +14 -0
- data/spec/support/api_helper.rb +4 -0
- data/spec/support/model_helper.rb +28 -9
- data/spec/support/protocol_msgbus_helper.rb +8 -1
- data/spec/support/test_app.rb +24 -14
- data/spec/unit/{realtime → models}/error_info_spec.rb +4 -4
- data/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +46 -9
- data/spec/unit/models/message_spec.rb +229 -0
- data/spec/unit/{rest/paged_resource_spec.rb → models/paginated_resource_spec.rb} +19 -11
- data/spec/unit/models/presence_message_spec.rb +230 -0
- data/spec/unit/models/protocol_message_spec.rb +280 -0
- data/spec/unit/{token_spec.rb → models/token_spec.rb} +18 -22
- data/spec/unit/modules/conversions_spec.rb +1 -1
- data/spec/unit/modules/event_emitter_spec.rb +36 -4
- data/spec/unit/realtime/channel_spec.rb +76 -2
- data/spec/unit/realtime/channels_spec.rb +50 -0
- data/spec/unit/realtime/client_spec.rb +31 -1
- data/spec/unit/realtime/connection_spec.rb +8 -15
- data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +6 -6
- data/spec/unit/realtime/presence_spec.rb +100 -0
- data/spec/unit/rest/channels_spec.rb +48 -0
- metadata +72 -38
- data/lib/ably/realtime/models/shared.rb +0 -17
- data/lib/ably/rest/models/message.rb +0 -64
- data/lib/ably/rest/models/presence_message.rb +0 -21
- data/lib/ably/token.rb +0 -80
- data/spec/unit/realtime/message_spec.rb +0 -117
- data/spec/unit/realtime/protocol_message_spec.rb +0 -172
- data/spec/unit/rest/message_spec.rb +0 -75
data/lib/ably/version.rb
CHANGED
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
describe Ably::Realtime::Channel do
|
5
|
+
include RSpec::EventMachine
|
6
|
+
|
7
|
+
[:msgpack, :json].each do |protocol|
|
8
|
+
context "over #{protocol}" do
|
9
|
+
let(:default_options) { options.merge(api_key: api_key, environment: environment, protocol: protocol) }
|
10
|
+
|
11
|
+
let(:client) do
|
12
|
+
Ably::Realtime::Client.new(default_options)
|
13
|
+
end
|
14
|
+
let(:channel) { client.channel(channel_name) }
|
15
|
+
|
16
|
+
let(:client2) do
|
17
|
+
Ably::Realtime::Client.new(default_options)
|
18
|
+
end
|
19
|
+
let(:channel2) { client2.channel(channel_name) }
|
20
|
+
|
21
|
+
let(:channel_name) { "persisted:#{SecureRandom.hex(2)}" }
|
22
|
+
let(:payload) { SecureRandom.hex(4) }
|
23
|
+
let(:messages) { [] }
|
24
|
+
|
25
|
+
let(:options) { { :protocol => :json } }
|
26
|
+
|
27
|
+
it 'retrieves real-time history' do
|
28
|
+
run_reactor do
|
29
|
+
channel.publish('event', payload) do |message|
|
30
|
+
history = channel.history
|
31
|
+
expect(history.length).to eql(1)
|
32
|
+
expect(history[0].data).to eql(payload)
|
33
|
+
stop_reactor
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'retrieves real-time history across two channels' do
|
39
|
+
run_reactor do
|
40
|
+
channel.publish('event', payload) do |message|
|
41
|
+
channel2.publish('event', payload) do |message|
|
42
|
+
history = channel2.history
|
43
|
+
expect(history.length).to eql(2)
|
44
|
+
expect(history.map(&:data).uniq).to eql([payload])
|
45
|
+
stop_reactor
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'with multiple messages' do
|
52
|
+
let(:messages_sent) { 20 }
|
53
|
+
let(:limit) { 10 }
|
54
|
+
|
55
|
+
def check_limited_history(direction)
|
56
|
+
history = channel.history(direction: direction, limit: limit)
|
57
|
+
expect(history.length).to eql(limit)
|
58
|
+
limit.times do |index|
|
59
|
+
expect(history[index].data).to eql("history#{index}")
|
60
|
+
end
|
61
|
+
|
62
|
+
history = history.next_page
|
63
|
+
|
64
|
+
expect(history.length).to eql(limit)
|
65
|
+
limit.times do |index|
|
66
|
+
expect(history[index].data).to eql("history#{index + limit}")
|
67
|
+
end
|
68
|
+
expect(history.last_page?).to eql(true)
|
69
|
+
|
70
|
+
stop_reactor
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'as one ProtocolMessage' do
|
74
|
+
it 'retrieves limited history forwards with pagination' do
|
75
|
+
run_reactor(5) do
|
76
|
+
messages_sent.times do |index|
|
77
|
+
channel.publish('event', "history#{index}") do
|
78
|
+
check_limited_history :forwards if index == messages_sent - 1
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'retrieves limited history backwards with pagination' do
|
85
|
+
run_reactor(5) do
|
86
|
+
messages_sent.times.to_a.reverse.each do |index|
|
87
|
+
channel.publish('event', "history#{index}") do
|
88
|
+
check_limited_history :backwards if index == messages_sent - 1
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'in multiple ProtocolMessages' do
|
96
|
+
it 'retrieves limited history forwards with pagination' do
|
97
|
+
run_reactor(5) do
|
98
|
+
messages_sent.times do |index|
|
99
|
+
EventMachine.add_timer(index.to_f / 10) do
|
100
|
+
channel.publish('event', "history#{index}") do
|
101
|
+
check_limited_history :forwards if index == messages_sent - 1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'retrieves limited history backwards with pagination' do
|
109
|
+
run_reactor(5) do
|
110
|
+
messages_sent.times.to_a.reverse.each do |index|
|
111
|
+
EventMachine.add_timer((messages_sent - index).to_f / 10) do
|
112
|
+
channel.publish('event', "history#{index}") do
|
113
|
+
check_limited_history :backwards if index == 0
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
skip 'ensure REST history message IDs match ProtocolMessage wrapped message IDs via Realtime'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -4,83 +4,155 @@ require 'securerandom'
|
|
4
4
|
describe Ably::Realtime::Channel do
|
5
5
|
include RSpec::EventMachine
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
let(:channel_name) { SecureRandom.hex(2) }
|
11
|
-
let(:payload) { SecureRandom.hex(4) }
|
12
|
-
|
13
|
-
it 'attachs to a channel' do
|
14
|
-
attached = false
|
15
|
-
|
16
|
-
run_reactor do
|
17
|
-
channel = client.channel(channel_name)
|
18
|
-
channel.attach
|
19
|
-
channel.on(:attached) do
|
20
|
-
expect(channel.state).to eq(:attached)
|
21
|
-
attached = true
|
22
|
-
stop_reactor
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
expect(attached).to eql(true)
|
27
|
-
end
|
7
|
+
[:msgpack, :json].each do |protocol|
|
8
|
+
context "over #{protocol}" do
|
9
|
+
let(:default_options) { { api_key: api_key, environment: environment, protocol: protocol } }
|
28
10
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
run_reactor do
|
33
|
-
channel = client.channel(channel_name)
|
34
|
-
channel.attach
|
35
|
-
channel.on(:attached) do
|
36
|
-
3.times { channel.publish('event', payload) }
|
11
|
+
let(:client) do
|
12
|
+
Ably::Realtime::Client.new(default_options)
|
37
13
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
14
|
+
let(:channel_name) { SecureRandom.hex(2) }
|
15
|
+
let(:payload) { SecureRandom.hex(4) }
|
16
|
+
let(:channel) { client.channel(channel_name) }
|
17
|
+
let(:messages) { [] }
|
18
|
+
|
19
|
+
it 'attaches to a channel' do
|
20
|
+
run_reactor do
|
21
|
+
channel.attach
|
22
|
+
channel.on(:attached) do
|
23
|
+
expect(channel.state).to eq(:attached)
|
24
|
+
stop_reactor
|
25
|
+
end
|
26
|
+
end
|
41
27
|
end
|
42
|
-
end
|
43
28
|
|
44
|
-
|
45
|
-
|
29
|
+
it 'attaches to a channel with a block' do
|
30
|
+
run_reactor do
|
31
|
+
channel.attach do
|
32
|
+
expect(channel.state).to eq(:attached)
|
33
|
+
stop_reactor
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
46
37
|
|
47
|
-
|
48
|
-
|
38
|
+
it 'detaches from a channel with a block' do
|
39
|
+
run_reactor do
|
40
|
+
channel.attach do |chan|
|
41
|
+
chan.detach do |detached_chan|
|
42
|
+
expect(detached_chan.state).to eq(:detached)
|
43
|
+
stop_reactor
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
it 'publishes 3 messages once attached' do
|
50
|
+
run_reactor do
|
51
|
+
channel.attach do
|
52
|
+
3.times { channel.publish('event', payload) }
|
53
|
+
end
|
54
|
+
channel.subscribe do |message|
|
55
|
+
messages << message if message.data == payload
|
56
|
+
stop_reactor if messages.length == 3
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
expect(messages.count).to eql(3)
|
56
61
|
end
|
57
|
-
end
|
58
62
|
|
59
|
-
|
60
|
-
|
63
|
+
it 'publishes 3 messages from queue before attached' do
|
64
|
+
run_reactor do
|
65
|
+
3.times { channel.publish('event', SecureRandom.hex) }
|
66
|
+
channel.subscribe do |message|
|
67
|
+
messages << message if message.name == 'event'
|
68
|
+
stop_reactor if messages.length == 3
|
69
|
+
end
|
70
|
+
end
|
61
71
|
|
62
|
-
|
63
|
-
|
72
|
+
expect(messages.count).to eql(3)
|
73
|
+
end
|
64
74
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
75
|
+
it 'publishes 3 messages from queue before attached in a single protocol message' do
|
76
|
+
run_reactor do
|
77
|
+
3.times { channel.publish('event', SecureRandom.hex) }
|
78
|
+
channel.subscribe do |message|
|
79
|
+
messages << message if message.name == 'event'
|
80
|
+
stop_reactor if messages.length == 3
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# All 3 messages should be batched into a single Protocol Message by the client library
|
85
|
+
# message.id = "{protocol_message.id}:{protocol_message_index}"
|
86
|
+
|
87
|
+
# Check that all messages share the same message_serial
|
88
|
+
message_id = messages.map { |msg| msg.id.split(':')[0] }
|
89
|
+
expect(message_id.uniq.count).to eql(1)
|
90
|
+
|
91
|
+
# Check that all messages use message index 0,1,2
|
92
|
+
message_indexes = messages.map { |msg| msg.id.split(':')[1] }
|
93
|
+
expect(message_indexes).to include("0", "1", "2")
|
71
94
|
end
|
72
|
-
end
|
73
95
|
|
74
|
-
|
75
|
-
|
96
|
+
it 'subscribes and unsubscribes' do
|
97
|
+
run_reactor do
|
98
|
+
channel.subscribe('click') do |message|
|
99
|
+
messages << message
|
100
|
+
end
|
101
|
+
channel.attach do
|
102
|
+
channel.unsubscribe('click')
|
103
|
+
channel.publish('click', 'data')
|
104
|
+
EventMachine.add_timer(2) do
|
105
|
+
stop_reactor
|
106
|
+
expect(messages.length).to eql(0)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
76
111
|
|
77
|
-
|
78
|
-
|
79
|
-
|
112
|
+
it 'subscribes and unsubscribes from multiple channels' do
|
113
|
+
run_reactor do
|
114
|
+
click_callback = -> (message) { messages << message }
|
115
|
+
|
116
|
+
channel.subscribe('click', &click_callback)
|
117
|
+
channel.subscribe('move', &click_callback)
|
118
|
+
channel.subscribe('press', &click_callback)
|
119
|
+
|
120
|
+
channel.attach do
|
121
|
+
channel.unsubscribe('click')
|
122
|
+
channel.unsubscribe('move', &click_callback)
|
123
|
+
channel.unsubscribe('press') { this_callback_is_not_subscribed_so_ignored }
|
124
|
+
|
125
|
+
channel.publish('click', 'data')
|
126
|
+
channel.publish('move', 'data')
|
127
|
+
channel.publish('press', 'data')
|
128
|
+
|
129
|
+
EventMachine.add_timer(2) do
|
130
|
+
stop_reactor
|
131
|
+
# Only the press subscribe callback should still be subscribed
|
132
|
+
expect(messages.length).to eql(1)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
80
137
|
|
81
|
-
|
82
|
-
|
83
|
-
|
138
|
+
context 'attach failure' do
|
139
|
+
let(:restricted_client) do
|
140
|
+
Ably::Realtime::Client.new(default_options.merge(api_key: restricted_api_key))
|
141
|
+
end
|
142
|
+
let(:restricted_channel) { restricted_client.channel("cannot_subscribe") }
|
143
|
+
|
144
|
+
it 'triggers failed event' do
|
145
|
+
run_reactor do
|
146
|
+
restricted_channel.attach
|
147
|
+
restricted_channel.on(:failed) do |error|
|
148
|
+
expect(restricted_channel.state).to eq(:failed)
|
149
|
+
expect(error.status_code).to eq(401)
|
150
|
+
stop_reactor
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
84
156
|
end
|
85
157
|
end
|
86
158
|
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ably::Realtime::Connection do
|
4
|
+
include RSpec::EventMachine
|
5
|
+
|
6
|
+
[:msgpack, :json].each do |protocol|
|
7
|
+
context "over #{protocol}" do
|
8
|
+
let(:client) do
|
9
|
+
Ably::Realtime::Client.new(api_key: api_key, environment: environment, protocol: protocol)
|
10
|
+
end
|
11
|
+
|
12
|
+
subject { client.connection }
|
13
|
+
|
14
|
+
it 'connects automatically' do
|
15
|
+
run_reactor do
|
16
|
+
subject.on(:connected) do
|
17
|
+
expect(subject.state).to eq(:connected)
|
18
|
+
stop_reactor
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'initialization phases' do
|
24
|
+
let(:phases) { [:initialized, :connecting, :connected] }
|
25
|
+
let(:events_triggered) { [] }
|
26
|
+
|
27
|
+
it 'are triggered in order' do
|
28
|
+
test_expectation = Proc.new do
|
29
|
+
expect(events_triggered).to eq(phases)
|
30
|
+
stop_reactor
|
31
|
+
end
|
32
|
+
|
33
|
+
run_reactor do
|
34
|
+
phases.each do |phase|
|
35
|
+
subject.on(phase) do
|
36
|
+
events_triggered << phase
|
37
|
+
test_expectation.call if events_triggered.length == phases.length
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
skip '#closed disconnects and closes the connection once timeout is reached'
|
45
|
+
|
46
|
+
specify '#closed disconnects and closes the connection gracefully' do
|
47
|
+
run_reactor(8) do
|
48
|
+
subject.close
|
49
|
+
subject.on(:closed) do
|
50
|
+
expect(subject.state).to eq(:closed)
|
51
|
+
stop_reactor
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'receives a heart beat' do
|
57
|
+
run_reactor(20) do
|
58
|
+
subject.on(:connected) do
|
59
|
+
subject.__incoming_protocol_msgbus__.subscribe(:message) do |protocol_message|
|
60
|
+
if protocol_message.action == :heartbeat
|
61
|
+
expect(protocol_message.action).to eq(:heartbeat)
|
62
|
+
stop_reactor
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
skip 'connects, closes gracefully and reconnects on #connect'
|
70
|
+
|
71
|
+
it 'connects, closes then connection when timeout is reaached and reconnects on #connect' do
|
72
|
+
run_reactor(15) do
|
73
|
+
subject.connect do
|
74
|
+
connection_id = subject.id
|
75
|
+
subject.close do
|
76
|
+
subject.connect do
|
77
|
+
expect(subject.id).to_not eql(connection_id)
|
78
|
+
stop_reactor
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -4,80 +4,66 @@ require 'securerandom'
|
|
4
4
|
describe 'Ably::Realtime::Channel Messages' do
|
5
5
|
include RSpec::EventMachine
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
[:msgpack, :json].each do |protocol|
|
8
|
+
context "over #{protocol}" do
|
9
|
+
let(:default_options) { options.merge(api_key: api_key, environment: environment, protocol: protocol) }
|
10
|
+
let(:client) do
|
11
|
+
Ably::Realtime::Client.new(default_options)
|
12
|
+
end
|
13
|
+
let(:channel) { client.channel(channel_name) }
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
let(:other_client) do
|
16
|
+
Ably::Realtime::Client.new(default_options)
|
17
|
+
end
|
18
|
+
let(:other_client_channel) { other_client.channel(channel_name) }
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
skip 'all tests with multiple messages'
|
21
|
-
end
|
20
|
+
let(:channel_name) { 'subscribe_send_text' }
|
21
|
+
let(:options) { { :protocol => :json } }
|
22
|
+
let(:payload) { 'Test message (subscribe_send_text)' }
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
channel.on(:attached) do
|
32
|
-
channel.publish('test_event', payload) do |message|
|
33
|
-
expect(message.data).to eql(payload)
|
34
|
-
stop_reactor
|
24
|
+
it 'sends a string message' do
|
25
|
+
run_reactor do
|
26
|
+
channel.attach
|
27
|
+
channel.on(:attached) do
|
28
|
+
channel.publish('test_event', payload) do |message|
|
29
|
+
expect(message.data).to eql(payload)
|
30
|
+
stop_reactor
|
31
|
+
end
|
35
32
|
end
|
36
33
|
end
|
37
34
|
end
|
38
|
-
end
|
39
35
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
36
|
+
it 'sends a single message with an echo on another connection' do
|
37
|
+
run_reactor do
|
38
|
+
other_client_channel.attach do
|
39
|
+
channel.publish 'test_event', payload
|
40
|
+
other_client_channel.subscribe('test_event') do |message|
|
41
|
+
expect(message.data).to eql(payload)
|
42
|
+
stop_reactor
|
43
|
+
end
|
48
44
|
end
|
49
45
|
end
|
50
46
|
end
|
51
|
-
end
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
48
|
+
context 'with echo_messages => false' do
|
49
|
+
let(:no_echo_client) do
|
50
|
+
Ably::Realtime::Client.new(default_options.merge(echo_messages: false))
|
51
|
+
end
|
52
|
+
let(:no_echo_channel) { no_echo_client.channel(channel_name) }
|
53
|
+
|
54
|
+
it 'sends a single message without a reply yet the messages is echoed on another normal connection' do
|
55
|
+
run_reactor do
|
56
|
+
channel.attach do |echo_channel|
|
57
|
+
no_echo_channel.attach do
|
58
|
+
no_echo_channel.publish 'test_event', payload
|
59
|
+
|
60
|
+
no_echo_channel.subscribe('test_event') do |message|
|
61
|
+
fail "Message should not have been echoed back"
|
62
|
+
end
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
other_client_channel => :other
|
68
|
-
}.each do |target_channel, echo_key|
|
69
|
-
EventMachine.defer do
|
70
|
-
target_channel.subscribe('test_event') do |message|
|
71
|
-
echos[echo_key] += 1
|
72
|
-
|
73
|
-
if echos[:client] == expected_echos && echos[:other] == expected_echos
|
74
|
-
# Wait briefly before doing the final check in case additional messages received
|
75
|
-
EventMachine.add_timer(0.5) do
|
76
|
-
expect(echos[:client]).to eql(expected_echos)
|
77
|
-
expect(echos[:other]).to eql(expected_echos)
|
78
|
-
expect(callbacks[:client]).to eql(send_count)
|
79
|
-
expect(callbacks[:other]).to eql(send_count)
|
80
|
-
stop_reactor
|
64
|
+
echo_channel.subscribe('test_event') do |message|
|
65
|
+
expect(message.data).to eql(payload)
|
66
|
+
EventMachine.add_timer(1.5) { stop_reactor }
|
81
67
|
end
|
82
68
|
end
|
83
69
|
end
|
@@ -85,48 +71,84 @@ describe 'Ably::Realtime::Channel Messages' do
|
|
85
71
|
end
|
86
72
|
end
|
87
73
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
74
|
+
context 'with multiple messages' do
|
75
|
+
let(:send_count) { 15 }
|
76
|
+
let(:expected_echos) { send_count * 2 }
|
77
|
+
let(:channel_name) { SecureRandom.hex }
|
78
|
+
let(:echos) do
|
79
|
+
{ client: 0, other: 0 }
|
80
|
+
end
|
81
|
+
let(:callbacks) do
|
82
|
+
{ client: 0, other: 0 }
|
83
|
+
end
|
92
84
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
85
|
+
def expect_messages_to_be_echoed_on_both_connections
|
86
|
+
{
|
87
|
+
channel => :client,
|
88
|
+
other_client_channel => :other
|
89
|
+
}.each do |target_channel, echo_key|
|
90
|
+
EventMachine.defer do
|
91
|
+
target_channel.subscribe('test_event') do |message|
|
92
|
+
echos[echo_key] += 1
|
93
|
+
|
94
|
+
if echos[:client] == expected_echos && echos[:other] == expected_echos
|
95
|
+
# Wait briefly before doing the final check in case additional messages received
|
96
|
+
EventMachine.add_timer(0.5) do
|
97
|
+
expect(echos[:client]).to eql(expected_echos)
|
98
|
+
expect(echos[:other]).to eql(expected_echos)
|
99
|
+
expect(callbacks[:client]).to eql(send_count)
|
100
|
+
expect(callbacks[:other]).to eql(send_count)
|
101
|
+
stop_reactor
|
102
|
+
end
|
98
103
|
end
|
99
|
-
|
100
|
-
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'sends and receives the messages on both opened connections (4 x send count due to local echos) and calls the callbacks' do
|
110
|
+
run_reactor(10) do
|
111
|
+
channel.attach
|
112
|
+
other_client_channel.attach
|
113
|
+
|
114
|
+
channel.on(:attached) do
|
115
|
+
other_client_channel.on(:attached) do
|
116
|
+
send_count.times do |index|
|
117
|
+
channel.publish('test_event', "#{index}: #{payload}") do
|
118
|
+
callbacks[:client] += 1
|
119
|
+
end
|
120
|
+
other_client_channel.publish('test_event', "#{index}: #{payload}") do
|
121
|
+
callbacks[:other] += 1
|
122
|
+
end
|
101
123
|
end
|
124
|
+
expect_messages_to_be_echoed_on_both_connections
|
102
125
|
end
|
103
|
-
expect_messages_to_be_echoed_on_both_connections
|
104
126
|
end
|
105
127
|
end
|
106
128
|
end
|
107
129
|
end
|
108
|
-
end
|
109
130
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
131
|
+
context 'without suitable publishing permissions' do
|
132
|
+
let(:restricted_client) do
|
133
|
+
Ably::Realtime::Client.new(options.merge(api_key: restricted_api_key, environment: environment, protocol: protocol))
|
134
|
+
end
|
135
|
+
let(:restricted_channel) { restricted_client.channel("cansubscribe:example") }
|
136
|
+
let(:payload) { 'Test message without permission to publish' }
|
116
137
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
138
|
+
it 'calls the error callback' do
|
139
|
+
run_reactor do
|
140
|
+
restricted_channel.attach
|
141
|
+
restricted_channel.on(:attached) do
|
142
|
+
deferrable = restricted_channel.publish('test_event', payload)
|
143
|
+
deferrable.errback do |message, error|
|
144
|
+
expect(message.data).to eql(payload)
|
145
|
+
expect(error.status).to eql(401)
|
146
|
+
stop_reactor
|
147
|
+
end
|
148
|
+
deferrable.callback do |message|
|
149
|
+
fail 'Success callback should not have been called'
|
150
|
+
stop_reactor
|
151
|
+
end
|
130
152
|
end
|
131
153
|
end
|
132
154
|
end
|