rapns 2.0.5 → 3.0.0.beta.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.
- data/lib/generators/rapns_generator.rb +1 -0
- data/lib/generators/templates/add_gcm.rb +86 -0
- data/lib/generators/templates/create_rapns_notifications.rb +1 -1
- data/lib/rapns/apns/app.rb +8 -0
- data/lib/rapns/apns/binary_notification_validator.rb +12 -0
- data/lib/rapns/apns/device_token_format_validator.rb +12 -0
- data/lib/rapns/apns/feedback.rb +14 -0
- data/lib/rapns/apns/notification.rb +84 -0
- data/lib/rapns/app.rb +5 -6
- data/lib/rapns/{config.rb → configuration.rb} +5 -5
- data/lib/rapns/daemon/apns/app_runner.rb +36 -0
- data/lib/rapns/daemon/apns/connection.rb +113 -0
- data/lib/rapns/daemon/apns/delivery.rb +63 -0
- data/lib/rapns/daemon/apns/delivery_handler.rb +21 -0
- data/lib/rapns/daemon/apns/disconnection_error.rb +20 -0
- data/lib/rapns/daemon/apns/feedback_receiver.rb +74 -0
- data/lib/rapns/daemon/app_runner.rb +76 -77
- data/lib/rapns/daemon/database_reconnectable.rb +3 -3
- data/lib/rapns/daemon/delivery.rb +43 -0
- data/lib/rapns/daemon/delivery_error.rb +6 -2
- data/lib/rapns/daemon/delivery_handler.rb +13 -79
- data/lib/rapns/daemon/delivery_queue_18.rb +2 -2
- data/lib/rapns/daemon/delivery_queue_19.rb +3 -3
- data/lib/rapns/daemon/feeder.rb +5 -5
- data/lib/rapns/daemon/gcm/app_runner.rb +13 -0
- data/lib/rapns/daemon/gcm/delivery.rb +206 -0
- data/lib/rapns/daemon/gcm/delivery_handler.rb +20 -0
- data/lib/rapns/daemon.rb +31 -20
- data/lib/rapns/gcm/app.rb +7 -0
- data/lib/rapns/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +11 -0
- data/lib/rapns/gcm/notification.rb +31 -0
- data/lib/rapns/gcm/payload_size_validator.rb +13 -0
- data/lib/rapns/multi_json_helper.rb +16 -0
- data/lib/rapns/notification.rb +28 -95
- data/lib/rapns/version.rb +1 -1
- data/lib/rapns.rb +14 -4
- data/lib/tasks/cane.rake +19 -0
- data/lib/tasks/test.rake +34 -0
- data/spec/acceptance/gcm_upgrade_spec.rb +34 -0
- data/spec/acceptance_spec_helper.rb +85 -0
- data/spec/support/simplecov_helper.rb +13 -0
- data/spec/support/simplecov_quality_formatter.rb +8 -0
- data/spec/unit/apns/app_spec.rb +15 -0
- data/spec/unit/apns/feedback_spec.rb +12 -0
- data/spec/{rapns → unit/apns}/notification_spec.rb +44 -72
- data/spec/unit/app_spec.rb +18 -0
- data/spec/unit/daemon/apns/app_runner_spec.rb +37 -0
- data/spec/{rapns/daemon → unit/daemon/apns}/connection_spec.rb +9 -9
- data/spec/unit/daemon/apns/delivery_handler_spec.rb +48 -0
- data/spec/unit/daemon/apns/delivery_spec.rb +154 -0
- data/spec/{rapns/daemon → unit/daemon/apns}/feedback_receiver_spec.rb +14 -14
- data/spec/unit/daemon/app_runner_shared.rb +66 -0
- data/spec/unit/daemon/app_runner_spec.rb +78 -0
- data/spec/{rapns → unit}/daemon/database_reconnectable_spec.rb +4 -5
- data/spec/{rapns → unit}/daemon/delivery_error_spec.rb +2 -2
- data/spec/unit/daemon/delivery_handler_shared.rb +19 -0
- data/spec/{rapns → unit}/daemon/delivery_queue_spec.rb +1 -1
- data/spec/{rapns → unit}/daemon/feeder_spec.rb +33 -33
- data/spec/unit/daemon/gcm/app_runner_spec.rb +15 -0
- data/spec/unit/daemon/gcm/delivery_handler_spec.rb +36 -0
- data/spec/unit/daemon/gcm/delivery_spec.rb +236 -0
- data/spec/{rapns → unit}/daemon/interruptible_sleep_spec.rb +1 -1
- data/spec/{rapns → unit}/daemon/logger_spec.rb +1 -1
- data/spec/{rapns → unit}/daemon_spec.rb +1 -1
- data/spec/unit/gcm/app_spec.rb +5 -0
- data/spec/unit/gcm/notification_spec.rb +55 -0
- data/spec/unit/notification_shared.rb +38 -0
- data/spec/unit/notification_spec.rb +6 -0
- data/spec/{rapns/app_spec.rb → unit_spec_helper.rb} +76 -16
- metadata +107 -45
- data/lib/rapns/binary_notification_validator.rb +0 -10
- data/lib/rapns/daemon/connection.rb +0 -114
- data/lib/rapns/daemon/delivery_handler_pool.rb +0 -18
- data/lib/rapns/daemon/disconnection_error.rb +0 -14
- data/lib/rapns/daemon/feedback_receiver.rb +0 -82
- data/lib/rapns/device_token_format_validator.rb +0 -10
- data/lib/rapns/feedback.rb +0 -12
- data/spec/rapns/daemon/app_runner_spec.rb +0 -193
- data/spec/rapns/daemon/delivery_handler_pool_spec.rb +0 -17
- data/spec/rapns/daemon/delivery_handler_spec.rb +0 -206
- data/spec/rapns/feedback_spec.rb +0 -12
- data/spec/spec_helper.rb +0 -78
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
ENV['RAILS_ENV'] = 'test'
|
5
|
+
require 'bundler'
|
6
|
+
Bundler.require(:default)
|
7
|
+
|
8
|
+
TMP_DIR = '/tmp'
|
9
|
+
RAILS_DIR = File.join(TMP_DIR, 'rapns_test')
|
10
|
+
if ENV['TRAVIS']
|
11
|
+
TRAVIS_BRANCH = 'gcm'
|
12
|
+
RAPNS_ROOT = 'git://github.com/ileitch/rapns.git'
|
13
|
+
else
|
14
|
+
RAPNS_ROOT = File.expand_path(__FILE__ + '/../../')
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup_rails
|
18
|
+
return if $rails_is_setup
|
19
|
+
`rm -rf #{RAILS_DIR}`
|
20
|
+
FileUtils.mkdir_p(RAILS_DIR)
|
21
|
+
cmd("bundle exec rails new #{RAILS_DIR} --skip-bundle")
|
22
|
+
branch = `git branch | grep '\*'`.split(' ').last
|
23
|
+
in_test_rails do
|
24
|
+
cmd('echo "gem \'rake\'" >> Gemfile')
|
25
|
+
if ENV['TRAVIS']
|
26
|
+
cmd("echo \"gem 'rapns', :git => '#{RAPNS_ROOT}', :branch => '#{TRAVIS_BRANCH}'\" >> Gemfile")
|
27
|
+
else
|
28
|
+
cmd("echo \"gem 'rapns', :git => '#{RAPNS_ROOT}', :branch => '#{branch}'\" >> Gemfile")
|
29
|
+
end
|
30
|
+
|
31
|
+
cmd("bundle install")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def as_test_rails_db(env='development')
|
36
|
+
orig_config = ActiveRecord::Base.connection_config
|
37
|
+
begin
|
38
|
+
in_test_rails do
|
39
|
+
config = YAML.load_file('config/database.yml')
|
40
|
+
ActiveRecord::Base.establish_connection(config[env])
|
41
|
+
yield
|
42
|
+
end
|
43
|
+
ensure
|
44
|
+
ActiveRecord::Base.establish_connection(orig_config)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def cmd(str, echo = true)
|
49
|
+
puts "* #{str.strip}" if echo
|
50
|
+
retval = Bundler.with_clean_env { `#{str}` }
|
51
|
+
puts retval.strip if echo
|
52
|
+
retval
|
53
|
+
end
|
54
|
+
|
55
|
+
def generate
|
56
|
+
in_test_rails { cmd('bundle exec rails g rapns') }
|
57
|
+
end
|
58
|
+
|
59
|
+
def migrate(*migrations)
|
60
|
+
in_test_rails do
|
61
|
+
if migrations.present?
|
62
|
+
migrations.each do |name|
|
63
|
+
migration = Dir.entries('db/migrate').find { |entry| entry =~ /#{name}/ }
|
64
|
+
version = migration.split('_').first
|
65
|
+
cmd("bundle exec rake db:migrate VERSION=#{version} RAILS_ENV=development")
|
66
|
+
end
|
67
|
+
else
|
68
|
+
cmd('bundle exec rake db:migrate RAILS_ENV=development')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def in_test_rails
|
74
|
+
pwd = Dir.pwd
|
75
|
+
begin
|
76
|
+
Dir.chdir(RAILS_DIR)
|
77
|
+
yield
|
78
|
+
ensure
|
79
|
+
Dir.chdir(pwd)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def runner(str)
|
84
|
+
in_test_rails { cmd("rails runner -e test '#{str}'").strip }
|
85
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require './spec/support/simplecov_quality_formatter'
|
3
|
+
|
4
|
+
module SimpleCovHelper
|
5
|
+
def start_simple_cov(name)
|
6
|
+
SimpleCov.start do
|
7
|
+
add_filter '/spec/'
|
8
|
+
add_filter '/lib/generators'
|
9
|
+
command_name name
|
10
|
+
formatter SimpleCov::Formatter::QualityFormatter
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
describe Rapns::App do
|
4
|
+
it 'does not validate an app with an invalid certificate' do
|
5
|
+
app = Rapns::Apns::App.new(:key => 'test', :environment => 'development', :certificate => 'foo')
|
6
|
+
app.valid?
|
7
|
+
app.errors[:certificate].should == ['Certificate value must contain a certificate and a private key.']
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'validates a real certificate' do
|
11
|
+
app = Rapns::Apns::App.new :key => 'test', :environment => 'development', :certificate => TEST_CERT
|
12
|
+
app.valid?
|
13
|
+
app.errors[:certificate].should == []
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "unit_spec_helper"
|
2
|
+
|
3
|
+
describe Rapns::Apns::Feedback do
|
4
|
+
it { should validate_presence_of(:device_token) }
|
5
|
+
it { should validate_presence_of(:failed_at) }
|
6
|
+
|
7
|
+
it "should validate the format of the device_token" do
|
8
|
+
notification = Rapns::Apns::Feedback.new(:device_token => "{$%^&*()}")
|
9
|
+
notification.valid?.should be_false
|
10
|
+
notification.errors[:device_token].include?("is invalid").should be_true
|
11
|
+
end
|
12
|
+
end
|
@@ -1,19 +1,24 @@
|
|
1
|
-
require "
|
1
|
+
require "unit_spec_helper"
|
2
|
+
require 'unit/notification_shared.rb'
|
3
|
+
|
4
|
+
describe Rapns::Apns::Notification do
|
5
|
+
it_should_behave_like 'an Notification subclass'
|
2
6
|
|
3
|
-
describe Rapns::Notification do
|
4
|
-
it { should validate_presence_of(:app) }
|
5
7
|
it { should validate_presence_of(:device_token) }
|
6
8
|
it { should validate_numericality_of(:badge) }
|
7
|
-
|
9
|
+
|
10
|
+
let(:notification_class) { Rapns::Apns::Notification }
|
11
|
+
let(:notification) { notification_class.new }
|
12
|
+
let(:data_setter) { 'attributes_for_device=' }
|
13
|
+
let(:data_getter) { 'attributes_for_device' }
|
8
14
|
|
9
15
|
it "should validate the format of the device_token" do
|
10
|
-
notification = Rapns::Notification.new(:device_token => "{$%^&*()}")
|
16
|
+
notification = Rapns::Apns::Notification.new(:device_token => "{$%^&*()}")
|
11
17
|
notification.valid?.should be_false
|
12
18
|
notification.errors[:device_token].include?("is invalid").should be_true
|
13
19
|
end
|
14
20
|
|
15
21
|
it "should validate the length of the binary conversion of the notification" do
|
16
|
-
notification = Rapns::Notification.new
|
17
22
|
notification.device_token = "a" * 64
|
18
23
|
notification.alert = "way too long!" * 100
|
19
24
|
notification.valid?.should be_false
|
@@ -21,90 +26,73 @@ describe Rapns::Notification do
|
|
21
26
|
end
|
22
27
|
|
23
28
|
it "should default the sound to 1.aiff" do
|
24
|
-
|
29
|
+
notification.sound.should == "1.aiff"
|
25
30
|
end
|
26
31
|
|
27
32
|
it "should default the expiry to 1 day" do
|
28
|
-
|
33
|
+
notification.expiry.should == 1.day.to_i
|
29
34
|
end
|
30
35
|
end
|
31
36
|
|
32
|
-
describe Rapns::Notification, "when assigning the device token" do
|
37
|
+
describe Rapns::Apns::Notification, "when assigning the device token" do
|
33
38
|
it "should strip spaces from the given string" do
|
34
|
-
notification = Rapns::Notification.new(:device_token => "o m g")
|
39
|
+
notification = Rapns::Apns::Notification.new(:device_token => "o m g")
|
35
40
|
notification.device_token.should == "omg"
|
36
41
|
end
|
37
42
|
|
38
43
|
it "should strip chevrons from the given string" do
|
39
|
-
notification = Rapns::Notification.new(:device_token => "<omg>")
|
44
|
+
notification = Rapns::Apns::Notification.new(:device_token => "<omg>")
|
40
45
|
notification.device_token.should == "omg"
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
44
|
-
describe Rapns::Notification, "
|
45
|
-
it "should raise an ArgumentError if something other than a Hash is assigned" do
|
46
|
-
expect { Rapns::Notification.new(:attributes_for_device => Array.new) }.to \
|
47
|
-
raise_error(ArgumentError, "attributes_for_device must be a Hash")
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should encode the given Hash as JSON" do
|
51
|
-
notification = Rapns::Notification.new(:attributes_for_device => {:hi => "mom"})
|
52
|
-
notification.read_attribute(:attributes_for_device).should == "{\"hi\":\"mom\"}"
|
53
|
-
end
|
54
|
-
|
55
|
-
it "should decode the JSON when using the reader method" do
|
56
|
-
notification = Rapns::Notification.new(:attributes_for_device => {:hi => "mom"})
|
57
|
-
notification.attributes_for_device.should == {"hi" => "mom"}
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe Rapns::Notification, "as_json" do
|
49
|
+
describe Rapns::Apns::Notification, "as_json" do
|
62
50
|
it "should include the alert if present" do
|
63
|
-
notification = Rapns::Notification.new(:alert => "hi mom")
|
51
|
+
notification = Rapns::Apns::Notification.new(:alert => "hi mom")
|
64
52
|
notification.as_json["aps"]["alert"].should == "hi mom"
|
65
53
|
end
|
66
54
|
|
67
55
|
it "should not include the alert key if the alert is not present" do
|
68
|
-
notification = Rapns::Notification.new(:alert => nil)
|
56
|
+
notification = Rapns::Apns::Notification.new(:alert => nil)
|
69
57
|
notification.as_json["aps"].key?("alert").should be_false
|
70
58
|
end
|
71
59
|
|
72
60
|
it "should encode the alert as JSON if it is a Hash" do
|
73
|
-
notification = Rapns::Notification.new(:alert => { 'body' => "hi mom", 'alert-loc-key' => "View" })
|
61
|
+
notification = Rapns::Apns::Notification.new(:alert => { 'body' => "hi mom", 'alert-loc-key' => "View" })
|
74
62
|
notification.as_json["aps"]["alert"].should == { 'body' => "hi mom", 'alert-loc-key' => "View" }
|
75
63
|
end
|
76
64
|
|
77
65
|
it "should include the badge if present" do
|
78
|
-
notification = Rapns::Notification.new(:badge => 6)
|
66
|
+
notification = Rapns::Apns::Notification.new(:badge => 6)
|
79
67
|
notification.as_json["aps"]["badge"].should == 6
|
80
68
|
end
|
81
69
|
|
82
70
|
it "should not include the badge key if the badge is not present" do
|
83
|
-
notification = Rapns::Notification.new(:badge => nil)
|
71
|
+
notification = Rapns::Apns::Notification.new(:badge => nil)
|
84
72
|
notification.as_json["aps"].key?("badge").should be_false
|
85
73
|
end
|
86
74
|
|
87
75
|
it "should include the sound if present" do
|
88
|
-
notification = Rapns::Notification.new(:alert => "my_sound.aiff")
|
76
|
+
notification = Rapns::Apns::Notification.new(:alert => "my_sound.aiff")
|
89
77
|
notification.as_json["aps"]["alert"].should == "my_sound.aiff"
|
90
78
|
end
|
91
79
|
|
92
80
|
it "should not include the sound key if the sound is not present" do
|
93
|
-
notification = Rapns::Notification.new(:sound => false)
|
81
|
+
notification = Rapns::Apns::Notification.new(:sound => false)
|
94
82
|
notification.as_json["aps"].key?("sound").should be_false
|
95
83
|
end
|
96
84
|
|
97
|
-
it "should include
|
98
|
-
notification = Rapns::Notification.new
|
85
|
+
it "should include attributes for the device" do
|
86
|
+
notification = Rapns::Apns::Notification.new
|
99
87
|
notification.attributes_for_device = {:omg => :lol, :wtf => :dunno}
|
100
88
|
notification.as_json["omg"].should == "lol"
|
101
89
|
notification.as_json["wtf"].should == "dunno"
|
102
90
|
end
|
103
91
|
end
|
104
92
|
|
105
|
-
describe Rapns::Notification, 'MDM' do
|
93
|
+
describe Rapns::Apns::Notification, 'MDM' do
|
106
94
|
let(:magic) { 'abc123' }
|
107
|
-
let(:notification) { Rapns::Notification.new }
|
95
|
+
let(:notification) { Rapns::Apns::Notification.new }
|
108
96
|
|
109
97
|
it 'includes the mdm magic in the payload' do
|
110
98
|
notification.mdm = magic
|
@@ -118,8 +106,8 @@ describe Rapns::Notification, 'MDM' do
|
|
118
106
|
end
|
119
107
|
end
|
120
108
|
|
121
|
-
describe Rapns::Notification, 'content-available' do
|
122
|
-
let(:notification) { Rapns::Notification.new }
|
109
|
+
describe Rapns::Apns::Notification, 'content-available' do
|
110
|
+
let(:notification) { Rapns::Apns::Notification.new }
|
123
111
|
|
124
112
|
it 'includes content-available in the payload' do
|
125
113
|
notification.content_available = true
|
@@ -136,43 +124,43 @@ describe Rapns::Notification, 'content-available' do
|
|
136
124
|
end
|
137
125
|
end
|
138
126
|
|
139
|
-
describe Rapns::Notification, "to_binary" do
|
127
|
+
describe Rapns::Apns::Notification, "to_binary" do
|
140
128
|
it "should correctly convert the notification to binary" do
|
141
|
-
notification = Rapns::Notification.new
|
129
|
+
notification = Rapns::Apns::Notification.new
|
142
130
|
notification.device_token = "a" * 64
|
143
131
|
notification.sound = "1.aiff"
|
144
132
|
notification.badge = 3
|
145
133
|
notification.alert = "Don't panic Mr Mainwaring, don't panic!"
|
146
134
|
notification.attributes_for_device = {:hi => :mom}
|
147
135
|
notification.expiry = 86400 # 1 day, \x00\x01Q\x80
|
148
|
-
notification.app = 'my_app'
|
136
|
+
notification.app = Rapns::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT)
|
149
137
|
notification.save!
|
150
138
|
notification.stub(:id).and_return(1234)
|
151
139
|
notification.to_binary.should == "\x01\x00\x00\x04\xD2\x00\x01Q\x80\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\x00a{\"aps\":{\"alert\":\"Don't panic Mr Mainwaring, don't panic!\",\"badge\":3,\"sound\":\"1.aiff\"},\"hi\":\"mom\"}"
|
152
140
|
end
|
153
141
|
end
|
154
142
|
|
155
|
-
describe Rapns::Notification, "bug #31" do
|
143
|
+
describe Rapns::Apns::Notification, "bug #31" do
|
156
144
|
it 'does not confuse a JSON looking string as JSON' do
|
157
|
-
notification = Rapns::Notification.new
|
145
|
+
notification = Rapns::Apns::Notification.new
|
158
146
|
notification.alert = "{\"one\":2}"
|
159
147
|
notification.alert.should == "{\"one\":2}"
|
160
148
|
end
|
161
149
|
|
162
150
|
it 'does confuse a JSON looking string as JSON if the alert_is_json attribute is not present' do
|
163
|
-
notification = Rapns::Notification.new
|
151
|
+
notification = Rapns::Apns::Notification.new
|
164
152
|
notification.stub(:has_attribute? => false)
|
165
153
|
notification.alert = "{\"one\":2}"
|
166
154
|
notification.alert.should == {"one" => 2}
|
167
155
|
end
|
168
156
|
end
|
169
157
|
|
170
|
-
describe Rapns::Notification, "bug #35" do
|
158
|
+
describe Rapns::Apns::Notification, "bug #35" do
|
171
159
|
it "should limit payload size to 256 bytes but not the entire packet" do
|
172
|
-
notification = Rapns::Notification.new do |n|
|
160
|
+
notification = Rapns::Apns::Notification.new do |n|
|
173
161
|
n.device_token = "a" * 64
|
174
162
|
n.alert = "a" * 210
|
175
|
-
n.app = 'my_app'
|
163
|
+
n.app = Rapns::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT)
|
176
164
|
end
|
177
165
|
|
178
166
|
notification.to_binary(:for_validation => true).bytesize.should > 256
|
@@ -181,36 +169,20 @@ describe Rapns::Notification, "bug #35" do
|
|
181
169
|
end
|
182
170
|
end
|
183
171
|
|
184
|
-
describe Rapns::Notification, "multi_json usage" do
|
185
|
-
describe Rapns::Notification, "alert" do
|
172
|
+
describe Rapns::Apns::Notification, "multi_json usage" do
|
173
|
+
describe Rapns::Apns::Notification, "alert" do
|
186
174
|
it "should call MultiJson.load when multi_json version is 1.3.0" do
|
187
|
-
notification = Rapns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
|
175
|
+
notification = Rapns::Apns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
|
188
176
|
Gem.stub(:loaded_specs).and_return( { 'multi_json' => Gem::Specification.new('multi_json', '1.3.0') } )
|
189
177
|
MultiJson.should_receive(:load).with(any_args())
|
190
178
|
notification.alert
|
191
179
|
end
|
192
180
|
|
193
181
|
it "should call MultiJson.decode when multi_json version is 1.2.9" do
|
194
|
-
notification = Rapns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
|
182
|
+
notification = Rapns::Apns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
|
195
183
|
Gem.stub(:loaded_specs).and_return( { 'multi_json' => Gem::Specification.new('multi_json', '1.2.9') } )
|
196
184
|
MultiJson.should_receive(:decode).with(any_args())
|
197
185
|
notification.alert
|
198
186
|
end
|
199
187
|
end
|
200
|
-
|
201
|
-
describe Rapns::Notification, "attributes_for_device=" do
|
202
|
-
it "should call MultiJson.dump when multi_json responds to :dump" do
|
203
|
-
notification = Rapns::Notification.new
|
204
|
-
MultiJson.stub(:respond_to?).with(:dump).and_return(true)
|
205
|
-
MultiJson.should_receive(:dump).with(any_args())
|
206
|
-
notification.attributes_for_device = { :pirates => 1 }
|
207
|
-
end
|
208
|
-
|
209
|
-
it "should call MultiJson.encode when multi_json does not respond to :dump" do
|
210
|
-
notification = Rapns::Notification.new
|
211
|
-
MultiJson.stub(:respond_to?).with(:dump).and_return(false)
|
212
|
-
MultiJson.should_receive(:encode).with(any_args())
|
213
|
-
notification.attributes_for_device = { :ninjas => 1 }
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|
188
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "unit_spec_helper"
|
2
|
+
|
3
|
+
describe Rapns::App do
|
4
|
+
it { should validate_numericality_of(:connections) }
|
5
|
+
|
6
|
+
it 'validates the uniqueness of name within type and environment' do
|
7
|
+
Rapns::Apns::App.create!(:name => 'test', :environment => 'production', :certificate => TEST_CERT)
|
8
|
+
app = Rapns::Apns::App.new(:name => 'test', :environment => 'production', :certificate => TEST_CERT)
|
9
|
+
app.valid?.should be_false
|
10
|
+
app.errors[:name].should == ['has already been taken']
|
11
|
+
|
12
|
+
app = Rapns::Apns::App.new(:name => 'test', :environment => 'development', :certificate => TEST_CERT)
|
13
|
+
app.valid?.should be_true
|
14
|
+
|
15
|
+
app = Rapns::Gcm::App.new(:name => 'test', :environment => 'production', :auth_key => TEST_CERT)
|
16
|
+
app.valid?.should be_true
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/../app_runner_shared.rb'
|
3
|
+
|
4
|
+
describe Rapns::Daemon::Apns::AppRunner do
|
5
|
+
it_behaves_like 'an AppRunner subclass'
|
6
|
+
|
7
|
+
let(:app_class) { Rapns::Apns::App }
|
8
|
+
let(:app) { app_class.create!(:name => 'my_app', :environment => 'development',
|
9
|
+
:certificate => TEST_CERT, :password => 'pass') }
|
10
|
+
let(:runner) { Rapns::Daemon::Apns::AppRunner.new(app) }
|
11
|
+
let(:handler) { stub(:start => nil, :stop => nil, :queue= => nil) }
|
12
|
+
let(:receiver) { stub(:start => nil, :stop => nil) }
|
13
|
+
let(:config) { {:feedback_poll => 60 } }
|
14
|
+
|
15
|
+
before do
|
16
|
+
Rapns::Daemon::Apns::DeliveryHandler.stub(:new => handler)
|
17
|
+
Rapns::Daemon::Apns::FeedbackReceiver.stub(:new => receiver)
|
18
|
+
Rapns::Daemon.stub(:config => config)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'instantiates a new feedback receiver when started' do
|
22
|
+
Rapns::Daemon::Apns::FeedbackReceiver.should_receive(:new).with(app, 'feedback.sandbox.push.apple.com',
|
23
|
+
2196, 60)
|
24
|
+
runner.start
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'starts the feedback receiver' do
|
28
|
+
receiver.should_receive(:start)
|
29
|
+
runner.start
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'stops the feedback receiver' do
|
33
|
+
runner.start
|
34
|
+
receiver.should_receive(:stop)
|
35
|
+
runner.stop
|
36
|
+
end
|
37
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require "
|
1
|
+
require "unit_spec_helper"
|
2
2
|
|
3
|
-
describe Rapns::Daemon::Connection do
|
3
|
+
describe Rapns::Daemon::Apns::Connection do
|
4
4
|
let(:ssl_context) { stub(:key= => nil, :cert= => nil) }
|
5
5
|
let(:rsa_key) { stub }
|
6
6
|
let(:certificate) { stub }
|
@@ -11,7 +11,7 @@ describe Rapns::Daemon::Connection do
|
|
11
11
|
let(:tcp_socket) { stub(:setsockopt => nil, :close => nil) }
|
12
12
|
let(:ssl_socket) { stub(:sync= => nil, :connect => nil, :close => nil, :write => nil, :flush => nil) }
|
13
13
|
let(:logger) { stub(:info => nil, :error => nil) }
|
14
|
-
let(:connection) { Rapns::Daemon::Connection.new('Connection 0', host, port, certificate, password) }
|
14
|
+
let(:connection) { Rapns::Daemon::Apns::Connection.new('Connection 0', host, port, certificate, password) }
|
15
15
|
|
16
16
|
before do
|
17
17
|
OpenSSL::SSL::SSLContext.stub(:new => ssl_context)
|
@@ -125,7 +125,7 @@ describe Rapns::Daemon::Connection do
|
|
125
125
|
logger.should_receive(:error).with("[Connection 0] Lost connection to gateway.push.apple.com:2195 (#{error_type.name}), reconnecting...").once
|
126
126
|
begin
|
127
127
|
connection.write(nil)
|
128
|
-
rescue Rapns::Daemon::ConnectionError
|
128
|
+
rescue Rapns::Daemon::Apns::ConnectionError
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
@@ -133,21 +133,21 @@ describe Rapns::Daemon::Connection do
|
|
133
133
|
connection.should_receive(:reconnect).exactly(3).times
|
134
134
|
begin
|
135
135
|
connection.write(nil)
|
136
|
-
rescue Rapns::Daemon::ConnectionError
|
136
|
+
rescue Rapns::Daemon::Apns::ConnectionError
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
140
|
it "raises a ConnectionError after 3 attempts at reconnecting" do
|
141
141
|
expect do
|
142
142
|
connection.write(nil)
|
143
|
-
end.to raise_error(Rapns::Daemon::ConnectionError, "Connection 0 tried 3 times to reconnect but failed (#{error_type.name}).")
|
143
|
+
end.to raise_error(Rapns::Daemon::Apns::ConnectionError, "Connection 0 tried 3 times to reconnect but failed (#{error_type.name}).")
|
144
144
|
end
|
145
145
|
|
146
146
|
it "sleeps 1 second before retrying the connection" do
|
147
147
|
connection.should_receive(:sleep).with(1)
|
148
148
|
begin
|
149
149
|
connection.write(nil)
|
150
|
-
rescue Rapns::Daemon::ConnectionError
|
150
|
+
rescue Rapns::Daemon::Apns::ConnectionError
|
151
151
|
end
|
152
152
|
end
|
153
153
|
end
|
@@ -206,7 +206,7 @@ describe Rapns::Daemon::Connection do
|
|
206
206
|
before { connection.connect }
|
207
207
|
|
208
208
|
it 'reconnects if the connection has been idle for more than the defined period' do
|
209
|
-
Rapns::Daemon::Connection.stub(:idle_period => 0.1)
|
209
|
+
Rapns::Daemon::Apns::Connection.stub(:idle_period => 0.1)
|
210
210
|
sleep 0.2
|
211
211
|
connection.should_receive(:reconnect)
|
212
212
|
connection.write('blah')
|
@@ -225,7 +225,7 @@ describe Rapns::Daemon::Connection do
|
|
225
225
|
end
|
226
226
|
|
227
227
|
it 'logs the the connection is idle' do
|
228
|
-
Rapns::Daemon::Connection.stub(:idle_period => 0.1)
|
228
|
+
Rapns::Daemon::Apns::Connection.stub(:idle_period => 0.1)
|
229
229
|
sleep 0.2
|
230
230
|
Rapns::Daemon.logger.should_receive(:info).with('[Connection 0] Idle period exceeded, reconnecting...')
|
231
231
|
connection.write('blah')
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/../delivery_handler_shared.rb'
|
3
|
+
|
4
|
+
describe Rapns::Daemon::Apns::DeliveryHandler do
|
5
|
+
it_should_behave_like 'an DeliveryHandler subclass'
|
6
|
+
|
7
|
+
let(:host) { 'localhost' }
|
8
|
+
let(:port) { 2195 }
|
9
|
+
let(:certificate) { stub }
|
10
|
+
let(:password) { stub }
|
11
|
+
let(:app) { stub(:password => password, :certificate => certificate, :name => 'MyApp')}
|
12
|
+
let(:delivery_handler) { Rapns::Daemon::Apns::DeliveryHandler.new(app, host, port) }
|
13
|
+
let(:connection) { stub('Connection', :select => false, :write => nil, :reconnect => nil, :close => nil, :connect => nil) }
|
14
|
+
let(:notification) { stub }
|
15
|
+
let(:http) { stub(:shutdown => nil)}
|
16
|
+
let(:queue) { Rapns::Daemon::DeliveryQueue.new }
|
17
|
+
|
18
|
+
before do
|
19
|
+
Rapns::Daemon::Apns::Connection.stub(:new => connection)
|
20
|
+
Rapns::Daemon::Apns::Delivery.stub(:perform)
|
21
|
+
delivery_handler.queue = queue
|
22
|
+
queue.push(notification)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "instantiates a new connection" do
|
26
|
+
Rapns::Daemon::Apns::Connection.should_receive(:new).with(app.name, host, port, certificate, password)
|
27
|
+
Rapns::Daemon::Apns::DeliveryHandler.new(app, host, port)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'performs delivery of an notification' do
|
31
|
+
Rapns::Daemon::Apns::Delivery.should_receive(:perform).with(app, connection, notification)
|
32
|
+
delivery_handler.start
|
33
|
+
delivery_handler.stop
|
34
|
+
end
|
35
|
+
|
36
|
+
it "connects the socket when instantiated" do
|
37
|
+
connection.should_receive(:connect)
|
38
|
+
Rapns::Daemon::Apns::DeliveryHandler.new(app, host, port)
|
39
|
+
delivery_handler.start
|
40
|
+
delivery_handler.stop
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'closes the connection stopped' do
|
44
|
+
connection.should_receive(:close)
|
45
|
+
delivery_handler.start
|
46
|
+
delivery_handler.stop
|
47
|
+
end
|
48
|
+
end
|