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.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +307 -163
  3. data/README.md +105 -19
  4. data/lib/generators/templates/add_adm.rb +1 -1
  5. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +2 -2
  6. data/lib/generators/templates/add_app_to_rapns.rb +2 -2
  7. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +1 -1
  8. data/lib/generators/templates/add_gcm.rb +11 -25
  9. data/lib/generators/templates/add_rpush.rb +33 -83
  10. data/lib/generators/templates/add_wpns.rb +1 -1
  11. data/lib/generators/templates/create_rapns_apps.rb +1 -1
  12. data/lib/generators/templates/create_rapns_feedback.rb +3 -9
  13. data/lib/generators/templates/create_rapns_notifications.rb +3 -9
  14. data/lib/generators/templates/rename_rapns_to_rpush.rb +9 -33
  15. data/lib/generators/templates/rpush.rb +5 -4
  16. data/lib/generators/templates/rpush_2_0_0_updates.rb +10 -18
  17. data/lib/generators/templates/rpush_2_1_0_updates.rb +1 -1
  18. data/lib/generators/templates/rpush_2_6_0_updates.rb +1 -1
  19. data/lib/generators/templates/rpush_2_7_0_updates.rb +1 -1
  20. data/lib/generators/templates/rpush_3_0_0_updates.rb +1 -1
  21. data/lib/generators/templates/rpush_3_0_1_updates.rb +1 -1
  22. data/lib/generators/templates/rpush_3_1_0_add_pushy.rb +1 -1
  23. data/lib/generators/templates/rpush_3_1_1_updates.rb +1 -1
  24. data/lib/generators/templates/rpush_3_2_0_add_apns_p8.rb +1 -1
  25. data/lib/generators/templates/rpush_3_2_4_updates.rb +1 -1
  26. data/lib/generators/templates/rpush_3_3_0_updates.rb +1 -1
  27. data/lib/generators/templates/rpush_3_3_1_updates.rb +3 -3
  28. data/lib/generators/templates/rpush_4_1_0_updates.rb +1 -1
  29. data/lib/generators/templates/rpush_4_1_1_updates.rb +1 -1
  30. data/lib/generators/templates/rpush_4_2_0_updates.rb +1 -1
  31. data/lib/rpush/cli.rb +1 -1
  32. data/lib/rpush/client/active_model/adm/data_validator.rb +1 -1
  33. data/lib/rpush/client/active_model/apns/app.rb +1 -17
  34. data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +2 -2
  35. data/lib/rpush/client/active_model/apns/notification.rb +13 -1
  36. data/lib/rpush/client/active_model/apns/notification_payload_size_validator.rb +15 -0
  37. data/lib/rpush/client/active_model/apns2/app.rb +7 -1
  38. data/lib/rpush/client/active_model/apns2/notification.rb +14 -0
  39. data/lib/rpush/client/active_model/certificate_private_key_validator.rb +19 -0
  40. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +1 -1
  41. data/lib/rpush/client/active_model/gcm/notification.rb +2 -2
  42. data/lib/rpush/client/active_model/payload_data_size_validator.rb +1 -1
  43. data/lib/rpush/client/active_model/registration_ids_count_validator.rb +1 -1
  44. data/lib/rpush/client/active_model/webpush/app.rb +41 -0
  45. data/lib/rpush/client/active_model/webpush/notification.rb +66 -0
  46. data/lib/rpush/client/active_model.rb +5 -1
  47. data/lib/rpush/client/active_record/apns/active_record_serializable_notification.rb +65 -0
  48. data/lib/rpush/client/active_record/apns/notification.rb +1 -57
  49. data/lib/rpush/client/active_record/apns2/notification.rb +4 -1
  50. data/lib/rpush/client/active_record/apnsp8/notification.rb +1 -0
  51. data/lib/rpush/client/active_record/webpush/app.rb +11 -0
  52. data/lib/rpush/client/active_record/webpush/notification.rb +12 -0
  53. data/lib/rpush/client/active_record.rb +4 -0
  54. data/lib/rpush/client/redis/apns2/notification.rb +1 -0
  55. data/lib/rpush/client/redis/apnsp8/notification.rb +2 -0
  56. data/lib/rpush/client/redis/pushy/notification.rb +0 -1
  57. data/lib/rpush/client/redis/webpush/app.rb +15 -0
  58. data/lib/rpush/client/redis/webpush/notification.rb +15 -0
  59. data/lib/rpush/client/redis.rb +3 -0
  60. data/lib/rpush/configuration.rb +3 -2
  61. data/lib/rpush/daemon/apns/feedback_receiver.rb +1 -1
  62. data/lib/rpush/daemon/apns2/delivery.rb +14 -2
  63. data/lib/rpush/daemon/apnsp8/delivery.rb +14 -3
  64. data/lib/rpush/daemon/app_runner.rb +1 -1
  65. data/lib/rpush/daemon/batch.rb +12 -5
  66. data/lib/rpush/daemon/delivery.rb +1 -2
  67. data/lib/rpush/daemon/store/active_record/reconnectable.rb +1 -1
  68. data/lib/rpush/daemon/store/active_record.rb +11 -7
  69. data/lib/rpush/daemon/store/redis.rb +6 -6
  70. data/lib/rpush/daemon/string_helpers.rb +1 -1
  71. data/lib/rpush/daemon/webpush/delivery.rb +114 -0
  72. data/lib/rpush/daemon/webpush.rb +10 -0
  73. data/lib/rpush/daemon.rb +4 -1
  74. data/lib/rpush/logger.rb +2 -1
  75. data/lib/rpush/version.rb +3 -3
  76. data/spec/functional/apns2_spec.rb +99 -2
  77. data/spec/functional/gcm_priority_spec.rb +40 -0
  78. data/spec/functional/retry_spec.rb +1 -1
  79. data/spec/functional/webpush_spec.rb +31 -0
  80. data/spec/spec_helper.rb +3 -1
  81. data/spec/support/active_record_setup.rb +4 -3
  82. data/spec/support/config/database.yml +4 -4
  83. data/spec/support/simplecov_helper.rb +2 -2
  84. data/spec/unit/client/active_record/adm/app_spec.rb +2 -54
  85. data/spec/unit/client/active_record/adm/notification_spec.rb +2 -39
  86. data/spec/unit/client/active_record/apns/app_spec.rb +3 -26
  87. data/spec/unit/client/active_record/apns/feedback_spec.rb +1 -5
  88. data/spec/unit/client/active_record/apns/notification_spec.rb +29 -293
  89. data/spec/unit/client/active_record/apns2/app_spec.rb +5 -0
  90. data/spec/unit/client/active_record/apns2/notification_spec.rb +65 -0
  91. data/spec/unit/client/active_record/apnsp8/notification_spec.rb +28 -0
  92. data/spec/unit/client/active_record/app_spec.rb +1 -26
  93. data/spec/unit/client/active_record/gcm/app_spec.rb +3 -1
  94. data/spec/unit/client/active_record/gcm/notification_spec.rb +6 -88
  95. data/spec/unit/client/active_record/notification_spec.rb +3 -11
  96. data/spec/unit/client/active_record/pushy/app_spec.rb +2 -13
  97. data/spec/unit/client/active_record/pushy/notification_spec.rb +2 -55
  98. data/spec/unit/client/active_record/shared/app.rb +14 -0
  99. data/spec/unit/{notification_shared.rb → client/active_record/shared/notification.rb} +12 -7
  100. data/spec/unit/client/active_record/webpush/app_spec.rb +6 -0
  101. data/spec/unit/client/active_record/webpush/notification_spec.rb +6 -0
  102. data/spec/unit/client/active_record/wns/badge_notification_spec.rb +1 -11
  103. data/spec/unit/client/active_record/wns/raw_notification_spec.rb +3 -12
  104. data/spec/unit/client/active_record/wpns/app_spec.rb +3 -1
  105. data/spec/unit/client/active_record/wpns/notification_spec.rb +2 -17
  106. data/spec/unit/client/redis/adm/app_spec.rb +5 -0
  107. data/spec/unit/client/redis/adm/notification_spec.rb +5 -0
  108. data/spec/unit/client/redis/apns/app_spec.rb +5 -0
  109. data/spec/unit/client/redis/apns/feedback_spec.rb +5 -0
  110. data/spec/unit/client/redis/apns/notification_spec.rb +50 -0
  111. data/spec/unit/client/redis/apns2/app_spec.rb +4 -0
  112. data/spec/unit/client/redis/apns2/notification_spec.rb +50 -0
  113. data/spec/unit/client/redis/apnsp8/notification_spec.rb +29 -0
  114. data/spec/unit/client/redis/app_spec.rb +5 -0
  115. data/spec/unit/client/redis/gcm/app_spec.rb +5 -0
  116. data/spec/unit/client/redis/gcm/notification_spec.rb +5 -0
  117. data/spec/unit/client/redis/notification_spec.rb +5 -0
  118. data/spec/unit/client/redis/pushy/app_spec.rb +5 -0
  119. data/spec/unit/client/redis/pushy/notification_spec.rb +5 -0
  120. data/spec/unit/client/redis/webpush/app_spec.rb +5 -0
  121. data/spec/unit/client/redis/webpush/notification_spec.rb +5 -0
  122. data/spec/unit/client/redis/wns/badge_notification_spec.rb +5 -0
  123. data/spec/unit/client/redis/wns/raw_notification_spec.rb +22 -0
  124. data/spec/unit/client/redis/wpns/app_spec.rb +5 -0
  125. data/spec/unit/client/redis/wpns/notification_spec.rb +5 -0
  126. data/spec/unit/client/shared/adm/app.rb +51 -0
  127. data/spec/unit/client/shared/adm/notification.rb +39 -0
  128. data/spec/unit/client/shared/apns/app.rb +29 -0
  129. data/spec/unit/client/shared/apns/feedback.rb +9 -0
  130. data/spec/unit/client/shared/apns/notification.rb +277 -0
  131. data/spec/unit/client/shared/app.rb +17 -0
  132. data/spec/unit/client/shared/gcm/app.rb +4 -0
  133. data/spec/unit/client/shared/gcm/notification.rb +77 -0
  134. data/spec/unit/client/shared/notification.rb +10 -0
  135. data/spec/unit/client/shared/pushy/app.rb +17 -0
  136. data/spec/unit/client/shared/pushy/notification.rb +55 -0
  137. data/spec/unit/client/shared/webpush/app.rb +33 -0
  138. data/spec/unit/client/shared/webpush/notification.rb +83 -0
  139. data/spec/unit/client/shared/wns/badge_notification.rb +15 -0
  140. data/spec/unit/client/shared/wns/raw_notification.rb +21 -0
  141. data/spec/unit/client/shared/wpns/app.rb +4 -0
  142. data/spec/unit/client/shared/wpns/notification.rb +18 -0
  143. data/spec/unit/daemon/apnsp8/delivery_spec.rb +53 -0
  144. data/spec/unit/daemon/batch_spec.rb +50 -2
  145. data/spec/unit/daemon/delivery_spec.rb +10 -0
  146. data/spec/unit/daemon/pushy/delivery_spec.rb +5 -3
  147. data/spec/unit/daemon/shared/store.rb +312 -0
  148. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +7 -7
  149. data/spec/unit/daemon/store/active_record_spec.rb +6 -287
  150. data/spec/unit/daemon/store/redis_spec.rb +2 -291
  151. data/spec/unit/daemon/webpush/delivery_spec.rb +144 -0
  152. data/spec/unit_spec_helper.rb +3 -0
  153. metadata +145 -18
  154. data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +0 -16
