rpush_extended 3.2.5

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 (248) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +365 -0
  3. data/LICENSE +7 -0
  4. data/README.md +393 -0
  5. data/bin/rpush +4 -0
  6. data/lib/generators/rpush_config_generator.rb +7 -0
  7. data/lib/generators/rpush_migration_generator.rb +66 -0
  8. data/lib/generators/templates/add_adm.rb +23 -0
  9. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
  10. data/lib/generators/templates/add_app_to_rapns.rb +11 -0
  11. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +9 -0
  12. data/lib/generators/templates/add_gcm.rb +117 -0
  13. data/lib/generators/templates/add_rpush.rb +402 -0
  14. data/lib/generators/templates/add_wpns.rb +16 -0
  15. data/lib/generators/templates/create_rapns_apps.rb +16 -0
  16. data/lib/generators/templates/create_rapns_feedback.rb +25 -0
  17. data/lib/generators/templates/create_rapns_notifications.rb +36 -0
  18. data/lib/generators/templates/rename_rapns_to_rpush.rb +87 -0
  19. data/lib/generators/templates/rpush.rb +135 -0
  20. data/lib/generators/templates/rpush_2_0_0_updates.rb +79 -0
  21. data/lib/generators/templates/rpush_2_1_0_updates.rb +11 -0
  22. data/lib/generators/templates/rpush_2_6_0_updates.rb +10 -0
  23. data/lib/generators/templates/rpush_2_7_0_updates.rb +12 -0
  24. data/lib/generators/templates/rpush_3_0_0_updates.rb +11 -0
  25. data/lib/generators/templates/rpush_3_0_1_updates.rb +13 -0
  26. data/lib/generators/templates/rpush_3_1_0_add_pushy.rb +9 -0
  27. data/lib/generators/templates/rpush_3_1_1_updates.rb +15 -0
  28. data/lib/generators/templates/rpush_3_2_0_add_apns_p8.rb +15 -0
  29. data/lib/generators/templates/rpush_3_2_4_updates.rb +9 -0
  30. data/lib/generators/templates/rpush_3_3_0_updates.rb +9 -0
  31. data/lib/generators/templates/rpush_3_3_1_updates.rb +11 -0
  32. data/lib/rpush/apns_feedback.rb +17 -0
  33. data/lib/rpush/cli.rb +213 -0
  34. data/lib/rpush/client/active_model/adm/app.rb +23 -0
  35. data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
  36. data/lib/rpush/client/active_model/adm/notification.rb +28 -0
  37. data/lib/rpush/client/active_model/apns/app.rb +37 -0
  38. data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
  39. data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
  40. data/lib/rpush/client/active_model/apns/notification.rb +104 -0
  41. data/lib/rpush/client/active_model/apns2/app.rb +15 -0
  42. data/lib/rpush/client/active_model/apns2/notification.rb +9 -0
  43. data/lib/rpush/client/active_model/apnsp8/app.rb +23 -0
  44. data/lib/rpush/client/active_model/apnsp8/notification.rb +9 -0
  45. data/lib/rpush/client/active_model/gcm/app.rb +19 -0
  46. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
  47. data/lib/rpush/client/active_model/gcm/notification.rb +59 -0
  48. data/lib/rpush/client/active_model/notification.rb +22 -0
  49. data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
  50. data/lib/rpush/client/active_model/pushy/app.rb +20 -0
  51. data/lib/rpush/client/active_model/pushy/notification.rb +31 -0
  52. data/lib/rpush/client/active_model/pushy/time_to_live_validator.rb +14 -0
  53. data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
  54. data/lib/rpush/client/active_model/wns/app.rb +23 -0
  55. data/lib/rpush/client/active_model/wns/notification.rb +32 -0
  56. data/lib/rpush/client/active_model/wpns/app.rb +13 -0
  57. data/lib/rpush/client/active_model/wpns/notification.rb +28 -0
  58. data/lib/rpush/client/active_model.rb +34 -0
  59. data/lib/rpush/client/active_record/adm/app.rb +11 -0
  60. data/lib/rpush/client/active_record/adm/notification.rb +11 -0
  61. data/lib/rpush/client/active_record/apns/app.rb +11 -0
  62. data/lib/rpush/client/active_record/apns/feedback.rb +18 -0
  63. data/lib/rpush/client/active_record/apns/notification.rb +40 -0
  64. data/lib/rpush/client/active_record/apns2/app.rb +11 -0
  65. data/lib/rpush/client/active_record/apns2/notification.rb +10 -0
  66. data/lib/rpush/client/active_record/apnsp8/app.rb +11 -0
  67. data/lib/rpush/client/active_record/apnsp8/notification.rb +10 -0
  68. data/lib/rpush/client/active_record/app.rb +13 -0
  69. data/lib/rpush/client/active_record/gcm/app.rb +11 -0
  70. data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
  71. data/lib/rpush/client/active_record/notification.rb +42 -0
  72. data/lib/rpush/client/active_record/pushy/app.rb +11 -0
  73. data/lib/rpush/client/active_record/pushy/notification.rb +11 -0
  74. data/lib/rpush/client/active_record/wns/app.rb +11 -0
  75. data/lib/rpush/client/active_record/wns/badge_notification.rb +15 -0
  76. data/lib/rpush/client/active_record/wns/notification.rb +11 -0
  77. data/lib/rpush/client/active_record/wns/raw_notification.rb +13 -0
  78. data/lib/rpush/client/active_record/wpns/app.rb +11 -0
  79. data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
  80. data/lib/rpush/client/active_record.rb +33 -0
  81. data/lib/rpush/client/redis/adm/app.rb +14 -0
  82. data/lib/rpush/client/redis/adm/notification.rb +11 -0
  83. data/lib/rpush/client/redis/apns/app.rb +11 -0
  84. data/lib/rpush/client/redis/apns/feedback.rb +20 -0
  85. data/lib/rpush/client/redis/apns/notification.rb +11 -0
  86. data/lib/rpush/client/redis/apns2/app.rb +11 -0
  87. data/lib/rpush/client/redis/apns2/notification.rb +11 -0
  88. data/lib/rpush/client/redis/apnsp8/app.rb +11 -0
  89. data/lib/rpush/client/redis/apnsp8/notification.rb +11 -0
  90. data/lib/rpush/client/redis/app.rb +29 -0
  91. data/lib/rpush/client/redis/gcm/app.rb +11 -0
  92. data/lib/rpush/client/redis/gcm/notification.rb +11 -0
  93. data/lib/rpush/client/redis/notification.rb +74 -0
  94. data/lib/rpush/client/redis/pushy/app.rb +16 -0
  95. data/lib/rpush/client/redis/pushy/notification.rb +18 -0
  96. data/lib/rpush/client/redis/wns/app.rb +14 -0
  97. data/lib/rpush/client/redis/wns/badge_notification.rb +15 -0
  98. data/lib/rpush/client/redis/wns/notification.rb +11 -0
  99. data/lib/rpush/client/redis/wns/raw_notification.rb +11 -0
  100. data/lib/rpush/client/redis/wpns/app.rb +11 -0
  101. data/lib/rpush/client/redis/wpns/notification.rb +11 -0
  102. data/lib/rpush/client/redis.rb +56 -0
  103. data/lib/rpush/configuration.rb +115 -0
  104. data/lib/rpush/daemon/adm/delivery.rb +226 -0
  105. data/lib/rpush/daemon/adm.rb +9 -0
  106. data/lib/rpush/daemon/apns/delivery.rb +43 -0
  107. data/lib/rpush/daemon/apns/feedback_receiver.rb +90 -0
  108. data/lib/rpush/daemon/apns.rb +17 -0
  109. data/lib/rpush/daemon/apns2/delivery.rb +127 -0
  110. data/lib/rpush/daemon/apns2.rb +10 -0
  111. data/lib/rpush/daemon/apnsp8/delivery.rb +166 -0
  112. data/lib/rpush/daemon/apnsp8/token.rb +43 -0
  113. data/lib/rpush/daemon/apnsp8.rb +10 -0
  114. data/lib/rpush/daemon/app_runner.rb +190 -0
  115. data/lib/rpush/daemon/batch.rb +138 -0
  116. data/lib/rpush/daemon/constants.rb +59 -0
  117. data/lib/rpush/daemon/delivery.rb +46 -0
  118. data/lib/rpush/daemon/delivery_error.rb +27 -0
  119. data/lib/rpush/daemon/dispatcher/apns_http2.rb +51 -0
  120. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +152 -0
  121. data/lib/rpush/daemon/dispatcher/apnsp8_http2.rb +33 -0
  122. data/lib/rpush/daemon/dispatcher/http.rb +21 -0
  123. data/lib/rpush/daemon/dispatcher/tcp.rb +22 -0
  124. data/lib/rpush/daemon/dispatcher_loop.rb +73 -0
  125. data/lib/rpush/daemon/errors.rb +18 -0
  126. data/lib/rpush/daemon/feeder.rb +69 -0
  127. data/lib/rpush/daemon/gcm/delivery.rb +241 -0
  128. data/lib/rpush/daemon/gcm.rb +9 -0
  129. data/lib/rpush/daemon/interruptible_sleep.rb +24 -0
  130. data/lib/rpush/daemon/loggable.rb +33 -0
  131. data/lib/rpush/daemon/proc_title.rb +17 -0
  132. data/lib/rpush/daemon/pushy/delivery.rb +90 -0
  133. data/lib/rpush/daemon/pushy.rb +9 -0
  134. data/lib/rpush/daemon/queue_payload.rb +12 -0
  135. data/lib/rpush/daemon/retry_header_parser.rb +23 -0
  136. data/lib/rpush/daemon/retryable_error.rb +22 -0
  137. data/lib/rpush/daemon/ring_buffer.rb +16 -0
  138. data/lib/rpush/daemon/rpc/client.rb +27 -0
  139. data/lib/rpush/daemon/rpc/server.rb +82 -0
  140. data/lib/rpush/daemon/rpc.rb +9 -0
  141. data/lib/rpush/daemon/service_config_methods.rb +51 -0
  142. data/lib/rpush/daemon/signal_handler.rb +75 -0
  143. data/lib/rpush/daemon/store/active_record/reconnectable.rb +80 -0
  144. data/lib/rpush/daemon/store/active_record.rb +214 -0
  145. data/lib/rpush/daemon/store/interface.rb +20 -0
  146. data/lib/rpush/daemon/store/redis.rb +166 -0
  147. data/lib/rpush/daemon/string_helpers.rb +15 -0
  148. data/lib/rpush/daemon/synchronizer.rb +62 -0
  149. data/lib/rpush/daemon/tcp_connection.rb +190 -0
  150. data/lib/rpush/daemon/wns/badge_request.rb +32 -0
  151. data/lib/rpush/daemon/wns/delivery.rb +178 -0
  152. data/lib/rpush/daemon/wns/post_request.rb +33 -0
  153. data/lib/rpush/daemon/wns/raw_request.rb +22 -0
  154. data/lib/rpush/daemon/wns/toast_request.rb +54 -0
  155. data/lib/rpush/daemon/wns.rb +9 -0
  156. data/lib/rpush/daemon/wpns/delivery.rb +132 -0
  157. data/lib/rpush/daemon/wpns.rb +9 -0
  158. data/lib/rpush/daemon.rb +179 -0
  159. data/lib/rpush/deprecatable.rb +24 -0
  160. data/lib/rpush/deprecation.rb +26 -0
  161. data/lib/rpush/embed.rb +41 -0
  162. data/lib/rpush/logger.rb +92 -0
  163. data/lib/rpush/multi_json_helper.rb +16 -0
  164. data/lib/rpush/plugin.rb +44 -0
  165. data/lib/rpush/push.rb +11 -0
  166. data/lib/rpush/reflectable.rb +13 -0
  167. data/lib/rpush/reflection_collection.rb +44 -0
  168. data/lib/rpush/reflection_public_methods.rb +11 -0
  169. data/lib/rpush/version.rb +14 -0
  170. data/lib/rpush.rb +43 -0
  171. data/lib/tasks/quality.rake +35 -0
  172. data/lib/tasks/test.rake +69 -0
  173. data/spec/.rubocop.yml +4 -0
  174. data/spec/functional/adm_spec.rb +50 -0
  175. data/spec/functional/apns2_spec.rb +232 -0
  176. data/spec/functional/apns_spec.rb +162 -0
  177. data/spec/functional/cli_spec.rb +36 -0
  178. data/spec/functional/embed_spec.rb +49 -0
  179. data/spec/functional/gcm_spec.rb +46 -0
  180. data/spec/functional/new_app_spec.rb +44 -0
  181. data/spec/functional/pushy_spec.rb +22 -0
  182. data/spec/functional/retry_spec.rb +42 -0
  183. data/spec/functional/synchronization_spec.rb +97 -0
  184. data/spec/functional/wpns_spec.rb +71 -0
  185. data/spec/functional_spec_helper.rb +32 -0
  186. data/spec/spec_helper.rb +69 -0
  187. data/spec/support/active_record_setup.rb +73 -0
  188. data/spec/support/cert_with_password.pem +90 -0
  189. data/spec/support/cert_without_password.pem +59 -0
  190. data/spec/support/config/database.yml +44 -0
  191. data/spec/support/simplecov_helper.rb +24 -0
  192. data/spec/support/simplecov_quality_formatter.rb +12 -0
  193. data/spec/tmp/.gitkeep +0 -0
  194. data/spec/unit/apns_feedback_spec.rb +28 -0
  195. data/spec/unit/client/active_record/adm/app_spec.rb +58 -0
  196. data/spec/unit/client/active_record/adm/notification_spec.rb +43 -0
  197. data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
  198. data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
  199. data/spec/unit/client/active_record/apns/notification_spec.rb +324 -0
  200. data/spec/unit/client/active_record/app_spec.rb +30 -0
  201. data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
  202. data/spec/unit/client/active_record/gcm/notification_spec.rb +67 -0
  203. data/spec/unit/client/active_record/notification_spec.rb +21 -0
  204. data/spec/unit/client/active_record/pushy/app_spec.rb +17 -0
  205. data/spec/unit/client/active_record/pushy/notification_spec.rb +65 -0
  206. data/spec/unit/client/active_record/wns/badge_notification_spec.rb +15 -0
  207. data/spec/unit/client/active_record/wns/raw_notification_spec.rb +26 -0
  208. data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
  209. data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
  210. data/spec/unit/configuration_spec.rb +46 -0
  211. data/spec/unit/daemon/adm/delivery_spec.rb +253 -0
  212. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
  213. data/spec/unit/daemon/apns/delivery_spec.rb +108 -0
  214. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +119 -0
  215. data/spec/unit/daemon/app_runner_spec.rb +188 -0
  216. data/spec/unit/daemon/batch_spec.rb +169 -0
  217. data/spec/unit/daemon/delivery_error_spec.rb +13 -0
  218. data/spec/unit/daemon/delivery_spec.rb +51 -0
  219. data/spec/unit/daemon/dispatcher/http_spec.rb +34 -0
  220. data/spec/unit/daemon/dispatcher/tcp_spec.rb +32 -0
  221. data/spec/unit/daemon/dispatcher_loop_spec.rb +53 -0
  222. data/spec/unit/daemon/feeder_spec.rb +96 -0
  223. data/spec/unit/daemon/gcm/delivery_spec.rb +387 -0
  224. data/spec/unit/daemon/proc_title_spec.rb +11 -0
  225. data/spec/unit/daemon/pushy/delivery_spec.rb +159 -0
  226. data/spec/unit/daemon/retryable_error_spec.rb +14 -0
  227. data/spec/unit/daemon/service_config_methods_spec.rb +36 -0
  228. data/spec/unit/daemon/signal_handler_spec.rb +99 -0
  229. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +165 -0
  230. data/spec/unit/daemon/store/active_record_spec.rb +357 -0
  231. data/spec/unit/daemon/store/redis_spec.rb +365 -0
  232. data/spec/unit/daemon/tcp_connection_spec.rb +292 -0
  233. data/spec/unit/daemon/wns/delivery_spec.rb +176 -0
  234. data/spec/unit/daemon/wns/post_request_spec.rb +117 -0
  235. data/spec/unit/daemon/wpns/delivery_spec.rb +167 -0
  236. data/spec/unit/daemon_spec.rb +138 -0
  237. data/spec/unit/deprecatable_spec.rb +32 -0
  238. data/spec/unit/deprecation_spec.rb +15 -0
  239. data/spec/unit/embed_spec.rb +47 -0
  240. data/spec/unit/logger_spec.rb +127 -0
  241. data/spec/unit/notification_shared.rb +53 -0
  242. data/spec/unit/plugin_spec.rb +36 -0
  243. data/spec/unit/push_spec.rb +34 -0
  244. data/spec/unit/reflectable_spec.rb +27 -0
  245. data/spec/unit/reflection_collection_spec.rb +26 -0
  246. data/spec/unit/rpush_spec.rb +8 -0
  247. data/spec/unit_spec_helper.rb +26 -0
  248. metadata +709 -0
