ably-rest 1.0.5 → 1.1.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.
Files changed (118) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +6 -3
  3. data/CHANGELOG.md +1 -1
  4. data/LICENSE +1 -1
  5. data/README.md +26 -7
  6. data/SPEC.md +2003 -1605
  7. data/ably-rest.gemspec +4 -2
  8. data/lib/submodules/ably-ruby/.editorconfig +14 -0
  9. data/lib/submodules/ably-ruby/.travis.yml +10 -8
  10. data/lib/submodules/ably-ruby/CHANGELOG.md +97 -1
  11. data/lib/submodules/ably-ruby/LICENSE +1 -3
  12. data/lib/submodules/ably-ruby/README.md +12 -7
  13. data/lib/submodules/ably-ruby/Rakefile +32 -0
  14. data/lib/submodules/ably-ruby/SPEC.md +1277 -835
  15. data/lib/submodules/ably-ruby/ably.gemspec +17 -11
  16. data/lib/submodules/ably-ruby/lib/ably/auth.rb +34 -8
  17. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -4
  18. data/lib/submodules/ably-ruby/lib/ably/logger.rb +8 -2
  19. data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +1 -1
  20. data/lib/submodules/ably-ruby/lib/ably/models/connection_state_change.rb +1 -1
  21. data/lib/submodules/ably-ruby/lib/ably/models/device_details.rb +87 -0
  22. data/lib/submodules/ably-ruby/lib/ably/models/device_push_details.rb +86 -0
  23. data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +23 -2
  24. data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +12 -12
  25. data/lib/submodules/ably-ruby/lib/ably/models/message.rb +6 -4
  26. data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +6 -4
  27. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +32 -2
  28. data/lib/submodules/ably-ruby/lib/ably/models/push_channel_subscription.rb +89 -0
  29. data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +2 -2
  30. data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +2 -2
  31. data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +2 -2
  32. data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +2 -2
  33. data/lib/submodules/ably-ruby/lib/ably/modules/exception_codes.rb +128 -0
  34. data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +15 -2
  35. data/lib/submodules/ably-ruby/lib/ably/modules/safe_deferrable.rb +1 -1
  36. data/lib/submodules/ably-ruby/lib/ably/modules/safe_yield.rb +1 -1
  37. data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +5 -5
  38. data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +2 -2
  39. data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
  40. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +2 -2
  41. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +27 -105
  42. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +4 -8
  43. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_state_machine.rb +2 -2
  44. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/publisher.rb +74 -0
  45. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/push_channel.rb +62 -0
  46. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +91 -3
  47. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +9 -4
  48. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +1 -1
  49. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +45 -26
  50. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +25 -9
  51. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +2 -2
  52. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +7 -7
  53. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +9 -9
  54. data/lib/submodules/ably-ruby/lib/ably/realtime/push.rb +40 -0
  55. data/lib/submodules/ably-ruby/lib/ably/realtime/push/admin.rb +61 -0
  56. data/lib/submodules/ably-ruby/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
  57. data/lib/submodules/ably-ruby/lib/ably/realtime/push/device_registrations.rb +105 -0
  58. data/lib/submodules/ably-ruby/lib/ably/rest.rb +1 -0
  59. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +54 -18
  60. data/lib/submodules/ably-ruby/lib/ably/rest/channel/push_channel.rb +62 -0
  61. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +171 -41
  62. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/parse_message_pack.rb +17 -1
  63. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -0
  64. data/lib/submodules/ably-ruby/lib/ably/rest/push.rb +42 -0
  65. data/lib/submodules/ably-ruby/lib/ably/rest/push/admin.rb +54 -0
  66. data/lib/submodules/ably-ruby/lib/ably/rest/push/channel_subscriptions.rb +121 -0
  67. data/lib/submodules/ably-ruby/lib/ably/rest/push/device_registrations.rb +103 -0
  68. data/lib/submodules/ably-ruby/lib/ably/version.rb +7 -2
  69. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +253 -49
  70. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +33 -21
  71. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +180 -62
  72. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +155 -2
  73. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +293 -13
  74. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +142 -39
  75. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +38 -36
  76. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +12 -3
  77. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +207 -173
  78. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_admin_spec.rb +736 -0
  79. data/lib/submodules/ably-ruby/spec/acceptance/realtime/push_spec.rb +27 -0
  80. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +62 -51
  81. data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +2 -2
  82. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +79 -4
  83. data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +6 -0
  84. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +318 -74
  85. data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +158 -6
  86. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_admin_spec.rb +952 -0
  87. data/lib/submodules/ably-ruby/spec/acceptance/rest/push_spec.rb +25 -0
  88. data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +1 -1
  89. data/lib/submodules/ably-ruby/spec/run_parallel_tests +33 -0
  90. data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +1 -9
  91. data/lib/submodules/ably-ruby/spec/spec_helper.rb +3 -1
  92. data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +9 -5
  93. data/lib/submodules/ably-ruby/spec/support/event_emitter_helper.rb +31 -0
  94. data/lib/submodules/ably-ruby/spec/support/event_machine_helper.rb +1 -1
  95. data/lib/submodules/ably-ruby/spec/support/test_app.rb +2 -2
  96. data/lib/submodules/ably-ruby/spec/support/test_logger_helper.rb +42 -0
  97. data/lib/submodules/ably-ruby/spec/unit/logger_spec.rb +11 -12
  98. data/lib/submodules/ably-ruby/spec/unit/models/device_details_spec.rb +102 -0
  99. data/lib/submodules/ably-ruby/spec/unit/models/device_push_details_spec.rb +101 -0
  100. data/lib/submodules/ably-ruby/spec/unit/models/error_info_spec.rb +51 -3
  101. data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +17 -2
  102. data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +1 -1
  103. data/lib/submodules/ably-ruby/spec/unit/models/push_channel_subscription_spec.rb +86 -0
  104. data/lib/submodules/ably-ruby/spec/unit/modules/async_wrapper_spec.rb +2 -2
  105. data/lib/submodules/ably-ruby/spec/unit/modules/enum_spec.rb +1 -1
  106. data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +3 -3
  107. data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +10 -10
  108. data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +1 -1
  109. data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +13 -1
  110. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +2 -2
  111. data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +1 -1
  112. data/lib/submodules/ably-ruby/spec/unit/realtime/push_channel_spec.rb +36 -0
  113. data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +30 -1
  114. data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +30 -0
  115. data/lib/submodules/ably-ruby/spec/unit/rest/push_channel_spec.rb +36 -0
  116. data/lib/submodules/ably-ruby/spec/unit/util/pub_sub_spec.rb +3 -3
  117. data/spec/spec_helper.rb +1 -0
  118. metadata +51 -10
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Ably::Rest::Push do
5
+ vary_by_protocol do
6
+ let(:default_options) { { key: api_key, environment: environment, protocol: protocol} }
7
+ let(:client_options) { default_options }
8
+ let(:client) do
9
+ Ably::Rest::Client.new(client_options)
10
+ end
11
+ subject { client.push }
12
+
13
+ describe '#activate' do
14
+ it 'raises an unsupported exception' do
15
+ expect { subject.activate('foo') }.to raise_error(Ably::Exceptions::PushNotificationsNotSupported)
16
+ end
17
+ end
18
+
19
+ describe '#deactivate' do
20
+ it 'raises an unsupported exception' do
21
+ expect { subject.deactivate('foo') }.to raise_error(Ably::Exceptions::PushNotificationsNotSupported)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -13,7 +13,7 @@ describe Ably::Rest::Client, '#time' do
13
13
 