@@ -0,0 +1,53 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Daemon::Apnsp8::Delivery do
4
+ subject(:delivery) { described_class.new(app, http2_client, token_provider, batch) }
5
+
6
+ let(:app) { double(bundle_id: 'MY BUNDLE ID') }
7
+ let(:notification1) { double('Notification 1', data: {}, as_json: {}).as_null_object }
8
+ let(:notification2) { double('Notification 2', data: {}, as_json: {}).as_null_object }
9
+
10
+ let(:token_provider) { double(token: 'MY JWT TOKEN') }
11
+ let(:max_concurrent_streams) { 100 }
12
+ let(:remote_settings) { { settings_max_concurrent_streams: max_concurrent_streams } }
13
+ let(:http_request) { double(on: nil) }
14
+ let(:http2_client) do
15
+ double(
16
+ stream_count: 0,
17
+ call_async: nil,
18
+ join: nil,
19
+ prepare_request: http_request,
20
+ remote_settings: remote_settings
21
+ )
22
+ end
23
+
24
+ let(:batch) { double(mark_delivered: nil, all_processed: nil) }
25
+ let(:logger) { double(info: nil) }
26
+
27
+ before do
28
+ allow(batch).to receive(:each_notification) do |&blk|
29
+ [notification1, notification2].each(&blk)
30
+ end
31
+ allow(Rpush).to receive_messages(logger: logger)
32
+ end
33
+
34
+ describe '#perform' do
35
+ context 'with an HTTP2 client where max concurrent streams is not set' do
36
+ let(:max_concurrent_streams) { 0x7fffffff }
37
+
38
+ it 'does not fall into an infinite loop on notifications after the first' do
39
+ start = Time.now
40
+ thread = Thread.new { delivery.perform }
41
+
42
+ loop do
43
+ break unless thread.alive?
44
+
45
+ if Time.now - start > 0.5
46
+ thread.kill
47
+ fail 'Stuck in an infinite loop'
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,8 +1,8 @@
1
1
  require 'unit_spec_helper'
