rpush 7.0.1 → 8.0.0

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -4
  3. data/README.md +38 -1
  4. data/lib/generators/rpush_migration_generator.rb +1 -0
  5. data/lib/generators/templates/rpush.rb +17 -0
  6. data/lib/generators/templates/rpush_7_1_0_updates.rb +12 -0
  7. data/lib/rpush/client/active_model/apns/notification.rb +0 -4
  8. data/lib/rpush/client/active_model/fcm/app.rb +20 -0
  9. data/lib/rpush/client/active_model/fcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
  10. data/lib/rpush/client/active_model/fcm/notification.rb +129 -0
  11. data/lib/rpush/client/active_model/fcm/notification_keys_in_allowed_list_validator.rb +20 -0
  12. data/lib/rpush/client/active_model.rb +5 -0
  13. data/lib/rpush/client/active_record/fcm/app.rb +11 -0
  14. data/lib/rpush/client/active_record/fcm/notification.rb +11 -0
  15. data/lib/rpush/client/active_record.rb +3 -0
  16. data/lib/rpush/client/redis/app.rb +2 -0
  17. data/lib/rpush/client/redis/fcm/app.rb +11 -0
  18. data/lib/rpush/client/redis/fcm/notification.rb +11 -0
  19. data/lib/rpush/client/redis.rb +3 -0
  20. data/lib/rpush/configuration.rb +1 -1
  21. data/lib/rpush/daemon/apns2/delivery.rb +0 -1
  22. data/lib/rpush/daemon/apnsp8/delivery.rb +0 -1
  23. data/lib/rpush/daemon/fcm/delivery.rb +162 -0
  24. data/lib/rpush/daemon/fcm.rb +9 -0
  25. data/lib/rpush/daemon/gcm/delivery.rb +1 -1
  26. data/lib/rpush/daemon/google_credential_cache.rb +41 -0
  27. data/lib/rpush/daemon/store/active_record.rb +15 -0
  28. data/lib/rpush/daemon/store/interface.rb +2 -2
  29. data/lib/rpush/daemon/store/redis.rb +13 -0
  30. data/lib/rpush/daemon/webpush/delivery.rb +2 -2
  31. data/lib/rpush/daemon.rb +4 -0
  32. data/lib/rpush/reflection_collection.rb +3 -2
  33. data/lib/rpush/version.rb +2 -2
  34. data/lib/rpush.rb +1 -0
  35. data/spec/functional/apns2_spec.rb +2 -6
  36. data/spec/functional/fcm_priority_spec.rb +46 -0
  37. data/spec/functional/fcm_spec.rb +77 -0
  38. data/spec/functional_spec_helper.rb +1 -1
  39. data/spec/spec_helper.rb +2 -1
  40. data/spec/support/active_record_setup.rb +3 -1
  41. data/spec/unit/client/active_record/fcm/app_spec.rb +6 -0
  42. data/spec/unit/client/active_record/fcm/notification_spec.rb +10 -0
  43. data/spec/unit/client/redis/fcm/app_spec.rb +5 -0
  44. data/spec/unit/client/redis/fcm/notification_spec.rb +5 -0
  45. data/spec/unit/client/shared/apns/notification.rb +0 -15
  46. data/spec/unit/client/shared/fcm/app.rb +4 -0
  47. data/spec/unit/client/shared/fcm/notification.rb +92 -0
  48. data/spec/unit/configuration_spec.rb +1 -1
  49. data/spec/unit/daemon/apnsp8/delivery_spec.rb +1 -1
  50. data/spec/unit/daemon/fcm/delivery_spec.rb +127 -0
  51. data/spec/unit/daemon/service_config_methods_spec.rb +1 -1
  52. data/spec/unit/daemon/tcp_connection_spec.rb +8 -7
  53. data/spec/unit/daemon/wns/delivery_spec.rb +1 -1
  54. data/spec/unit/logger_spec.rb +1 -1
  55. data/spec/unit_spec_helper.rb +1 -1
  56. metadata +81 -17