14
14
  context 'with reconfigured HTTP timeout' do
15
15
  let(:client) do
16
- Ably::Rest::Client.new(http_request_timeout: 0.0001, key: api_key, environment: environment, protocol: protocol)
16
+ Ably::Rest::Client.new(http_request_timeout: 0.0001, key: api_key, environment: environment, protocol: protocol, log_retries_as_info: true)
17
17
  end
18
18
 
19
19
  it 'should raise a timeout exception' do
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+ #
3
+ # Run the unit tests first without RSpec parallel, then run acceptance tests in parallel
4
+ #
5
+ # When splitting all tests across all parallel processes, it's quite plausible
6
+ # that some processes only run a majority of unit tests, whilst others only run a
7
+ # a majority of acceptance tests. This ensures acceptance tests are split out.
8
+
9
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
10
+
11
+ bundle exec rspec "${DIR}/unit"
12
+ unit_status=$?
13
+
14
+ if ruby -v | grep -e "1.9"; then
15
+ # Output with test ID is not supported with this old version of RSpec
16
+ # So it will be jumbled sadly for 1.9.*
17
+ bundle exec parallel_rspec "${DIR}/acceptance"
18
+ else
19
+ bundle exec parallel_rspec "${DIR}/acceptance" --prefix-output-with-test-env-number
20
+ fi
21
+ acceptance_status=$?
22
+
23
+ if [ $unit_status -ne 0 ]; then
24
+ echo -e "\e[31m⚠ Note: Unit tests have also failed, but are not listed in the test failures above. Scroll up to the unit tests ⚠\e[0m"
25
+ fi
26
+
27
+ if [ $unit_status -ne 0 ] || [ $acceptance_status -ne 0 ]; then
28
+ echo "Unit tests exit code: ${unit_status}"
29
+ echo "Acceptance tests exit code: ${acceptance_status}"
30
+ exit 1
31
+ fi
32
+
33
+
@@ -261,15 +261,7 @@ shared_examples 'a client initializer' do
261
261
  end