2
2
 
3
3
  describe Rpush::Daemon::Batch do
4
- let(:notification1) { double(:notification1, id: 1) }
5
- let(:notification2) { double(:notification2, id: 2) }
4
+ let(:notification1) { double(:notification1, id: 1, delivered: false, failed: false) }
5
+ let(:notification2) { double(:notification2, id: 2, delivered: false, failed: false) }
6
6
  let(:batch) { Rpush::Daemon::Batch.new([notification1, notification2]) }
7
7
  let(:store) { double.as_null_object }
8
8
  let(:time) { Time.now }
@@ -50,6 +50,54 @@ describe Rpush::Daemon::Batch do
50
50
  end
51
51
  end
52
52
 
53
+ describe 'mark_all_retryable' do
54
+ let(:error) { StandardError.new('Exception') }
55
+
56
+ it 'marks all notifications as retryable without persisting' do
57
+ expect(store).to receive(:mark_retryable).ordered.with(notification1, time, persist: false)
58
+ expect(store).to receive(:mark_retryable).ordered.with(notification2, time, persist: false)
59
+
60
+ batch.mark_all_retryable(time, error)
61
+ end
62
+
63
+ it 'defers persisting' do
64
+ batch.mark_all_retryable(time, error)
65
+ expect(batch.retryable).to eq(time => [notification1, notification2])
66
+ end
67
+
68
+ context 'when one of the notifications delivered' do
69
+ let(:notification2) { double(:notification2, id: 2, delivered: true, failed: false) }
70
+
71
+ it 'marks all only pending notification as retryable without persisting' do
72
+ expect(store).to receive(:mark_retryable).ordered.with(notification1, time, persist: false)
73
+ expect(store).not_to receive(:mark_retryable).ordered.with(notification2, time, persist: false)
74
+
75
+ batch.mark_all_retryable(time, error)
76
+ end
77
+
78
+ it 'defers persisting' do
79
+ batch.mark_all_retryable(time, error)
80
+ expect(batch.retryable).to eq(time => [notification1])
81
+ end
82
+ end
83
+
84
+ context 'when one of the notifications failed' do
85
+ let(:notification2) { double(:notification2, id: 2, delivered: false, failed: true) }
86
+
87
+ it 'marks all only pending notification as retryable without persisting' do
88
+ expect(store).to receive(:mark_retryable).ordered.with(notification1, time, persist: false)
89
+ expect(store).not_to receive(:mark_retryable).ordered.with(notification2, time, persist: false)
90
+
91
+ batch.mark_all_retryable(time, error)
92
+ end
93
+
94
+ it 'defers persisting' do
95
+ batch.mark_all_retryable(time, error)
96
+ expect(batch.retryable).to eq(time => [notification1])
97
+ end
98
+ end
99
+ end
100
+
53
101
  describe 'mark_failed' do