@@ -0,0 +1,9 @@
1
+ module Rpush
2
+ module Daemon
3
+ module Fcm
4
+ extend ServiceConfigMethods
5
+
6
+ dispatcher :http
7
+ end
8
+ end
9
+ end
@@ -238,4 +238,4 @@ module Rpush
238
238
  end
239
239
  end
240
240
  end
241
- end
241
+ end
@@ -0,0 +1,41 @@
1
+ require 'singleton'
2
+ module Rpush
3
+ module Daemon
4
+ class GoogleCredentialCache
5
+ include Singleton
6
+ include Loggable
7
+
8
+ # Assuming tokens are valid for 1 hour
9
+ TOKEN_VALID_FOR_SEC = 60 * 59
10
+
11
+ def initialize
12
+ @credentials_cache = {}
13
+ end
14
+
15
+ def access_token(scope, json_key)
16
+ key = hash_key(scope, json_key)
17
+
18
+ if @credentials_cache[key].nil? || Time.now > @credentials_cache[key][:expires_at]
19
+ token = fetch_fresh_token(scope, json_key)
20
+ expires_at = Time.now + TOKEN_VALID_FOR_SEC
21
+ @credentials_cache[key] = { token: token, expires_at: expires_at }
22
+ end
23
+
24
+ @credentials_cache[key][:token]
25
+ end
26
+
27
+ private
28
+
29
+ def fetch_fresh_token(scope, json_key)
30
+ json_key_io = json_key ? StringIO.new(json_key) : nil
31
+ log_debug("FCM - Obtaining access token.")
32
+ authorizer = Google::Auth::ServiceAccountCredentials.make_creds(scope: scope, json_key_io: json_key_io)
33
+ authorizer.fetch_access_token
34
+ end
35
+
36
+ def hash_key(scope, json_key)
37
+ scope.hash ^ json_key.hash
38
+ end
39
+ end
40
+ end
41
+ end
@@ -145,6 +145,11 @@ module Rpush
145
145
  end
146
146
  end
147
147
 
148
+ def create_fcm_notification(attrs, data, app)
149
+ notification = Rpush::Client::ActiveRecord::Fcm::Notification.new
150
+ create_fcm_like_notification(notification, attrs, data, app)
151
+ end
152
+
148
153
  def create_gcm_notification(attrs, data, registration_ids, deliver_after, app)
149
154
  notification = Rpush::Client::ActiveRecord::Gcm::Notification.new
150
155
  create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app)
@@ -194,6 +199,16 @@ module Rpush
194
199
 
195
200
  private
196
201
 
202
+ def create_fcm_like_notification(notification, attrs, data, app) # rubocop:disable Metrics/ParameterLists
203
+ with_database_reconnect_and_retry do
204
+ notification.assign_attributes(attrs)
205
+ notification.data = data
206
+ notification.app = app
207
+ notification.save!
208
+ notification
209
+ end
210
+ end
211
+
197
212
  def create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app) # rubocop:disable Metrics/ParameterLists
198
213
  with_database_reconnect_and_retry do
199
214
  notification.assign_attributes(attrs)
@@ -5,8 +5,8 @@ module Rpush
5
5
  PUBLIC_METHODS = [:deliverable_notifications, :mark_retryable,
6
6
  :mark_batch_retryable, :mark_delivered, :mark_batch_delivered,
7
7
  :mark_failed, :mark_batch_failed, :create_apns_feedback,
8
- :create_gcm_notification, :create_adm_notification, :update_app,
9
- :update_notification, :release_connection,
8
+ :create_fcm_notification, :create_gcm_notification, :create_adm_notification,
9
+ :update_app, :update_notification, :release_connection,
10
10
  :all_apps, :app, :mark_ids_failed, :mark_ids_retryable,
11
11
  :reopen_log, :pending_delivery_count, :translate_integer_notification_id]
12
12
 
