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,386 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
require 'shared/model_behaviour'
|
|
4
|
+
|
|
5
|
+
describe Ably::Models::PresenceMessage do
|
|
6
|
+
include Ably::Modules::Conversions
|
|
7
|
+
|
|
8
|
+
subject { Ably::Models::PresenceMessage }
|
|
9
|
+
let(:protocol_message_timestamp) { as_since_epoch(Time.now) }
|
|
10
|
+
let(:protocol_message) { Ably::Models::ProtocolMessage.new(action: 1, timestamp: protocol_message_timestamp) }
|
|
11
|
+
|
|
12
|
+
it_behaves_like 'a model', with_simple_attributes: %w(client_id data encoding) do
|
|
13
|
+
let(:model_args) { [protocol_message] }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context '#connection_id attribute' do
|
|
17
|
+
let(:protocol_connection_id) { random_str }
|
|
18
|
+
let(:protocol_message) { Ably::Models::ProtocolMessage.new('connectionId' => protocol_connection_id, action: 1, timestamp: protocol_message_timestamp) }
|
|
19
|
+
let(:model_connection_id) { random_str }
|
|
20
|
+
|
|
21
|
+
context 'when this model has a connectionId attribute' do
|
|
22
|
+
context 'but no protocol message' do
|
|
23
|
+
let(:model) { subject.new('connectionId' => model_connection_id ) }
|
|
24
|
+
|
|
25
|
+
it 'uses the model value' do
|
|
26
|
+
expect(model.connection_id).to eql(model_connection_id)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'with a protocol message with a different connectionId' do
|
|
31
|
+
let(:model) { subject.new({ 'connectionId' => model_connection_id }, protocol_message) }
|
|
32
|
+
|
|
33
|
+
it 'uses the model value' do
|
|
34
|
+
expect(model.connection_id).to eql(model_connection_id)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'when this model has no connectionId attribute' do
|
|
40
|
+
context 'and no protocol message' do
|
|
41
|
+
let(:model) { subject.new({ }) }
|
|
42
|
+
|
|
43
|
+
it 'uses the model value' do
|
|
44
|
+
expect(model.connection_id).to be_nil
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context 'with a protocol message with a connectionId' do
|
|
49
|
+
let(:model) { subject.new({ }, protocol_message) }
|
|
50
|
+
|
|
51
|
+
it 'uses the model value' do
|
|
52
|
+
expect(model.connection_id).to eql(protocol_connection_id)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context '#member_key attribute' do
|
|
59
|
+
let(:model) { subject.new(client_id: 'client_id', connection_id: 'connection_id') }
|
|
60
|
+
|
|
61
|
+
it 'is string in format connection_id:client_id' do
|
|
62
|
+
expect(model.member_key).to eql('connection_id:client_id')
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context 'with the same client id across multiple connections' do
|
|
66
|
+
let(:connection_1) { subject.new({ client_id: 'same', connection_id: 'unique' }, protocol_message) }
|
|
67
|
+
let(:connection_2) { subject.new({ client_id: 'same', connection_id: 'different' }, protocol_message) }
|
|
68
|
+
|
|
69
|
+
it 'is unique' do
|
|
70
|
+
expect(connection_1.member_key).to_not eql(connection_2.member_key)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context 'with a single connection and different client_ids' do
|
|
75
|
+
let(:client_1) { subject.new({ client_id: 'unique', connection_id: 'same' }, protocol_message) }
|
|
76
|
+
let(:client_2) { subject.new({ client_id: 'different', connection_id: 'same' }, protocol_message) }
|
|
77
|
+
|
|
78
|
+
it 'is unique' do
|
|
79
|
+
expect(client_1.member_key).to_not eql(client_2.member_key)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context '#timestamp' do
|
|
85
|
+
let(:model) { subject.new({}, protocol_message) }
|
|
86
|
+
it 'retrieves attribute :timestamp as a Time object from ProtocolMessage' do
|
|
87
|
+
expect(model.timestamp).to be_a(Time)
|
|
88
|
+
expect(model.timestamp.to_i).to be_within(1).of(Time.now.to_i)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context 'Java naming', :api_private do
|
|
93
|
+
let(:model) { subject.new({ clientId: 'joe' }, protocol_message) }
|
|
94
|
+
|
|
95
|
+
it 'converts the attribute to ruby symbol naming convention' do
|
|
96
|
+
expect(model.client_id).to eql('joe')
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context 'with action', :api_private do
|
|
101
|
+
context 'absent' do
|
|
102
|
+
let(:model) { subject.new({ action: 0 }, protocol_message) }
|
|
103
|
+
|
|
104
|
+
it 'provides action as an Enum' do
|
|
105
|
+
expect(model.action).to eq(:absent)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context 'enter' do
|
|
110
|
+
let(:model) { subject.new({ action: 2 }, protocol_message) }
|
|
111
|
+
|
|
112
|
+
it 'provides action as an Enum' do
|
|
113
|
+
expect(model.action).to eq(:enter)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
context 'without action', :api_private do
|
|
119
|
+
let(:model) { subject.new({}, protocol_message) }
|
|
120
|
+
|
|
121
|
+
it 'raises an exception when accessed' do
|
|
122
|
+
expect { model.action }.to raise_error KeyError
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
context 'initialized with' do
|
|
127
|
+
%w(client_id connection_id encoding).each do |attribute|
|
|
128
|
+
context ":#{attribute}" do
|
|
129
|
+
let(:encoded_value) { value.encode(encoding) }
|
|
130
|
+
let(:value) { random_str }
|
|
131
|
+
let(:options) { { attribute.to_sym => encoded_value } }
|
|
132
|
+
let(:model) { subject.new(options, protocol_message) }
|
|
133
|
+
let(:model_attribute) { model.public_send(attribute) }
|
|
134
|
+
|
|
135
|
+
context 'as UTF_8 string' do
|
|
136
|
+
let(:encoding) { Encoding::UTF_8 }
|
|
137
|
+
|
|
138
|
+
it 'is permitted' do
|
|
139
|
+
expect(model_attribute).to eql(encoded_value)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it 'remains as UTF-8' do
|
|
143
|
+
expect(model_attribute.encoding).to eql(Encoding::UTF_8)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
context 'as SHIFT_JIS string' do
|
|
148
|
+
let(:encoding) { Encoding::SHIFT_JIS }
|
|
149
|
+
|
|
150
|
+
it 'gets converted to UTF-8' do
|
|
151
|
+
expect(model_attribute.encoding).to eql(Encoding::UTF_8)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'is compatible with original encoding' do
|
|
155
|
+
expect(model_attribute.encode(encoding)).to eql(encoded_value)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context 'as ASCII_8BIT string' do
|
|
160
|
+
let(:encoding) { Encoding::ASCII_8BIT }
|
|
161
|
+
|
|
162
|
+
it 'gets converted to UTF-8' do
|
|
163
|
+
expect(model_attribute.encoding).to eql(Encoding::UTF_8)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'is compatible with original encoding' do
|
|
167
|
+
expect(model_attribute.encode(encoding)).to eql(encoded_value)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context 'as Integer' do
|
|
172
|
+
let(:encoded_value) { 1 }
|
|
173
|
+
|
|
174
|
+
it 'raises an argument error' do
|
|
175
|
+
expect { model_attribute }.to raise_error ArgumentError, /must be a String/
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
context 'as Nil' do
|
|
180
|
+
let(:encoded_value) { nil }
|
|
181
|
+
|
|
182
|
+
it 'is permitted' do
|
|
183
|
+
expect(model_attribute).to be_nil
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
context '#to_json', :api_private do
|
|
191
|
+
let(:json_object) { JSON.parse(model.to_json) }
|
|
192
|
+
|
|
193
|
+
context 'with valid data' do
|
|
194
|
+
let(:model) { subject.new({ action: 'enter', clientId: 'joe' }, protocol_message) }
|
|
195
|
+
|
|
196
|
+
it 'converts the attribute back to Java mixedCase notation using string keys' do
|
|
197
|
+
expect(json_object["clientId"]).to eql('joe')
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
context 'with invalid data' do
|
|
202
|
+
let(:model) { subject.new({ clientId: 'joe' }, protocol_message) }
|
|
203
|
+
|
|
204
|
+
it 'raises an exception' do
|
|
205
|
+
expect { model.to_json }.to raise_error KeyError, /cannot generate a valid Hash/
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
context 'with binary data' do
|
|
210
|
+
let(:data) { MessagePack.pack(random_str(32)) }
|
|
211
|
+
let(:model) { subject.new({ action: 'enter', data: data }, protocol_message) }
|
|
212
|
+
|
|
213
|
+
it 'encodes as Base64 so that it can be converted to UTF-8 automatically by JSON#dump' do
|
|
214
|
+
expect(json_object["data"]).to eql(::Base64.encode64(data))
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it 'adds Base64 encoding' do
|
|
218
|
+
expect(json_object["encoding"]).to eql('base64')
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
context 'from REST request with embedded fields', :api_private do
|
|
224
|
+
let(:id) { random_str }
|
|
225
|
+
let(:message_time) { Time.now + 60 }
|
|
226
|
+
let(:timestamp) { as_since_epoch(message_time) }
|
|
227
|
+
let(:model) { subject.new(id: id, timestamp: timestamp) }
|
|
228
|
+
|
|
229
|
+
context 'with protocol message' do
|
|
230
|
+
specify '#id prefers embedded ID' do
|
|
231
|
+
expect(model.id).to eql(id)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
specify '#timestamp prefers embedded timestamp' do
|
|
235
|
+
expect(model.timestamp.to_i).to be_within(1).of(message_time.to_i)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
context 'without protocol message' do
|
|
240
|
+
specify '#id uses embedded ID' do
|
|
241
|
+
expect(model.id).to eql(id)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
specify '#timestamp uses embedded timestamp' do
|
|
245
|
+
expect(model.timestamp.to_i).to be_within(1).of(message_time.to_i)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
context 'part of ProtocolMessage', :api_private do
|
|
251
|
+
let(:ably_time) { Time.now + 5 }
|
|
252
|
+
let(:message_serial) { random_int_str(1_000_000) }
|
|
253
|
+
let(:connection_id) { random_str }
|
|
254
|
+
|
|
255
|
+
let(:presence_0_payload) { random_str(8) }
|
|
256
|
+
let(:presence_0_json) do
|
|
257
|
+
{
|
|
258
|
+
client_id: 'zero',
|
|
259
|
+
data: presence_0_payload
|
|
260
|
+
}
|
|
261
|
+
end
|
|
262
|
+
let(:presence_1_payload) { random_str(8) }
|
|
263
|
+
let(:presence_1_json) do
|
|
264
|
+
{
|
|
265
|
+
client_id: 'one',
|
|
266
|
+
data: presence_1_payload
|
|
267
|
+
}
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
let(:protocol_message_id) { random_str }
|
|
271
|
+
let(:protocol_message) do
|
|
272
|
+
Ably::Models::ProtocolMessage.new({
|
|
273
|
+
action: :message,
|
|
274
|
+
timestamp: ably_time.to_i,
|
|
275
|
+
msg_serial: message_serial,
|
|
276
|
+
id: protocol_message_id,
|
|
277
|
+
presence: [
|
|
278
|
+
presence_0_json, presence_1_json
|
|
279
|
+
]
|
|
280
|
+
})
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
let(:presence_0) { protocol_message.presence.first }
|
|
284
|
+
let(:presence_1) { protocol_message.presence.last }
|
|
285
|
+
|
|
286
|
+
it 'should generate a message ID from the index, serial and connection id' do
|
|
287
|
+
expect(presence_0.id).to eql("#{protocol_message_id}:0")
|
|
288
|
+
expect(presence_1.id).to eql("#{protocol_message_id}:1")
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
it 'should not modify the data payload' do
|
|
292
|
+
expect(presence_0.data).to eql(presence_0_payload)
|
|
293
|
+
expect(presence_1.data).to eql(presence_1_payload)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
context 'PresenceMessage conversion method', :api_private do
|
|
298
|
+
let(:json) { { client_id: 'test' } }
|
|
299
|
+
|
|
300
|
+
context 'with JSON' do
|
|
301
|
+
context 'without ProtocolMessage' do
|
|
302
|
+
subject { Ably::Models.PresenceMessage(json) }
|
|
303
|
+
|
|
304
|
+
it 'returns a PresenceMessage object' do
|
|
305
|
+
expect(subject).to be_a(Ably::Models::PresenceMessage)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it 'initializes with the JSON' do
|
|
309
|
+
expect(subject.client_id).to eql('test')
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
it 'raises an exception when accessing ProtocolMessage' do
|
|
313
|
+
expect { subject.protocol_message }.to raise_error RuntimeError
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
it 'has no ProtocolMessage' do
|
|
317
|
+
expect(subject.assigned_to_protocol_message?).to eql(false)
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
context 'with ProtocolMessage' do
|
|
322
|
+
subject { Ably::Models.PresenceMessage(json, protocol_message) }
|
|
323
|
+
|
|
324
|
+
it 'returns a PresenceMessage object' do
|
|
325
|
+
expect(subject).to be_a(Ably::Models::PresenceMessage)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it 'initializes with the JSON' do
|
|
329
|
+
expect(subject.client_id).to eql('test')
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
it 'provides access to ProtocolMessage' do
|
|
333
|
+
expect(subject.protocol_message).to eql(protocol_message)
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
it 'has a ProtocolMessage' do
|
|
337
|
+
expect(subject.assigned_to_protocol_message?).to eql(true)
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
context 'with another PresenceMessage' do
|
|
343
|
+
let(:message) { Ably::Models::PresenceMessage.new(json) }
|
|
344
|
+
|
|
345
|
+
context 'without ProtocolMessage' do
|
|
346
|
+
subject { Ably::Models.PresenceMessage(message) }
|
|
347
|
+
|
|
348
|
+
it 'returns a PresenceMessage object' do
|
|
349
|
+
expect(subject).to be_a(Ably::Models::PresenceMessage)
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
it 'initializes with the JSON' do
|
|
353
|
+
expect(subject.client_id).to eql('test')
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
it 'raises an exception when accessing ProtocolMessage' do
|
|
357
|
+
expect { subject.protocol_message }.to raise_error RuntimeError
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
it 'has no ProtocolMessage' do
|
|
361
|
+
expect(subject.assigned_to_protocol_message?).to eql(false)
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
context 'with ProtocolMessage' do
|
|
366
|
+
subject { Ably::Models.PresenceMessage(message, protocol_message) }
|
|
367
|
+
|
|
368
|
+
it 'returns a PresenceMessage object' do
|
|
369
|
+
expect(subject).to be_a(Ably::Models::PresenceMessage)
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it 'initializes with the JSON' do
|
|
373
|
+
expect(subject.client_id).to eql('test')
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
it 'provides access to ProtocolMessage' do
|
|
377
|
+
expect(subject.protocol_message).to eql(protocol_message)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
it 'has a ProtocolMessage' do
|
|
381
|
+
expect(subject.assigned_to_protocol_message?).to eql(true)
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
end
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
require 'shared/model_behaviour'
|
|
4
|
+
|
|
5
|
+
describe Ably::Models::ProtocolMessage do
|
|
6
|
+
include Ably::Modules::Conversions
|
|
7
|
+
subject { Ably::Models::ProtocolMessage }
|
|
8
|
+
|
|
9
|
+
def new_protocol_message(options)
|
|
10
|
+
subject.new({ action: 1 }.merge(options))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it_behaves_like 'a model',
|
|
14
|
+
with_simple_attributes: %w(id channel channel_serial connection_id),
|
|
15
|
+
base_model_options: { action: 1 } do
|
|
16
|
+
|
|
17
|
+
let(:model_args) { [] }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context 'initializer action coercion', :api_private do
|
|
21
|
+
it 'ignores actions that are Integers' do
|
|
22
|
+
protocol_message = subject.new(action: 14)
|
|
23
|
+
expect(protocol_message.hash[:action]).to eql(14)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'converts actions to Integers if a symbol' do
|
|
27
|
+
protocol_message = subject.new(action: :message)
|
|
28
|
+
expect(protocol_message.hash[:action]).to eql(15)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'converts actions to Integers if a ACTION' do
|
|
32
|
+
protocol_message = subject.new(action: Ably::Models::ProtocolMessage::ACTION.Message)
|
|
33
|
+
expect(protocol_message.hash[:action]).to eql(15)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'raises an argument error if nil' do
|
|
37
|
+
expect { subject.new({}) }.to raise_error(ArgumentError)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'attributes' do
|
|
42
|
+
let(:unique_value) { random_str }
|
|
43
|
+
|
|
44
|
+
context 'Java naming', :api_private do
|
|
45
|
+
let(:protocol_message) { new_protocol_message(channelSerial: unique_value) }
|
|
46
|
+
|
|
47
|
+
it 'converts the attribute to ruby symbol naming convention' do
|
|
48
|
+
expect(protocol_message.channel_serial).to eql(unique_value)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context '#action', :api_private do
|
|
53
|
+
let(:protocol_message) { new_protocol_message(action: 14) }
|
|
54
|
+
|
|
55
|
+
it 'returns an Enum that behaves like a symbol' do
|
|
56
|
+
expect(protocol_message.action).to eq(:presence)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'returns an Enum that behaves like a Numeric' do
|
|
60
|
+
expect(protocol_message.action).to eq(14)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'returns an Enum that behaves like a String' do
|
|
64
|
+
expect(protocol_message.action).to eq('Presence')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'returns an Enum that matchdes the ACTION constant' do
|
|
68
|
+
expect(protocol_message.action).to eql(Ably::Models::ProtocolMessage::ACTION.Presence)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context '#timestamp' do
|
|
73
|
+
let(:protocol_message) { new_protocol_message(timestamp: as_since_epoch(Time.now)) }
|
|
74
|
+
it 'retrieves attribute :timestamp as Time object' do
|
|
75
|
+
expect(protocol_message.timestamp).to be_a(Time)
|
|
76
|
+
expect(protocol_message.timestamp.to_i).to be_within(1).of(Time.now.to_i)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context '#count' do
|
|
81
|
+
context 'when missing' do
|
|
82
|
+
let(:protocol_message) { new_protocol_message({}) }
|
|
83
|
+
it 'is 1' do
|
|
84
|
+
expect(protocol_message.count).to eql(1)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
context 'when non numeric' do
|
|
89
|
+
let(:protocol_message) { new_protocol_message(count: 'A') }
|
|
90
|
+
it 'is 1' do
|
|
91
|
+
expect(protocol_message.count).to eql(1)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context 'when greater than 1' do
|
|
96
|
+
let(:protocol_message) { new_protocol_message(count: '666') }
|
|
97
|
+
it 'is the value of count' do
|
|
98
|
+
expect(protocol_message.count).to eql(666)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context '#message_serial' do
|
|
104
|
+
let(:protocol_message) { new_protocol_message(msg_serial: "55") }
|
|
105
|
+
it 'converts :msg_serial to an Integer' do
|
|
106
|
+
expect(protocol_message.message_serial).to be_a(Integer)
|
|
107
|
+
expect(protocol_message.message_serial).to eql(55)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context '#has_message_serial?' do
|
|
112
|
+
context 'without msg_serial' do
|
|
113
|
+
let(:protocol_message) { new_protocol_message({}) }
|
|
114
|
+
|
|
115
|
+
it 'returns false' do
|
|
116
|
+
expect(protocol_message.has_message_serial?).to eql(false)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context 'with msg_serial' do
|
|
121
|
+
let(:protocol_message) { new_protocol_message(msg_serial: "55") }
|
|
122
|
+
|
|
123
|
+
it 'returns true' do
|
|
124
|
+
expect(protocol_message.has_message_serial?).to eql(true)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
context '#connection_serial' do
|
|
130
|
+
let(:protocol_message) { new_protocol_message(connection_serial: "55") }
|
|
131
|
+
it 'converts :connection_serial to an Integer' do
|
|
132
|
+
expect(protocol_message.connection_serial).to be_a(Integer)
|
|
133
|
+
expect(protocol_message.connection_serial).to eql(55)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
context '#flags' do
|
|
138
|
+
context 'when nil' do
|
|
139
|
+
let(:protocol_message) { new_protocol_message({}) }
|
|
140
|
+
|
|
141
|
+
it 'is zero' do
|
|
142
|
+
expect(protocol_message.flags).to eql(0)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
context 'when numeric' do
|
|
147
|
+
let(:protocol_message) { new_protocol_message(flags: '25') }
|
|
148
|
+
|
|
149
|
+
it 'is an Integer' do
|
|
150
|
+
expect(protocol_message.flags).to eql(25)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context 'when has_presence' do
|
|
155
|
+
let(:protocol_message) { new_protocol_message(flags: 1) }
|
|
156
|
+
|
|
157
|
+
it '#has_presence_flag? is true' do
|
|
158
|
+
expect(protocol_message.has_presence_flag?).to be_truthy
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
context 'when has another future flag' do
|
|
163
|
+
let(:protocol_message) { new_protocol_message(flags: 2) }
|
|
164
|
+
|
|
165
|
+
it '#has_presence_flag? is false' do
|
|
166
|
+
expect(protocol_message.has_presence_flag?).to be_falsey
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context '#has_connection_serial?' do
|
|
172
|
+
context 'without connection_serial' do
|
|
173
|
+
let(:protocol_message) { new_protocol_message({}) }
|
|
174
|
+
|
|
175
|
+
it 'returns false' do
|
|
176
|
+
expect(protocol_message.has_connection_serial?).to eql(false)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
context 'with connection_serial' do
|
|
181
|
+
let(:protocol_message) { new_protocol_message(connection_serial: "55") }
|
|
182
|
+
|
|
183
|
+
it 'returns true' do
|
|
184
|
+
expect(protocol_message.has_connection_serial?).to eql(true)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
context '#serial' do
|
|
190
|
+
context 'with underlying msg_serial' do
|
|
191
|
+
let(:protocol_message) { new_protocol_message(msg_serial: "55") }
|
|
192
|
+
it 'converts :msg_serial to an Integer' do
|
|
193
|
+
expect(protocol_message.serial).to be_a(Integer)
|
|
194
|
+
expect(protocol_message.serial).to eql(55)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
context 'with underlying connection_serial' do
|
|
199
|
+
let(:protocol_message) { new_protocol_message(connection_serial: "55") }
|
|
200
|
+
it 'converts :connection_serial to an Integer' do
|
|
201
|
+
expect(protocol_message.serial).to be_a(Integer)
|
|
202
|
+
expect(protocol_message.serial).to eql(55)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
context 'with underlying connection_serial and msg_serial' do
|
|
207
|
+
let(:protocol_message) { new_protocol_message(connection_serial: "99", msg_serial: "11") }
|
|
208
|
+
it 'prefers connection_serial and converts :connection_serial to an Integer' do
|
|
209
|
+
expect(protocol_message.serial).to be_a(Integer)
|
|
210
|
+
expect(protocol_message.serial).to eql(99)
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
context '#has_serial?' do
|
|
216
|
+
context 'without msg_serial or connection_serial' do
|
|
217
|
+
let(:protocol_message) { new_protocol_message({}) }
|
|
218
|
+
|
|
219
|
+
it 'returns false' do
|
|
220
|
+
expect(protocol_message.has_serial?).to eql(false)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context 'with msg_serial' do
|
|
225
|
+
let(:protocol_message) { new_protocol_message(msg_serial: "55") }
|
|
226
|
+
|
|
227
|
+
it 'returns true' do
|
|
228
|
+
expect(protocol_message.has_serial?).to eql(true)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context 'with connection_serial' do
|
|
233
|
+
let(:protocol_message) { new_protocol_message(connection_serial: "55") }
|
|
234
|
+
|
|
235
|
+
it 'returns true' do
|
|
236
|
+
expect(protocol_message.has_serial?).to eql(true)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
context '#error' do
|
|
242
|
+
context 'with no error attribute' do
|
|
243
|
+
let(:protocol_message) { new_protocol_message(action: 1) }
|
|
244
|
+
|
|
245
|
+
it 'returns nil' do
|
|
246
|
+
expect(protocol_message.error).to be_nil
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
context 'with nil error' do
|
|
251
|
+
let(:protocol_message) { new_protocol_message(error: nil) }
|
|
252
|
+
|
|
253
|
+
it 'returns nil' do
|
|
254
|
+
expect(protocol_message.error).to be_nil
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
context 'with error' do
|
|
259
|
+
let(:protocol_message) { new_protocol_message(error: { message: 'test_error' }) }
|
|
260
|
+
|
|
261
|
+
it 'returns a valid ErrorInfo object' do
|
|
262
|
+
expect(protocol_message.error).to be_a(Ably::Models::ErrorInfo)
|
|
263
|
+
expect(protocol_message.error.message).to eql('test_error')
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
context '#to_json', :api_private do
|
|
270
|
+
let(:json_object) { JSON.parse(model.to_json) }
|
|
271
|
+
let(:message) { { 'name' => 'event', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
|
272
|
+
let(:attached_action) { Ably::Models::ProtocolMessage::ACTION.Attached }
|
|
273
|
+
let(:message_action) { Ably::Models::ProtocolMessage::ACTION.Message }
|
|
274
|
+
|
|
275
|
+
context 'with valid data' do
|
|
276
|
+
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [message] }) }
|
|
277
|
+
|
|
278
|
+
it 'converts the attribute back to Java mixedCase notation using string keys' do
|
|
279
|
+
expect(json_object["channelSerial"]).to eql('unique')
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
it 'populates the messages' do
|
|
283
|
+
expect(json_object["messages"].first).to include(message)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
context 'with missing msg_serial for ack message' do
|
|
288
|
+
let(:model) { new_protocol_message({ :action => message_action }) }
|
|
289
|
+
|
|
290
|
+
it 'it raises an exception' do
|
|
291
|
+
expect { model.to_json }.to raise_error TypeError, /msg_serial.*missing/
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
context 'is aliased by #to_s' do
|
|
296
|
+
let(:model) { new_protocol_message({ :action => attached_action, :channelSerial => 'unique', messages: [message], :timestamp => as_since_epoch(Time.now) }) }
|
|
297
|
+
|
|
298
|
+
specify do
|
|
299
|
+
expect(json_object).to eql(JSON.parse("#{model}"))
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
context '#to_msgpack', :api_private do
|
|
305
|
+
let(:model) { new_protocol_message({ :connectionSerial => 'unique', messages: [message] }) }
|
|
306
|
+
let(:message) { { 'name' => 'event', 'clientId' => 'joe', 'timestamp' => as_since_epoch(Time.now) } }
|
|
307
|
+
let(:packed) { model.to_msgpack }
|
|
308
|
+
let(:unpacked) { MessagePack.unpack(packed) }
|
|
309
|
+
|
|
310
|
+
it 'returns a unpackable msgpack object' do
|
|
311
|
+
expect(unpacked['connectionSerial']).to eq('unique')
|
|
312
|
+
expect(unpacked['messages'][0]['name']).to eq('event')
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
end
|