54
102
  it 'marks the notification as failed without persisting' do
55
103
  expect(store).to receive(:mark_failed).with(notification1, 1, 'an error', time, persist: false)
@@ -41,6 +41,16 @@ describe Rpush::Daemon::Delivery do
41
41
  end
42
42
  end
43
43
 
44
+ describe 'mark_batch_retryable' do
45
+ let(:batch) { double(Rpush::Daemon::Batch) }
46
+ let(:error) { StandardError.new('Exception') }
47
+
48
+ it 'marks all notifications as retryable' do
49
+ expect(batch).to receive(:mark_all_retryable)
50
+ delivery.mark_batch_retryable(Time.now + 1.hour, error)
51
+ end
52
+ end
53
+
44
54
  describe 'mark_batch_failed' do
45
55
  it 'marks all notifications as delivered' do
46
56
  error = Rpush::DeliveryError.new(1, 42, 'an error')
@@ -61,10 +61,12 @@ describe Rpush::Daemon::Pushy::Delivery do
61
61
  it_behaves_like 'process notification'
62
62
  end
63
63
 
64
- shared_examples 'retry delivery' do |response_code:|
65
- let(:response_code) { response_code }
64
+ shared_examples 'retry delivery' do |options|
65
+ let(:response_code) { options[:response_code] }
66
+
67
+ shared_examples 'logs' do |log_options|
68
+ let(:deliver_after) { log_options[:deliver_after] }
66
69
 