262
262
 
263
263
  context 'with custom logger and log_level' do
264
- let(:custom_logger) do
265
- Class.new do
266
- extend Forwardable
267
- def initialize
268
- @logger = Logger.new(STDOUT)
269
- end
270
- def_delegators :@logger, :fatal, :error, :warn, :info, :debug, :level, :level=
271
- end
272
- end
264
+ let(:custom_logger) { TestLogger }
273
265
  let(:client_options) { default_options.merge(logger: custom_logger.new, log_level: Logger::DEBUG, auto_connect: false) }
274
266
 
275
267
  it 'uses the custom logger' do
@@ -4,7 +4,7 @@ def console(message)
4
4
  puts "\033[31m[#{Time.now.strftime('%H:%M:%S.%L')}]\033[0m \033[33m#{message}\033[0m"
5
5
  end
6
6
 
7
- unless RUBY_VERSION.match(/^1/)
7
+ unless RUBY_VERSION.match(/^1\./)
8
8
  require 'coveralls'
9
9
  Coveralls.wear!
10
10
  end
@@ -15,9 +15,11 @@ require 'ably'
15
15
 
16
16
  require 'support/api_helper'
17
17
  require 'support/debug_failure_helper'
18
+ require 'support/event_emitter_helper'
18
19
  require 'support/private_api_formatter'
19
20
  require 'support/protocol_helper'
20
21
  require 'support/random_helper'
22
+ require 'support/test_logger_helper'
21
23
 
22
24
  require 'rspec_config'
23
25
 
@@ -2,6 +2,8 @@ RSpec.configure do |config|
2
2
  config.before(:example) do |example|
3
3
  next if example.metadata[:prevent_log_stubbing]
4
4
 
5
+ log_mutex = Mutex.new
6
+
5
7
  @log_output = []
6
8
  %w(fatal error warn info debug).each do |method_name|
7
9
  allow_any_instance_of(Ably::Logger).to receive(method_name.to_sym).and_wrap_original do |method, *args, &block|
@@ -10,11 +12,13 @@ RSpec.configure do |config|
10
12
 
11
13
  prefix = "#{Time.now.strftime('%H:%M:%S.%L')} [\e[33m#{method_name}\e[0m] "
12
14
 
13
- begin
14
- args << block.call unless block.nil?
15
- @log_output << "#{prefix}#{args.compact.join(' ')}"
16
- rescue StandardError => e
17
- @log_output << "#{prefix}Failed to log block - #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}}"
15
+ log_mutex.synchronize do
16
+ begin
17
+ args << block.call unless block.nil?
18
+ @log_output << "#{prefix}#{args.compact.join(' ')}"
19
+ rescue StandardError => e
20
+ @log_output << "#{prefix}Failed to log block - #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}}"
21
+ end
18
22
  end