@@ -92,6 +92,11 @@ module Rpush
92
92
  Rpush::Client::Redis::Apns::Feedback.create!(failed_at: failed_at, device_token: device_token, app_id: app.id)
93
93
  end
94
94
 
95
+ def create_fcm_notification(attrs, data, app)
96
+ notification = Rpush::Client::Redis::Fcm::Notification.new
97
+ create_fcm_like_notification(notification, attrs, data, app)
98
+ end
99
+
95
100
  def create_gcm_notification(attrs, data, registration_ids, deliver_after, app)
96
101
  notification = Rpush::Client::Redis::Gcm::Notification.new
97
102
  create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app)
@@ -138,6 +143,14 @@ module Rpush
138
143
  nil
139
144
  end
140
145
 
146
+ def create_fcm_like_notification(notification, attrs, data, app) # rubocop:disable Metrics/ParameterLists
147
+ notification.assign_attributes(attrs)
148
+ notification.data = data
149
+ notification.app = app
150
+ notification.save!
151
+ notification
152
+ end
153
+
141
154
  def create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app) # rubocop:disable Metrics/ParameterLists
142
155
  notification.assign_attributes(attrs)
143
156
  notification.data = data
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "webpush"
3
+ require "web-push"
4
4
 
5
5
  module Rpush
6
6
  module Daemon
@@ -10,7 +10,7 @@ module Rpush
10
10
  # We just override #perform to inject the http instance that is managed
11
11
  # by Rpush.
12
12
  #
13
- class Request < ::Webpush::Request
13
+ class Request < ::WebPush::Request
14
14
  def perform(http)
15
15
  req = Net::HTTP::Post.new(uri.request_uri, headers)
16
16
  req.body = body
data/lib/rpush/daemon.rb CHANGED
@@ -49,6 +49,10 @@ require 'rpush/daemon/apnsp8/delivery'
49
49
  require 'rpush/daemon/apnsp8/token'
50
50
  require 'rpush/daemon/apnsp8'
51
51
 
52
+ require 'rpush/daemon/fcm/delivery'
53
+ require 'rpush/daemon/fcm'
54
+ require 'rpush/daemon/google_credential_cache'
55
+
52
56
  require 'rpush/daemon/gcm/delivery'
53
57
  require 'rpush/daemon/gcm'
54
58
 
@@ -4,8 +4,9 @@ module Rpush
4
4
 
5
5
  REFLECTIONS = [
6
6
  :apns_feedback, :notification_enqueued, :notification_delivered,
7
- :notification_failed, :notification_will_retry, :gcm_delivered_to_recipient,
8
- :gcm_failed_to_recipient, :gcm_canonical_id, :gcm_invalid_registration_id,
7
+ :notification_failed, :notification_will_retry,
8
+ :gcm_delivered_to_recipient, :gcm_failed_to_recipient, :gcm_canonical_id, :gcm_invalid_registration_id,
9
+ :fcm_delivered_to_recipient, :fcm_failed_to_recipient, :fcm_canonical_id, :fcm_invalid_device_token,
9
10
  :error, :adm_canonical_id, :adm_failed_to_recipient, :wns_invalid_channel,
10
11
  :tcp_connection_lost, :ssl_certificate_will_expire, :ssl_certificate_revoked,
11
12
  :notification_id_will_retry, :notification_id_failed
data/lib/rpush/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Rpush
2
2
  module VERSION
3
- MAJOR = 7
3
+ MAJOR = 8
4
4
  MINOR = 0
5
- TINY = 1
5
+ TINY = 0
6
6
  PRE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".").freeze
data/lib/rpush.rb CHANGED
@@ -3,6 +3,7 @@ require 'multi_json'
3
3
  require 'active_support/all'
4
4
  require 'net-http2'
5
5
  require 'jwt'
6
+ require 'googleauth'
6
7
 
7
8
  require 'rails'
8
9
 