67
- shared_examples 'logs' do |deliver_after:|
68
70
  let(:expected_log_message) do
69
71
  "Pushy responded with a #{response_code} error. Notification #{notification.id} " \
70
72
  "will be retried after #{deliver_after} (retry 1)."
@@ -0,0 +1,312 @@
1
+ require 'unit_spec_helper'
2
+
3
+ shared_examples 'Rpush::Daemon::Store' do
4
+ subject(:store) { described_class.new }
5
+
6
+ let(:app) { Rpush::Apns::App.create!(name: 'my_app', environment: 'development', certificate: TEST_CERT) }
7
+ let(:notification) { Rpush::Apns::Notification.create!(device_token: "a" * 64, app: app) }
8
+ let(:time) { Time.parse('2019/06/06 02:45').utc }
9
+ let(:logger) { double(Rpush::Logger, error: nil, internal_logger: nil) }
10
+
11
+ before do
12
+ allow(Rpush).to receive_messages(logger: logger)
13
+ end
14
+
15
+ before(:each) do
16
+ Timecop.freeze(time)
17
+ end
18
+
19
+ after do
20
+ Timecop.return
21
+ end
22
+
23
+ it 'updates an notification' do
24
+ expect(notification).to receive(:save!)
25
+ store.update_notification(notification)
26
+ end
27
+
28
+ it 'updates an app' do
29
+ expect(app).to receive(:save!)
30
+ store.update_app(app)
31
+ end
32
+
33
+ it 'finds an app by ID' do
34
+ expect(store.app(app.id)).to eq(app)
35
+ end
36
+
37
+ it 'finds all apps' do
38
+ app
39
+ expect(store.all_apps).to eq([app])
40
+ end
41
+
42
+ it 'translates an Integer notification ID' do
43
+ expect(store.translate_integer_notification_id(notification.id)).to eq(notification.id)
44
+ end
45
+
46
+ it 'returns the pending notification count' do
47
+ notification
48
+ expect(store.pending_delivery_count).to eq(1)
49
+ end
50
+
51
+ describe 'mark_retryable' do
52
+ it 'increments the retry count' do
53
+ expect do
54
+ store.mark_retryable(notification, time)
55
+ end.to change(notification, :retries).by(1)
56
+ end
57
+
58
+ it 'sets the deliver after timestamp' do
59
+ deliver_after = (time + 10.seconds)
60
+ expect do
61
+ store.mark_retryable(notification, deliver_after)
62
+ end.to change(notification, :deliver_after).to(deliver_after)
63
+ end
64
+
65
+ it 'saves the notification without validation' do
66
+ expect(notification).to receive(:save!).with(validate: false)
67
+ store.mark_retryable(notification, time)
68
+ end
69
+
70
+ it 'does not save the notification if persist: false' do
71
+ expect(notification).not_to receive(:save!)
72
+ store.mark_retryable(notification, time, persist: false)
73
+ end
74
+ end
75
+
76
+ describe 'mark_batch_retryable' do
77
+ let(:deliver_after) { time + 10.seconds }
78
+
79
+ it 'sets the attributes on the object for use in reflections' do
80
+ store.mark_batch_retryable([notification], deliver_after)
81
+ expect(notification.deliver_after.to_s).to eq deliver_after.to_s
82
+ expect(notification.retries).to eq 1
83
+ end
84
+
85
+ it 'increments the retired count' do
86
+ expect do
87
+ store.mark_batch_retryable([notification], deliver_after)
88
+ notification.reload
89
+ end.to change(notification, :retries).by(1)
90
+ end
91
+
92
+ it 'sets the deliver after timestamp' do
93
+ expect do
94
+ store.mark_batch_retryable([notification], deliver_after)
95
+ notification.reload
96
+ end.to change { notification.deliver_after.try(:utc).to_s }.to(deliver_after.utc.to_s)
97
+ end
98
+ end
99
+
100
+ describe 'mark_delivered' do
101
+ it 'marks the notification as delivered' do
102
+ expect do
103
+ store.mark_delivered(notification, time)
104
+ end.to change(notification, :delivered).to(true)
105
+ end
106
+
107
+ it 'sets the time the notification was delivered' do
108
+ expect do
109
+ store.mark_delivered(notification, time)
110
+ notification.reload
111
+ end.to change { notification.delivered_at.try(:utc).to_s }.to(time.to_s)
112
+ end
113
+
114
+ it 'saves the notification without validation' do
115
+ expect(notification).to receive(:save!).with(validate: false)
116
+ store.mark_delivered(notification, time)
117
+ end
118
+
119
+ it 'does not save the notification if persist: false' do
120
+ expect(notification).not_to receive(:save!)
121
+ store.mark_delivered(notification, time, persist: false)
122
+ end
123
+ end
124
+
125
+ describe 'mark_batch_delivered' do
126
+ it 'sets the attributes on the object for use in reflections' do
127
+ store.mark_batch_delivered([notification])
128
+ expect(notification.delivered_at.to_s).to eq time.to_s
129
+ expect(notification.delivered).to be_truthy
130
+ end
131
+
132
+ it 'marks the notifications as delivered' do
133
+ expect do
134
+ store.mark_batch_delivered([notification])
135
+ notification.reload
136
+ end.to change(notification, :delivered).to(true)
137
+ end
138
+
139
+ it 'sets the time the notifications were delivered' do
140
+ expect do
141
+ store.mark_batch_delivered([notification])
142
+ notification.reload
143
+ end.to change { notification.delivered_at.try(:utc)&.to_s }.to(time.to_s)
144
+ end
145
+ end
146
+
147
+ describe 'mark_failed' do
148
+ it 'marks the notification as not delivered' do
149
+ store.mark_failed(notification, nil, '', time)
150
+ expect(notification.delivered).to eq(false)
151
+ end
152
+
153
+ it 'marks the notification as failed' do
154
+ expect do
155
+ store.mark_failed(notification, nil, '', time)
156
+ notification.reload
157
+ end.to change(notification, :failed).to(true)
158
+ end
159
+
160
+ it 'sets the time the notification delivery failed' do
161
+ expect do
162
+ store.mark_failed(notification, nil, '', time)
163
+ notification.reload
164
+ end.to change { notification.failed_at.try(:utc).to_s }.to(time.to_s)
165
+ end
166
+
167
+ it 'sets the error code' do
168
+ expect do
169
+ store.mark_failed(notification, 42, '', time)
170
+ end.to change(notification, :error_code).to(42)
171
+ end
172
+
173
+ it 'sets the error description' do
174
+ expect do
175
+ store.mark_failed(notification, 42, 'Weeee', time)
176
+ end.to change(notification, :error_description).to('Weeee')
177
+ end
178
+
179
+ it 'saves the notification without validation' do
180
+ expect(notification).to receive(:save!).with(validate: false)
181
+ store.mark_failed(notification, nil, '', time)
182
+ end
183
+
184
+ it 'does not save the notification if persist: false' do
185
+ expect(notification).not_to receive(:save!)
186
+ store.mark_failed(notification, nil, '', time, persist: false)
187
+ end
188
+ end
189
+
190
+ describe 'mark_batch_failed' do
191
+ it 'sets the attributes on the object for use in reflections' do
192
+ store.mark_batch_failed([notification], 123, 'an error')
193
+ expect(notification.failed_at.to_s).to eq time.to_s
194
+ expect(notification.delivered_at).to be_nil
195
+ expect(notification.delivered).to eq(false)
196
+ expect(notification.failed).to be_truthy
197
+ expect(notification.error_code).to eq 123
198
+ expect(notification.error_description).to eq 'an error'
199
+ end
200
+
201
+ it 'marks the notification as not delivered' do
202
+ store.mark_batch_failed([notification], nil, '')
203
+ notification.reload
204
+ expect(notification.delivered).to be_falsey
205
+ end
206
+
207
+ it 'marks the notification as failed' do
208
+ expect do
209
+ store.mark_batch_failed([notification], nil, '')
210
+ notification.reload
211
+ end.to change(notification, :failed).to(true)
212
+ end
213
+
214
+ it 'sets the time the notification delivery failed' do
215
+ expect do
216
+ store.mark_batch_failed([notification], nil, '')
217
+ notification.reload
218
+ end.to change { notification.failed_at.try(:utc) }.to(time)
219
+ end
220
+
221
+ it 'sets the error code' do
222
+ expect do
223
+ store.mark_batch_failed([notification], 42, '')
224
+ notification.reload
225
+ end.to change(notification, :error_code).to(42)
226
+ end
227
+
228
+ it 'sets the error description' do
229
+ expect do
230
+ store.mark_batch_failed([notification], 42, 'Weeee')
231
+ notification.reload
232
+ end.to change(notification, :error_description).to('Weeee')
233
+ end
234
+ end
235
+
236
+ describe 'create_apns_feedback' do
237
+ it 'creates the Feedback record' do
238
+ expect(Rpush::Apns::Feedback).to receive(:create!).with(
239
+ failed_at: time, device_token: 'ab' * 32, app_id: app.id
240
+ )
241
+ store.create_apns_feedback(time, 'ab' * 32, app)
242
+ end
243
+ end
244
+
245
+ describe 'create_gcm_notification' do
246
+ let(:data) { { 'data' => true } }
247
+ let(:attributes) { { device_token: 'ab' * 32 } }
248
+ let(:registration_ids) { %w[123 456] }
249
+ let(:deliver_after) { time + 10.seconds }
250
+ let(:args) { [attributes, data, registration_ids, deliver_after, app] }
251
+
252
+ it 'sets the given attributes' do
253
+ new_notification = store.create_gcm_notification(*args)
254
+ expect(new_notification.device_token).to eq 'ab' * 32
255
+ end
256
+
257
+ it 'sets the given data' do
258
+ new_notification = store.create_gcm_notification(*args)
259
+ expect(new_notification.data['data']).to be_truthy
260
+ end
261
+
262
+ it 'sets the given registration IDs' do
263
+ new_notification = store.create_gcm_notification(*args)
264
+ expect(new_notification.registration_ids).to eq registration_ids
265
+ end
266
+
267
+ it 'sets the deliver_after timestamp' do
268
+ new_notification = store.create_gcm_notification(*args)
269
+ expect(new_notification.deliver_after).to eq deliver_after
270
+ end
271
+
272
+ it 'saves the new notification' do
273
+ new_notification = store.create_gcm_notification(*args)
274
+ expect(new_notification.new_record?).to be_falsey
275
+ end
276
+ end
277
+
278
+ describe 'create_adm_notification' do
279
+ let(:data) { { 'data' => true } }
280
+ let(:attributes) { { app_id: app.id, collapse_key: 'ckey', delay_while_idle: true } }
281
+ let(:registration_ids) { %w[123 456] }
282
+ let(:deliver_after) { time + 10.seconds }
283
+ let(:args) { [attributes, data, registration_ids, deliver_after, app] }
284
+
285
+ it 'sets the given attributes' do
286
+ new_notification = store.create_adm_notification(*args)
287
+ expect(new_notification.app_id).to eq app.id
288
+ expect(new_notification.collapse_key).to eq 'ckey'
289
+ expect(new_notification.delay_while_idle).to be_truthy
290
+ end
291
+
292
+ it 'sets the given data' do
293
+ new_notification = store.create_adm_notification(*args)
294
+ expect(new_notification.data['data']).to be_truthy
295
+ end
296
+
297
+ it 'sets the given registration IDs' do
298
+ new_notification = store.create_adm_notification(*args)
299
+ expect(new_notification.registration_ids).to eq registration_ids
300
+ end
301
+
302
+ it 'sets the deliver_after timestamp' do
303
+ new_notification = store.create_adm_notification(*args)
304
+ expect(new_notification.deliver_after.to_s).to eq deliver_after.to_s
305
+ end
306
+
307
+ it 'saves the new notification' do
308
+ new_notification = store.create_adm_notification(*args)
309
+ expect(new_notification.new_record?).to be_falsey
310
+ end
311
+ end
312
+ end
@@ -80,8 +80,8 @@ describe Rpush::Daemon::Store::ActiveRecord::Reconnectable do
80
80
  test_doubles.each(&:perform)
