ably-rest 1.1.2 → 1.2.2
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 +3 -0
- data/CHANGELOG.md +1 -1
- data/MAINTAINERS.md +1 -0
- data/README.md +4 -2
- data/ably-rest.gemspec +15 -18
- data/lib/ably-rest.rb +2 -0
- data/lib/submodules/ably-ruby/.github/workflows/check.yml +50 -0
- data/lib/submodules/ably-ruby/CHANGELOG.md +200 -0
- data/lib/submodules/ably-ruby/COPYRIGHT +1 -0
- data/lib/submodules/ably-ruby/LICENSE +172 -11
- data/lib/submodules/ably-ruby/MAINTAINERS.md +1 -0
- data/lib/submodules/ably-ruby/README.md +24 -22
- data/lib/submodules/ably-ruby/SPEC.md +1020 -929
- data/lib/submodules/ably-ruby/UPDATING.md +30 -0
- data/lib/submodules/ably-ruby/ably.gemspec +16 -23
- data/lib/submodules/ably-ruby/lib/ably/agent.rb +3 -0
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +20 -10
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +8 -2
- data/lib/submodules/ably-ruby/lib/ably/logger.rb +4 -4
- data/lib/submodules/ably-ruby/lib/ably/models/channel_details.rb +59 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_metrics.rb +84 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_occupancy.rb +43 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_options.rb +97 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_status.rb +53 -0
- data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +8 -0
- data/lib/submodules/ably-ruby/lib/ably/models/delta_extras.rb +29 -0
- data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +6 -2
- data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +4 -0
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +28 -3
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +14 -0
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +31 -14
- data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +7 -2
- data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/ably.rb +11 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/channels_collection.rb +22 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +34 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +19 -7
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_properties.rb +24 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +10 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +6 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +56 -28
- data/lib/submodules/ably-ruby/lib/ably/realtime/channels.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +9 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +13 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_state_machine.rb +4 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +67 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +6 -5
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +0 -14
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +44 -29
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +60 -29
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/encoder.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/external_exceptions.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +5 -2
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/logger.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_json.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/version.rb +2 -14
- data/lib/submodules/ably-ruby/lib/ably.rb +1 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +4 -4
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +25 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +476 -21
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channels_spec.rb +59 -7
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +72 -16
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +85 -13
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +301 -34
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +77 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +3 -59
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +84 -158
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +3 -19
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +24 -75
- data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +8 -4
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +141 -10
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +23 -6
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +146 -47
- data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +61 -3
- data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +3 -19
- data/lib/submodules/ably-ruby/spec/lib/unit/models/channel_options_spec.rb +52 -0
- data/lib/submodules/ably-ruby/spec/run_parallel_tests +2 -7
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +131 -8
- data/lib/submodules/ably-ruby/spec/shared/model_behaviour.rb +1 -1
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +12 -2
- data/lib/submodules/ably-ruby/spec/support/serialization_helper.rb +21 -0
- data/lib/submodules/ably-ruby/spec/support/test_app.rb +3 -3
- data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +6 -14
- data/lib/submodules/ably-ruby/spec/unit/models/channel_details_spec.rb +30 -0
- data/lib/submodules/ably-ruby/spec/unit/models/channel_metrics_spec.rb +42 -0
- data/lib/submodules/ably-ruby/spec/unit/models/channel_occupancy_spec.rb +17 -0
- data/lib/submodules/ably-ruby/spec/unit/models/channel_status_spec.rb +36 -0
- data/lib/submodules/ably-ruby/spec/unit/models/delta_extras_spec.rb +14 -0
- data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +17 -1
- data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +97 -0
- data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +49 -0
- data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +125 -27
- data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +14 -0
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +3 -2
- data/lib/submodules/ably-ruby/spec/unit/realtime/channels_spec.rb +53 -15
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +19 -6
- data/lib/submodules/ably-ruby/spec/unit/realtime/incoming_message_dispatcher_spec.rb +38 -0
- data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +44 -1
- data/lib/submodules/ably-ruby/spec/unit/rest/channels_spec.rb +81 -14
- data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +47 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/unit/client_spec.rb +30 -0
- metadata +88 -25
- data/lib/submodules/ably-ruby/.travis.yml +0 -19
|
@@ -498,7 +498,9 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
|
498
498
|
end
|
|
499
499
|
|
|
500
500
|
presence_client_one.enter do
|
|
501
|
-
|
|
501
|
+
EventMachine.add_timer(0.5) do
|
|
502
|
+
presence_client_one.leave
|
|
503
|
+
end
|
|
502
504
|
end
|
|
503
505
|
end
|
|
504
506
|
end
|
|
@@ -705,7 +707,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
|
705
707
|
|
|
706
708
|
context '#sync_complete? and SYNC flags (#RTP1)' do
|
|
707
709
|
context 'when attaching to a channel without any members present' do
|
|
708
|
-
|
|
710
|
+
xit 'sync_complete? is true, there is no presence flag, and the presence channel is considered synced immediately (#RTP1)' do
|
|
709
711
|
flag_checked = false
|
|
710
712
|
|
|
711
713
|
anonymous_client.connection.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
|
@@ -1211,10 +1213,11 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
|
1211
1213
|
channel_client_one.attach do
|
|
1212
1214
|
presence_client_one.subscribe(:enter) do
|
|
1213
1215
|
presence_client_one.unsubscribe :enter
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1216
|
+
EventMachine.add_timer(0.5) do
|
|
1217
|
+
expect(presence_client_one.members).to be_in_sync
|
|
1218
|
+
expect(presence_client_one.members.send(:members).count).to eql(1)
|
|
1219
|
+
presence_client_one.leave data
|
|
1220
|
+
end
|
|
1218
1221
|
end
|
|
1219
1222
|
|
|
1220
1223
|
presence_client_one.enter(enter_data) do
|
|
@@ -2137,16 +2140,18 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
|
2137
2140
|
end
|
|
2138
2141
|
|
|
2139
2142
|
it 'emits an error when cipher does not match and presence data cannot be decoded' do
|
|
2140
|
-
incompatible_encrypted_channel.
|
|
2143
|
+
incompatible_encrypted_channel.once(:attached) do
|
|
2141
2144
|
expect(client_two.logger).to receive(:error) do |*args, &block|
|
|
2142
2145
|
expect(args.concat([block ? block.call : nil]).join(',')).to match(/Cipher algorithm AES-128-CBC does not match/)
|
|
2143
2146
|
stop_reactor
|
|
2144
|
-
end
|
|
2147
|
+
end.at_least(:once)
|
|
2145
2148
|
|
|
2146
2149
|
encrypted_channel.attach do
|
|
2147
2150
|
encrypted_channel.presence.enter data
|
|
2148
2151
|
end
|
|
2149
2152
|
end
|
|
2153
|
+
|
|
2154
|
+
incompatible_encrypted_channel.attach
|
|
2150
2155
|
end
|
|
2151
2156
|
end
|
|
2152
2157
|
end
|
|
@@ -2449,173 +2454,77 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
|
2449
2454
|
end
|
|
2450
2455
|
end
|
|
2451
2456
|
|
|
2452
|
-
|
|
2453
|
-
let(:
|
|
2454
|
-
let(:sync_action) { Ably::Models::ProtocolMessage::ACTION.Sync.to_i }
|
|
2455
|
-
let(:presence_action) { Ably::Models::ProtocolMessage::ACTION.Presence.to_i }
|
|
2456
|
-
let(:present_action) { Ably::Models::PresenceMessage::ACTION.Present.to_i }
|
|
2457
|
-
let(:resume_flag) { 4 }
|
|
2458
|
-
let(:presence_flag) { 1 }
|
|
2459
|
-
|
|
2460
|
-
def fabricate_incoming_protocol_message(protocol_message)
|
|
2461
|
-
client_one.connection.__incoming_protocol_msgbus__.publish :protocol_message, protocol_message
|
|
2462
|
-
end
|
|
2463
|
-
|
|
2464
|
-
# Prevents any messages from the WebSocket transport being sent / received
|
|
2465
|
-
# Connection protocol message subscriptions are still active, but nothing reaches or comes from the WebSocket transport
|
|
2466
|
-
def cripple_websocket_transport
|
|
2467
|
-
client_one.connection.transport.__incoming_protocol_msgbus__.unsubscribe
|
|
2468
|
-
client_one.connection.transport.__outgoing_protocol_msgbus__.unsubscribe
|
|
2469
|
-
end
|
|
2457
|
+
describe '#RTP17b' do
|
|
2458
|
+
let(:leave_action) { Ably::Models::PresenceMessage::ACTION.Leave }
|
|
2470
2459
|
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
client_one.connection.transport.__outgoing_protocol_msgbus__.subscribe do |message|
|
|
2479
|
-
raise "No presence state updates to Ably are expected. Message sent: #{message.to_json}" if client_one.connection.connected?
|
|
2460
|
+
it 'updates presence members on leave' do
|
|
2461
|
+
presence_client_two.subscribe(:enter) do
|
|
2462
|
+
channel_anonymous_client.attach do
|
|
2463
|
+
channel_anonymous_client.presence.get do |members|
|
|
2464
|
+
presence_client_two.subscribe(:leave) do
|
|
2465
|
+
expect(presence_client_two.members.local_members).to be_empty
|
|
2466
|
+
stop_reactor
|
|
2480
2467
|
end
|
|
2481
2468
|
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2469
|
+
leave_message = Ably::Models::PresenceMessage.new(
|
|
2470
|
+
'id' => "#{client_two.connection.id}:#{presence_client_two.client_id}:1",
|
|
2471
|
+
'clientId' => presence_client_two.client_id,
|
|
2472
|
+
'connectionId' => client_two.connection.id,
|
|
2473
|
+
'timestamp' => as_since_epoch(Time.now),
|
|
2474
|
+
'action' => leave_action
|
|
2488
2475
|
)
|
|
2489
2476
|
|
|
2490
|
-
|
|
2491
|
-
presence_client_one.get do |members|
|
|
2492
|
-
expect(members.length).to eql(1)
|
|
2493
|
-
expect(presence_client_one.members.local_members.length).to eql(1)
|
|
2494
|
-
stop_reactor
|
|
2495
|
-
end
|
|
2496
|
-
end
|
|
2477
|
+
presence_client_two.__incoming_msgbus__.publish :presence, leave_message
|
|
2497
2478
|
end
|
|
2498
2479
|
end
|
|
2499
2480
|
end
|
|
2500
2481
|
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
it 'does nothing as MemberMap is in sync (#RTP5c2)' do
|
|
2504
|
-
presence_client_one.enter
|
|
2505
|
-
presence_client_one.subscribe(:enter) do
|
|
2506
|
-
presence_client_one.unsubscribe :enter
|
|
2507
|
-
|
|
2508
|
-
expect(presence_client_one.members.length).to eql(1)
|
|
2509
|
-
expect(presence_client_one.members.local_members.length).to eql(1)
|
|
2510
|
-
|
|
2511
|
-
presence_client_one.members.once(:in_sync) do
|
|
2512
|
-
presence_client_one.get do |members|
|
|
2513
|
-
expect(members.length).to eql(1)
|
|
2514
|
-
expect(presence_client_one.members.local_members.length).to eql(1)
|
|
2515
|
-
stop_reactor
|
|
2516
|
-
end
|
|
2517
|
-
end
|
|
2518
|
-
|
|
2519
|
-
client_one.connection.transport.__outgoing_protocol_msgbus__.subscribe do |message|
|
|
2520
|
-
raise "No presence state updates to Ably are expected. Message sent: #{message.to_json}" if client_one.connection.connected?
|
|
2521
|
-
end
|
|
2482
|
+
presence_client_two.enter
|
|
2483
|
+
end
|
|
2522
2484
|
|
|
2523
|
-
|
|
2485
|
+
it 'does no update presence members on fabricated leave' do
|
|
2486
|
+
presence_client_two.subscribe(:enter) do
|
|
2487
|
+
channel_anonymous_client.attach do
|
|
2488
|
+
channel_anonymous_client.presence.get do |members|
|
|
2489
|
+
presence_client_two.subscribe(:leave) do
|
|
2490
|
+
expect(presence_client_two.members.local_members).to_not be_empty
|
|
2491
|
+
stop_reactor
|
|
2492
|
+
end
|
|
2524
2493
|
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
)
|
|
2494
|
+
fabricated_leave_message = Ably::Models::PresenceMessage.new(
|
|
2495
|
+
'id' => "#{client_two.connection.id}:#{presence_client_two.client_id}:1",
|
|
2496
|
+
'clientId' => presence_client_two.client_id,
|
|
2497
|
+
'connectionId' => "fabricated:#{presence_client_two.client_id}:0",
|
|
2498
|
+
'timestamp' => as_since_epoch(Time.now),
|
|
2499
|
+
'action' => leave_action
|
|
2500
|
+
)
|
|
2530
2501
|
|
|
2531
|
-
|
|
2532
|
-
action: sync_action,
|
|
2533
|
-
channel: channel_name,
|
|
2534
|
-
presence: presence_client_one.members.map(&:shallow_clone).map(&:as_json),
|
|
2535
|
-
channelSerial: nil # no further SYNC messages expected
|
|
2536
|
-
)
|
|
2537
|
-
end
|
|
2502
|
+
presence_client_two.__incoming_msgbus__.publish :presence, fabricated_leave_message
|
|
2538
2503
|
end
|
|
2539
2504
|
end
|
|
2505
|
+
end
|
|
2540
2506
|
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
presence_client_one.enter
|
|
2546
|
-
presence_client_one.subscribe(:enter) do
|
|
2547
|
-
presence_client_one.unsubscribe :enter
|
|
2548
|
-
|
|
2549
|
-
expect(presence_client_one.members.length).to eql(1)
|
|
2550
|
-
expect(presence_client_one.members.local_members.length).to eql(1)
|
|
2551
|
-
|
|
2552
|
-
client_one.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |message|
|
|
2553
|
-
next if message.action == :close # ignore finalization of connection
|
|
2554
|
-
|
|
2555
|
-
expect(message.action).to eq(:presence)
|
|
2556
|
-
presence_message = message.presence.first
|
|
2557
|
-
expect(presence_message.action).to eq(:enter)
|
|
2558
|
-
expect(presence_message.client_id).to eq(client_one.auth.client_id)
|
|
2559
|
-
|
|
2560
|
-
presence_client_one.subscribe(:enter) do |message|
|
|
2561
|
-
expect(message.connection_id).to eql(client_one.connection.id)
|
|
2562
|
-
expect(message.client_id).to eq(client_one.auth.client_id)
|
|
2563
|
-
|
|
2564
|
-
EventMachine.next_tick do
|
|
2565
|
-
expect(presence_client_one.members.length).to eql(2)
|
|
2566
|
-
expect(presence_client_one.members.local_members.length).to eql(1)
|
|
2567
|
-
expect(sync_check_completed).to be_truthy
|
|
2568
|
-
stop_reactor
|
|
2569
|
-
end
|
|
2570
|
-
end
|
|
2571
|
-
|
|
2572
|
-
# Fabricate Ably sending back the Enter PresenceMessage to the client a short while after
|
|
2573
|
-
# ensuring the PresenceMap for a short period does not have this member as to be expected in reality
|
|
2574
|
-
EventMachine.add_timer(0.2) do
|
|
2575
|
-
connection_id = random_str
|
|
2576
|
-
fabricate_incoming_protocol_message Ably::Models::ProtocolMessage.new(
|
|
2577
|
-
action: presence_action,
|
|
2578
|
-
channel: channel_name,
|
|
2579
|
-
connectionId: client_one.connection.id,
|
|
2580
|
-
connectionSerial: 50,
|
|
2581
|
-
timestamp: as_since_epoch(Time.now),
|
|
2582
|
-
presence: [presence_message.shallow_clone(id: "#{client_one.connection.id}:0:0", timestamp: as_since_epoch(Time.now)).as_json]
|
|
2583
|
-
)
|
|
2584
|
-
end
|
|
2585
|
-
end
|
|
2586
|
-
|
|
2587
|
-
presence_client_one.members.once(:in_sync) do
|
|
2588
|
-
# For a brief period, the client will have re-entered the missing members from the local_members
|
|
2589
|
-
# but the enter from Ably will have not been received, so at this point the local_members will be empty
|
|
2590
|
-
presence_client_one.get do |members|
|
|
2591
|
-
expect(members.length).to eql(1)
|
|
2592
|
-
expect(members.first.connection_id).to_not eql(client_one.connection.id)
|
|
2593
|
-
expect(presence_client_one.members.local_members.length).to eql(0)
|
|
2594
|
-
sync_check_completed = true
|
|
2595
|
-
end
|
|
2596
|
-
end
|
|
2507
|
+
presence_client_two.enter
|
|
2508
|
+
end
|
|
2509
|
+
end
|
|
2597
2510
|
|
|
2598
|
-
|
|
2511
|
+
context 'when a channel becomes attached again' do
|
|
2512
|
+
let(:attached_action) { Ably::Models::ProtocolMessage::ACTION.Attached.to_i }
|
|
2513
|
+
let(:sync_action) { Ably::Models::ProtocolMessage::ACTION.Sync.to_i }
|
|
2514
|
+
let(:presence_action) { Ably::Models::ProtocolMessage::ACTION.Presence.to_i }
|
|
2515
|
+
let(:present_action) { Ably::Models::PresenceMessage::ACTION.Present.to_i }
|
|
2516
|
+
let(:resume_flag) { 4 }
|
|
2517
|
+
let(:presence_flag) { 1 }
|
|
2599
2518
|
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
flags: resume_flag + presence_flag
|
|
2604
|
-
)
|
|
2519
|
+
def fabricate_incoming_protocol_message(protocol_message)
|
|
2520
|
+
client_one.connection.__incoming_protocol_msgbus__.publish :protocol_message, protocol_message
|
|
2521
|
+
end
|
|
2605
2522
|
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
timestamp: as_since_epoch(Time.now),
|
|
2612
|
-
presence: [{ id: "#{connection_id}:0:0", action: present_action, connection_id: connection_id, client_id: random_str }],
|
|
2613
|
-
chanenlSerial: nil # no further SYNC messages expected
|
|
2614
|
-
)
|
|
2615
|
-
end
|
|
2616
|
-
end
|
|
2617
|
-
end
|
|
2618
|
-
end
|
|
2523
|
+
# Prevents any messages from the WebSocket transport being sent / received
|
|
2524
|
+
# Connection protocol message subscriptions are still active, but nothing reaches or comes from the WebSocket transport
|
|
2525
|
+
def cripple_websocket_transport
|
|
2526
|
+
client_one.connection.transport.__incoming_protocol_msgbus__.unsubscribe
|
|
2527
|
+
client_one.connection.transport.__outgoing_protocol_msgbus__.unsubscribe
|
|
2619
2528
|
end
|
|
2620
2529
|
|
|
2621
2530
|
context 'and the resume flag is false' do
|
|
@@ -2725,7 +2634,24 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
|
2725
2634
|
end
|
|
2726
2635
|
end
|
|
2727
2636
|
|
|
2728
|
-
context 'channel state side effects' do
|
|
2637
|
+
context 'channel state side effects (RTP5)' do
|
|
2638
|
+
context 'channel transitions to the ATTACHED state (RTP5b)' do
|
|
2639
|
+
it 'all queued presence messages are sent' do
|
|
2640
|
+
channel_client_one.on(:attached) do
|
|
2641
|
+
client_one.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
|
2642
|
+
if protocol_message.action == :presence
|
|
2643
|
+
expect(protocol_message.action).to eq(:presence)
|
|
2644
|
+
stop_reactor
|
|
2645
|
+
end
|
|
2646
|
+
end
|
|
2647
|
+
end
|
|
2648
|
+
|
|
2649
|
+
presence_client_one.enter do
|
|
2650
|
+
channel_client_one.attach
|
|
2651
|
+
end
|
|
2652
|
+
end
|
|
2653
|
+
end
|
|
2654
|
+
|
|
2729
2655
|
context 'channel transitions to the FAILED state' do
|
|
2730
2656
|
let(:anonymous_client) { auto_close Ably::Realtime::Client.new(client_options.merge(log_level: :fatal)) }
|
|
2731
2657
|
let(:client_one) { auto_close Ably::Realtime::Client.new(client_options.merge(client_id: client_one_id, log_level: :fatal)) }
|
|
@@ -101,31 +101,15 @@ describe Ably::Realtime::Push::Admin, :event_machine do
|
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
-
def request_body(request, protocol)
|
|
105
|
-
if protocol == :msgpack
|
|
106
|
-
MessagePack.unpack(request.body)
|
|
107
|
-
else
|
|
108
|
-
JSON.parse(request.body)
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def serialize(object, protocol)
|
|
113
|
-
if protocol == :msgpack
|
|
114
|
-
MessagePack.pack(object)
|
|
115
|
-
else
|
|
116
|
-
JSON.dump(object)
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
|
|
120
104
|
let!(:publish_stub) do
|
|
121
105
|
stub_request(:post, "#{client.rest_client.endpoint}/push/publish").
|
|
122
106
|
with do |request|
|
|
123
|
-
expect(
|
|
124
|
-
expect(
|
|
107
|
+
expect(deserialize_body(request.body, protocol)['recipient']['camelCase']['secondLevelCamelCase']).to eql('val')
|
|
108
|
+
expect(deserialize_body(request.body, protocol)['recipient']).to_not have_key('camel_case')
|
|
125
109
|
true
|
|
126
110
|
end.to_return(
|
|
127
111
|
:status => 201,
|
|
128
|
-
:body =>
|
|
112
|
+
:body => serialize_body({}, protocol),
|
|
129
113
|
:headers => { 'Content-Type' => content_type }
|
|
130
114
|
)
|
|
131
115
|
end
|
|
@@ -41,22 +41,10 @@ describe Ably::Auth do
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def request_body_includes(request, protocol, key, val)
|
|
44
|
-
body =
|
|
45
|
-
MessagePack.unpack(request.body)
|
|
46
|
-
else
|
|
47
|
-
JSON.parse(request.body)
|
|
48
|
-
end
|
|
44
|
+
body = deserialize_body(request.body, protocol)
|
|
49
45
|
body[convert_to_mixed_case(key)].to_s == val.to_s
|
|
50
46
|
end
|
|
51
47
|
|
|
52
|
-
def serialize(object, protocol)
|
|
53
|
-
if protocol == :msgpack
|
|
54
|
-
MessagePack.pack(object)
|
|
55
|
-
else
|
|
56
|
-
JSON.dump(object)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
48
|
it 'has immutable options' do
|
|
61
49
|
expect { auth.options['key_name'] = 'new_name' }.to raise_error RuntimeError, /can't modify frozen.*Hash/
|
|
62
50
|
end
|
|
@@ -74,7 +62,7 @@ describe Ably::Auth do
|
|
|
74
62
|
|
|
75
63
|
it 'creates a TokenRequest automatically and sends it to Ably to obtain a token', webmock: true do
|
|
76
64
|
token_request_stub = stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken").
|
|
77
|
-
to_return(status: 201, body:
|
|
65
|
+
to_return(status: 201, body: serialize_body({}, protocol), headers: { 'Content-Type' => content_type })
|
|
78
66
|
expect(auth).to receive(:create_token_request).and_call_original
|
|
79
67
|
auth.request_token
|
|
80
68
|
|
|
@@ -107,7 +95,7 @@ describe Ably::Auth do
|
|
|
107
95
|
request_body_includes(request, protocol, token_param, coerce_if_time_value(token_param, random, multiply: 1000))
|
|
108
96
|
end.to_return(
|
|
109
97
|
:status => 201,
|
|
110
|
-
:body =>
|
|
98
|
+
:body => serialize_body(token_response, protocol),
|
|
111
99
|
:headers => { 'Content-Type' => content_type }
|
|
112
100
|
)
|
|
113
101
|
end
|
|
@@ -138,7 +126,7 @@ describe Ably::Auth do
|
|
|
138
126
|
request_body_includes(request, protocol, 'mac', mac)
|
|
139
127
|
end.to_return(
|
|
140
128
|
:status => 201,
|
|
141
|
-
:body =>
|
|
129
|
+
:body => serialize_body(token_response, protocol),
|
|
142
130
|
:headers => { 'Content-Type' => content_type })
|
|
143
131
|
end
|
|
144
132
|
|
|
@@ -168,7 +156,7 @@ describe Ably::Auth do
|
|
|
168
156
|
request_body_includes(request, protocol, 'mac', mac)
|
|
169
157
|
end.to_return(
|
|
170
158
|
:status => 201,
|
|
171
|
-
:body =>
|
|
159
|
+
:body => serialize_body(token_response, protocol),
|
|
172
160
|
:headers => { 'Content-Type' => content_type })
|
|
173
161
|
end
|
|
174
162
|
|
|
@@ -310,7 +298,7 @@ describe Ably::Auth do
|
|
|
310
298
|
request_body_includes(request, protocol, 'key_name', key_name)
|
|
311
299
|
end.to_return(
|
|
312
300
|
:status => 201,
|
|
313
|
-
:body =>
|
|
301
|
+
:body => serialize_body(token_response, protocol),
|
|
314
302
|
:headers => { 'Content-Type' => content_type }
|
|
315
303
|
)
|
|
316
304
|
end
|
|
@@ -1129,63 +1117,6 @@ describe Ably::Auth do
|
|
|
1129
1117
|
end
|
|
1130
1118
|
end
|
|
1131
1119
|
|
|
1132
|
-
context 'when implicit as a result of using :client_id' do
|
|
1133
|
-
let(:client_id) { '999' }
|
|
1134
|
-
let(:client) do
|
|
1135
|
-
Ably::Rest::Client.new(key: api_key, client_id: client_id, environment: environment, protocol: protocol)
|
|
1136
|
-
end
|
|
1137
|
-
let(:token) { 'unique-token' }
|
|
1138
|
-
let(:token_response) do
|
|
1139
|
-
{
|
|
1140
|
-
token: token
|
|
1141
|
-
}.to_json
|
|
1142
|
-
end
|
|
1143
|
-
|
|
1144
|
-
context 'and requests to the Ably server are mocked', :webmock do
|
|
1145
|
-
let!(:request_token_stub) do
|
|
1146
|
-
stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken").
|
|
1147
|
-
to_return(:status => 201, :body => token_response, :headers => { 'Content-Type' => 'application/json' })
|
|
1148
|
-
end
|
|
1149
|
-
let!(:publish_message_stub) do
|
|
1150
|
-
stub_request(:post, "#{client.endpoint}/channels/foo/publish").
|
|
1151
|
-
with(headers: { 'Authorization' => "Bearer #{encode64(token)}" }).
|
|
1152
|
-
to_return(status: 201, body: '{}', headers: { 'Content-Type' => 'application/json' })
|
|
1153
|
-
end
|
|
1154
|
-
|
|
1155
|
-
it 'will send a token request to the server' do
|
|
1156
|
-
client.channel('foo').publish('event', 'data')
|
|
1157
|
-
expect(request_token_stub).to have_been_requested
|
|
1158
|
-
end
|
|
1159
|
-
end
|
|
1160
|
-
|
|
1161
|
-
describe 'a token is created' do
|
|
1162
|
-
let(:token) { client.auth.current_token_details }
|
|
1163
|
-
|
|
1164
|
-
it 'before a request is made' do
|
|
1165
|
-
expect(token).to be_nil
|
|
1166
|
-
end
|
|
1167
|
-
|
|
1168
|
-
it 'when a message is published' do
|
|
1169
|
-
expect(client.channel('foo').publish('event', 'data')).to be_truthy
|
|
1170
|
-
end
|
|
1171
|
-
|
|
1172
|
-
it 'with capability and TTL defaults (#TK2a, #TK2b)' do
|
|
1173
|
-
client.channel('foo').publish('event', 'data')
|
|
1174
|
-
|
|
1175
|
-
expect(token).to be_a(Ably::Models::TokenDetails)
|
|
1176
|
-
capability_with_str_key = { "*" => ["*"] } # Ably default is all capabilities
|
|
1177
|
-
capability = Hash[capability_with_str_key.keys.map(&:to_s).zip(capability_with_str_key.values)]
|
|
1178
|
-
expect(token.capability).to eq(capability)
|
|
1179
|
-
expect(token.expires.to_i).to be_within(2).of(Time.now.to_i + 60 * 60) # Ably default is 1hr
|
|
1180
|
-
expect(token.client_id).to eq(client_id)
|
|
1181
|
-
end
|
|
1182
|
-
|
|
1183
|
-
specify '#client_id contains the client_id' do
|
|
1184
|
-
expect(client.auth.client_id).to eql(client_id)
|
|
1185
|
-
end
|
|
1186
|
-
end
|
|
1187
|
-
end
|
|
1188
|
-
|
|
1189
1120
|
context 'when token expires' do
|
|
1190
1121
|
before do
|
|
1191
1122
|
stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', 0 # allow token to be used even if about to expire
|
|
@@ -1234,6 +1165,24 @@ describe Ably::Auth do
|
|
|
1234
1165
|
end
|
|
1235
1166
|
end
|
|
1236
1167
|
|
|
1168
|
+
context 'when token does not expire' do
|
|
1169
|
+
let(:client_options) { default_options.merge(use_token_auth: true, key: api_key, query_time: true) }
|
|
1170
|
+
let(:channel) { client.channels.get(random_str) }
|
|
1171
|
+
|
|
1172
|
+
context 'for the next 2 hours' do
|
|
1173
|
+
let(:local_time) { Time.now - 2 * 60 * 60 }
|
|
1174
|
+
|
|
1175
|
+
before { allow(Time).to receive(:now).and_return(local_time) }
|
|
1176
|
+
|
|
1177
|
+
it 'should not request for the new token (#RSA4b1)' do
|
|
1178
|
+
expect { channel.publish 'event' }.to change { auth.current_token_details }
|
|
1179
|
+
expect do
|
|
1180
|
+
expect { channel.publish 'event' }.not_to change { auth.current_token_details }
|
|
1181
|
+
end.not_to change { auth.current_token_details.expires }
|
|
1182
|
+
end
|
|
1183
|
+
end
|
|
1184
|
+
end
|
|
1185
|
+
|
|
1237
1186
|
context 'when :client_id is provided in a token' do
|
|
1238
1187
|
let(:client_id) { '123' }
|
|
1239
1188
|
let(:token) do
|
|
@@ -87,8 +87,10 @@ describe Ably::Rest do
|
|
|
87
87
|
let(:error_response) { '{ "error": { "statusCode": 500, "code": 50000, "message": "Internal error" } }' }
|
|
88
88
|
|
|
89
89
|
before do
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
(client.fallback_hosts.map { |host| "https://#{host}" } + [client.endpoint]).each do |host|
|
|
91
|
+
stub_request(:get, "#{host}/time")
|
|
92
|
+
.to_return(:status => 500, :body => error_response, :headers => { 'Content-Type' => 'application/json' })
|
|
93
|
+
end
|
|
92
94
|
end
|
|
93
95
|
|
|
94
96
|
it 'should raise a ServerError exception' do
|
|
@@ -98,8 +100,10 @@ describe Ably::Rest do
|
|
|
98
100
|
|
|
99
101
|
describe '500 server error without a valid JSON response body', :webmock do
|
|
100
102
|
before do
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
(client.fallback_hosts.map { |host| "https://#{host}" } + [client.endpoint]).each do |host|
|
|
104
|
+
stub_request(:get, "#{host}/time").
|
|
105
|
+
to_return(:status => 500, :headers => { 'Content-Type' => 'application/json' })
|
|
106
|
+
end
|
|
103
107
|
end
|
|
104
108
|
|
|
105
109
|
it 'should raise a ServerError exception' do
|