@@ -79,8 +79,7 @@ describe 'APNs http2 adapter' do
79
79
  headers: {
80
80
  'apns-expiration' => '0',
81
81
  'apns-priority' => '10',
82
- 'apns-topic' => 'com.example.app',
83
- 'apns-push-type' => 'background'
82
+ 'apns-topic' => 'com.example.app'
84
83
  }
85
84
  }
86
85
  )
@@ -114,8 +113,7 @@ describe 'APNs http2 adapter' do
114
113
  headers: {
115
114
  'apns-topic' => bundle_id,
116
115
  'apns-expiration' => '0',
117
- 'apns-priority' => '10',
118
- 'apns-push-type' => 'background'
116
+ 'apns-priority' => '10'
119
117
  }
120
118
  }
121
119
  ).and_return(fake_http2_request)
@@ -257,7 +255,6 @@ describe 'APNs http2 adapter' do
257
255
  Rpush.reflect do |on|
258
256
  on.error do |error|
259
257
  expect(error).to be_kind_of(StandardError)
260
- reflector.accept
261
258
  end
262
259
  end
263
260
 
@@ -292,7 +289,6 @@ describe 'APNs http2 adapter' do
292
289
  on.error do |error|
293
290
  reflected_error = true
294
291
  expect(error).to be_kind_of(StandardError)
295
- reflector.accept
296
292
  end
297
293
  end
298
294
 
@@ -0,0 +1,46 @@
1
+ require 'functional_spec_helper'
2
+
3
+ describe 'FCM priority' do
4
+ let(:app) { Rpush::Fcm::App.new }
5
+ let(:notification) { Rpush::Fcm::Notification.new }
6
+ let(:hydrated_notification) { Rpush::Fcm::Notification.find(notification.id) }
7
+ let(:response) { double(Net::HTTPResponse, code: 200) }
8
+ let(:http) { double(Net::HTTP::Persistent, request: response, shutdown: nil) }
9
+ let(:priority) { 'normal' }
10
+ let(:fake_device_token) { 'a' * 108 }
11
+
12
+ before do
13
+ app.name = 'test'
14
+ app.auth_key = 'abc123'
15
+ app.save!
16
+
17
+ notification.app_id = app.id
18
+ notification.device_token = fake_device_token
19
+ notification.data = { message: 'test' }
20
+ notification.notification = { title: 'title' }
21
+ notification.priority = priority
22
+ notification.save!
23
+
24
+ allow(Net::HTTP::Persistent).to receive_messages(new: http)
25
+ end
26
+
27
+ it 'supports normal priority' do
28
+ json = hydrated_notification.as_json
29
+ expect(json["message"]["android"]["notification"]["notification_priority"]).to eq('PRIORITY_DEFAULT')
30
+ expect(json["message"]["android"]["priority"]).to eq('normal')
31
+ end
32
+
33
+ context 'high priority' do
34
+ let(:priority) { 'high' }
35
+
36
+ it 'supports high priority' do
37
+ json = hydrated_notification.as_json
38
+ expect(json["message"]["android"]["notification"]["notification_priority"]).to eq('PRIORITY_MAX')
39
+ expect(json["message"]["android"]["priority"]).to eq('high')
40
+ end
41
+ end
42
+
43
+ it 'does not add an error when receiving expected priority' do
44
+ expect(hydrated_notification.errors.messages[:priority]).to be_empty
45
+ end
46
+ end
@@ -0,0 +1,77 @@
1
+ require 'functional_spec_helper'
2
+
3
+ describe 'FCM' do
4
+ let(:app) { Rpush::Fcm::App.new }
5
+ let(:notification) { Rpush::Fcm::Notification.new }
6
+ let(:response) { double(Net::HTTPResponse, code: 200) }
7
+ let(:http) { double(Net::HTTP::Persistent, request: response, shutdown: nil) }
8
+ let(:fake_device_token) { 'a' * 108 }
9
+ let(:creds) {double(Google::Auth::UserRefreshCredentials)}
10
+
11
+ before do
12
+ app.name = 'test'
13
+ app.auth_key = 'abc123'
14
+ app.save!
15
+
16
+ notification.app_id = app.id
17
+ notification.device_token = fake_device_token
18
+ notification.data = { message: 'test' }
19
+ notification.save!
20
+
21
+ allow(Net::HTTP::Persistent).to receive_messages(new: http)
22
+ allow(creds).to receive(:fetch_access_token).and_return({'access_token': 'face_access_token'})
23
+
24
+ allow(::Google::Auth::ServiceAccountCredentials).to receive(:fetch_access_token).and_return({access_token: 'bbbbbb'})
25
+ allow(::Google::Auth::ServiceAccountCredentials).to receive(:make_creds).and_return(creds)
26
+ allow_any_instance_of(::Rpush::Daemon::Fcm::Delivery).to receive(:necessary_data_exists?).and_return(true)
27
+ end
28
+
29
+ it 'delivers a notification successfully' do
30
+ example_success_body = {
31
+ "multicast_id": 108,
32
+ "success": 1,
33
+ "failure": 0,
34
+ "canonical_ids": 0,
35
+ "results": [
36
+ { "message_id": "1:08" }
37
+ ]
38
+ }.to_json
39
+ allow(response).to receive_messages(body: example_success_body)
40
+
41
+ expect do
42
+ Rpush.push
43
+ notification.reload
44
+ end.to change(notification, :delivered).to(true)
45
+ end
46
+
47
+ it 'fails to deliver a notification successfully' do
48
+ example_error_body = {
49
+ "error": {
50
+ "code": 400,
51
+ "message": "The registration token is not a valid FCM registration token",
52
+ "errors": [
53
+ {
54
+ "message": "The registration token is not a valid FCM registration token",
55
+ "domain": "global",
56
+ "reason": "badRequest"
57
+ }
58
+ ],
59
+ "status": "INVALID_ARGUMENT"
60
+ }
61
+ }.to_json
62
+
63
+ allow(response).to receive_messages(code: 400, body: example_error_body)
64
+ Rpush.push
65
+ notification.reload
66
+ expect(notification.delivered).to eq(false)
67
+ end
68
+
69
+ it 'retries notification that fail due to a SocketError' do
70
+ expect(http).to receive(:request).and_raise(SocketError.new)
71
+ expect(notification.deliver_after).to be_nil
72
+ expect do
73
+ Rpush.push
74
+ notification.reload
75
+ end.to change(notification, :deliver_after).to(kind_of(Time))
76
+ end
77
+ end
@@ -21,7 +21,7 @@ RSpec.configure do |config|
21
21
  config.before(:each) do
