rpush 2.3.1 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +36 -28
  4. data/lib/rpush/configuration.rb +1 -0
  5. data/lib/rpush/daemon/feeder.rb +16 -12
  6. data/lib/rpush/daemon/interruptible_sleep.rb +26 -5
  7. data/lib/rpush/daemon/store/active_record.rb +4 -0
  8. data/lib/rpush/daemon/store/interface.rb +1 -1
  9. data/lib/rpush/daemon/store/redis.rb +10 -0
  10. data/lib/rpush/embed.rb +1 -0
  11. data/lib/rpush/logger.rb +1 -0
  12. data/lib/rpush/push.rb +1 -2
  13. data/lib/rpush/version.rb +1 -1
  14. data/spec/functional/adm_spec.rb +6 -8
  15. data/spec/functional/apns_spec.rb +9 -9
  16. data/spec/functional/embed_spec.rb +3 -3
  17. data/spec/functional/gcm_spec.rb +6 -8
  18. data/spec/functional/new_app_spec.rb +5 -20
  19. data/spec/functional/retry_spec.rb +8 -12
  20. data/spec/functional/synchronization_spec.rb +1 -1
  21. data/spec/functional/wpns_spec.rb +7 -7
  22. data/spec/functional_spec_helper.rb +4 -5
  23. data/spec/spec_helper.rb +1 -1
  24. data/spec/unit/apns_feedback_spec.rb +4 -4
  25. data/spec/unit/client/active_record/adm/app_spec.rb +12 -12
  26. data/spec/unit/client/active_record/adm/notification_spec.rb +9 -9
  27. data/spec/unit/client/active_record/apns/app_spec.rb +4 -4
  28. data/spec/unit/client/active_record/apns/feedback_spec.rb +2 -2
  29. data/spec/unit/client/active_record/apns/notification_spec.rb +46 -46
  30. data/spec/unit/client/active_record/app_spec.rb +6 -6
  31. data/spec/unit/client/active_record/gcm/notification_spec.rb +7 -7
  32. data/spec/unit/client/active_record/notification_spec.rb +2 -2
  33. data/spec/unit/client/active_record/wpns/notification_spec.rb +2 -8
  34. data/spec/unit/configuration_spec.rb +5 -5
  35. data/spec/unit/daemon/adm/delivery_spec.rb +69 -69
  36. data/spec/unit/daemon/apns/delivery_spec.rb +13 -13
  37. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +24 -26
  38. data/spec/unit/daemon/app_runner_spec.rb +29 -29
  39. data/spec/unit/daemon/batch_spec.rb +30 -30
  40. data/spec/unit/daemon/delivery_error_spec.rb +2 -2
  41. data/spec/unit/daemon/delivery_spec.rb +6 -6
  42. data/spec/unit/daemon/dispatcher/http_spec.rb +5 -5
  43. data/spec/unit/daemon/dispatcher/tcp_spec.rb +4 -4
  44. data/spec/unit/daemon/dispatcher_loop_spec.rb +9 -9
  45. data/spec/unit/daemon/feeder_spec.rb +22 -23
  46. data/spec/unit/daemon/gcm/delivery_spec.rb +56 -56
  47. data/spec/unit/daemon/retryable_error_spec.rb +2 -2
  48. data/spec/unit/daemon/service_config_methods_spec.rb +5 -5
  49. data/spec/unit/daemon/signal_handler_spec.rb +13 -13
  50. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +13 -13
  51. data/spec/unit/daemon/store/active_record_spec.rb +49 -49
  52. data/spec/unit/daemon/tcp_connection_spec.rb +50 -50
  53. data/spec/unit/daemon/wpns/delivery_spec.rb +36 -36
  54. data/spec/unit/daemon_spec.rb +33 -30
  55. data/spec/unit/deprecatable_spec.rb +3 -3
  56. data/spec/unit/deprecation_spec.rb +2 -2
  57. data/spec/unit/embed_spec.rb +7 -7
  58. data/spec/unit/logger_spec.rb +25 -25
  59. data/spec/unit/notification_shared.rb +7 -7
  60. data/spec/unit/plugin_spec.rb +1 -1
  61. data/spec/unit/push_spec.rb +8 -8
  62. data/spec/unit/reflectable_spec.rb +5 -5
  63. data/spec/unit/reflection_collection_spec.rb +2 -2
  64. data/spec/unit/rpush_spec.rb +1 -1
  65. data/spec/unit_spec_helper.rb +4 -5
  66. metadata +10 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0da1cac03ae3688486b3d3a35f9adf1aff283bed