@@ -0,0 +1,43 @@
1
+ require 'unit_spec_helper'
2
+ require 'unit/notification_shared.rb'
3
+
4
+ describe Rpush::Client::ActiveRecord::Adm::Notification do
5
+ it_should_behave_like 'an Notification subclass'
6
+
7
+ let(:app) { Rpush::Client::ActiveRecord::Adm::App.create!(name: 'test', client_id: 'CLIENT_ID', client_secret: 'CLIENT_SECRET') }
8
+ let(:notification_class) { Rpush::Client::ActiveRecord::Adm::Notification }
9
+ let(:notification) { notification_class.new }
10
+
11
+ it "has a 'data' payload limit of 6144 bytes" do
12
+ notification.data = { key: "a" * 6144 }
13
+ expect(notification.valid?).to eq(false)
14
+ expect(notification.errors[:base]).to eq ["Notification payload data cannot be larger than 6144 bytes."]
15
+ end
16
+
17
+ it 'limits the number of registration ids to 100' do
18
+ notification.registration_ids = ['a'] * (100 + 1)
19
+ expect(notification.valid?).to eq(false)
20
+ expect(notification.errors[:base]).to eq ["Number of registration_ids cannot be larger than 100."]
21
+ end
22
+
23
+ it 'validates data can be blank if collapse_key is set' do
24
+ notification.app = app
25
+ notification.registration_ids = 'a'
26
+ notification.collapse_key = 'test'
27
+ notification.data = nil
28
+ expect(notification.valid?).to eq(true)
29
+ expect(notification.errors[:data]).to be_empty
30
+ end
31
+
32
+ it 'validates data is present if collapse_key is not set' do
33
+ notification.collapse_key = nil
34
+ notification.data = nil
35
+ expect(notification.valid?).to eq(false)
36
+ expect(notification.errors[:data]).to eq ['must be set unless collapse_key is specified']
37
+ end
38
+
39
+ it 'includes expiresAfter in the payload' do
40
+ notification.expiry = 100
41
+ expect(notification.as_json['expiresAfter']).to eq 100
42
+ end
43
+ end if active_record?
@@ -0,0 +1,29 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::App do
4
+ it 'does not validate an app with an invalid certificate' do
5
+ app = Rpush::Client::ActiveRecord::Apns::App.new(name: 'test', environment: 'development', certificate: 'foo')
6
+ app.valid?
7
+ expect(app.errors[:certificate]).to eq ['value must contain a certificate and a private key.']
8
+ end
9
+
10
+ it 'validates a certificate without a password' do
11
+ app = Rpush::Client::ActiveRecord::Apns::App.new name: 'test', environment: 'development', certificate: TEST_CERT
12
+ app.valid?
13
+ expect(app.errors[:certificate]).to eq []
14
+ end
15
+
16
+ it 'validates a certificate with a password' do
17
+ app = Rpush::Client::ActiveRecord::Apns::App.new name: 'test', environment: 'development',
18
+ certificate: TEST_CERT_WITH_PASSWORD, password: 'fubar'
19
+ app.valid?
20
+ expect(app.errors[:certificate]).to eq []
21
+ end
22
+
23
+ it 'validates a certificate with an incorrect password' do
24
+ app = Rpush::Client::ActiveRecord::Apns::App.new name: 'test', environment: 'development',
25
+ certificate: TEST_CERT_WITH_PASSWORD, password: 'incorrect'
26
+ app.valid?
27
+ expect(app.errors[:certificate]).to eq ['value must contain a certificate and a private key.']
28
+ end
29
+ end if active_record?
@@ -0,0 +1,9 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Apns::Feedback do
4
+ it 'validates the format of the device_token' do
5
+ notification = Rpush::Client::ActiveRecord::Apns::Feedback.new(device_token: "{$%^&*()}")
6
+ expect(notification.valid?).to be_falsey
7
+ expect(notification.errors[:device_token]).to include('is invalid')
8
+ end
9
+ end if active_record?
@@ -0,0 +1,324 @@
1
+ # encoding: US-ASCII
2
+
3
+ require "unit_spec_helper"
4
+ require 'unit/notification_shared.rb'
5
+
6
+ describe Rpush::Client::ActiveRecord::Apns::Notification do
7
+ it_should_behave_like 'an Notification subclass'
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 }
12
+
13
+ it "should validate the format of the device_token" do
14
+ notification = Rpush::Client::ActiveRecord::Apns::Notification.new(device_token: "{$%^&*()}")
15
+ expect(notification.valid?).to be_falsey
16
+ expect(notification.errors[:device_token].include?("is invalid")).to be_truthy
17
+ end
18
+
19
+ it "should validate the length of the binary conversion of the notification" do
20
+ notification.device_token = "a" * 108
21
+ notification.alert = "way too long!" * 200
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
25
+
26
+ it "should store long alerts" do
27
+ notification.app = app
28
+ notification.device_token = "a" * 108
29
+ notification.alert = "*" * 300
30
+ expect(notification.valid?).to be_truthy
31
+
32
+ notification.save!
33
+ notification.reload
34
+ expect(notification.alert).to eq("*" * 300)
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(alert: "my_sound.aiff")
86
+ expect(notification.as_json["aps"]["alert"]).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 include attributes for the device" do
95
+ notification = Rpush::Client::ActiveRecord::Apns::Notification.new
96
+ notification.data = { omg: :lol, wtf: :dunno }
97
+ expect(notification.as_json["omg"]).to eq "lol"
98
+ expect(notification.as_json["wtf"]).to eq "dunno"
99
+ end
100
+
101
+ it "should allow attributes to include a hash" do
102
+ notification = Rpush::Client::ActiveRecord::Apns::Notification.new
103
+ notification.data = { omg: { ilike: :hashes } }
104
+ expect(notification.as_json["omg"]["ilike"]).to eq "hashes"
105
+ end
106
+ end if active_record?
107
+
108
+ describe Rpush::Client::ActiveRecord::Apns::Notification, 'MDM' do
109
+ let(:magic) { 'abc123' }
110
+ let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
111
+
112
+ before do
113
+ notification.device_token = "a" * 108
114
+ notification.id = 1234
115
+ end
116
+
117
+ it 'includes the mdm magic in the payload' do
118
+ notification.mdm = magic
119
+ expect(notification.as_json).to eq('mdm' => magic)
120
+ end
121
+
122
+ it 'does not include aps attribute' do
123
+ notification.alert = "i'm doomed"
124
+ notification.mdm = magic
125
+ expect(notification.as_json.key?('aps')).to be_falsey
126
+ end
127
+
128
+ it 'can be converted to binary' do
129
+ notification.mdm = magic
130
+ expect(notification.to_binary).to be_present
131
+ end
132
+ end if active_record?
133
+
134
+ describe Rpush::Client::ActiveRecord::Apns::Notification, 'mutable-content' do
135
+ let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
136
+
137
+ it 'includes mutable-content in the payload' do
138
+ notification.mutable_content = true
139
+ expect(notification.as_json['aps']['mutable-content']).to eq 1
140
+ end
141
+
142
+ it 'does not include content-available in the payload if not set' do
143
+ expect(notification.as_json['aps'].key?('mutable-content')).to be_falsey
144
+ end
145
+
146
+ it 'does not include mutable-content as a non-aps attribute' do
147
+ notification.mutable_content = true
148
+ expect(notification.as_json.key?('mutable-content')).to be_falsey
149
+ end
150
+
151
+ it 'does not overwrite existing attributes for the device' do
152
+ notification.data = { hi: :mom }
153
+ notification.mutable_content = true
154
+ expect(notification.as_json['aps']['mutable-content']).to eq 1
155
+ expect(notification.as_json['hi']).to eq 'mom'
156
+ end
157
+
158
+ it 'does not overwrite the mutable-content flag when setting attributes for the device' do
159
+ notification.mutable_content = true
160
+ notification.data = { hi: :mom }
161
+ expect(notification.as_json['aps']['mutable-content']).to eq 1
162
+ expect(notification.as_json['hi']).to eq 'mom'
163
+ end
164
+ end if active_record?
165
+
166
+ describe Rpush::Client::ActiveRecord::Apns::Notification, 'content-available' do
167
+ let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
168
+
169
+ it 'includes content-available in the payload' do
170
+ notification.content_available = true
171
+ expect(notification.as_json['aps']['content-available']).to eq 1
172
+ end
173
+
174
+ it 'does not include content-available in the payload if not set' do
175
+ expect(notification.as_json['aps'].key?('content-available')).to be_falsey
176
+ end
177
+
178
+ it 'does not include content-available as a non-aps attribute' do
179
+ notification.content_available = true
180
+ expect(notification.as_json.key?('content-available')).to be_falsey
181
+ end
182
+
183
+ it 'does not overwrite existing attributes for the device' do
184
+ notification.data = { hi: :mom }
185
+ notification.content_available = true
186
+ expect(notification.as_json['aps']['content-available']).to eq 1
187
+ expect(notification.as_json['hi']).to eq 'mom'
188
+ end
189
+
190
+ it 'does not overwrite the content-available flag when setting attributes for the device' do
191
+ notification.content_available = true
192
+ notification.data = { hi: :mom }
193
+ expect(notification.as_json['aps']['content-available']).to eq 1
194
+ expect(notification.as_json['hi']).to eq 'mom'
195
+ end
196
+ end if active_record?
197
+
198
+ describe Rpush::Client::ActiveRecord::Apns::Notification, 'url-args' do
199
+ let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
200
+
201
+ it 'includes url-args in the payload' do
202
+ notification.url_args = ['url-arg-1']
203
+ expect(notification.as_json['aps']['url-args']).to eq ['url-arg-1']
204
+ end
205
+
206
+ it 'does not include url-args in the payload if not set' do
207
+ expect(notification.as_json['aps'].key?('url-args')).to be_falsey
208
+ end
209
+ end if active_record?
210
+
211
+ describe Rpush::Client::ActiveRecord::Apns::Notification, 'category' do
212
+ let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
213
+
214
+ it 'includes category in the payload' do
215
+ notification.category = 'INVITE_CATEGORY'
216
+ expect(notification.as_json['aps']['category']).to eq 'INVITE_CATEGORY'
217
+ end
218
+
219
+ it 'does not include category in the payload if not set' do
220
+ expect(notification.as_json['aps'].key?('category')).to be_falsey
221
+ end
222
+ end if active_record?
223
+
224
+ describe Rpush::Client::ActiveRecord::Apns::Notification, 'to_binary' do
225
+ let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
226
+
227
+ before do
228
+ notification.device_token = "a" * 108
229
+ notification.id = 1234
230
+ end
231
+
232
+ it 'uses APNS_PRIORITY_CONSERVE_POWER if content-available is the only key' do
233
+ notification.alert = nil
234
+ notification.badge = nil
235
+ notification.sound = nil
236
+ notification.content_available = true
237
+ bytes = notification.to_binary.bytes.to_a[-4..-1]
238
+ expect(bytes.first).to eq 5 # priority item ID
239
+ expect(bytes.last).to eq Rpush::Client::ActiveRecord::Apns::Notification::APNS_PRIORITY_CONSERVE_POWER
240
+ end
241
+
242
+ it 'uses APNS_PRIORITY_IMMEDIATE if content-available is not the only key' do
243
+ notification.alert = "New stuff!"
244
+ notification.badge = nil
245
+ notification.sound = nil
246
+ notification.content_available = true
247
+ bytes = notification.to_binary.bytes.to_a[-4..-1]
248
+ expect(bytes.first).to eq 5 # priority item ID
249
+ expect(bytes.last).to eq Rpush::Client::ActiveRecord::Apns::Notification::APNS_PRIORITY_IMMEDIATE
250
+ end
251
+
252
+ it "should correctly convert the notification to binary" do
253
+ notification.sound = "1.aiff"
254
+ notification.badge = 3
255
+ notification.alert = "Don't panic Mr Mainwaring, don't panic!"
256
+ notification.data = { hi: :mom }
257
+ notification.expiry = 86_400 # 1 day
258
+ notification.priority = Rpush::Client::ActiveRecord::Apns::Notification::APNS_PRIORITY_IMMEDIATE
259
+ notification.app = Rpush::Client::ActiveRecord::Apns::App.new(name: 'my_app', environment: 'development', certificate: TEST_CERT)
260
+ now = Time.now
261
+ allow(Time).to receive_messages(now: now)
262
+ 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"
263
+ end
264
+ end if active_record?
265
+
266
+ describe Rpush::Client::ActiveRecord::Apns::Notification, "bug #31" do
267
+ it 'does not confuse a JSON looking string as JSON' do
268
+ notification = Rpush::Client::ActiveRecord::Apns::Notification.new
269
+ notification.alert = "{\"one\":2}"
270
+ expect(notification.alert).to eq "{\"one\":2}"
271
+ end
272
+
273
+ it 'does confuse a JSON looking string as JSON if the alert_is_json attribute is not present' do
274
+ notification = Rpush::Client::ActiveRecord::Apns::Notification.new
275
+ allow(notification).to receive_messages(has_attribute?: false)
276
+ notification.alert = "{\"one\":2}"
277
+ expect(notification.alert).to eq('one' => 2)
278
+ end
279
+ end if active_record?
280
+
281
+ describe Rpush::Client::ActiveRecord::Apns::Notification, "bug #35" do
282
+ it "should limit payload size to 256 bytes but not the entire packet" do
283
+ notification = Rpush::Client::ActiveRecord::Apns::Notification.new do |n|
284
+ n.device_token = "a" * 108
285
+ n.alert = "a" * 210
286
+ n.app = Rpush::Client::ActiveRecord::Apns::App.create!(name: 'my_app', environment: 'development', certificate: TEST_CERT)
287
+ end
288
+
289
+ expect(notification.to_binary(for_validation: true).bytesize).to be > 256
290
+ expect(notification.payload.bytesize).to be < 256
291
+ expect(notification).to be_valid
292
+ end
293
+ end if active_record?
294
+
295
+ describe Rpush::Client::ActiveRecord::Apns::Notification, "multi_json usage" do
296
+ describe Rpush::Client::ActiveRecord::Apns::Notification, "alert" do
297
+ it "should call MultiJson.load when multi_json version is 1.3.0" do
298
+ notification = Rpush::Client::ActiveRecord::Apns::Notification.new(alert: { a: 1 }, alert_is_json: true)
299
+ allow(Gem).to receive(:loaded_specs).and_return('multi_json' => Gem::Specification.new('multi_json', '1.3.0'))
300
+ expect(MultiJson).to receive(:load).with(any_args)
301
+ notification.alert
302
+ end
303
+
304
+ it "should call MultiJson.decode when multi_json version is 1.2.9" do
305
+ notification = Rpush::Client::ActiveRecord::Apns::Notification.new(alert: { a: 1 }, alert_is_json: true)
306
+ allow(Gem).to receive(:loaded_specs).and_return('multi_json' => Gem::Specification.new('multi_json', '1.2.9'))
307
+ expect(MultiJson).to receive(:decode).with(any_args)
308
+ notification.alert
309
+ end
310
+ end
311
+ end if active_record?
312
+
313
+ describe Rpush::Client::ActiveRecord::Apns::Notification, 'thread-id' do
314
+ let(:notification) { Rpush::Client::ActiveRecord::Apns::Notification.new }
315
+
316
+ it 'includes thread-id in the payload' do
317
+ notification.thread_id = 'THREAD-ID'
318
+ expect(notification.as_json['aps']['thread-id']).to eq 'THREAD-ID'
319
+ end
320
+
321
+ it 'does not include thread-id in the payload if not set' do
322
+ expect(notification.as_json['aps']).to_not have_key('thread-id')
323
+ end
324
+ end if active_record?
@@ -0,0 +1,30 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::App do
4
+ it 'validates the uniqueness of name within type and environment' do
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
30
+ end if active_record?
@@ -0,0 +1,4 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Gcm::App do
4
+ end
@@ -0,0 +1,67 @@
1
+ require 'unit_spec_helper'
2
+ require 'unit/notification_shared.rb'
3
+
4
+ describe Rpush::Client::ActiveRecord::Gcm::Notification do
5
+ it_should_behave_like 'an Notification subclass'
6
+
7
+ let(:app) { Rpush::Client::ActiveRecord::Gcm::App.create!(name: 'test', auth_key: 'abc') }
8
+ let(:notification_class) { Rpush::Client::ActiveRecord::Gcm::Notification }
9
+ let(:notification) { notification_class.new }
10
+
11
+ it "has a 'data' payload limit of 4096 bytes" do
12
+ notification.data = { key: "a" * 4096 }
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 'sets the priority to high when set to high' do
41
+ notification.priority = 'high'
42
+ expect(notification.as_json['priority']).to eq 'high'
43
+ end
44
+
45
+ it 'sets the priority to normal when set to normal' do
46
+ notification.priority = 'normal'
47
+ expect(notification.as_json['priority']).to eq 'normal'
48
+ end
49
+
50
+ it 'validates the priority is either "normal" or "high"' do
51
+ notification.priority = 'invalid'
52
+ expect(notification.errors[:priority]).to eq ['must be one of either "normal" or "high"']
53
+ end
54
+
55
+ it 'excludes the priority if it is not defined' do
56
+ expect(notification.as_json).not_to have_key 'priority'
57
+ end
58
+
59
+ it 'includes the notification payload if defined' do
60
+ notification.notification = { key: 'any key is allowed' }
61
+ expect(notification.as_json).to have_key 'notification'
62
+ end
63
+
64
+ it 'excludes the notification payload if undefined' do
65
+ expect(notification.as_json).not_to have_key 'notification'
66
+ end
67
+ end if active_record?
@@ -0,0 +1,21 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Notification do
4
+ let(:notification) { Rpush::Client::ActiveRecord::Notification.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
+
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
15
+
16
+ it 'saves its parent App if required' do
17
+ notification.app = Rpush::Client::ActiveRecord::App.new(name: "aname")
18
+ expect(notification.app).to be_valid
19
+ expect(notification).to be_valid
20
+ end
21
+ end if active_record?
@@ -0,0 +1,17 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::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 if active_record?
@@ -0,0 +1,65 @@
1
+ require 'unit_spec_helper'
2
+ require 'unit/notification_shared.rb'
3
+
4
+ describe Rpush::Client::ActiveRecord::Pushy::Notification do
5
+ let(:notification_class) { described_class }
6
+ subject(:notification) { notification_class.new }
7
+
8
+ it_behaves_like 'an Notification subclass'
9
+
10
+ describe 'validates' do
11
+ let(:app) { Rpush::Client::ActiveRecord::Pushy::App.create!(name: 'MyApp', api_key: 'my_api_key') }
12
+
13
+ describe 'data' do
14
+ subject { described_class.new(app: app, registration_ids: ['id']) }
15
+ it 'validates presence' do
16
+ is_expected.not_to be_valid
17
+ expect(subject.errors[:data]).to eq ["can't be blank"]
18
+ end
19
+
20
+ it "has a 'data' payload limit of 4096 bytes" do
21
+ subject.data = { message: 'a' * 4096 }
22
+ is_expected.not_to be_valid
23
+ expected_errors = ["Notification payload data cannot be larger than 4096 bytes."]
24
+ expect(subject.errors[:base]).to eq expected_errors
25
+ end
26
+ end
27
+
28
+ describe 'registration_ids' do
29
+ subject { described_class.new(app: app, data: { message: 'test' }) }
30
+ it 'validates presence' do
31
+ is_expected.not_to be_valid
32
+ expect(subject.errors[:registration_ids]).to eq ["can't be blank"]
33
+ end
34
+
35
+ it 'limits the number of registration ids to 1000' do
36
+ subject.registration_ids = ['a'] * (1000 + 1)
37
+ is_expected.not_to be_valid
38
+ expected_errors = ["Number of registration_ids cannot be larger than 1000."]
39
+ expect(subject.errors[:base]).to eq expected_errors
40
+ end
41
+ end
42
+
43
+ describe 'time_to_live' do
44
+ subject { described_class.new(app: app, data: { message: 'test' }, registration_ids: ['id']) }
45
+
46
+ it 'should be > 0' do
47
+ subject.time_to_live = -1
48
+ is_expected.not_to be_valid
49
+ expect(subject.errors[:time_to_live]).to eq ['must be greater than 0']
50
+ end
51
+
52
+ it 'should be integer' do
53
+ subject.time_to_live = 1.4
54
+ is_expected.not_to be_valid
55
+ expect(subject.errors[:time_to_live]).to eq ['must be an integer']
56
+ end
57
+
58
+ it 'should be <= 1.year.seconds' do
59
+ subject.time_to_live = 2.years.seconds.to_i
60
+ is_expected.not_to be_valid
61
+ expect(subject.errors[:time_to_live]).to eq ['The maximum value is 1 year']
62
+ end
63
+ end
64
+ end
65
+ end if active_record?
@@ -0,0 +1,15 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Wns::BadgeNotification do
4
+ let(:notification) do
5
+ notif = Rpush::Client::ActiveRecord::Wns::BadgeNotification.new
6
+ notif.app = Rpush::Client::ActiveRecord::Wns::App.new(name: "aname")
7
+ notif.uri = 'https://db5.notify.windows.com/?token=TOKEN'
8
+ notif.badge = 42
9
+ notif
10
+ end
11
+
12
+ it 'should allow a notification without data' do
13
+ expect(notification.valid?).to be(true)
14
+ end
15
+ end if active_record?
@@ -0,0 +1,26 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Wns::RawNotification do
4
+ let(:notification) do
5
+ notif = Rpush::Client::ActiveRecord::Wns::RawNotification.new
6
+ notif.app = Rpush::Client::ActiveRecord::Wns::App.new(name: "aname")
7
+ notif.uri = 'https://db5.notify.windows.com/?token=TOKEN'
8
+ notif.data = { foo: 'foo', bar: 'bar' }
9
+ notif
10
+ end
11
+
12
+ it 'does not allow the size of payload over 5 KB' do
13
+ allow(notification).to receive(:payload_data_size) { 5121 }
14
+ expect(notification.valid?).to be(false)
15
+ end
16
+
17
+ it 'allows exact payload of 5 KB' do
18
+ allow(notification).to receive(:payload_data_size) { 5120 }
19
+ expect(notification.valid?).to be(true)
20
+ end
21
+
22
+ it 'allows the size of payload under 5 KB' do
23
+ allow(notification).to receive(:payload_data_size) { 5119 }
24
+ expect(notification.valid?).to be(true)
25
+ end
26
+ end if active_record?
@@ -0,0 +1,4 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Wpns::App do
4
+ end