81
81
  end
82
82
 
83
- it "should test out the new connection by performing a count" do
84
- expect(Rpush::Client::ActiveRecord::Notification).to receive(:count).twice
83
+ it "should test out the new connection by performing an exists" do
84
+ expect(Rpush::Client::ActiveRecord::Notification).to receive(:exists?).twice
85
85
  test_doubles.each(&:perform)
86
86
  end
87
87
 
@@ -118,13 +118,13 @@ describe Rpush::Daemon::Store::ActiveRecord::Reconnectable do
118
118
  context "when the reconnection attempt is not successful" do
119
119
  before do
120
120
  class << Rpush::Client::ActiveRecord::Notification
121
- def count
122
- @count_calls += 1
123
- return if @count_calls == 2
121
+ def exists?
122
+ @exists_calls += 1
123
+ return if @exists_calls == 2
124
124
  fail @error
125
125
  end
126
126
  end
127
- Rpush::Client::ActiveRecord::Notification.instance_variable_set("@count_calls", 0)
127
+ Rpush::Client::ActiveRecord::Notification.instance_variable_set("@exists_calls", 0)
128
128
  Rpush::Client::ActiveRecord::Notification.instance_variable_set("@error", error)
129
129
  end
130
130
 
@@ -152,7 +152,7 @@ describe Rpush::Daemon::Store::ActiveRecord::Reconnectable do
152
152
  end
153
153
 
154
154
  it "should log errors raised when the reconnection is not successful" do
155
- expect(Rpush.logger).to receive(:error).with(error)
155
+ expect(Rpush.logger).to receive(:error).with(timeout)
156
156
  test_doubles[1].perform
157
157
  end
158
158