rapns 0.1.0
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/README.md +105 -0
- data/bin/rapns +26 -0
- data/lib/generators/rapns_generator.rb +16 -0
- data/lib/generators/templates/create_rapns_notifications.rb +26 -0
- data/lib/generators/templates/rapns.yml +17 -0
- data/lib/rapns/binary_notification_validator.rb +10 -0
- data/lib/rapns/daemon/certificate.rb +27 -0
- data/lib/rapns/daemon/configuration.rb +69 -0
- data/lib/rapns/daemon/connection.rb +99 -0
- data/lib/rapns/daemon/connection_pool.rb +31 -0
- data/lib/rapns/daemon/delivery_error.rb +15 -0
- data/lib/rapns/daemon/delivery_handler.rb +53 -0
- data/lib/rapns/daemon/delivery_handler_pool.rb +24 -0
- data/lib/rapns/daemon/feeder.rb +31 -0
- data/lib/rapns/daemon/logger.rb +49 -0
- data/lib/rapns/daemon/pool.rb +41 -0
- data/lib/rapns/daemon.rb +76 -0
- data/lib/rapns/notification.rb +44 -0
- data/lib/rapns/version.rb +3 -0
- data/lib/rapns.rb +5 -0
- data/spec/rapns/daemon/certificate_spec.rb +16 -0
- data/spec/rapns/daemon/configuration_spec.rb +125 -0
- data/spec/rapns/daemon/connection_pool_spec.rb +40 -0
- data/spec/rapns/daemon/connection_spec.rb +247 -0
- data/spec/rapns/daemon/delivery_error_spec.rb +11 -0
- data/spec/rapns/daemon/delivery_handler_pool_spec.rb +26 -0
- data/spec/rapns/daemon/delivery_handler_spec.rb +110 -0
- data/spec/rapns/daemon/feeder_spec.rb +61 -0
- data/spec/rapns/daemon/logger_spec.rb +96 -0
- data/spec/rapns/daemon_spec.rb +141 -0
- data/spec/rapns/notification_spec.rb +112 -0
- data/spec/spec_helper.rb +25 -0
- metadata +91 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rapns::Daemon::DeliveryHandler do
|
4
|
+
before do
|
5
|
+
@notification = Rapns::Notification.create!(:device_token => "a" * 64)
|
6
|
+
Rapns::Daemon.stub(:delivery_queue).and_return(Queue.new)
|
7
|
+
Rapns::Daemon.delivery_queue.push(@notification)
|
8
|
+
@connection = mock("Connection", :connect => nil, :write => nil)
|
9
|
+
Rapns::Daemon::Connection.stub(:new).and_return(@connection)
|
10
|
+
@connection_pool = Rapns::Daemon::ConnectionPool.new(1)
|
11
|
+
@connection_pool.populate
|
12
|
+
Rapns::Daemon.stub(:connection_pool).and_return(@connection_pool)
|
13
|
+
@delivery_handler = Rapns::Daemon::DeliveryHandler.new
|
14
|
+
@logger = mock("Logger", :error => nil, :info => nil)
|
15
|
+
Rapns::Daemon.stub(:logger).and_return(@logger)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should pop a new notification from the delivery queue" do
|
19
|
+
Rapns::Daemon.delivery_queue.should_receive(:pop)
|
20
|
+
@delivery_handler.send(:handle_next_notification)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should claim a connection for the delivery" do
|
24
|
+
Rapns::Daemon.connection_pool.should_receive(:claim_connection)
|
25
|
+
@delivery_handler.send(:handle_next_notification)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should send the binary version of the notification" do
|
29
|
+
@notification.stub((:to_binary)).and_return("hi mom")
|
30
|
+
@connection.should_receive(:write).with("hi mom")
|
31
|
+
@delivery_handler.send(:handle_next_notification)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should log the notification delivery" do
|
35
|
+
Rapns::Daemon.logger.should_receive(:info).with("Notification #{@notification.id} delivered to #{@notification.device_token}")
|
36
|
+
@delivery_handler.send(:handle_next_notification)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should mark the notification as delivered" do
|
40
|
+
expect { @delivery_handler.send(:handle_next_notification); @notification.reload }.to change(@notification, :delivered).to(true)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should set the time the notification was delivered" do
|
44
|
+
@notification.delivered_at.should be_nil
|
45
|
+
@delivery_handler.send(:handle_next_notification)
|
46
|
+
@notification.reload
|
47
|
+
@notification.delivered_at.should be_kind_of(Time)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not trigger validations when saving the notification" do
|
51
|
+
@notification.should_receive(:save!).with(:validate => false)
|
52
|
+
@delivery_handler.send(:handle_next_notification)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should log if an error is raised when updating the notification" do
|
56
|
+
e = StandardError.new("bork!")
|
57
|
+
@notification.stub(:save!).and_raise(e)
|
58
|
+
Rapns::Daemon.logger.should_receive(:error).with(e)
|
59
|
+
@delivery_handler.send(:handle_next_notification)
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "when delivery fails" do
|
63
|
+
before do
|
64
|
+
@error = Rapns::DeliveryError.new(4, "Missing payload", 1)
|
65
|
+
@connection.stub(:write).and_raise(@error)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should set the notification as not delivered" do
|
69
|
+
@notification.should_receive(:delivered=).with(false)
|
70
|
+
@delivery_handler.send(:handle_next_notification)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should set the notification delivered_at timestamp to nil" do
|
74
|
+
@notification.should_receive(:delivered_at=).with(nil)
|
75
|
+
@delivery_handler.send(:handle_next_notification)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should set the notification as failed" do
|
79
|
+
@notification.should_receive(:failed=).with(true)
|
80
|
+
@delivery_handler.send(:handle_next_notification)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should set the notification failed_at timestamp" do
|
84
|
+
now = Time.now
|
85
|
+
Time.stub(:now).and_return(now)
|
86
|
+
@notification.should_receive(:failed_at=).with(now)
|
87
|
+
@delivery_handler.send(:handle_next_notification)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should set the notification error code" do
|
91
|
+
@notification.should_receive(:error_code=).with(4)
|
92
|
+
@delivery_handler.send(:handle_next_notification)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should log the delivery error" do
|
96
|
+
Rapns::Daemon.logger.should_receive(:error).with(@error)
|
97
|
+
@delivery_handler.send(:handle_next_notification)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should set the notification error description" do
|
101
|
+
@notification.should_receive(:error_description=).with("Missing payload")
|
102
|
+
@delivery_handler.send(:handle_next_notification)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should skip validation when saving the notification" do
|
106
|
+
@notification.should_receive(:save!).with(:validate => false)
|
107
|
+
@delivery_handler.send(:handle_next_notification)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rapns::Daemon::Feeder do
|
4
|
+
before do
|
5
|
+
Rapns::Daemon::Feeder.stub(:sleep)
|
6
|
+
@notification = Rapns::Notification.create!(:device_token => "a" * 64)
|
7
|
+
@logger = mock("Logger", :info => nil, :error => nil)
|
8
|
+
Rapns::Daemon.stub(:logger).and_return(@logger)
|
9
|
+
@queue = mock(:push => nil)
|
10
|
+
Rapns::Daemon.stub(:delivery_queue).and_return(@queue)
|
11
|
+
Rapns::Daemon.stub(:configuration => mock("Configuration", :poll => 2))
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should enqueue an undelivered notification" do
|
15
|
+
@notification.update_attributes!(:delivered => false)
|
16
|
+
Rapns::Daemon.delivery_queue.should_receive(:push)
|
17
|
+
Rapns::Daemon::Feeder.enqueue_notifications
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should enqueue an undelivered notification without deliver_after set" do
|
21
|
+
@notification.update_attributes!(:delivered => false, :deliver_after => nil)
|
22
|
+
Rapns::Daemon.delivery_queue.should_receive(:push)
|
23
|
+
Rapns::Daemon::Feeder.enqueue_notifications
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should enqueue a notification with a deliver_after time in the past" do
|
27
|
+
@notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.ago)
|
28
|
+
Rapns::Daemon.delivery_queue.should_receive(:push)
|
29
|
+
Rapns::Daemon::Feeder.enqueue_notifications
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not enqueue a notification with a deliver_after time in the future" do
|
33
|
+
@notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.from_now)
|
34
|
+
Rapns::Daemon.delivery_queue.should_not_receive(:push)
|
35
|
+
Rapns::Daemon::Feeder.enqueue_notifications
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not enqueue a previously delivered notification" do
|
39
|
+
@notification.update_attributes!(:delivered => true, :delivered_at => Time.now)
|
40
|
+
Rapns::Daemon.delivery_queue.should_not_receive(:push)
|
41
|
+
Rapns::Daemon::Feeder.enqueue_notifications
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not enqueue a notification that has previously failed delivery" do
|
45
|
+
@notification.update_attributes!(:delivered => false, :failed => true)
|
46
|
+
Rapns::Daemon.delivery_queue.should_not_receive(:push)
|
47
|
+
Rapns::Daemon::Feeder.enqueue_notifications
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should sleep for the given period" do
|
51
|
+
Rapns::Daemon::Feeder.should_receive(:sleep).with(2)
|
52
|
+
Rapns::Daemon::Feeder.enqueue_notifications
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should log errors" do
|
56
|
+
e = StandardError.new("bork")
|
57
|
+
Rapns::Notification.stub(:ready_for_delivery).and_raise(e)
|
58
|
+
Rapns::Daemon.logger.should_receive(:error).with(e)
|
59
|
+
Rapns::Daemon::Feeder.enqueue_notifications
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rapns::Daemon::Logger do
|
4
|
+
module Rails
|
5
|
+
def self.logger
|
6
|
+
@logger
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.logger=(logger)
|
10
|
+
@logger = logger
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module HoptoadNotifier
|
15
|
+
def self.notify(e)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Airbrake
|
20
|
+
def self.notify(e)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
before do
|
25
|
+
Rails.stub(:root).and_return("/rails_root")
|
26
|
+
@buffered_logger = mock("BufferedLogger", :info => nil, :error => nil, :level => 0, :auto_flushing => 1, :auto_flushing= => nil)
|
27
|
+
Rails.logger = @buffered_logger
|
28
|
+
ActiveSupport::BufferedLogger.stub(:new).and_return(@buffered_logger)
|
29
|
+
configuration = mock("Configuration", :airbrake_notify? => true)
|
30
|
+
Rapns::Daemon.stub(:configuration).and_return(configuration)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should open the a log file in the Rails log directory" do
|
34
|
+
ActiveSupport::BufferedLogger.should_receive(:new).with("/rails_root/log/rapns.log", Rails.logger.level)
|
35
|
+
Rapns::Daemon::Logger.new(:foreground => true)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should print out the msg if running in the foreground" do
|
39
|
+
logger = Rapns::Daemon::Logger.new(:foreground => true)
|
40
|
+
logger.should_receive(:puts).with(/hi mom/)
|
41
|
+
logger.info("hi mom")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not print out the msg if not running in the foreground" do
|
45
|
+
logger = Rapns::Daemon::Logger.new(:foreground => false)
|
46
|
+
logger.should_not_receive(:puts).with(/hi mom/)
|
47
|
+
logger.info("hi mom")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should prefix log lines with the current time" do
|
51
|
+
now = Time.now
|
52
|
+
Time.stub(:now).and_return(now)
|
53
|
+
logger = Rapns::Daemon::Logger.new(:foreground => false)
|
54
|
+
@buffered_logger.should_receive(:info).with(/#{Regexp.escape("[#{now.to_s(:db)}]")}/)
|
55
|
+
logger.info("blah")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should prefix error logs with the ERROR label" do
|
59
|
+
logger = Rapns::Daemon::Logger.new(:foreground => false)
|
60
|
+
@buffered_logger.should_receive(:error).with(/#{Regexp.escape("[ERROR]")}/)
|
61
|
+
logger.error("eeek")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should prefix warn logs with the WARNING label" do
|
65
|
+
logger = Rapns::Daemon::Logger.new(:foreground => false)
|
66
|
+
@buffered_logger.should_receive(:warn).with(/#{Regexp.escape("[WARNING]")}/)
|
67
|
+
logger.warn("eeek")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should handle an Exception instance" do
|
71
|
+
e = RuntimeError.new("hi mom")
|
72
|
+
logger = Rapns::Daemon::Logger.new(:foreground => false)
|
73
|
+
@buffered_logger.should_receive(:error).with(/RuntimeError, hi mom/)
|
74
|
+
logger.error(e)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should notify Airbrake of the exception" do
|
78
|
+
e = RuntimeError.new("hi mom")
|
79
|
+
logger = Rapns::Daemon::Logger.new(:foreground => false, :airbrake_notify => true)
|
80
|
+
Airbrake.should_receive(:notify).with(e)
|
81
|
+
logger.error(e)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should not notify Airbrake of the exception if the airbrake_notify option is false" do
|
85
|
+
e = RuntimeError.new("hi mom")
|
86
|
+
logger = Rapns::Daemon::Logger.new(:foreground => false, :airbrake_notify => false)
|
87
|
+
Airbrake.should_not_receive(:notify).with(e)
|
88
|
+
logger.error(e)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should not attempt to notify Airbrake of the error is not an Exception" do
|
92
|
+
logger = Rapns::Daemon::Logger.new(:foreground => false)
|
93
|
+
Airbrake.should_not_receive(:notify)
|
94
|
+
logger.error("string error message")
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rapns::Daemon, "when starting" do
|
4
|
+
module Rails
|
5
|
+
end
|
6
|
+
|
7
|
+
before do
|
8
|
+
Rails.stub(:root).and_return("/rails_root")
|
9
|
+
|
10
|
+
@configuration = Rapns::Daemon::Configuration.new("development", "/rails_root/config/rapns/rapns.yml")
|
11
|
+
@configuration.stub(:read_config).and_return({"development" => {"port" => 123, "host" => "localhost", "certificate" => "development.pem", "certificate_password" => "abc123"}})
|
12
|
+
Rapns::Daemon::Configuration.stub(:new).and_return(@configuration)
|
13
|
+
|
14
|
+
@certificate = Rapns::Daemon::Certificate.new("/rails_root/config/rapns/development.pem")
|
15
|
+
@certificate.stub(:read_certificate).and_return("certificate contents")
|
16
|
+
Rapns::Daemon::Certificate.stub(:new).and_return(@certificate)
|
17
|
+
|
18
|
+
@connection_pool = Rapns::Daemon::ConnectionPool.new(3)
|
19
|
+
@connection_pool.stub(:populate)
|
20
|
+
Rapns::Daemon::ConnectionPool.stub(:new).and_return(@connection_pool)
|
21
|
+
|
22
|
+
@handler_pool = Rapns::Daemon::DeliveryHandlerPool.new(3)
|
23
|
+
@handler_pool.stub(:populate)
|
24
|
+
Rapns::Daemon::DeliveryHandlerPool.stub(:new).and_return(@handler_pool)
|
25
|
+
|
26
|
+
Rapns::Daemon::Feeder.stub(:start)
|
27
|
+
Rapns::Daemon::Feeder.stub(:wait)
|
28
|
+
Rapns::Daemon.stub(:daemonize)
|
29
|
+
@logger = mock("Logger")
|
30
|
+
Rapns::Daemon::Logger.stub(:new).and_return(@logger)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should load the configuration" do
|
34
|
+
Rapns::Daemon::Configuration.should_receive(:new).with("development", "/rails_root/config/rapns/rapns.yml").and_return(@configuration)
|
35
|
+
@configuration.load
|
36
|
+
@configuration.should_receive(:load)
|
37
|
+
Rapns::Daemon.start("development", {})
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should make the configuration accessible" do
|
41
|
+
Rapns::Daemon.start("development", {})
|
42
|
+
Rapns::Daemon.configuration.should == @configuration
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should load the certificate" do
|
46
|
+
Rapns::Daemon::Certificate.should_receive(:new).with("/rails_root/config/rapns/development.pem").and_return(@certificate)
|
47
|
+
@certificate.should_receive(:load)
|
48
|
+
Rapns::Daemon.start("development", {})
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should make the certificate accessible" do
|
52
|
+
Rapns::Daemon.start("development", {})
|
53
|
+
Rapns::Daemon.certificate.should == @certificate
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should populate the connection pool" do
|
57
|
+
Rapns::Daemon::ConnectionPool.should_receive(:new).with(3).and_return(@connection_pool)
|
58
|
+
@connection_pool.should_receive(:populate)
|
59
|
+
Rapns::Daemon.start("development", {})
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should make the connection pool accessible" do
|
63
|
+
Rapns::Daemon.start("development", {})
|
64
|
+
Rapns::Daemon.connection_pool.should == @connection_pool
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should populate the delivery handler pool" do
|
68
|
+
Rapns::Daemon::DeliveryHandlerPool.should_receive(:new).with(3).and_return(@handler_pool)
|
69
|
+
@handler_pool.should_receive(:populate)
|
70
|
+
Rapns::Daemon.start("development", {})
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should make the delivery handler pool accessible" do
|
74
|
+
Rapns::Daemon.start("development", {})
|
75
|
+
Rapns::Daemon.delivery_handler_pool.should == @handler_pool
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should fork a child process if the foreground option is false" do
|
79
|
+
Rapns::Daemon.should_receive(:daemonize)
|
80
|
+
Rapns::Daemon.start("development", false)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should not fork a child process if the foreground option is true" do
|
84
|
+
Rapns::Daemon.should_not_receive(:daemonize)
|
85
|
+
Rapns::Daemon.start("development", true)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should start the feeder" do
|
89
|
+
Rapns::Daemon::Feeder.should_receive(:start)
|
90
|
+
Rapns::Daemon.start("development", true)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should setup the logger" do
|
94
|
+
Rapns::Daemon::Logger.should_receive(:new).with(:foreground => true, :airbrake_notify => true).and_return(@logger)
|
95
|
+
Rapns::Daemon.start("development", true)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should make the logger accessible" do
|
99
|
+
Rapns::Daemon::Logger.stub(:new).and_return(@logger)
|
100
|
+
Rapns::Daemon.start("development", true)
|
101
|
+
Rapns::Daemon.logger.should == @logger
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe Rapns::Daemon, "when being shutdown" do
|
106
|
+
before do
|
107
|
+
Rapns::Daemon::Feeder.stub(:stop)
|
108
|
+
@connection_pool = mock("ConnectionPool", :drain => nil)
|
109
|
+
Rapns::Daemon.stub(:connection_pool).and_return(@connection_pool)
|
110
|
+
@handler_pool = mock("DeliveryHandlerPool", :drain => nil)
|
111
|
+
Rapns::Daemon.stub(:delivery_handler_pool).and_return(@handler_pool)
|
112
|
+
Rapns::Daemon.stub(:puts)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should stop the feeder" do
|
116
|
+
Rapns::Daemon::Feeder.should_receive(:stop)
|
117
|
+
Rapns::Daemon.send(:shutdown)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should drain the connection pool" do
|
121
|
+
@connection_pool.should_receive(:drain)
|
122
|
+
Rapns::Daemon.send(:shutdown)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should not attempt to drain the connection pool if it has not been initialized" do
|
126
|
+
Rapns::Daemon.stub(:connection_pool).and_return(nil)
|
127
|
+
@connection_pool.should_not_receive(:drain)
|
128
|
+
Rapns::Daemon.send(:shutdown)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should drain the delivery handler pool" do
|
132
|
+
@handler_pool.should_receive(:drain)
|
133
|
+
Rapns::Daemon.send(:shutdown)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should not attempt to drain the delivery handler pool if it has not been initialized" do
|
137
|
+
Rapns::Daemon.stub(:delivery_handler_pool).and_return(nil)
|
138
|
+
@handler_pool.should_not_receive(:drain)
|
139
|
+
Rapns::Daemon.send(:shutdown)
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rapns::Notification do
|
4
|
+
it { should validate_presence_of(:device_token) }
|
5
|
+
it { should validate_numericality_of(:badge) }
|
6
|
+
it { should validate_numericality_of(:expiry) }
|
7
|
+
|
8
|
+
it "should validate the format of the device_token" do
|
9
|
+
notification = Rapns::Notification.new(:device_token => "{$%^&*()}")
|
10
|
+
notification.valid?.should be_false
|
11
|
+
notification.errors[:device_token].include?("is invalid").should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should validate the length of the binary conversion of the notification" do
|
15
|
+
notification = Rapns::Notification.new
|
16
|
+
notification.device_token = "a" * 64
|
17
|
+
notification.alert = "way too long!" * 100
|
18
|
+
notification.valid?.should be_false
|
19
|
+
notification.errors[:base].include?("APN notification cannot be larger than 256 bytes. Try condensing your alert and device attributes.").should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should default the sound to 1.aiff" do
|
23
|
+
Rapns::Notification.new.sound.should == "1.aiff"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should default the expiry to 1 day" do
|
27
|
+
Rapns::Notification.new.expiry.should == 1.day.to_i
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Rapns::Notification, "when assigning the device token" do
|
32
|
+
it "should strip spaces from the given string" do
|
33
|
+
notification = Rapns::Notification.new(:device_token => "o m g")
|
34
|
+
notification.device_token.should == "omg"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should strip chevrons from the given string" do
|
38
|
+
notification = Rapns::Notification.new(:device_token => "<omg>")
|
39
|
+
notification.device_token.should == "omg"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe Rapns::Notification, "when assigning the attributes for the device" do
|
44
|
+
it "should raise an ArgumentError if something other than a Hash is assigned" do
|
45
|
+
expect { Rapns::Notification.new(:attributes_for_device => Array.new) }.should
|
46
|
+
raise_error(ArgumentError, "attributes_for_device must be a Hash")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should encode the given Hash as JSON" do
|
50
|
+
notification = Rapns::Notification.new(:attributes_for_device => {:hi => "mom"})
|
51
|
+
notification.read_attribute(:attributes_for_device).should == "{\"hi\":\"mom\"}"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should decode the JSON when using the reader method" do
|
55
|
+
notification = Rapns::Notification.new(:attributes_for_device => {:hi => "mom"})
|
56
|
+
notification.attributes_for_device.should == {"hi" => "mom"}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe Rapns::Notification, "as_json" do
|
61
|
+
it "should include the alert if present" do
|
62
|
+
notification = Rapns::Notification.new(:alert => "hi mom")
|
63
|
+
notification.as_json["aps"]["alert"].should == "hi mom"
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not include the alert key if the alert is not present" do
|
67
|
+
notification = Rapns::Notification.new(:alert => nil)
|
68
|
+
notification.as_json["aps"].key?("alert").should be_false
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should include the badge if present" do
|
72
|
+
notification = Rapns::Notification.new(:badge => 6)
|
73
|
+
notification.as_json["aps"]["badge"].should == 6
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should not include the badge key if the badge is not present" do
|
77
|
+
notification = Rapns::Notification.new(:badge => nil)
|
78
|
+
notification.as_json["aps"].key?("badge").should be_false
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should include the sound if present" do
|
82
|
+
notification = Rapns::Notification.new(:alert => "my_sound.aiff")
|
83
|
+
notification.as_json["aps"]["alert"].should == "my_sound.aiff"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not include the sound key if the sound is not present" do
|
87
|
+
notification = Rapns::Notification.new(:sound => false)
|
88
|
+
notification.as_json["aps"].key?("sound").should be_false
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should include attrbutes for the device" do
|
92
|
+
notification = Rapns::Notification.new
|
93
|
+
notification.attributes_for_device = {:omg => :lol, :wtf => :dunno}
|
94
|
+
notification.as_json["omg"].should == "lol"
|
95
|
+
notification.as_json["wtf"].should == "dunno"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe Rapns::Notification, "to_binary" do
|
100
|
+
it "should correctly convert the notification to binary" do
|
101
|
+
notification = Rapns::Notification.new
|
102
|
+
notification.device_token = "a" * 64
|
103
|
+
notification.sound = "1.aiff"
|
104
|
+
notification.badge = 3
|
105
|
+
notification.alert = "Don't panic Mr Mainwaring, don't panic!"
|
106
|
+
notification.attributes_for_device = {:hi => :mom}
|
107
|
+
notification.expiry = 86400 # 1 day, \x00\x01Q\x80
|
108
|
+
notification.save!
|
109
|
+
notification.stub(:id).and_return(1234)
|
110
|
+
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\"}"
|
111
|
+
end
|
112
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
|
3
|
+
require "active_record"
|
4
|
+
|
5
|
+
ActiveRecord::Base.establish_connection("adapter" => "postgresql", "database" => "rapns_test")
|
6
|
+
require "generators/templates/create_rapns_notifications"
|
7
|
+
|
8
|
+
CreateRapnsNotifications.down rescue ActiveRecord::StatementInvalid
|
9
|
+
CreateRapnsNotifications.up
|
10
|
+
|
11
|
+
Bundler.require(:default)
|
12
|
+
|
13
|
+
require "shoulda"
|
14
|
+
require 'database_cleaner'
|
15
|
+
DatabaseCleaner.strategy = :truncation
|
16
|
+
|
17
|
+
require "rapns"
|
18
|
+
require "rapns/daemon"
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.before(:each) { DatabaseCleaner.clean }
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rapns
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ian Leitch
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-30 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: Easy to use library for Apple's Push Notification Service with Rails
|
15
|
+
3
|
16
|
+
email:
|
17
|
+
- port001@gmail.com
|
18
|
+
executables:
|
19
|
+
- rapns
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- lib/generators/rapns_generator.rb
|
24
|
+
- lib/generators/templates/create_rapns_notifications.rb
|
25
|
+
- lib/generators/templates/rapns.yml
|
26
|
+
- lib/rapns.rb
|
27
|
+
- lib/rapns/binary_notification_validator.rb
|
28
|
+
- lib/rapns/daemon.rb
|
29
|
+
- lib/rapns/daemon/certificate.rb
|
30
|
+
- lib/rapns/daemon/configuration.rb
|
31
|
+
- lib/rapns/daemon/connection.rb
|
32
|
+
- lib/rapns/daemon/connection_pool.rb
|
33
|
+
- lib/rapns/daemon/delivery_error.rb
|
34
|
+
- lib/rapns/daemon/delivery_handler.rb
|
35
|
+
- lib/rapns/daemon/delivery_handler_pool.rb
|
36
|
+
- lib/rapns/daemon/feeder.rb
|
37
|
+
- lib/rapns/daemon/logger.rb
|
38
|
+
- lib/rapns/daemon/pool.rb
|
39
|
+
- lib/rapns/notification.rb
|
40
|
+
- lib/rapns/version.rb
|
41
|
+
- README.md
|
42
|
+
- spec/rapns/daemon/certificate_spec.rb
|
43
|
+
- spec/rapns/daemon/configuration_spec.rb
|
44
|
+
- spec/rapns/daemon/connection_pool_spec.rb
|
45
|
+
- spec/rapns/daemon/connection_spec.rb
|
46
|
+
- spec/rapns/daemon/delivery_error_spec.rb
|
47
|
+
- spec/rapns/daemon/delivery_handler_pool_spec.rb
|
48
|
+
- spec/rapns/daemon/delivery_handler_spec.rb
|
49
|
+
- spec/rapns/daemon/feeder_spec.rb
|
50
|
+
- spec/rapns/daemon/logger_spec.rb
|
51
|
+
- spec/rapns/daemon_spec.rb
|
52
|
+
- spec/rapns/notification_spec.rb
|
53
|
+
- spec/spec_helper.rb
|
54
|
+
- bin/rapns
|
55
|
+
homepage: ''
|
56
|
+
licenses: []
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.8.6
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Easy to use library for Apple's Push Notification Service with Rails 3
|
79
|
+
test_files:
|
80
|
+
- spec/rapns/daemon/certificate_spec.rb
|
81
|
+
- spec/rapns/daemon/configuration_spec.rb
|
82
|
+
- spec/rapns/daemon/connection_pool_spec.rb
|
83
|
+
- spec/rapns/daemon/connection_spec.rb
|
84
|
+
- spec/rapns/daemon/delivery_error_spec.rb
|
85
|
+
- spec/rapns/daemon/delivery_handler_pool_spec.rb
|
86
|
+
- spec/rapns/daemon/delivery_handler_spec.rb
|
87
|
+
- spec/rapns/daemon/feeder_spec.rb
|
88
|
+
- spec/rapns/daemon/logger_spec.rb
|
89
|
+
- spec/rapns/daemon_spec.rb
|
90
|
+
- spec/rapns/notification_spec.rb
|
91
|
+
- spec/spec_helper.rb
|