rpush 7.0.1 → 8.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -4
- data/README.md +38 -1
- data/lib/generators/rpush_migration_generator.rb +1 -0
- data/lib/generators/templates/rpush.rb +17 -0
- data/lib/generators/templates/rpush_7_1_0_updates.rb +12 -0
- data/lib/rpush/client/active_model/apns/notification.rb +0 -4
- data/lib/rpush/client/active_model/fcm/app.rb +20 -0
- data/lib/rpush/client/active_model/fcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
- data/lib/rpush/client/active_model/fcm/notification.rb +129 -0
- data/lib/rpush/client/active_model/fcm/notification_keys_in_allowed_list_validator.rb +20 -0
- data/lib/rpush/client/active_model.rb +5 -0
- data/lib/rpush/client/active_record/fcm/app.rb +11 -0
- data/lib/rpush/client/active_record/fcm/notification.rb +11 -0
- data/lib/rpush/client/active_record.rb +3 -0
- data/lib/rpush/client/redis/app.rb +2 -0
- data/lib/rpush/client/redis/fcm/app.rb +11 -0
- data/lib/rpush/client/redis/fcm/notification.rb +11 -0
- data/lib/rpush/client/redis.rb +3 -0
- data/lib/rpush/configuration.rb +1 -1
- data/lib/rpush/daemon/apns2/delivery.rb +0 -1
- data/lib/rpush/daemon/apnsp8/delivery.rb +0 -1
- data/lib/rpush/daemon/fcm/delivery.rb +162 -0
- data/lib/rpush/daemon/fcm.rb +9 -0
- data/lib/rpush/daemon/gcm/delivery.rb +1 -1
- data/lib/rpush/daemon/google_credential_cache.rb +41 -0
- data/lib/rpush/daemon/store/active_record.rb +15 -0
- data/lib/rpush/daemon/store/interface.rb +2 -2
- data/lib/rpush/daemon/store/redis.rb +13 -0
- data/lib/rpush/daemon/webpush/delivery.rb +2 -2
- data/lib/rpush/daemon.rb +4 -0
- data/lib/rpush/reflection_collection.rb +3 -2
- data/lib/rpush/version.rb +2 -2
- data/lib/rpush.rb +1 -0
- data/spec/functional/apns2_spec.rb +2 -6
- data/spec/functional/fcm_priority_spec.rb +46 -0
- data/spec/functional/fcm_spec.rb +77 -0
- data/spec/functional_spec_helper.rb +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/support/active_record_setup.rb +3 -1
- data/spec/unit/client/active_record/fcm/app_spec.rb +6 -0
- data/spec/unit/client/active_record/fcm/notification_spec.rb +10 -0
- data/spec/unit/client/redis/fcm/app_spec.rb +5 -0
- data/spec/unit/client/redis/fcm/notification_spec.rb +5 -0
- data/spec/unit/client/shared/apns/notification.rb +0 -15
- data/spec/unit/client/shared/fcm/app.rb +4 -0
- data/spec/unit/client/shared/fcm/notification.rb +92 -0
- data/spec/unit/configuration_spec.rb +1 -1
- data/spec/unit/daemon/apnsp8/delivery_spec.rb +1 -1
- data/spec/unit/daemon/fcm/delivery_spec.rb +127 -0
- data/spec/unit/daemon/service_config_methods_spec.rb +1 -1
- data/spec/unit/daemon/tcp_connection_spec.rb +8 -7
- data/spec/unit/daemon/wns/delivery_spec.rb +1 -1
- data/spec/unit/logger_spec.rb +1 -1
- data/spec/unit_spec_helper.rb +1 -1
- metadata +81 -17
@@ -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
|
-
:
|
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 "
|
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 < ::
|
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,
|
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
data/lib/rpush.rb
CHANGED
@@ -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 =
|
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,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?
|
@@ -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,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
|