22
22
  Modis.with_connection do |redis|
23
23
  redis.keys('rpush:*').each { |key| redis.del(key) }
24
- end if redis?
24
+ end if redis? && functional_example?(self.class.metadata)
25
25
 
26
26
  Rpush.config.logger = ::Logger.new(STDOUT) if functional_example?(self.class.metadata)
27
27
  end
data/spec/spec_helper.rb CHANGED
@@ -13,6 +13,7 @@ if !ENV['CI'] || (ENV['CI'] && ENV['QUALITY'] == 'true')
13
13
  end
14
14
  end
15
15
 
16
+ require 'debug'
16
17
  require 'timecop'
17
18
  require 'activerecord-jdbc-adapter' if defined? JRUBY_VERSION
18
19
 
@@ -46,7 +47,7 @@ path = File.join(File.dirname(__FILE__), 'support')
46
47
  TEST_CERT = File.read(File.join(path, 'cert_without_password.pem'))
47
48
  TEST_CERT_WITH_PASSWORD = File.read(File.join(path, 'cert_with_password.pem'))
48
49
 
49
- VAPID_KEYPAIR = Webpush.generate_key.to_hash.merge(subject: 'rpush-test@example.org').to_json
50
+ VAPID_KEYPAIR = WebPush.generate_key.to_hash.merge(subject: 'rpush-test@example.org').to_json
50
51
 