4
- data.tar.gz: 3710bfdf83a7fd76a790a42d4ee95278ed07f7e2
3
+ metadata.gz: 927abaa3a2c391f3d390a0075f5aeaf3ae12a9d0
4
+ data.tar.gz: b272119c8cc1ba826dea17fd5e0bde2e261e12a5
5
5
  SHA512:
6
- metadata.gz: e84ccee43191d9876c30f4df293299dc8c4d08de3ad96882aec3eb7fc0302217d32de0b1bede2faa296d686a9fa4c451ebb8a27a0560f664dcb5d578765465ae
7
- data.tar.gz: 6cd9310c439cb97f8eab52456303d94b3c2c43872498a7c361f6343031b545476c2200707b1645f462de2b151fe585b6b476234edf7864a6875fe3c69a4156e6
6
+ metadata.gz: f30b21a842cca1acfa350be012d2292bb0a2dcb85ab3a859d37f5e63836af026def22481aa6b2d09fe6bfb5527ba8964c3033e804c64274a9ce1119c058b74aa
7
+ data.tar.gz: 559c85b0d96ae83c36c37ce62080a6d0f054fadaac6ec26d5b1035cef2f1c1fbcd33efa9da75737608335cf12cda30c463ce5a4b71304f7bc05a0b1858eb2036
@@ -1,3 +1,9 @@
1
+ ## 2.3.2 (Jan 30, 2015)
2
+ Bug fixes:
3
+ * Internal sleep mechanism would sometimes no wait for the full duration specified.
4
+ * Rpush.push nows delivers all pending notifications before returning.
5
+ * Require thor >= 0.18.1 (#121).
6
+
1
7
  ## 2.3.1 (Jan 24, 2015)
2
8
  * Fix CPU thrashing while waiting for an APNs connection be established (#119).
3
9
 
data/README.md CHANGED
@@ -7,24 +7,27 @@
7
7
 
8
8
  ### Rpush. The push notification service for Ruby.
9
9
 
10
- * Supported services:
10
+ Rpush aims to be the *de facto* gem for sending push notifications in Ruby. Its core goals are ease of use, reliability and a rich feature set. Rpush provides numerous advanced features not found in others gems, giving you greater control & insight as your project grows. These are a few of the reasons why companies worldwide rely on Rpush to deliver their notifications.
11
+
12
+ #### Supported Services
13
+
11
14
  * [**Apple Push Notification Service**](#apple-push-notification-service)
12
15
  * Including Safari Push Notifications.
13
16
  * [**Google Cloud Messaging**](#google-cloud-messaging)
14
17
  * [**Amazon Device Messaging**](#amazon-device-messaging)
15
18
  * [**Windows Phone Push Notification Service**](#windows-phone-notification-service)
16
19
 
17
- * Supported storage backends:
18
- * [**ActiveRecord**](https://github.com/rpush/rpush/wiki/Using-ActiveRecord)
19
- * [**Redis**](https://github.com/rpush/rpush/wiki/Using-Redis)
20
+ #### Feature Highlights
20
21
 
21
- * Optional Rails integration (version 3 & 4).
22
+ * Use [**ActiveRecord**](https://github.com/rpush/rpush/wiki/Using-ActiveRecord) or [**Redis**](https://github.com/rpush/rpush/wiki/Using-Redis) for storage.
23
+ * Plugins for [**Bugsnag**](https://github.com/rpush/rpush-plugin-bugsnag),
24
+ [**Sentry**](https://github.com/rpush/rpush-plugin-sentry), [**StatsD**](https://github.com/rpush/rpush-plugin-statsd).
25
+ * Seamless integration with your projects, including **Rails**.
26
+ * Run as a [daemon](https://github.com/rpush/rpush#as-a-daemon-recommended), inside a [job queue](https://github.com/rpush/rpush/wiki/Push-API), on the [command-line](https://github.com/rpush/rpush#on-the-command-line) or [embedded](https://github.com/rpush/rpush/wiki/Embedding-API) in another process.
22
27
  * Scales vertically (threading) and horizontally (multiple processes).
23
28
  * Designed for uptime - new apps are loaded automatically, signal `HUP` to update running apps.
24
- * Run as a daemon or inside an [existing process](https://github.com/rpush/rpush/wiki/Embedding-API).
25
- * Use in a scheduler for low-workload deployments ([Push API](https://github.com/rpush/rpush/wiki/Push-API)).
26
29
  * Hooks for fine-grained instrumentation and error handling ([Reflection API](https://github.com/rpush/rpush/wiki/Reflection-API)).
27
- * Works with MRI, JRuby and Rubinius.
30
+ * Works with **MRI**, **JRuby** and **Rubinius**.
28
31
 
29
32
 
30
33
  ### Getting Started
@@ -35,11 +38,11 @@ Add it to your Gemfile:
35
38
  gem 'rpush'
36
39
  ```
37
40
 
38
- Initialize Rpush into your project. Rails will be detected automatically.
41
+ Initialize Rpush into your project. **Rails will be detected automatically.**
39
42
 
40
- ```
41
- cd /path/to/project
42
- rpush init
43
+ ```sh
44
+ $ cd /path/to/project
45
+ $ rpush init
43
46
  ```
44
47
 
45
48
  ### Create an App & Notification
@@ -134,24 +137,24 @@ n.save!
134
137
 
135
138
  It is recommended to run Rpush as a separate process in most cases, though embedding and manual modes are provided for low-workload environments.
136
139
 
137
- #### As a daemon (recommended):
138
-
139
- ```
140
- cd /path/to/project
141
- rpush start
142
- ```
143
-
144
140
  See `rpush help` for all available commands and options.
145
141
 
146
- #### One-off, manual
147
-
148
- On the command-line:
142
+ #### As a daemon
149
143
 
144
+ ```sh
145
+ $ cd /path/to/project
146
+ $ rpush start
150
147
  ```
151
- rpush push
148
+
149
+ #### On the command-line
150
+
151
+ ```sh
152
+ $ rpush push
152
153
  ```
153
154
 
154
- In your code:
155
+ Rpush will deliver all pending notifications and then exit.
156
+
157
+ #### In a scheduled job
155
158
 
156
159
  ```ruby
157
160
  Rpush.push
@@ -163,11 +166,16 @@ See [Push API](https://github.com/rpush/rpush/wiki/Push-API) for more details.
163
166
  #### Embedded inside an existing process
164
167
 
165
168
  ```ruby
166
- # Call this during startup of your application, for example, by adding it to the end of config/rpush.rb
167
- Rpush.embed
169
+ if defined?(Rails)
170
+ ActiveSupport.on_load(:after_initialize) do
171
+ Rpush.embed
172
+ end
173
+ else
174
+ Rpush.embed
175
+ end
168
176
  ```
169
177
 
170
- See [Embedding API](https://github.com/rpush/rpush/wiki/Embedding-API) for more details.
178
+ Call this during startup of your application, for example, by adding it to the end of `config/rpush.rb`. See [Embedding API](https://github.com/rpush/rpush/wiki/Embedding-API) for more details.
171
179
 
172
180
  ### Configuration
173
181
 
@@ -177,7 +185,7 @@ See [Configuration](https://github.com/rpush/rpush/wiki/Configuration) for a lis
177
185
 
178
186
  You should run `rpush init` after upgrading Rpush to check for configuration and migration changes.
179
187
 
180
- ### Wiki
188
+ ### From The Wiki
181
189
 
182
190
  ### General
183
191
  * [Using Redis](https://github.com/rpush/rpush/wiki/Using-Redis)
@@ -77,6 +77,7 @@ module Rpush
77
77
  self.pid_file = 'tmp/rpush.pid'
78
78
  self.log_level = (defined?(Rails) && Rails.logger) ? Rails.logger.level : ::Logger::Severity::INFO
79
79
  self.plugin = OpenStruct.new
80
+ self.foreground = false
80
81
 
81
82
  # Internal options.
82
83
  self.embedded = false
@@ -3,9 +3,15 @@ module Rpush
3
3
  class Feeder
4
4
  extend Reflectable
5
5
 
6
- def self.start
6
+ def self.start(push_mode = false)
7
7
  self.should_stop = false
8
- Rpush.config.push ? enqueue_notifications : feed_forever
8
+
9
+ @thread = Thread.new do
10
+ push_mode ? feed_all : feed_forever
11
+ Rpush::Daemon.store.release_connection
12
+ end
13
+
14
+ @thread.join
9
15
  end
10
16
 
11
17
  def self.stop
@@ -22,18 +28,16 @@ module Rpush
22
28
  attr_accessor :should_stop
23
29
  end
24
30
 
25
- def self.feed_forever
26
- @thread = Thread.new do
27
- loop do
28
- enqueue_notifications
29
- interruptible_sleeper.sleep
30
- break if should_stop
31
- end
31
+ def self.feed_all
32
+ enqueue_notifications until Rpush::Daemon.store.pending_delivery_count == 0
33
+ end
32
34
 
33
- Rpush::Daemon.store.release_connection
35
+ def self.feed_forever
36
+ loop do
37
+ enqueue_notifications
38
+ interruptible_sleeper.sleep
39
+ break if should_stop
34
40
  end
35
-
36
- @thread.join
37
41
  end
38
42
 
39
43
  def self.enqueue_notifications
@@ -5,15 +5,21 @@ module Rpush
5
5
  class InterruptibleSleep
6
6
  def initialize(duration)
7
7
  @duration = duration
8
- @obj = Object.new
9
- @obj.extend(MonitorMixin)
10
- @condition = @obj.new_cond
11
8
  @stop = false
9
+
10
+ @wakeup_obj = Object.new
11
+ @wakeup_obj.extend(MonitorMixin)
12
+ @wakeup_condition = @wakeup_obj.new_cond
13
+
14
+ @sleep_obj = Object.new
15
+ @sleep_obj.extend(MonitorMixin)
16
+ @sleep_condition = @sleep_obj.new_cond
12
17
  end
13
18
 
14
19
  def sleep
15
20
  return if @stop
16
- @obj.synchronize { @condition.wait(100_000) }
21
+ goto_sleep
22
+ wait_for_wakeup
17
23
  end
18
24
 
19
25
  def start
@@ -21,6 +27,7 @@ module Rpush
21
27
 
22
28
  @thread = Thread.new do
23
29
  loop do
30
+ wait_for_sleeper
24
31
  break if @stop
25
32
  Kernel.sleep(@duration)
26
33
  wakeup
@@ -35,7 +42,21 @@ module Rpush
35
42
  end
36
43
 
37
44
  def wakeup
38
- @obj.synchronize { @condition.signal }
45
+ @wakeup_obj.synchronize { @wakeup_condition.signal }
46
+ end
47
+
48
+ private
49
+
50
+ def goto_sleep
51
+ @sleep_obj.synchronize { @sleep_condition.signal }
52
+ end
53
+
54
+ def wait_for_wakeup
55
+ @wakeup_obj.synchronize { @wakeup_condition.wait(@duration * 2) }
56
+ end
57
+
58
+ def wait_for_sleeper
59
+ @sleep_obj.synchronize { @sleep_condition.wait }
39
60
  end
40
61
  end
41
62
  end
@@ -165,6 +165,10 @@ module Rpush
165
165
  Rpush.logger.error(e)
166
166
  end
167
167
 
168
+ def pending_delivery_count
169
+ ready_for_delivery.count
170
+ end
171
+
168
172
  private
169
173
 
170
174
  def create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app) # rubocop:disable ParameterLists
@@ -8,7 +8,7 @@ module Rpush
8
8
  :create_gcm_notification, :create_adm_notification, :update_app,
9
9
  :update_notification, :release_connection,
10
10
  :all_apps, :app, :mark_ids_failed, :mark_ids_retryable,
11
- :reopen_log]
11
+ :reopen_log, :pending_delivery_count]
12
12
 
13
13
  def self.check(klass)
14
14
  missing = PUBLIC_METHODS - klass.instance_methods.map(&:to_sym)
@@ -106,6 +106,15 @@ module Rpush
106
106
  def reopen_log
107
107
  end
108
108
 
109
+ def pending_delivery_count
110
+ Modis.with_connection do |redis|
111
+ pending = redis.zrange(Rpush::Client::Redis::Notification.absolute_pending_namespace, 0, -1)
112
+ retryable = redis.zrangebyscore(Rpush::Client::Redis::Notification.absolute_retryable_namespace, 0, Time.now.to_i)
113
+
114
+ pending.count + retryable.count
115
+ end
116
+ end
117
+
109
118
  private
110
119
 
111
120
  def create_gcm_like_notification(notification, attrs, data, registration_ids, deliver_after, app) # rubocop:disable ParameterLists
@@ -133,6 +142,7 @@ module Rpush
133
142
  end
134
143
 
135
144
  def pending_notification_ids(limit)
145
+ limit = [0, limit - 1].max # 'zrange key 0 1' will return 2 values, not 1.
136
146
  pending_ns = Rpush::Client::Redis::Notification.absolute_pending_namespace
137
147
 
138
148
  Modis.with_connection do |redis|
@@ -9,6 +9,7 @@ module Rpush
9
9
  config = Rpush::ConfigurationWithoutDefaults.new
10
10
  options.each { |k, v| config.send("#{k}=", v) }
11
11
  config.embedded = true
12
+ config.foreground = true
12
13
  Rpush.config.update(config)
13
14
  Kernel.at_exit { shutdown }
14
15
  @embed_thread = Thread.new { Rpush::Daemon.start }
@@ -69,6 +69,7 @@ module Rpush
69
69
  end
70
70
 
71
71
  formatted_msg = "[#{Time.now.to_s(:db)}] "
72
+ formatted_msg << '[rpush] ' if Rpush.config.embedded
72
73
  formatted_msg << "[#{prefix}] " if prefix
73
74
  formatted_msg << msg
74
75
 
@@ -9,8 +9,7 @@ module Rpush
9
9
 
10
10
  Rpush::Daemon.common_init
11
11
  Rpush::Daemon::Synchronizer.sync
12
- Rpush::Daemon::Feeder.start
13
- # TODO: Wait until there are no more notifications.
12
+ Rpush::Daemon::Feeder.start(true) # non-blocking
14
13
  Rpush::Daemon::AppRunner.stop
15
14
  end
16
15
  end
@@ -1,3 +1,3 @@
1
1
  module Rpush
2
- VERSION = '2.3.1'
2
+ VERSION = '2.3.2'
3
3
  end
@@ -20,11 +20,11 @@ describe 'ADM' do
20
20
  notification.data = { message: 'test' }
21
21
  notification.save!
22
22
 
23
- Net::HTTP::Persistent.stub(new: http)
23
+ allow(Net::HTTP::Persistent).to receive_messages(new: http)
24
24
  end
25
25
 
26
26
  it 'delivers a notification successfully' do
27
- response.stub(body: JSON.dump(registrationID: notification.registration_ids.first.to_s))
27
+ allow(response).to receive_messages(body: JSON.dump(registrationID: notification.registration_ids.first.to_s))
28
28
 
29
29
  expect do
30
30
  Rpush.push
@@ -33,12 +33,10 @@ describe 'ADM' do
33
33
  end
34
34
 
35
35
  it 'fails to deliver a notification successfully' do
36
- response.stub(code: 400, body: JSON.dump(reason: 'error', registrationID: notification.registration_ids.first.to_s))
37
-
38
- expect do
39
- Rpush.push
40
- notification.reload
41
- end.to_not change(notification, :delivered).to(true)
36
+ allow(response).to receive_messages(code: 400, body: JSON.dump(reason: 'error', registrationID: notification.registration_ids.first.to_s))
37
+ Rpush.push
38
+ notification.reload
39
+ expect(notification.delivered).to eq(false)
42
40
  end
43
41
 
44
42
  it 'retries notification that fail due to a SocketError' do
@@ -33,8 +33,8 @@ describe 'APNs' do
33
33
  end
34
34
 
35
35
  def stub_tcp_connection
36
- Rpush::Daemon::TcpConnection.any_instance.stub(connect_socket: [tcp_socket, ssl_socket])
37
- Rpush::Daemon::TcpConnection.any_instance.stub(setup_ssl_context: double.as_null_object)
36
+ allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(connect_socket: [tcp_socket, ssl_socket])
37
+ allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(setup_ssl_context: double.as_null_object)
38
38
  stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
39
39
  end
40
40
 
@@ -55,13 +55,13 @@ describe 'APNs' do
55
55
  end
56
56
 
57
57
  def fail_notification(notification)
58
- ssl_socket.stub(read: [8, 4, notification.id].pack('ccN'))
58
+ allow(ssl_socket).to receive_messages(read: [8, 4, notification.id].pack('ccN'))
59
59
  enable_io_select
60
60
  end
61
61
 
62
62
  def enable_io_select
63
63
  called = false
64
- io_double.stub(:select) do
64
+ allow(io_double).to receive(:select) do
65
65
  if called
66
66
  nil
67
67
  else
@@ -88,9 +88,9 @@ describe 'APNs' do
88
88
  allow(ssl_socket).to receive(:read).and_return(tuple, nil)
89
89
  Rpush.apns_feedback
90
90
  feedback = Rpush::Apns::Feedback.all.first
91
- feedback.should_not be_nil
92
- feedback.app_id.should eq(app.id)
93
- feedback.device_token.should eq('834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17')
91
+ expect(feedback).not_to be_nil
92
+ expect(feedback.app_id).to eq(app.id)
93
+ expect(feedback.device_token).to eq('834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17')
94
94
  end
95
95
 
96
96
  describe 'delivery failures' do
@@ -132,7 +132,7 @@ describe 'APNs' do
132
132
 
133
133
  describe 'with a failed connection' do
134
134
  it 'retries all notifications' do
135
- Rpush::Daemon::TcpConnection.any_instance.stub(sleep: nil)
135
+ allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(sleep: nil)
136
136
  expect(ssl_socket).to receive(:write).at_least(1).times.and_raise(Errno::EPIPE)
137
137
  notifications = 2.times.map { create_notification }
138
138
  notifications.each { |n| wait_for_notification_to_retry(n) }
@@ -159,7 +159,7 @@ describe 'APNs' do
159
159
 
160
160
  expect(failed_ids).to_not include(notification1.id)
161
161
  notification1.reload
162
- notification1.delivered.should be_true
162
+ expect(notification1.delivered).to eq(true)
163
163
  end
164
164
 
165
165
  it 'marks notifications following the failed one as retryable' do
@@ -23,10 +23,10 @@ describe 'embedding' do
23
23
  end
24
24
 
25
25
  def stub_tcp_connection
26
- Rpush::Daemon::TcpConnection.any_instance.stub(connect_socket: [tcp_socket, ssl_socket])
27
- Rpush::Daemon::TcpConnection.any_instance.stub(setup_ssl_context: double.as_null_object)
26
+ allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(connect_socket: [tcp_socket, ssl_socket])
27
+ allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(setup_ssl_context: double.as_null_object)
28
28
  stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
29
- Rpush::Daemon::Apns::FeedbackReceiver.stub(new: double.as_null_object)
29
+ allow(Rpush::Daemon::Apns::FeedbackReceiver).to receive_messages(new: double.as_null_object)
30
30
  end
31
31
 
32
32
  before do
@@ -16,11 +16,11 @@ describe 'GCM' do
16
16
  notification.data = { message: 'test' }
17
17
  notification.save!
18
18
 
19
- Net::HTTP::Persistent.stub(new: http)
19
+ allow(Net::HTTP::Persistent).to receive_messages(new: http)
20
20
  end
21
21
 
22
22
  it 'delivers a notification successfully' do
23
- response.stub(body: JSON.dump(results: [{ message_id: notification.registration_ids.first.to_s }]))
23
+ allow(response).to receive_messages(body: JSON.dump(results: [{ message_id: notification.registration_ids.first.to_s }]))
24
24
 
25
25
  expect do
26
26
  Rpush.push
@@ -29,12 +29,10 @@ describe 'GCM' do
29
29
  end
30
30
 
31
31
  it 'fails to deliver a notification successfully' do
32
- response.stub(body: JSON.dump(results: [{ error: 'Err' }]))
33
-
34
- expect do
35
- Rpush.push
36
- notification.reload
37
- end.to_not change(notification, :delivered).to(true)
32
+ allow(response).to receive_messages(body: JSON.dump(results: [{ error: 'Err' }]))
33
+ Rpush.push
34
+ notification.reload
35
+ expect(notification.delivered).to eq(false)
38
36
  end
39
37
 
40
38
  it 'retries notification that fail due to a SocketError' do