rpush 4.2.0 → 5.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +248 -163
- data/README.md +103 -17
- data/lib/generators/templates/add_gcm.rb +4 -4
- data/lib/generators/templates/add_rpush.rb +4 -4
- data/lib/generators/templates/rpush.rb +4 -0
- data/lib/generators/templates/rpush_3_3_1_updates.rb +2 -2
- data/lib/rpush/cli.rb +1 -1
- data/lib/rpush/client/active_model.rb +4 -1
- data/lib/rpush/client/active_model/adm/data_validator.rb +1 -1
- data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +2 -2
- data/lib/rpush/client/active_model/apns/notification.rb +9 -1
- data/lib/rpush/client/active_model/apns/notification_payload_size_validator.rb +15 -0
- data/lib/rpush/client/active_model/apns2/notification.rb +14 -0
- data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +1 -1
- data/lib/rpush/client/active_model/gcm/notification.rb +2 -2
- data/lib/rpush/client/active_model/payload_data_size_validator.rb +1 -1
- data/lib/rpush/client/active_model/registration_ids_count_validator.rb +1 -1
- data/lib/rpush/client/active_model/webpush/app.rb +41 -0
- data/lib/rpush/client/active_model/webpush/notification.rb +66 -0
- data/lib/rpush/client/active_record.rb +4 -0
- data/lib/rpush/client/active_record/apns/active_record_serializable_notification.rb +65 -0
- data/lib/rpush/client/active_record/apns/notification.rb +1 -57
- data/lib/rpush/client/active_record/apns2/notification.rb +4 -1
- data/lib/rpush/client/active_record/apnsp8/notification.rb +1 -0
- data/lib/rpush/client/active_record/webpush/app.rb +11 -0
- data/lib/rpush/client/active_record/webpush/notification.rb +12 -0
- data/lib/rpush/client/redis.rb +3 -0
- data/lib/rpush/client/redis/apns2/notification.rb +1 -0
- data/lib/rpush/client/redis/apnsp8/notification.rb +2 -0
- data/lib/rpush/client/redis/pushy/notification.rb +0 -1
- data/lib/rpush/client/redis/webpush/app.rb +15 -0
- data/lib/rpush/client/redis/webpush/notification.rb +15 -0
- data/lib/rpush/configuration.rb +3 -2
- data/lib/rpush/daemon.rb +4 -1
- data/lib/rpush/daemon/apns/feedback_receiver.rb +1 -1
- data/lib/rpush/daemon/apns2/delivery.rb +13 -2
- data/lib/rpush/daemon/apnsp8/delivery.rb +7 -2
- data/lib/rpush/daemon/app_runner.rb +1 -1
- data/lib/rpush/daemon/batch.rb +12 -5
- data/lib/rpush/daemon/delivery.rb +1 -2
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +1 -1
- data/lib/rpush/daemon/webpush.rb +10 -0
- data/lib/rpush/daemon/webpush/delivery.rb +114 -0
- data/lib/rpush/logger.rb +1 -0
- data/lib/rpush/version.rb +2 -2
- data/spec/functional/apns2_spec.rb +97 -2
- data/spec/functional/gcm_priority_spec.rb +40 -0
- data/spec/functional/webpush_spec.rb +30 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/simplecov_helper.rb +1 -1
- data/spec/unit/client/active_record/adm/app_spec.rb +2 -54
- data/spec/unit/client/active_record/adm/notification_spec.rb +2 -39
- data/spec/unit/client/active_record/apns/app_spec.rb +3 -26
- data/spec/unit/client/active_record/apns/feedback_spec.rb +1 -5
- data/spec/unit/client/active_record/apns/notification_spec.rb +29 -293
- data/spec/unit/client/active_record/apns2/app_spec.rb +4 -0
- data/spec/unit/client/active_record/apns2/notification_spec.rb +65 -0
- data/spec/unit/client/active_record/apnsp8/notification_spec.rb +28 -0
- data/spec/unit/client/active_record/app_spec.rb +1 -26
- data/spec/unit/client/active_record/gcm/app_spec.rb +3 -1
- data/spec/unit/client/active_record/gcm/notification_spec.rb +6 -88
- data/spec/unit/client/active_record/notification_spec.rb +3 -11
- data/spec/unit/client/active_record/pushy/app_spec.rb +2 -13
- data/spec/unit/client/active_record/pushy/notification_spec.rb +2 -55
- data/spec/unit/client/active_record/shared/app.rb +14 -0
- data/spec/unit/{notification_shared.rb → client/active_record/shared/notification.rb} +12 -7
- data/spec/unit/client/active_record/webpush/app_spec.rb +6 -0
- data/spec/unit/client/active_record/webpush/notification_spec.rb +6 -0
- data/spec/unit/client/active_record/wns/badge_notification_spec.rb +1 -11
- data/spec/unit/client/active_record/wns/raw_notification_spec.rb +3 -12
- data/spec/unit/client/active_record/wpns/app_spec.rb +3 -1
- data/spec/unit/client/active_record/wpns/notification_spec.rb +2 -17
- data/spec/unit/client/redis/adm/app_spec.rb +5 -0
- data/spec/unit/client/redis/adm/notification_spec.rb +5 -0
- data/spec/unit/client/redis/apns/app_spec.rb +5 -0
- data/spec/unit/client/redis/apns/feedback_spec.rb +5 -0
- data/spec/unit/client/redis/apns/notification_spec.rb +50 -0
- data/spec/unit/client/redis/apns2/app_spec.rb +4 -0
- data/spec/unit/client/redis/apns2/notification_spec.rb +50 -0
- data/spec/unit/client/redis/apnsp8/notification_spec.rb +29 -0
- data/spec/unit/client/redis/app_spec.rb +5 -0
- data/spec/unit/client/redis/gcm/app_spec.rb +5 -0
- data/spec/unit/client/redis/gcm/notification_spec.rb +5 -0
- data/spec/unit/client/redis/notification_spec.rb +5 -0
- data/spec/unit/client/redis/pushy/app_spec.rb +5 -0
- data/spec/unit/client/redis/pushy/notification_spec.rb +5 -0
- data/spec/unit/client/redis/webpush/app_spec.rb +5 -0
- data/spec/unit/client/redis/webpush/notification_spec.rb +5 -0
- data/spec/unit/client/redis/wns/badge_notification_spec.rb +5 -0
- data/spec/unit/client/redis/wns/raw_notification_spec.rb +22 -0
- data/spec/unit/client/redis/wpns/app_spec.rb +5 -0
- data/spec/unit/client/redis/wpns/notification_spec.rb +5 -0
- data/spec/unit/client/shared/adm/app.rb +51 -0
- data/spec/unit/client/shared/adm/notification.rb +39 -0
- data/spec/unit/client/shared/apns/app.rb +29 -0
- data/spec/unit/client/shared/apns/feedback.rb +9 -0
- data/spec/unit/client/shared/apns/notification.rb +262 -0
- data/spec/unit/client/shared/app.rb +17 -0
- data/spec/unit/client/shared/gcm/app.rb +4 -0
- data/spec/unit/client/shared/gcm/notification.rb +77 -0
- data/spec/unit/client/shared/notification.rb +10 -0
- data/spec/unit/client/shared/pushy/app.rb +17 -0
- data/spec/unit/client/shared/pushy/notification.rb +55 -0
- data/spec/unit/client/shared/webpush/app.rb +33 -0
- data/spec/unit/client/shared/webpush/notification.rb +83 -0
- data/spec/unit/client/shared/wns/badge_notification.rb +15 -0
- data/spec/unit/client/shared/wns/raw_notification.rb +21 -0
- data/spec/unit/client/shared/wpns/app.rb +4 -0
- data/spec/unit/client/shared/wpns/notification.rb +18 -0
- data/spec/unit/daemon/batch_spec.rb +50 -2
- data/spec/unit/daemon/delivery_spec.rb +10 -0
- data/spec/unit/daemon/pushy/delivery_spec.rb +5 -3
- data/spec/unit/daemon/shared/store.rb +312 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +7 -7
- data/spec/unit/daemon/store/active_record_spec.rb +2 -290
- data/spec/unit/daemon/store/redis_spec.rb +2 -291
- data/spec/unit/daemon/webpush/delivery_spec.rb +144 -0
- data/spec/unit_spec_helper.rb +3 -0
- metadata +135 -12
- data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +0 -16
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples 'Rpush::Client::Apns::Feedback' do
|
|
4
|
+
it 'validates the format of the device_token' do
|
|
5
|
+
notification = described_class.new(device_token: "{$%^&*()}")
|
|
6
|
+
expect(notification.valid?).to be_falsey
|
|
7
|
+
expect(notification.errors[:device_token]).to include('is invalid')
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# encoding: US-ASCII
|
|
2
|
+
|
|
3
|
+
require "unit_spec_helper"
|
|
4
|
+
|
|
5
|
+
shared_examples 'Rpush::Client::Apns::Notification' do
|
|
6
|
+
let(:notification) { described_class.new }
|
|
7
|
+
let(:app) { Rpush::Apns::App.create!(name: 'my_app', environment: 'development', certificate: TEST_CERT) }
|
|
8
|
+
|
|
9
|
+
it "should validate the format of the device_token" do
|
|
10
|
+
notification = described_class.new(device_token: "{$%^&*()}")
|
|
11
|
+
expect(notification.valid?).to be_falsey
|
|
12
|
+
expect(notification.errors[:device_token].include?("is invalid")).to be_truthy
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should store long alerts" do
|
|
16
|
+
notification.app = app
|
|
17
|
+
notification.device_token = "a" * 108
|
|
18
|
+
notification.alert = "*" * 300
|
|
19
|
+
expect(notification.valid?).to be_truthy
|
|
20
|
+
|
|
21
|
+
notification.save!
|
|
22
|
+
notification.reload
|
|
23
|
+
expect(notification.alert).to eq("*" * 300)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should default the expiry to 1 day" do
|
|
27
|
+
expect(notification.expiry).to eq 1.day.to_i
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe "when assigning the device token" do
|
|
31
|
+
it "should strip spaces from the given string" do
|
|
32
|
+
notification = described_class.new(device_token: "o m g")
|
|
33
|
+
expect(notification.device_token).to eq "omg"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should strip chevrons from the given string" do
|
|
37
|
+
notification = described_class.new(device_token: "<omg>")
|
|
38
|
+
expect(notification.device_token).to eq "omg"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe "as_json" do
|
|
43
|
+
it "should include the alert if present" do
|
|
44
|
+
notification = described_class.new(alert: "hi mom")
|
|
45
|
+
expect(notification.as_json["aps"]["alert"]).to eq "hi mom"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should not include the alert key if the alert is not present" do
|
|
49
|
+
notification = described_class.new(alert: nil)
|
|
50
|
+
expect(notification.as_json["aps"].key?("alert")).to be_falsey
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should encode the alert as JSON if it is a Hash" do
|
|
54
|
+
notification = described_class.new(alert: { 'body' => "hi mom", 'alert-loc-key' => "View" })
|
|
55
|
+
expect(notification.as_json["aps"]["alert"]).to eq('body' => "hi mom", 'alert-loc-key' => "View")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should include the badge if present" do
|
|
59
|
+
notification = described_class.new(badge: 6)
|
|
60
|
+
expect(notification.as_json["aps"]["badge"]).to eq 6
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should not include the badge key if the badge is not present" do
|
|
64
|
+
notification = described_class.new(badge: nil)
|
|
65
|
+
expect(notification.as_json["aps"].key?("badge")).to be_falsey
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should include the sound if present" do
|
|
69
|
+
notification = described_class.new(sound: "my_sound.aiff")
|
|
70
|
+
expect(notification.as_json["aps"]["sound"]).to eq "my_sound.aiff"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should not include the sound key if the sound is not present" do
|
|
74
|
+
notification = described_class.new(sound: nil)
|
|
75
|
+
expect(notification.as_json["aps"].key?("sound")).to be_falsey
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should encode the sound as JSON if it is a Hash" do
|
|
79
|
+
notification = described_class.new(sound: { 'name' => "my_sound.aiff", 'critical' => 1, 'volume' => 0.5 })
|
|
80
|
+
expect(notification.as_json["aps"]["sound"]).to eq('name' => "my_sound.aiff", 'critical' => 1, 'volume' => 0.5)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "should include attributes for the device" do
|
|
84
|
+
notification = described_class.new
|
|
85
|
+
notification.data = { 'omg' => 'lol', 'wtf' => 'dunno' }
|
|
86
|
+
expect(notification.as_json["omg"]).to eq "lol"
|
|
87
|
+
expect(notification.as_json["wtf"]).to eq "dunno"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "should allow attributes to include a hash" do
|
|
91
|
+
notification = described_class.new
|
|
92
|
+
notification.data = { 'omg' => { 'ilike' => 'hashes' } }
|
|
93
|
+
expect(notification.as_json["omg"]["ilike"]).to eq "hashes"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe 'MDM' do
|
|
98
|
+
let(:magic) { 'abc123' }
|
|
99
|
+
|
|
100
|
+
before do
|
|
101
|
+
notification.device_token = "a" * 108
|
|
102
|
+
notification.id = 1234
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'includes the mdm magic in the payload' do
|
|
106
|
+
notification.mdm = magic
|
|
107
|
+
expect(notification.as_json).to eq('mdm' => magic)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'does not include aps attribute' do
|
|
111
|
+
notification.alert = "i'm doomed"
|
|
112
|
+
notification.mdm = magic
|
|
113
|
+
expect(notification.as_json.key?('aps')).to be_falsey
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'can be converted to binary' do
|
|
117
|
+
notification.mdm = magic
|
|
118
|
+
expect(notification.to_binary).to be_present
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
describe 'mutable-content' do
|
|
123
|
+
it 'includes mutable-content in the payload' do
|
|
124
|
+
notification.mutable_content = true
|
|
125
|
+
expect(notification.as_json['aps']['mutable-content']).to eq 1
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'does not include content-available in the payload if not set' do
|
|
129
|
+
expect(notification.as_json['aps'].key?('mutable-content')).to be_falsey
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'does not include mutable-content as a non-aps attribute' do
|
|
133
|
+
notification.mutable_content = true
|
|
134
|
+
expect(notification.as_json.key?('mutable-content')).to be_falsey
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'does not overwrite existing attributes for the device' do
|
|
138
|
+
notification.data = { 'hi' => 'mom' }
|
|
139
|
+
notification.mutable_content = true
|
|
140
|
+
expect(notification.as_json['aps']['mutable-content']).to eq 1
|
|
141
|
+
expect(notification.as_json['hi']).to eq 'mom'
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe 'content-available' do
|
|
146
|
+
it 'includes content-available in the payload' do
|
|
147
|
+
notification.content_available = true
|
|
148
|
+
expect(notification.as_json['aps']['content-available']).to eq 1
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'does not include content-available in the payload if not set' do
|
|
152
|
+
expect(notification.as_json['aps'].key?('content-available')).to be_falsey
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it 'does not include content-available as a non-aps attribute' do
|
|
156
|
+
notification.content_available = true
|
|
157
|
+
expect(notification.as_json.key?('content-available')).to be_falsey
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'does not overwrite existing attributes for the device' do
|
|
161
|
+
notification.data = { 'hi' => 'mom' }
|
|
162
|
+
notification.content_available = true
|
|
163
|
+
expect(notification.as_json['aps']['content-available']).to eq 1
|
|
164
|
+
expect(notification.as_json['hi']).to eq 'mom'
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
describe 'url-args' do
|
|
169
|
+
it 'includes url-args in the payload' do
|
|
170
|
+
notification.url_args = ['url-arg-1']
|
|
171
|
+
expect(notification.as_json['aps']['url-args']).to eq ['url-arg-1']
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'does not include url-args in the payload if not set' do
|
|
175
|
+
expect(notification.as_json['aps'].key?('url-args')).to be_falsey
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
describe 'category' do
|
|
180
|
+
it 'includes category in the payload' do
|
|
181
|
+
notification.category = 'INVITE_CATEGORY'
|
|
182
|
+
expect(notification.as_json['aps']['category']).to eq 'INVITE_CATEGORY'
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'does not include category in the payload if not set' do
|
|
186
|
+
expect(notification.as_json['aps'].key?('category')).to be_falsey
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
describe 'to_binary' do
|
|
191
|
+
before do
|
|
192
|
+
notification.device_token = "a" * 108
|
|
193
|
+
notification.id = 1234
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'uses APNS_PRIORITY_CONSERVE_POWER if content-available is the only key' do
|
|
197
|
+
notification.alert = nil
|
|
198
|
+
notification.badge = nil
|
|
199
|
+
notification.sound = nil
|
|
200
|
+
notification.content_available = true
|
|
201
|
+
bytes = notification.to_binary.bytes.to_a[-4..-1]
|
|
202
|
+
expect(bytes.first).to eq 5 # priority item ID
|
|
203
|
+
expect(bytes.last).to eq described_class::APNS_PRIORITY_CONSERVE_POWER
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it 'uses APNS_PRIORITY_IMMEDIATE if content-available is not the only key' do
|
|
207
|
+
notification.alert = "New stuff!"
|
|
208
|
+
notification.badge = nil
|
|
209
|
+
notification.sound = nil
|
|
210
|
+
notification.content_available = true
|
|
211
|
+
bytes = notification.to_binary.bytes.to_a[-4..-1]
|
|
212
|
+
expect(bytes.first).to eq 5 # priority item ID
|
|
213
|
+
expect(bytes.last).to eq described_class::APNS_PRIORITY_IMMEDIATE
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it "should correctly convert the notification to binary" do
|
|
217
|
+
notification.sound = "1.aiff"
|
|
218
|
+
notification.badge = 3
|
|
219
|
+
notification.alert = "Don't panic Mr Mainwaring, don't panic!"
|
|
220
|
+
notification.data = { hi: :mom }
|
|
221
|
+
notification.expiry = 86_400 # 1 day
|
|
222
|
+
notification.priority = described_class::APNS_PRIORITY_IMMEDIATE
|
|
223
|
+
notification.app = app
|
|
224
|
+
now = Time.now
|
|
225
|
+
allow(Time).to receive_messages(now: now)
|
|
226
|
+
expect(notification.to_binary).to eq "\x02\x00\x00\x00\xAF\x01\x00 \xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\x02\x00a{\"aps\":{\"alert\":\"Don't panic Mr Mainwaring, don't panic!\",\"badge\":3,\"sound\":\"1.aiff\"},\"hi\":\"mom\"}\x03\x00\x04\x00\x00\x04\xD2\x04\x00\x04#{[now.to_i + 86_400].pack('N')}\x05\x00\x01\n"
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
describe "bug #31" do
|
|
231
|
+
it 'does not confuse a JSON looking string as JSON' do
|
|
232
|
+
notification = described_class.new
|
|
233
|
+
notification.alert = "{\"one\":2}"
|
|
234
|
+
expect(notification.alert).to eq "{\"one\":2}"
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
describe "bug #35" do
|
|
239
|
+
it "should limit payload size to 256 bytes but not the entire packet" do
|
|
240
|
+
notification = described_class.new.tap do |n|
|
|
241
|
+
n.device_token = "a" * 108
|
|
242
|
+
n.alert = "a" * 210
|
|
243
|
+
n.app = app
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
expect(notification.to_binary(for_validation: true).bytesize).to be > 256
|
|
247
|
+
expect(notification.payload.bytesize).to be < 256
|
|
248
|
+
expect(notification).to be_valid
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
describe 'thread-id' do
|
|
253
|
+
it 'includes thread-id in the payload' do
|
|
254
|
+
notification.thread_id = 'THREAD-ID'
|
|
255
|
+
expect(notification.as_json['aps']['thread-id']).to eq 'THREAD-ID'
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it 'does not include thread-id in the payload if not set' do
|
|
259
|
+
expect(notification.as_json['aps']).to_not have_key('thread-id')
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples 'Rpush::Client::App' do
|
|
4
|
+
context 'validating certificates' do
|
|
5
|
+
it 'rescues from certificate error' do
|
|
6
|
+
app = Rpush::Apns::App.new(name: 'test', environment: 'development', certificate: 'bad')
|
|
7
|
+
expect { app.valid? }.not_to raise_error
|
|
8
|
+
expect(app.valid?).to eq(false)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'raises other errors' do
|
|
12
|
+
app = Rpush::Apns::App.new(name: 'test', environment: 'development', certificate: 'bad')
|
|
13
|
+
allow(OpenSSL::X509::Certificate).to receive(:new).and_raise(NameError, 'simulating no openssl')
|
|
14
|
+
expect { app.valid? }.to raise_error(NameError)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples 'Rpush::Client::Gcm::Notification' do
|
|
4
|
+
let(:app) { Rpush::Gcm::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.data = { key: "a" * 4096 }
|
|
9
|
+
expect(notification.valid?).to be_falsey
|
|
10
|
+
expect(notification.errors[:base]).to eq ["Notification payload data cannot be larger than 4096 bytes."]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'limits the number of registration ids to 1000' do
|
|
14
|
+
notification.registration_ids = ['a'] * (1000 + 1)
|
|
15
|
+
expect(notification.valid?).to be_falsey
|
|
16
|
+
expect(notification.errors[:base]).to eq ["Number of registration_ids cannot be larger than 1000."]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'validates expiry is present if collapse_key is set' do
|
|
20
|
+
notification.collapse_key = 'test'
|
|
21
|
+
notification.expiry = nil
|
|
22
|
+
expect(notification.valid?).to be_falsey
|
|
23
|
+
expect(notification.errors[:expiry]).to eq ['must be set when using a collapse_key']
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'includes time_to_live in the payload' do
|
|
27
|
+
notification.expiry = 100
|
|
28
|
+
expect(notification.as_json['time_to_live']).to eq 100
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'includes content_available in the payload' do
|
|
32
|
+
notification.content_available = true
|
|
33
|
+
expect(notification.as_json['content_available']).to eq true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'includes mutable_content in the payload' do
|
|
37
|
+
notification.mutable_content = true
|
|
38
|
+
expect(notification.as_json['mutable_content']).to eq true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'sets the priority to high when set to high' do
|
|
42
|
+
notification.priority = 'high'
|
|
43
|
+
expect(notification.as_json['priority']).to eq 'high'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'sets the priority to normal when set to normal' do
|
|
47
|
+
notification.priority = 'normal'
|
|
48
|
+
expect(notification.as_json['priority']).to eq 'normal'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'validates the priority is either "normal" or "high"' do
|
|
52
|
+
notification.priority = 'invalid'
|
|
53
|
+
expect(notification.errors[:priority]).to eq ['must be one of either "normal" or "high"']
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'excludes the priority if it is not defined' do
|
|
57
|
+
expect(notification.as_json).not_to have_key 'priority'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'includes the notification payload if defined' do
|
|
61
|
+
notification.notification = { key: 'any key is allowed' }
|
|
62
|
+
expect(notification.as_json).to have_key 'notification'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'excludes the notification payload if undefined' do
|
|
66
|
+
expect(notification.as_json).not_to have_key 'notification'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'includes the dry_run payload if defined' do
|
|
70
|
+
notification.dry_run = true
|
|
71
|
+
expect(notification.as_json['dry_run']).to eq true
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'excludes the dry_run payload if undefined' do
|
|
75
|
+
expect(notification.as_json).not_to have_key 'dry_run'
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples 'Rpush::Client::Notification' do
|
|
4
|
+
let(:notification) { described_class.new }
|
|
5
|
+
|
|
6
|
+
it 'allows assignment of many registration IDs' do
|
|
7
|
+
notification.registration_ids = %w[a b]
|
|
8
|
+
expect(notification.registration_ids).to eq %w[a b]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples 'Rpush::Client::Pushy::App' do
|
|
4
|
+
describe 'validates' do
|
|
5
|
+
subject { described_class.new }
|
|
6
|
+
|
|
7
|
+
it 'validates presence of name' do
|
|
8
|
+
is_expected.not_to be_valid
|
|
9
|
+
expect(subject.errors[:name]).to eq ["can't be blank"]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'validates presence of api_key' do
|
|
13
|
+
is_expected.not_to be_valid
|
|
14
|
+
expect(subject.errors[:api_key]).to eq ["can't be blank"]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples 'Rpush::Client::Pushy::Notification' do
|
|
4
|
+
subject(:notification) { described_class.new }
|
|
5
|
+
|
|
6
|
+
describe 'validates' do
|
|
7
|
+
let(:app) { Rpush::Pushy::App.create!(name: 'MyApp', api_key: 'my_api_key') }
|
|
8
|
+
|
|
9
|
+
describe 'data' do
|
|
10
|
+
subject { described_class.new(app: app, registration_ids: ['id']) }
|
|
11
|
+
it 'validates presence' do
|
|
12
|
+
is_expected.not_to be_valid
|
|
13
|
+
expect(subject.errors[:data]).to eq ["can't be blank"]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "has a 'data' payload limit of 4096 bytes" do
|
|
17
|
+
subject.data = { message: 'a' * 4096 }
|
|
18
|
+
is_expected.not_to be_valid
|
|
19
|
+
expected_errors = ["Notification payload data cannot be larger than 4096 bytes."]
|
|
20
|
+
expect(subject.errors[:base]).to eq expected_errors
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe 'registration_ids' do
|
|
25
|
+
subject { described_class.new(app: app, data: { message: 'test' }) }
|
|
26
|
+
it 'validates presence' do
|
|
27
|
+
is_expected.not_to be_valid
|
|
28
|
+
expect(subject.errors[:registration_ids]).to eq ["can't be blank"]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'limits the number of registration ids to 1000' do
|
|
32
|
+
subject.registration_ids = ['a'] * (1000 + 1)
|
|
33
|
+
is_expected.not_to be_valid
|
|
34
|
+
expected_errors = ["Number of registration_ids cannot be larger than 1000."]
|
|
35
|
+
expect(subject.errors[:base]).to eq expected_errors
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe 'time_to_live' do
|
|
40
|
+
subject { described_class.new(app: app, data: { message: 'test' }, registration_ids: ['id']) }
|
|
41
|
+
|
|
42
|
+
it 'should be > 0' do
|
|
43
|
+
subject.time_to_live = -1
|
|
44
|
+
is_expected.not_to be_valid
|
|
45
|
+
expect(subject.errors[:time_to_live]).to eq ['must be greater than 0']
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'should be <= 1.year.seconds' do
|
|
49
|
+
subject.time_to_live = 2.years.seconds.to_i
|
|
50
|
+
is_expected.not_to be_valid
|
|
51
|
+
expect(subject.errors[:time_to_live]).to eq ['The maximum value is 1 year']
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|