rpush 4.2.0 → 7.0.1
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 +307 -163
- data/README.md +105 -19
- data/lib/generators/templates/add_adm.rb +1 -1
- data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +2 -2
- data/lib/generators/templates/add_app_to_rapns.rb +2 -2
- data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +1 -1
- data/lib/generators/templates/add_gcm.rb +11 -25
- data/lib/generators/templates/add_rpush.rb +33 -83
- data/lib/generators/templates/add_wpns.rb +1 -1
- data/lib/generators/templates/create_rapns_apps.rb +1 -1
- data/lib/generators/templates/create_rapns_feedback.rb +3 -9
- data/lib/generators/templates/create_rapns_notifications.rb +3 -9
- data/lib/generators/templates/rename_rapns_to_rpush.rb +9 -33
- data/lib/generators/templates/rpush.rb +5 -4
- data/lib/generators/templates/rpush_2_0_0_updates.rb +10 -18
- data/lib/generators/templates/rpush_2_1_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_2_6_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_2_7_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_0_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_0_1_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_1_0_add_pushy.rb +1 -1
- data/lib/generators/templates/rpush_3_1_1_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_2_0_add_apns_p8.rb +1 -1
- data/lib/generators/templates/rpush_3_2_4_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_3_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_3_3_1_updates.rb +3 -3
- data/lib/generators/templates/rpush_4_1_0_updates.rb +1 -1
- data/lib/generators/templates/rpush_4_1_1_updates.rb +1 -1
- data/lib/generators/templates/rpush_4_2_0_updates.rb +1 -1
- data/lib/rpush/cli.rb +1 -1
- data/lib/rpush/client/active_model/adm/data_validator.rb +1 -1
- data/lib/rpush/client/active_model/apns/app.rb +1 -17
- data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +2 -2
- data/lib/rpush/client/active_model/apns/notification.rb +13 -1
- data/lib/rpush/client/active_model/apns/notification_payload_size_validator.rb +15 -0
- data/lib/rpush/client/active_model/apns2/app.rb +7 -1
- data/lib/rpush/client/active_model/apns2/notification.rb +14 -0
- data/lib/rpush/client/active_model/certificate_private_key_validator.rb +19 -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_model.rb +5 -1
- 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/active_record.rb +4 -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/client/redis.rb +3 -0
- data/lib/rpush/configuration.rb +3 -2
- data/lib/rpush/daemon/apns/feedback_receiver.rb +1 -1
- data/lib/rpush/daemon/apns2/delivery.rb +14 -2
- data/lib/rpush/daemon/apnsp8/delivery.rb +14 -3
- 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/store/active_record.rb +11 -7
- data/lib/rpush/daemon/store/redis.rb +6 -6
- data/lib/rpush/daemon/string_helpers.rb +1 -1
- data/lib/rpush/daemon/webpush/delivery.rb +114 -0
- data/lib/rpush/daemon/webpush.rb +10 -0
- data/lib/rpush/daemon.rb +4 -1
- data/lib/rpush/logger.rb +2 -1
- data/lib/rpush/version.rb +3 -3
- data/spec/functional/apns2_spec.rb +99 -2
- data/spec/functional/gcm_priority_spec.rb +40 -0
- data/spec/functional/retry_spec.rb +1 -1
- data/spec/functional/webpush_spec.rb +31 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/support/active_record_setup.rb +4 -3
- data/spec/support/config/database.yml +4 -4
- data/spec/support/simplecov_helper.rb +2 -2
- 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 +5 -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 +277 -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/apnsp8/delivery_spec.rb +53 -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 +6 -287
- 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 +145 -18
- data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +0 -16
|
@@ -1,329 +1,65 @@
|
|
|
1
|
-
# encoding: US-ASCII
|
|
2
|
-
|
|
3
1
|
require "unit_spec_helper"
|
|
4
|
-
require 'unit/notification_shared.rb'
|
|
5
2
|
|
|
6
3
|
describe Rpush::Client::ActiveRecord::Apns::Notification do
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
let(:app) { Rpush::Client::ActiveRecord::Apns::App.create!(name: 'my_app', environment: 'development', certificate: TEST_CERT) }
|
|
10
|
-
let(:notification_class) { Rpush::Client::ActiveRecord::Apns::Notification }
|
|
11
|
-
let(:notification) { notification_class.new }
|
|
4
|
+
subject(:notification) { described_class.new }
|
|
12
5
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
expect(notification.valid?).to be_falsey
|
|
16
|
-
expect(notification.errors[:device_token].include?("is invalid")).to be_truthy
|
|
17
|
-
end
|
|
6
|
+
it_behaves_like 'Rpush::Client::Apns::Notification'
|
|
7
|
+
it_behaves_like 'Rpush::Client::ActiveRecord::Notification'
|
|
18
8
|
|
|
19
9
|
it "should validate the length of the binary conversion of the notification" do
|
|
10
|
+
notification = described_class.new
|
|
11
|
+
notification.app = Rpush::Apns2::App.create(name: 'test', environment: 'development', certificate: TEST_CERT)
|
|
20
12
|
notification.device_token = "a" * 108
|
|
21
|
-
notification.alert = "
|
|
22
|
-
expect(notification.valid?).to be_falsey
|
|
23
|
-
expect(notification.errors[:base].include?("APN notification cannot be larger than 2048 bytes. Try condensing your alert and device attributes.")).to be_truthy
|
|
24
|
-
end
|
|
13
|
+
notification.alert = ""
|
|
25
14
|
|
|
26
|
-
|
|
27
|
-
notification.app = app
|
|
28
|
-
notification.device_token = "a" * 108
|
|
29
|
-
notification.alert = "*" * 300
|
|
15
|
+
notification.alert << "a" until notification.payload.bytesize == 2048
|
|
30
16
|
expect(notification.valid?).to be_truthy
|
|
17
|
+
expect(notification.errors[:base]).to be_empty
|
|
31
18
|
|
|
32
|
-
notification.
|
|
33
|
-
notification.
|
|
34
|
-
expect(notification.
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
it "should default the sound to nil" do
|
|
38
|
-
expect(notification.sound).to be_nil
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
it "should default the expiry to 1 day" do
|
|
42
|
-
expect(notification.expiry).to eq 1.day.to_i
|
|
43
|
-
end
|
|
44
|
-
end if active_record?
|
|
45
|
-
|
|
46
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, "when assigning the device token" do
|
|
47
|
-
it "should strip spaces from the given string" do
|
|
48
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(device_token: "o m g")
|
|
49
|
-
expect(notification.device_token).to eq "omg"
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "should strip chevrons from the given string" do
|
|
53
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(device_token: "<omg>")
|
|
54
|
-
expect(notification.device_token).to eq "omg"
|
|
55
|
-
end
|
|
56
|
-
end if active_record?
|
|
57
|
-
|
|
58
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, "as_json" do
|
|
59
|
-
it "should include the alert if present" do
|
|
60
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(alert: "hi mom")
|
|
61
|
-
expect(notification.as_json["aps"]["alert"]).to eq "hi mom"
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
it "should not include the alert key if the alert is not present" do
|
|
65
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(alert: nil)
|
|
66
|
-
expect(notification.as_json["aps"].key?("alert")).to be_falsey
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it "should encode the alert as JSON if it is a Hash" do
|
|
70
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(alert: { 'body' => "hi mom", 'alert-loc-key' => "View" })
|
|
71
|
-
expect(notification.as_json["aps"]["alert"]).to eq('body' => "hi mom", 'alert-loc-key' => "View")
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
it "should include the badge if present" do
|
|
75
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(badge: 6)
|
|
76
|
-
expect(notification.as_json["aps"]["badge"]).to eq 6
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
it "should not include the badge key if the badge is not present" do
|
|
80
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(badge: nil)
|
|
81
|
-
expect(notification.as_json["aps"].key?("badge")).to be_falsey
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
it "should include the sound if present" do
|
|
85
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(sound: "my_sound.aiff")
|
|
86
|
-
expect(notification.as_json["aps"]["sound"]).to eq "my_sound.aiff"
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it "should not include the sound key if the sound is not present" do
|
|
90
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(sound: nil)
|
|
91
|
-
expect(notification.as_json["aps"].key?("sound")).to be_falsey
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
it "should encode the sound as JSON if it is a Hash" do
|
|
95
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(sound: { 'name' => "my_sound.aiff", 'critical' => 1, 'volume' => 0.5 })
|
|
96
|
-
expect(notification.as_json["aps"]["sound"]).to eq('name' => "my_sound.aiff", 'critical' => 1, 'volume' => 0.5)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
it "should include attributes for the device" do
|
|
100
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new
|
|
101
|
-
notification.data = { omg: :lol, wtf: :dunno }
|
|
102
|
-
expect(notification.as_json["omg"]).to eq "lol"
|
|
103
|
-
expect(notification.as_json["wtf"]).to eq "dunno"
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
it "should allow attributes to include a hash" do
|
|
107
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new
|
|
108
|
-
notification.data = { omg: { ilike: :hashes } }
|
|
109
|
-
expect(notification.as_json["omg"]["ilike"]).to eq "hashes"
|
|
110
|
-
end
|
|
111
|
-
end if active_record?
|
|
112
|
-
|
|
113
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, 'MDM' do
|
|
114
|
-
let(:magic) { 'abc123' }
|
|
115
|
-
let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
|
|
116
|
-
|
|
117
|
-
before do
|
|
118
|
-
notification.device_token = "a" * 108
|
|
119
|
-
notification.id = 1234
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
it 'includes the mdm magic in the payload' do
|
|
123
|
-
notification.mdm = magic
|
|
124
|
-
expect(notification.as_json).to eq('mdm' => magic)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
it 'does not include aps attribute' do
|
|
128
|
-
notification.alert = "i'm doomed"
|
|
129
|
-
notification.mdm = magic
|
|
130
|
-
expect(notification.as_json.key?('aps')).to be_falsey
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
it 'can be converted to binary' do
|
|
134
|
-
notification.mdm = magic
|
|
135
|
-
expect(notification.to_binary).to be_present
|
|
19
|
+
notification.alert << "a"
|
|
20
|
+
expect(notification.valid?).to be_falsey
|
|
21
|
+
expect(notification.errors[:base].include?("APN notification cannot be larger than 2048 bytes. Try condensing your alert and device attributes.")).to be_truthy
|
|
136
22
|
end
|
|
137
|
-
end if active_record?
|
|
138
23
|
|
|
139
|
-
describe
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
it 'includes mutable-content in the payload' do
|
|
143
|
-
notification.mutable_content = true
|
|
144
|
-
expect(notification.as_json['aps']['mutable-content']).to eq 1
|
|
145
|
-
end
|
|
24
|
+
describe "multi_json usage" do
|
|
25
|
+
describe "alert" do
|
|
26
|
+
subject(:notification) { described_class.new(alert: { a: 1 }, alert_is_json: true) }
|
|
146
27
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
28
|
+
it "should call MultiJson.load when multi_json version is 1.3.0" do
|
|
29
|
+
allow(Gem).to receive(:loaded_specs).and_return('multi_json' => Gem::Specification.new('multi_json', '1.3.0'))
|
|
30
|
+
expect(MultiJson).to receive(:load).with(any_args)
|
|
31
|
+
notification.alert
|
|
32
|
+
end
|
|
150
33
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
34
|
+
it "should call MultiJson.decode when multi_json version is 1.2.9" do
|
|
35
|
+
allow(Gem).to receive(:loaded_specs).and_return('multi_json' => Gem::Specification.new('multi_json', '1.2.9'))
|
|
36
|
+
expect(MultiJson).to receive(:decode).with(any_args)
|
|
37
|
+
notification.alert
|
|
38
|
+
end
|
|
39
|
+
end
|
|
154
40
|
end
|
|
155
41
|
|
|
156
|
-
it
|
|
157
|
-
notification.
|
|
158
|
-
notification.mutable_content = true
|
|
159
|
-
expect(notification.as_json['aps']['mutable-content']).to eq 1
|
|
160
|
-
expect(notification.as_json['hi']).to eq 'mom'
|
|
42
|
+
it "should default the sound to nil" do
|
|
43
|
+
expect(notification.sound).to be_nil
|
|
161
44
|
end
|
|
162
45
|
|
|
163
46
|
it 'does not overwrite the mutable-content flag when setting attributes for the device' do
|
|
164
47
|
notification.mutable_content = true
|
|
165
|
-
notification.data = { hi
|
|
48
|
+
notification.data = { 'hi' => 'mom' }
|
|
166
49
|
expect(notification.as_json['aps']['mutable-content']).to eq 1
|
|
167
50
|
expect(notification.as_json['hi']).to eq 'mom'
|
|
168
51
|
end
|
|
169
|
-
end if active_record?
|
|
170
|
-
|
|
171
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, 'content-available' do
|
|
172
|
-
let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
|
|
173
|
-
|
|
174
|
-
it 'includes content-available in the payload' do
|
|
175
|
-
notification.content_available = true
|
|
176
|
-
expect(notification.as_json['aps']['content-available']).to eq 1
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
it 'does not include content-available in the payload if not set' do
|
|
180
|
-
expect(notification.as_json['aps'].key?('content-available')).to be_falsey
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
it 'does not include content-available as a non-aps attribute' do
|
|
184
|
-
notification.content_available = true
|
|
185
|
-
expect(notification.as_json.key?('content-available')).to be_falsey
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
it 'does not overwrite existing attributes for the device' do
|
|
189
|
-
notification.data = { hi: :mom }
|
|
190
|
-
notification.content_available = true
|
|
191
|
-
expect(notification.as_json['aps']['content-available']).to eq 1
|
|
192
|
-
expect(notification.as_json['hi']).to eq 'mom'
|
|
193
|
-
end
|
|
194
52
|
|
|
195
53
|
it 'does not overwrite the content-available flag when setting attributes for the device' do
|
|
196
54
|
notification.content_available = true
|
|
197
|
-
notification.data = { hi
|
|
55
|
+
notification.data = { 'hi' => 'mom' }
|
|
198
56
|
expect(notification.as_json['aps']['content-available']).to eq 1
|
|
199
57
|
expect(notification.as_json['hi']).to eq 'mom'
|
|
200
58
|
end
|
|
201
|
-
end if active_record?
|
|
202
|
-
|
|
203
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, 'url-args' do
|
|
204
|
-
let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
|
|
205
|
-
|
|
206
|
-
it 'includes url-args in the payload' do
|
|
207
|
-
notification.url_args = ['url-arg-1']
|
|
208
|
-
expect(notification.as_json['aps']['url-args']).to eq ['url-arg-1']
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
it 'does not include url-args in the payload if not set' do
|
|
212
|
-
expect(notification.as_json['aps'].key?('url-args')).to be_falsey
|
|
213
|
-
end
|
|
214
|
-
end if active_record?
|
|
215
|
-
|
|
216
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, 'category' do
|
|
217
|
-
let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
|
|
218
|
-
|
|
219
|
-
it 'includes category in the payload' do
|
|
220
|
-
notification.category = 'INVITE_CATEGORY'
|
|
221
|
-
expect(notification.as_json['aps']['category']).to eq 'INVITE_CATEGORY'
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
it 'does not include category in the payload if not set' do
|
|
225
|
-
expect(notification.as_json['aps'].key?('category')).to be_falsey
|
|
226
|
-
end
|
|
227
|
-
end if active_record?
|
|
228
|
-
|
|
229
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, 'to_binary' do
|
|
230
|
-
let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
|
|
231
|
-
|
|
232
|
-
before do
|
|
233
|
-
notification.device_token = "a" * 108
|
|
234
|
-
notification.id = 1234
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
it 'uses APNS_PRIORITY_CONSERVE_POWER if content-available is the only key' do
|
|
238
|
-
notification.alert = nil
|
|
239
|
-
notification.badge = nil
|
|
240
|
-
notification.sound = nil
|
|
241
|
-
notification.content_available = true
|
|
242
|
-
bytes = notification.to_binary.bytes.to_a[-4..-1]
|
|
243
|
-
expect(bytes.first).to eq 5 # priority item ID
|
|
244
|
-
expect(bytes.last).to eq Rpush::Client::ActiveRecord::Apns::Notification::APNS_PRIORITY_CONSERVE_POWER
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
it 'uses APNS_PRIORITY_IMMEDIATE if content-available is not the only key' do
|
|
248
|
-
notification.alert = "New stuff!"
|
|
249
|
-
notification.badge = nil
|
|
250
|
-
notification.sound = nil
|
|
251
|
-
notification.content_available = true
|
|
252
|
-
bytes = notification.to_binary.bytes.to_a[-4..-1]
|
|
253
|
-
expect(bytes.first).to eq 5 # priority item ID
|
|
254
|
-
expect(bytes.last).to eq Rpush::Client::ActiveRecord::Apns::Notification::APNS_PRIORITY_IMMEDIATE
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
it "should correctly convert the notification to binary" do
|
|
258
|
-
notification.sound = "1.aiff"
|
|
259
|
-
notification.badge = 3
|
|
260
|
-
notification.alert = "Don't panic Mr Mainwaring, don't panic!"
|
|
261
|
-
notification.data = { hi: :mom }
|
|
262
|
-
notification.expiry = 86_400 # 1 day
|
|
263
|
-
notification.priority = Rpush::Client::ActiveRecord::Apns::Notification::APNS_PRIORITY_IMMEDIATE
|
|
264
|
-
notification.app = Rpush::Client::ActiveRecord::Apns::App.new(name: 'my_app', environment: 'development', certificate: TEST_CERT)
|
|
265
|
-
now = Time.now
|
|
266
|
-
allow(Time).to receive_messages(now: now)
|
|
267
|
-
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"
|
|
268
|
-
end
|
|
269
|
-
end if active_record?
|
|
270
|
-
|
|
271
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, "bug #31" do
|
|
272
|
-
it 'does not confuse a JSON looking string as JSON' do
|
|
273
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new
|
|
274
|
-
notification.alert = "{\"one\":2}"
|
|
275
|
-
expect(notification.alert).to eq "{\"one\":2}"
|
|
276
|
-
end
|
|
277
59
|
|
|
278
60
|
it 'does confuse a JSON looking string as JSON if the alert_is_json attribute is not present' do
|
|
279
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new
|
|
280
61
|
allow(notification).to receive_messages(has_attribute?: false)
|
|
281
62
|
notification.alert = "{\"one\":2}"
|
|
282
63
|
expect(notification.alert).to eq('one' => 2)
|
|
283
64
|
end
|
|
284
65
|
end if active_record?
|
|
285
|
-
|
|
286
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, "bug #35" do
|
|
287
|
-
it "should limit payload size to 256 bytes but not the entire packet" do
|
|
288
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new do |n|
|
|
289
|
-
n.device_token = "a" * 108
|
|
290
|
-
n.alert = "a" * 210
|
|
291
|
-
n.app = Rpush::Client::ActiveRecord::Apns::App.create!(name: 'my_app', environment: 'development', certificate: TEST_CERT)
|
|
292
|
-
end
|
|
293
|
-
|
|
294
|
-
expect(notification.to_binary(for_validation: true).bytesize).to be > 256
|
|
295
|
-
expect(notification.payload.bytesize).to be < 256
|
|
296
|
-
expect(notification).to be_valid
|
|
297
|
-
end
|
|
298
|
-
end if active_record?
|
|
299
|
-
|
|
300
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, "multi_json usage" do
|
|
301
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, "alert" do
|
|
302
|
-
it "should call MultiJson.load when multi_json version is 1.3.0" do
|
|
303
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(alert: { a: 1 }, alert_is_json: true)
|
|
304
|
-
allow(Gem).to receive(:loaded_specs).and_return('multi_json' => Gem::Specification.new('multi_json', '1.3.0'))
|
|
305
|
-
expect(MultiJson).to receive(:load).with(any_args)
|
|
306
|
-
notification.alert
|
|
307
|
-
end
|
|
308
|
-
|
|
309
|
-
it "should call MultiJson.decode when multi_json version is 1.2.9" do
|
|
310
|
-
notification = Rpush::Client::ActiveRecord::Apns::Notification.new(alert: { a: 1 }, alert_is_json: true)
|
|
311
|
-
allow(Gem).to receive(:loaded_specs).and_return('multi_json' => Gem::Specification.new('multi_json', '1.2.9'))
|
|
312
|
-
expect(MultiJson).to receive(:decode).with(any_args)
|
|
313
|
-
notification.alert
|
|
314
|
-
end
|
|
315
|
-
end
|
|
316
|
-
end if active_record?
|
|
317
|
-
|
|
318
|
-
describe Rpush::Client::ActiveRecord::Apns::Notification, 'thread-id' do
|
|
319
|
-
let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
|
|
320
|
-
|
|
321
|
-
it 'includes thread-id in the payload' do
|
|
322
|
-
notification.thread_id = 'THREAD-ID'
|
|
323
|
-
expect(notification.as_json['aps']['thread-id']).to eq 'THREAD-ID'
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
it 'does not include thread-id in the payload if not set' do
|
|
327
|
-
expect(notification.as_json['aps']).to_not have_key('thread-id')
|
|
328
|
-
end
|
|
329
|
-
end if active_record?
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require "unit_spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Rpush::Client::ActiveRecord::Apns2::Notification do
|
|
4
|
+
subject(:notification) { described_class.new }
|
|
5
|
+
|
|
6
|
+
it_behaves_like 'Rpush::Client::Apns::Notification'
|
|
7
|
+
it_behaves_like 'Rpush::Client::ActiveRecord::Notification'
|
|
8
|
+
|
|
9
|
+
it "should validate the length of the binary conversion of the notification" do
|
|
10
|
+
notification = described_class.new
|
|
11
|
+
notification.app = Rpush::Apns2::App.create(name: 'test', environment: 'development', certificate: TEST_CERT)
|
|
12
|
+
notification.device_token = "a" * 108
|
|
13
|
+
notification.alert = ""
|
|
14
|
+
|
|
15
|
+
notification.alert << "a" until notification.payload.bytesize == 4096
|
|
16
|
+
expect(notification.valid?).to be_truthy
|
|
17
|
+
expect(notification.errors[:base]).to be_empty
|
|
18
|
+
|
|
19
|
+
notification.alert << "a"
|
|
20
|
+
expect(notification.valid?).to be_falsey
|
|
21
|
+
expect(notification.errors[:base].include?("APN notification cannot be larger than 4096 bytes. Try condensing your alert and device attributes.")).to be_truthy
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe "multi_json usage" do
|
|
25
|
+
describe "alert" do
|
|
26
|
+
subject(:notification) { described_class.new(alert: { a: 1 }, alert_is_json: true) }
|
|
27
|
+
|
|
28
|
+
it "should call MultiJson.load when multi_json version is 1.3.0" do
|
|
29
|
+
allow(Gem).to receive(:loaded_specs).and_return('multi_json' => Gem::Specification.new('multi_json', '1.3.0'))
|
|
30
|
+
expect(MultiJson).to receive(:load).with(any_args)
|
|
31
|
+
notification.alert
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should call MultiJson.decode when multi_json version is 1.2.9" do
|
|
35
|
+
allow(Gem).to receive(:loaded_specs).and_return('multi_json' => Gem::Specification.new('multi_json', '1.2.9'))
|
|
36
|
+
expect(MultiJson).to receive(:decode).with(any_args)
|
|
37
|
+
notification.alert
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should default the sound to nil" do
|
|
43
|
+
expect(notification.sound).to be_nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'does not overwrite the mutable-content flag when setting attributes for the device' do
|
|
47
|
+
notification.mutable_content = true
|
|
48
|
+
notification.data = { 'hi' => 'mom' }
|
|
49
|
+
expect(notification.as_json['aps']['mutable-content']).to eq 1
|
|
50
|
+
expect(notification.as_json['hi']).to eq 'mom'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'does not overwrite the content-available flag when setting attributes for the device' do
|
|
54
|
+
notification.content_available = true
|
|
55
|
+
notification.data = { 'hi' => 'mom' }
|
|
56
|
+
expect(notification.as_json['aps']['content-available']).to eq 1
|
|
57
|
+
expect(notification.as_json['hi']).to eq 'mom'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'does confuse a JSON looking string as JSON if the alert_is_json attribute is not present' do
|
|
61
|
+
allow(notification).to receive_messages(has_attribute?: false)
|
|
62
|
+
notification.alert = "{\"one\":2}"
|
|
63
|
+
expect(notification.alert).to eq('one' => 2)
|
|
64
|
+
end
|
|
65
|
+
end if active_record?
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require "unit_spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Rpush::Client::ActiveRecord::Apnsp8::Notification do
|
|
4
|
+
subject(:notification) { described_class.new }
|
|
5
|
+
|
|
6
|
+
it_behaves_like 'Rpush::Client::Apns::Notification'
|
|
7
|
+
it_behaves_like 'Rpush::Client::ActiveRecord::Notification'
|
|
8
|
+
|
|
9
|
+
it "should validate the length of the binary conversion of the notification", :aggregate_failures do
|
|
10
|
+
notification = described_class.new
|
|
11
|
+
notification.app = Rpush::Apnsp8::App.create(apn_key: "1",
|
|
12
|
+
apn_key_id: "2",
|
|
13
|
+
name: 'test',
|
|
14
|
+
environment: 'development',
|
|
15
|
+
team_id: "3",
|
|
16
|
+
bundle_id: "4")
|
|
17
|
+
notification.device_token = "a" * 108
|
|
18
|
+
notification.alert = ""
|
|
19
|
+
|
|
20
|
+
notification.alert << "a" until notification.payload.bytesize == 4096
|
|
21
|
+
expect(notification.valid?).to be_truthy
|
|
22
|
+
expect(notification.errors[:base]).to be_empty
|
|
23
|
+
|
|
24
|
+
notification.alert << "a"
|
|
25
|
+
expect(notification.valid?).to be_falsey
|
|
26
|
+
expect(notification.errors[:base].include?("APN notification cannot be larger than 4096 bytes. Try condensing your alert and device attributes.")).to be_truthy
|
|
27
|
+
end
|
|
28
|
+
end if active_record?
|
|
@@ -1,30 +1,5 @@
|
|
|
1
1
|
require 'unit_spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Rpush::Client::ActiveRecord::App do
|
|
4
|
-
|
|
5
|
-
Rpush::Client::ActiveRecord::Apns::App.create!(name: 'test', environment: 'production', certificate: TEST_CERT)
|
|
6
|
-
app = Rpush::Client::ActiveRecord::Apns::App.new(name: 'test', environment: 'production', certificate: TEST_CERT)
|
|
7
|
-
expect(app.valid?).to eq(false)
|
|
8
|
-
expect(app.errors[:name]).to eq ['has already been taken']
|
|
9
|
-
|
|
10
|
-
app = Rpush::Client::ActiveRecord::Apns::App.new(name: 'test', environment: 'development', certificate: TEST_CERT)
|
|
11
|
-
expect(app.valid?).to eq(true)
|
|
12
|
-
|
|
13
|
-
app = Rpush::Client::ActiveRecord::Gcm::App.new(name: 'test', environment: 'production', auth_key: TEST_CERT)
|
|
14
|
-
expect(app.valid?).to eq(true)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
context 'validating certificates' do
|
|
18
|
-
it 'rescues from certificate error' do
|
|
19
|
-
app = Rpush::Client::ActiveRecord::Apns::App.new(name: 'test', environment: 'development', certificate: 'bad')
|
|
20
|
-
expect { app.valid? }.not_to raise_error
|
|
21
|
-
expect(app.valid?).to eq(false)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it 'raises other errors' do
|
|
25
|
-
app = Rpush::Client::ActiveRecord::Apns::App.new(name: 'test', environment: 'development', certificate: 'bad')
|
|
26
|
-
allow(OpenSSL::X509::Certificate).to receive(:new).and_raise(NameError, 'simulating no openssl')
|
|
27
|
-
expect { app.valid? }.to raise_error(NameError)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
4
|
+
it_behaves_like 'Rpush::Client::App'
|
|
30
5
|
end if active_record?
|
|
@@ -1,96 +1,14 @@
|
|
|
1
1
|
require 'unit_spec_helper'
|
|
2
|
-
require 'unit/notification_shared.rb'
|
|
3
2
|
|
|
4
3
|
describe Rpush::Client::ActiveRecord::Gcm::Notification do
|
|
5
|
-
|
|
4
|
+
it_behaves_like 'Rpush::Client::Gcm::Notification'
|
|
5
|
+
it_behaves_like 'Rpush::Client::ActiveRecord::Notification'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
let(:
|
|
9
|
-
let(:notification) { notification_class.new }
|
|
7
|
+
subject(:notification) { described_class.new }
|
|
8
|
+
let(:app) { Rpush::Gcm::App.create!(name: 'test', auth_key: 'abc') }
|
|
10
9
|
|
|
11
|
-
it
|
|
12
|
-
notification.
|
|
13
|
-
expect(notification.valid?).to be_falsey
|
|
14
|
-
expect(notification.errors[:base]).to eq ["Notification payload data cannot be larger than 4096 bytes."]
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
it 'limits the number of registration ids to 1000' do
|
|
18
|
-
notification.registration_ids = ['a'] * (1000 + 1)
|
|
19
|
-
expect(notification.valid?).to be_falsey
|
|
20
|
-
expect(notification.errors[:base]).to eq ["Number of registration_ids cannot be larger than 1000."]
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
it 'validates expiry is present if collapse_key is set' do
|
|
24
|
-
notification.collapse_key = 'test'
|
|
25
|
-
notification.expiry = nil
|
|
26
|
-
expect(notification.valid?).to be_falsey
|
|
27
|
-
expect(notification.errors[:expiry]).to eq ['must be set when using a collapse_key']
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it 'includes time_to_live in the payload' do
|
|
31
|
-
notification.expiry = 100
|
|
32
|
-
expect(notification.as_json['time_to_live']).to eq 100
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it 'includes content_available in the payload' do
|
|
36
|
-
notification.content_available = true
|
|
37
|
-
expect(notification.as_json['content_available']).to eq true
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it 'includes mutable_content in the payload' do
|
|
41
|
-
notification.mutable_content = true
|
|
42
|
-
expect(notification.as_json['mutable_content']).to eq true
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it 'sets the priority to high when set to high' do
|
|
46
|
-
notification.priority = 'high'
|
|
47
|
-
expect(notification.as_json['priority']).to eq 'high'
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
it 'sets the priority to normal when set to normal' do
|
|
51
|
-
notification.priority = 'normal'
|
|
52
|
-
expect(notification.as_json['priority']).to eq 'normal'
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
it 'validates the priority is either "normal" or "high"' do
|
|
56
|
-
notification.priority = 'invalid'
|
|
57
|
-
expect(notification.errors[:priority]).to eq ['must be one of either "normal" or "high"']
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
it 'excludes the priority if it is not defined' do
|
|
61
|
-
expect(notification.as_json).not_to have_key 'priority'
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
it 'includes the notification payload if defined' do
|
|
65
|
-
notification.notification = { key: 'any key is allowed' }
|
|
66
|
-
expect(notification.as_json).to have_key 'notification'
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it 'excludes the notification payload if undefined' do
|
|
70
|
-
expect(notification.as_json).not_to have_key 'notification'
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
it 'includes the dry_run payload if defined' do
|
|
74
|
-
notification.dry_run = true
|
|
10
|
+
it 'accepts non-booleans as a truthy value' do
|
|
11
|
+
notification.dry_run = 'Not a boolean'
|
|
75
12
|
expect(notification.as_json['dry_run']).to eq true
|
|
76
13
|
end
|
|
77
|
-
|
|
78
|
-
it 'excludes the dry_run payload if undefined' do
|
|
79
|
-
expect(notification.as_json).not_to have_key 'dry_run'
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# In Rails 4.2 this value casts to `false` and thus will not be included in
|
|
83
|
-
# the payload. This changed to match Ruby's semantics, and will casts to
|
|
84
|
-
# `true` in Rails 5 and above.
|
|
85
|
-
if ActiveRecord.version <= Gem::Version.new('5')
|
|
86
|
-
it 'accepts non-booleans as a falsey value' do
|
|
87
|
-
notification.dry_run = 'Not a boolean'
|
|
88
|
-
expect(notification.as_json).not_to have_key 'dry_run'
|
|
89
|
-
end
|
|
90
|
-
else
|
|
91
|
-
it 'accepts non-booleans as a truthy value' do
|
|
92
|
-
notification.dry_run = 'Not a boolean'
|
|
93
|
-
expect(notification.as_json['dry_run']).to eq true
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
14
|
end if active_record?
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
require 'unit_spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Rpush::Client::ActiveRecord::Notification do
|
|
4
|
-
|
|
4
|
+
it_behaves_like 'Rpush::Client::Notification'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
notification.registration_ids = %w(a b)
|
|
8
|
-
expect(notification.registration_ids).to eq %w(a b)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
it 'allows assignment of a single registration ID' do
|
|
12
|
-
notification.registration_ids = 'a'
|
|
13
|
-
expect(notification.registration_ids).to eq ['a']
|
|
14
|
-
end
|
|
6
|
+
subject(:notification) { described_class.new }
|
|
15
7
|
|
|
16
8
|
it 'saves its parent App if required' do
|
|
17
|
-
notification.app = Rpush::
|
|
9
|
+
notification.app = Rpush::App.new(name: "aname")
|
|
18
10
|
expect(notification.app).to be_valid
|
|
19
11
|
expect(notification).to be_valid
|
|
20
12
|
end
|
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
require 'unit_spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Rpush::Client::ActiveRecord::Pushy::App do
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
4
|
+
it_behaves_like 'Rpush::Client::Pushy::App'
|
|
5
|
+
it_behaves_like 'Rpush::Client::ActiveRecord::App'
|
|
17
6
|
end if active_record?
|