19
23
 
20
24
  # Call original
@@ -0,0 +1,31 @@
1
+ module Ably
2
+ module Modules
3
+ module EventEmitter
4
+ # Unplugs currently registered listener callbacks
5
+ # Ensures multiple calls to unplug is not destructive
6
+ def unplug_listeners
7
+ unplugged_callbacks[:callbacks] = unplugged_callbacks.fetch(:callbacks).merge(callbacks)
8
+ unplugged_callbacks[:callbacks_any] = unplugged_callbacks.fetch(:callbacks_any) + callbacks_any
9
+ callbacks.clear
10
+ callbacks_any.clear
11
+ end
12
+
13
+ # Plug in previously unplugged listener callbacks
14
+ # But merge them together in case other listners have been added in the mean time
15
+ def plugin_listeners
16
+ @callbacks = callbacks.merge(unplugged_callbacks.fetch(:callbacks))
17
+ @callbacks_any = callbacks_any + unplugged_callbacks.fetch(:callbacks_any)
18
+ unplugged_callbacks.fetch(:callbacks).clear
19
+ unplugged_callbacks.fetch(:callbacks_any).clear
20
+ end
21
+
22
+ private
23
+ def unplugged_callbacks
24
+ @unplugged_callbacks ||= {
25
+ callbacks: Hash.new { |hash, key| hash[key] = [] },
26
+ callbacks_any: []
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -124,7 +124,7 @@ RSpec.configure do |config|
124
124
  example_block = example.example.instance_variable_get('@example_block')
125
125
  example_group_instance = example.example.instance_variable_get('@example_group_instance')
126
126
 
127
- event_machine_block = Proc.new do
127
+ event_machine_block = lambda do |*args|
128
128
  RSpec::EventMachine.run_reactor(timeout) do
129
129
  example_group_instance.instance_exec(example, &example_block)
130
130
  end
@@ -4,11 +4,11 @@ class TestApp
4
4
  TEST_RESOURCES_PATH = File.expand_path('../../../lib/submodules/ably-common/test-resources', __FILE__)
5
5
 
6
6
  # App configuration for test app
7
- # See https://github.com/ably/ably-common/blob/master/test-resources/test-app-setup.json
7
+ # See https://github.com/ably/ably-common/blob/main/test-resources/test-app-setup.json
8
8
  APP_SPEC = JSON.parse(File.read(File.join(TEST_RESOURCES_PATH, 'test-app-setup.json')))['post_apps']
9
9
 
10
10
  # Cipher details used for client_encoded presence data in test app
11
- # See https://github.com/ably/ably-common/blob/master/test-resources/test-app-setup.json
11
+ # See https://github.com/ably/ably-common/blob/main/test-resources/test-app-setup.json
12
12
  APP_SPEC_CIPHER = JSON.parse(File.read(File.join(TEST_RESOURCES_PATH, 'test-app-setup.json')))['cipher']
13
13
 
14
14
  # If an app has already been created and we need a new app, create a new test app
@@ -0,0 +1,42 @@
1
+ # Class with standard Ruby Logger interface
2
+ # but it keeps a record of the lof entries for later inspection
3
+ #
4
+ # Recommendation: Use :prevent_log_stubbing attibute on tests that use this logger
5
+ #
6
+ class TestLogger
7
+ def initialize
8
+ @messages = []
9
+ end
10
+
11
+ SEVERITIES = [:fatal, :error, :warn, :info, :debug]
12
+ SEVERITIES.each do |severity_sym|
13
+ define_method(severity_sym) do |*args, &block|
14
+ if block
15
+ @messages << [severity_sym, block.call]
16
+ else
17
+ @messages << [severity_sym, args.join(', ')]
18
+ end
19
+ end
20
+ end
21
+
22
+ def logs(options = {})
23
+ min_severity = options[:min_severity]
24
+ if min_severity
25
+ severity_level = SEVERITIES.index(min_severity)
26
+ raise "Unknown severity: #{min_severity}" if severity_level.nil?
27
+
28
+ @messages.select do |severity, message|
29
+ SEVERITIES.index(severity) <= severity_level
30
+ end
31
+ else
32
+ @messages
33
+ end
34
+ end
35
+
36
+ def level
37
+ 1
38
+ end
39
+
40
+ def level=(new_level)
41
+ end
42
+ end
@@ -17,11 +17,15 @@ describe Ably::Logger do
17
17
  end
18
18
 
19
19
  context 'internals', :api_private do
20
- it 'delegates to the logger object' do
21
- expect(subject.logger).to receive(:warn) do |*args, &block|
20
+ it 'delegates to the default Logger object' do
21
+ received = false
22
+ expect(subject.logger).to be_a(::Logger)
23
+ allow_any_instance_of(::Logger).to receive(:warn) do |*args, &block|
22
24
  expect(args.concat([block ? block.call : nil]).join(',')).to match(/message/)
25
+ received = true
23
26
  end
24
27
  subject.warn 'message'
28
+ expect(received).to be_truthy
25
29
  end
26
30
 
27
31
  context 'formatter' do
@@ -121,15 +125,7 @@ describe Ably::Logger do
121
125
  end
122
126
 
123
127
  context 'with a valid interface' do
124
- let(:custom_logger) do
125
- Class.new do
126
- extend Forwardable
127
- def initialize
128
- @logger = Logger.new(STDOUT)
129
- end
130
- def_delegators :@logger, :fatal, :error, :warn, :info, :debug, :level, :level=
131
- end
132
- end
128
+ let(:custom_logger) { TestLogger }
133
129
  let(:custom_logger_object) { custom_logger.new }
134
130
 
135
131
  subject { Ably::Logger.new(rest_client, Logger::INFO, custom_logger_object) }
@@ -140,10 +136,13 @@ describe Ably::Logger do
140
136
  end
141
137
 
142
138
  it 'delegates log messages to logger', :api_private do
143
- expect(custom_logger_object).to receive(:fatal) do |*args, &block|
139
+ received = false
140
+ allow(custom_logger_object).to receive(:fatal) do |*args, &block|
144
141
  expect(args.concat([block ? block.call : nil]).join(',')).to match(/message/)
142
+ received = true
145
143
  end
146
144
  subject.fatal 'message'
145
+ expect(received).to be_truthy
147
146
  end
148
147
  end
149
148
  end
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'shared/model_behaviour'
4
+
5
+ describe Ably::Models::DeviceDetails do
6
+ include Ably::Modules::Conversions
7
+
8
+ subject { Ably::Models::DeviceDetails }
9
+
10
+ %w(id platform form_factor client_id device_secret).each do |string_attribute|
11
+ let(:empty_device_details) { subject.new }
12
+
13
+ describe "##{string_attribute} and ##{string_attribute}=" do
14
+ let(:new_val) { random_str }
15
+
16
+ specify 'setter accepts a string value and getter returns the new value' do
17
+ expect(empty_device_details.public_send(string_attribute)).to be_nil
18
+ empty_device_details.public_send("#{string_attribute}=", new_val)
19
+ expect(empty_device_details.public_send(string_attribute)).to eql(new_val)
20
+ end
21
+
22
+ specify 'setter accepts nil' do
23
+ empty_device_details.public_send("#{string_attribute}=", new_val)
24
+ expect(empty_device_details.public_send(string_attribute)).to eql(new_val)
25
+ empty_device_details.public_send("#{string_attribute}=", nil)
26
+ expect(empty_device_details.public_send(string_attribute)).to be_nil
27
+ end
28
+
29
+ specify 'rejects non string or nil values' do
30
+ expect { empty_device_details.public_send("#{string_attribute}=", {}) }.to raise_error(ArgumentError)
31
+ end
32
+ end
33
+ end
34
+
35
+ context 'camelCase constructor attributes' do
36
+ let(:client_id) { random_str }
37
+ let(:device_details) { subject.new("clientId" => client_id ) }
38
+
39
+ specify 'are rubyfied and exposed as underscore case' do
40
+ expect(device_details.client_id).to eql(client_id)
41
+ end
42
+
43
+ specify 'are generated when the object is serialised to JSON' do
44
+ expect(JSON.parse(device_details.to_json)["clientId"]).to eql(client_id)
45
+ end
46
+ end
47
+
48
+ describe "#metadata and #metadata=" do
49
+ let(:new_val) { { foo: random_str } }
50
+
51
+ specify 'setter accepts a Hash value and getter returns the new value' do
52
+ expect(empty_device_details.metadata).to eql({})
53
+ empty_device_details.metadata = new_val
54
+ expect(empty_device_details.metadata.to_json).to eql(new_val.to_json)
55
+ end
56
+
57
+ specify 'setter accepts nil but always returns an empty hash' do
58
+ empty_device_details.metadata = new_val
59
+ expect(empty_device_details.metadata.to_json).to eql(new_val.to_json)
60
+ empty_device_details.metadata = nil
61
+ expect(empty_device_details.metadata).to eql({})
62
+ end
63
+
64
+ specify 'rejects non Hash or nil values' do
65
+ expect { empty_device_details.metadata = "foo" }.to raise_error(ArgumentError)
66
+ end
67
+ end
68
+
69
+ describe "#push and #push=" do
70
+ let(:transport_type) { random_str }
71
+ let(:new_val) { { recipient: { transport_type: transport_type } } }
72
+ let(:json_val) { { recipient: { transportType: transport_type } }.to_json }
73
+
74
+ specify 'setter accepts a DevicePushDetails object and getter returns a DevicePushDetails object' do
75
+ expect(empty_device_details.push.to_json).to eql({}.to_json)
76
+ empty_device_details.push = DevicePushDetails(new_val)
77
+ expect(empty_device_details.push).to be_a(Ably::Models::DevicePushDetails)
78
+ expect(empty_device_details.push.recipient[:transport_type]).to eql(transport_type)
79
+ expect(empty_device_details.push.to_json).to eql(json_val)
80
+ end
81
+
82
+ specify 'setter accepts a Hash value and getter returns a DevicePushDetails object' do
83
+ expect(empty_device_details.push.to_json).to eql({}.to_json)
84
+ empty_device_details.push = new_val
85
+ expect(empty_device_details.push).to be_a(Ably::Models::DevicePushDetails)
86
+ expect(empty_device_details.push.recipient[:transport_type]).to eql(transport_type)
87
+ expect(empty_device_details.push.to_json).to eql(json_val)
88
+ end
89
+
90
+ specify 'setter accepts nil but always returns a DevicePushDetails object' do
91
+ empty_device_details.push = new_val
92
+ expect(empty_device_details.push.to_json).to eql(json_val)
93
+ empty_device_details.push = nil
94
+ expect(empty_device_details.push).to be_a(Ably::Models::DevicePushDetails)
95
+ expect(empty_device_details.push.to_json).to eql({}.to_json)
96
+ end
97
+
98
+ specify 'rejects non Hash, DevicePushDetails or nil values' do
99
+ expect { empty_device_details.metadata = "foo" }.to raise_error(ArgumentError)
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,101 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'shared/model_behaviour'
4
+
5
+ describe Ably::Models::DevicePushDetails do
6
+ include Ably::Modules::Conversions
7
+
8
+ subject { Ably::Models::DevicePushDetails }
9
+
10
+ %w(state).each do |string_attribute|
11
+ let(:empty_push_details) { subject.new }
12
+
13
+ describe "##{string_attribute} and ##{string_attribute}=" do
14
+ let(:new_val) { random_str }
15
+
16
+ specify 'setter accepts a string value and getter returns the new value' do
17
+ expect(empty_push_details.public_send(string_attribute)).to be_nil
18
+ empty_push_details.public_send("#{string_attribute}=", new_val)
19
+ expect(empty_push_details.public_send(string_attribute)).to eql(new_val)
20
+ end
21
+
22
+ specify 'setter accepts nil' do
23
+ empty_push_details.public_send("#{string_attribute}=", new_val)
24
+ expect(empty_push_details.public_send(string_attribute)).to eql(new_val)
25
+ empty_push_details.public_send("#{string_attribute}=", nil)
26
+ expect(empty_push_details.public_send(string_attribute)).to be_nil
27
+ end
28
+
29
+ specify 'rejects non string or nil values' do
30
+ expect { empty_push_details.public_send("#{string_attribute}=", {}) }.to raise_error(ArgumentError)
31
+ end
32
+ end
33
+ end
34
+
35
+ context 'camelCase constructor attributes' do
36
+ let(:transport_type) { random_str }
37
+ let(:push_details) { subject.new('errorReason' => { 'message' => 'foo' }, 'recipient' => { 'transportType' => transport_type }) }
38
+
39
+ specify 'are rubyfied and exposed as underscore case' do
40
+ expect(push_details.recipient[:transport_type]).to eql(transport_type)
41
+ expect(push_details.error_reason.message).to eql('foo')
42
+ end
43
+
44
+ specify 'are generated when the object is serialised to JSON' do
45
+ expect(JSON.parse(push_details.to_json)['recipient']['transportType']).to eql(transport_type)
46
+ end
47
+ end
48
+
49
+ describe "#recipient and #recipient=" do
50
+ let(:new_val) { { foo: random_str } }
51
+
52
+ specify 'setter accepts a Hash value and getter returns the new value' do
53
+ expect(empty_push_details.recipient).to eql({})
54
+ empty_push_details.recipient = new_val
55
+ expect(empty_push_details.recipient.to_json).to eql(new_val.to_json)
56
+ end
57
+
58
+ specify 'setter accepts nil but always returns an empty hash' do
59
+ empty_push_details.recipient = new_val
60
+ expect(empty_push_details.recipient.to_json).to eql(new_val.to_json)
61
+ empty_push_details.recipient = nil
62
+ expect(empty_push_details.recipient).to eql({})
63
+ end
64
+
65
+ specify 'rejects non Hash or nil values' do
66
+ expect { empty_push_details.recipient = "foo" }.to raise_error(ArgumentError)
67
+ end
68
+ end
69
+
70
+ describe "#error_reason and #error_reason=" do
71
+ let(:error_message) { random_str }
72
+ let(:error_attributes) { { message: error_message } }
73
+
74
+ specify 'setter accepts a ErrorInfo object and getter returns a ErrorInfo object' do
75
+ expect(empty_push_details.error_reason).to be_nil
76
+ empty_push_details.error_reason = ErrorInfo(error_attributes)
77
+ expect(empty_push_details.error_reason).to be_a(Ably::Models::ErrorInfo)
78
+ expect(empty_push_details.error_reason.message).to eql(error_message)
79
+ expect(empty_push_details.error_reason.to_json).to eql(error_attributes.to_json)
80
+ end
81
+
82
+ specify 'setter accepts a Hash value and getter returns a ErrorInfo object' do
83
+ expect(empty_push_details.error_reason).to be_nil
84
+ empty_push_details.error_reason = error_attributes
85
+ expect(empty_push_details.error_reason).to be_a(Ably::Models::ErrorInfo)
86
+ expect(empty_push_details.error_reason.message).to eql(error_message)
87
+ expect(empty_push_details.error_reason.to_json).to eql(error_attributes.to_json)
88
+ end
89
+
90
+ specify 'setter accepts nil values' do
91
+ empty_push_details.error_reason = error_attributes
92
+ expect(empty_push_details.error_reason.to_json).to eql(error_attributes.to_json)
93
+ empty_push_details.error_reason = nil
94
+ expect(empty_push_details.error_reason).to be_nil
95
+ end
96
+
97
+ specify 'rejects non Hash, ErrorInfo or nil values' do
98
+ expect { empty_push_details.error_reason = "foo" }.to raise_error(ArgumentError)
99
+ end
100
+ end
101
+ end