51
52
  def after_example_cleanup
52
53
  Rpush.logger = nil
@@ -43,6 +43,7 @@ require 'generators/templates/rpush_3_3_1_updates'
43
43
  require 'generators/templates/rpush_4_1_0_updates'
44
44
  require 'generators/templates/rpush_4_1_1_updates'
45
45
  require 'generators/templates/rpush_4_2_0_updates'
46
+ require 'generators/templates/rpush_7_1_0_updates'
46
47
 
47
48
  migrations = [
48
49
  AddRpush,
@@ -60,7 +61,8 @@ migrations = [
60
61
  Rpush331Updates,
61
62
  Rpush410Updates,
62
63
  Rpush411Updates,
63
- Rpush420Updates
64
+ Rpush420Updates,
65
+ Rpush710Updates
64
66
  ]
65
67
 
66
68
  unless ENV['CI']
@@ -0,0 +1,6 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Fcm::App do
4
+ it_behaves_like 'Rpush::Client::Fcm::App'
5
+ it_behaves_like 'Rpush::Client::ActiveRecord::App'
6
+ end if active_record?
@@ -0,0 +1,10 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Fcm::Notification do
4
+ it_behaves_like 'Rpush::Client::Fcm::Notification'
5
+ it_behaves_like 'Rpush::Client::ActiveRecord::Notification'
6
+
7
+ subject(:notification) { described_class.new }
8
+ let(:app) { Rpush::Fcm::App.create!(name: 'test', auth_key: 'abc') }
9
+
10
+ end if active_record?
@@ -0,0 +1,5 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::Redis::Fcm::App do
4
+ it_behaves_like 'Rpush::Client::Fcm::App'
5
+ end if redis?
@@ -0,0 +1,5 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::Redis::Fcm::Notification do
4
+ it_behaves_like 'Rpush::Client::Fcm::Notification'
5
+ end if redis?
@@ -165,21 +165,6 @@ shared_examples 'Rpush::Client::Apns::Notification' do
165
165
  end
166
166
  end
167
167
 
168
- describe 'content_available?' do
169
- context 'if not set' do
170
- it 'should be false' do
171
- expect(notification.content_available?).to be_falsey
172
- end
173
- end
174
-
175
- context 'if set' do
176
- it 'should be true' do
177
- notification.content_available = true
178
- expect(notification.content_available?).to be_truthy
179
- end
180
- end
181
- end
182
-
183
168
  describe 'url-args' do
184
169
  it 'includes url-args in the payload' do
185
170
  notification.url_args = ['url-arg-1']
@@ -0,0 +1,4 @@
1
+ require 'unit_spec_helper'
2
+
3
+ shared_examples 'Rpush::Client::Fcm::App' do
4
+ end
@@ -0,0 +1,92 @@
1
+ require 'unit_spec_helper'
2
+
3
+ shared_examples 'Rpush::Client::Fcm::Notification' do
4
+ let(:app) { Rpush::Fcm::App.create!(name: 'test', auth_key: 'abc') }
5
+ let(:notification) { described_class.new }
6
+
7
+ it "has a 'data' payload limit of 4096 bytes" do
8
+ notification.app = app
9
+ notification.device_token = "valid"
10
+ notification.data = { key: "a" * 4096 }
11
+ expect(notification.valid?).to be_falsey
12
+ expect(notification.errors[:base]).to eq ["Notification payload data cannot be larger than 4096 bytes."]
13
+ end
14
+
15
+ it "validates notification keys" do
16
+ notification.app = app
17
+ notification.device_token = "valid"
18
+ notification.notification = { "title" => "valid", "body" => "valid", "color" => "valid for android", "garbage" => "invalid" }
19
+ expect(notification.valid?).to be_falsey
20
+ expect(notification.errors[:notification]).to eq ["contains invalid keys: garbage"]
21
+ end
22
+
23
+ it "allows notifications with either symbol keys or string keys" do
24
+ notification.app = app
25
+ notification.notification = { "title" => "title", body: "body" }
26
+ expect(notification.as_json['message']['notification']).to eq({"title"=>"title", "body"=>"body"})
27
+ end
28
+
29
+ it "moves notification keys to the correcdt location" do
30
+ notification.app = app
31
+ notification.device_token = "valid"
32
+ notification.notification = { "title" => "valid", "body" => "valid", "color" => "valid for android" }
33
+ expect(notification.valid?).to be_truthy
34
+ expect(notification.as_json['message']['notification']).to eq("title"=>"valid", "body"=>"valid")
35
+ expect(notification.as_json['message']['android']['notification']['color']).to eq('valid for android')
36
+ end
37
+
38
+ it 'validates expiry is present if collapse_key is set' do
39
+ notification.collapse_key = 'test'
40
+ notification.expiry = nil
41
+ expect(notification.valid?).to be_falsey
42
+ expect(notification.errors[:expiry]).to eq ['must be set when using a collapse_key']
43
+ end
44
+
45
+ it 'includes time_to_live in the payload' do
46
+ notification.expiry = 100
47
+ expect(notification.as_json['message']['android']['ttl']).to eq '100s'
48
+ end
49
+
50
+ it 'includes content_available in the payload' do
51
+ notification.content_available = true
52
+ expect(notification.as_json["message"]["apns"]["payload"]["aps"]["content-available"]).to eq 1
53
+ end
54
+
55
+ it 'sets the priority to high when set to high' do
56
+ notification.notification = { title: "Title" }
57
+ notification.priority = 'high'
58
+ expect(notification.as_json['message']['android']['priority']).to eq 'high'
59
+ expect(notification.as_json['message']['android']['notification']['notification_priority']).to eq 'PRIORITY_MAX'
60
+ # TODO Add notification_priority
61
+ end
62
+
63
+ it 'sets the priority to normal when set to normal' do
64
+ notification.notification = { title: "Title" }
65
+ notification.priority = 'normal'
66
+ expect(notification.as_json['message']['android']['priority']).to eq 'normal'
67
+ expect(notification.as_json['message']['android']['notification']['notification_priority']).to eq 'PRIORITY_DEFAULT'
68
+ # TODO Add notification_priority
69
+ end
70
+
71
+ it 'validates the priority is either "normal" or "high"' do
72
+ notification.priority = 'invalid'
73
+ expect(notification.errors[:priority]).to eq ['must be one of either "normal" or "high"']
74
+ end
75
+
76
+ it 'excludes the priority if it is not defined' do
77
+ expect(notification.as_json['message']['android']).not_to have_key 'priority'
78
+ end
79
+
80
+ it 'includes the notification payload if defined' do
81
+ notification.notification = { key: 'any key is allowed' }
82
+ expect(notification.as_json['message']).to have_key 'notification'
83
+ end
84
+
85
+ it 'excludes the notification payload if undefined' do
86
+ expect(notification.as_json['message']).not_to have_key 'notification'
87
+ end
88
+
89
+ it 'fails when trying to set the dry_run option' do
90
+ expect { notification.dry_run = true }.to raise_error(ArgumentError)
91
+ end
92
+ end
@@ -41,6 +41,6 @@ describe Rpush::Configuration do
41
41
  it 'delegate redis_options to Modis' do
42
42
  Rpush.config.client = :redis
43
43
  Rpush.config.redis_options = { hi: :mom }
44
- expect(Modis.redis_options).to eq(hi: :mom)
44
+ expect(Modis.redis_options[:default]).to eq(hi: :mom)
45
45
  end
46
46
  end
@@ -42,7 +42,7 @@ describe Rpush::Daemon::Apnsp8::Delivery do
42
42
  loop do
43
43
  break unless thread.alive?
44
44
 
45
- if Time.now - start > 0.5
45
+ if Time.now - start > 1
46
46
  thread.kill
47
47
  fail 'Stuck in an infinite loop'
48
48
  end