mercurius 0.0.1 → 0.0.2

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.
@@ -0,0 +1,20 @@
1
+ describe APNS::Notification do
2
+
3
+ describe '#==' do
4
+ it 'doesnt care about object equality' do
5
+ a = APNS::Notification.new(alert: '1', badge: 1, other: { a: :b }, sound: 'default')
6
+ b = APNS::Notification.new(alert: '1', badge: 1, other: { a: :b }, sound: 'default')
7
+ expect(a == b).to eq true
8
+ end
9
+
10
+ %w(alert badge other sound).each do |attr|
11
+ it "must match #{attr} to be considered equal" do
12
+ attributes = { alert: '1', badge: 1, other: { a: :b }, sound: 'default' }
13
+ a = APNS::Notification.new(attributes)
14
+ b = APNS::Notification.new(attributes.merge(attr => SecureRandom.hex))
15
+ expect(a == b).to eq false
16
+ end
17
+ end
18
+ end
19
+
20
+ end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,5 @@
1
1
  require 'mercurius'
2
+ require 'webmock/rspec'
3
+ require 'support/fake_socket'
4
+
5
+ WebMock.disable_net_connect!
@@ -0,0 +1,61 @@
1
+ Bag Attributes
2
+ friendlyName: Fake APNs Provider Certificate
3
+ localKeyID: C0 9A 0E C0 77 F5 7A A4 71 1B 07 9D 10 0E 2D FB 8C B5 62 BC
4
+ subject=/CN=Fake APNs Provider Certificate/O=Fake Provider/OU=Fake Notification Sending Division/ST=Fake Tennessee/C=US/L=Fake Franklin/emailAddress=support@metova.com
5
+ issuer=/CN=Fake APNs Certificate Authority/O=Fake Apple/OU=Fake Certificate Signing Division/ST=Fake California/C=US/L=Fake Cupertino/emailAddress=support@metova.com
6
+ -----BEGIN CERTIFICATE-----
7
+ MIIENDCCAxygAwIBAgIBAjALBgkqhkiG9w0BAQswgcoxKDAmBgNVBAMMH0Zha2Ug
8
+ QVBOcyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEzARBgNVBAoMCkZha2UgQXBwbGUx
9
+ KjAoBgNVBAsMIUZha2UgQ2VydGlmaWNhdGUgU2lnbmluZyBEaXZpc2lvbjEYMBYG
10
+ A1UECAwPRmFrZSBDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzEXMBUGA1UEBwwORmFr
11
+ ZSBDdXBlcnRpbm8xHTAbBgkqhkiG9w0BCQEWDmluZm9Ad2F2aWkuY29tMB4XDTEy
12
+ MDQwNDIwNTYzNloXDTEzMDQwNDIwNTYzNlowgcsxJzAlBgNVBAMMHkZha2UgQVBO
13
+ cyBQcm92aWRlciBDZXJ0aWZpY2F0ZTEWMBQGA1UECgwNRmFrZSBQcm92aWRlcjEr
14
+ MCkGA1UECwwiRmFrZSBOb3RpZmljYXRpb24gU2VuZGluZyBEaXZpc2lvbjEYMBYG
15
+ A1UECAwPRmFrZSBXYXNoaW5ndG9uMQswCQYDVQQGEwJVUzEVMBMGA1UEBwwMRmFr
16
+ ZSBTZWF0dGxlMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHdhdmlpLmNvbTCCASIwDQYJ
17
+ KoZIhvcNAQEBBQADggEPADCCAQoCggEBALeeRtyoGCoyTZPLr4mjbK8nQpbwcf6/
18
+ 2GlkqDDaYy17kFjZXA3ZrdPncWnC1gA+93ZAtvy/a1PdSyKMNrTdkqmiId4EzRl5
19
+ oEFVAEXYSy5DmL78KiMYfmhGXtusq+mj0HvsBHRRsTESqmRhwHj8Th4wYBp6w4jr
20
+ UmFDIP2FuTqck1WgtgsVQMgVgrgyUUDCzejMfGxBkvavP9TRmYqlZPqRkadMoads
21
+ T+JTA8JAa7srtQVmdfCg0PvIKZxegIAiGjdoO0ZoWSlS2fWFzDKfsIybXbqinO/s
22
+ Og5C9ITAYR5+A/pBYXv+R3MOvYLxZ4SgHFOqs4J0oF26324jovt1FWkCAwEAAaMk
23
+ MCIwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEB
24
+ CwUAA4IBAQCfsBLbFlCfMFA1t5o4C1QWMA3tfM+MyGUDSJ4qIWFF1/zBQl8bSTc/
25
+ XkUaNZ42R/NZ+anwyPlYNK/N7JBC5nJiIDkn+SF/ifXUMZcJ6ryWwEIuM9oPf+yM
26
+ LABztG23gD6RbFw5n3PhO2IsO8dKa2HS4yxBPWAJuOnn9A+H87G+Vy7f7hc9ZgR+
27
+ BmUNVj9Wm+NBrZrWU431HbLUyi2udD2vDfXk2LopBUN05iOD7BqHEUbdeQ5bPxe5
28
+ 7smdpmEV3QrbpfCfWtoV28OJ/EA0qB0GwihJ3Pkx3V7SaASOwEwhhiwHQDPN/Ksy
29
+ lG47dCmL1Q47TN9Rzv7LnCSuKXuEycxo
30
+ -----END CERTIFICATE-----
31
+ Bag Attributes
32
+ friendlyName: Fake APNs Provider Certificate
33
+ localKeyID: C0 9A 0E C0 77 F5 7A A4 71 1B 07 9D 10 0E 2D FB 8C B5 62 BC
34
+ Key Attributes: <No Attributes>
35
+ -----BEGIN RSA PRIVATE KEY-----
36
+ MIIEowIBAAKCAQEAt55G3KgYKjJNk8uviaNsrydClvBx/r/YaWSoMNpjLXuQWNlc
37
+ Ddmt0+dxacLWAD73dkC2/L9rU91LIow2tN2SqaIh3gTNGXmgQVUARdhLLkOYvvwq
38
+ Ixh+aEZe26yr6aPQe+wEdFGxMRKqZGHAePxOHjBgGnrDiOtSYUMg/YW5OpyTVaC2
39
+ CxVAyBWCuDJRQMLN6Mx8bEGS9q8/1NGZiqVk+pGRp0yhp2xP4lMDwkBruyu1BWZ1
40
+ 8KDQ+8gpnF6AgCIaN2g7RmhZKVLZ9YXMMp+wjJtduqKc7+w6DkL0hMBhHn4D+kFh
41
+ e/5Hcw69gvFnhKAcU6qzgnSgXbrfbiOi+3UVaQIDAQABAoIBAAKv1zudXhUn/Uif
42
+ X2c1M/7wJSJOTGy84+7O4UMtvuvIdhlGvPka6VdDeL5icn04bqiVU9go+OoWP+Y2
43
+ hQpqf53p2HMGQPYReI3cL4/WFWuM46xPxlITJq5h8TtnsHBPzFoz3vDQzTX5nvKv
44
+ F4DtuDrq3E0m5LuZLfBsagwrq8U2xPzIQaRVfl+BGATOFBa30hSwNByqMHW3AuMd
45
+ 5qZQAAXa5C2OhWTEV5sfqQT3hJN/fHgn2gSOi3R3CW8F9yEx0M4ECR+kYb0NdYt/
46
+ FczNtgnrneK60yhQnOkX19Tr5MGvj44GryLndxAkrFTp5ipfBm+Gc26XKNkfoWJ+
47
+ ovzT1n0CgYEA2Q5umhJudO3W13WsKOxoU7ErtewemzDpYb0CrxdI9/i9Fxi1QV7C
48
+ +JSSf0XFKu+nW50D8jMJ60WwU4WX4v8DoG3M0vrXiJ0CZyIClFWgvk+VWi0hGh9b
49
+ e3PcjNMIKQNK2FyOnOwUnL0DerNFMtYD1kLkDS5CsjGY4VYGPVFRx1sCgYEA2JAB
50
+ rdUcmN3bfixXeHedRGzw6YFkEbEXqKt8Oa0dVlsDL20JX/Cj5xAESIXyswsIfuAo
51
+ Rjv4mI/J6lxXhoEiNo/9VsNJ+QH77zv8mVPqs1Z5pxjtp1lNag9jOMZZAX6vgJ1e
52
+ Glx/stLxxkIhX5aI1ppIZXNFCIY7e8qx9OPYNYsCgYBAw/imimdhBnK7mYYEM/4x
53
+ MsVLJChBwEdy/XXmjrkcHKE3Wg0Dc2YTzCkmRsg9NoMmZ+R8iVQlWobxdQRMHDGV
54
+ 1g1uyqAzSD4mTdSdNCuhfZef76VX6RFf9cNSVcmyiyPzCTMYiazg09lM7F7yez9r
55
+ 2Eu5zxrhlsD6Q7Pa6f/PzwKBgQCitPd9+mrk83MQxhHmAcCYA12xorRjknFbGZRY
56
+ 5Rbwpaqr/DkZ6vvKA7+kGXdyS6zTXmkD89TgEtA6k6xy8xyYb/CAOnOecX4ujRxI
57
+ usLQgP0frVwI6tB+ChebNXLz65HCiPmFxs9utIxQT6kxXzFqQzp3dnZ8ZBXW+UBg
58
+ 5Lqx5wKBgFIi2DP5/cF5nUDqOtiQTzl0MeJWW3w3UBS9jQF7Cx00YyLSqIF1batv
59
+ Zk0Yq5w/2oh9C5EDrf8eyCYfK3iU2Ij4Jy6N6zITjRhW/kxxZigjmcTb/Tsme2Xh
60
+ IFo5RoAfOV1dPiXM4oqZFPNmppAxiZH2ohEmo593DHYosQHMjXYG
61
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,30 @@
1
+ class FakeSocket < StringIO
2
+ attr_reader :wrote
3
+
4
+ def initialize(*)
5
+ @_open = false
6
+ super
7
+ end
8
+
9
+ def write(data)
10
+ @wrote ||= []
11
+ @wrote << data
12
+ super
13
+ end
14
+
15
+ def read
16
+ end
17
+
18
+ def connect
19
+ @_open = true
20
+ end
21
+
22
+ def close
23
+ @_open = false
24
+ end
25
+
26
+ def closed?
27
+ @_open == false
28
+ end
29
+
30
+ end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mercurius
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Beck
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-28 00:00:00.000000000 Z
11
+ date: 2015-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: httparty
14
+ name: json
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: json
28
+ name: faraday
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -38,6 +38,48 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday_middleware
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activemodel
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 4.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 4.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: activesupport
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 4.1.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 4.1.0
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: rake
43
85
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +108,20 @@ dependencies:
66
108
  - - ">="
67
109
  - !ruby/object:Gem::Version
68
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
69
125
  description: |2
70
126
  This gem is a wrapper to send push notifications to devices through native push services.
71
127
  email:
@@ -75,6 +131,7 @@ extensions: []
75
131
  extra_rdoc_files: []
76
132
  files:
77
133
  - ".gitignore"
134
+ - ".rspec"
78
135
  - ".ruby-gemset"
79
136
  - ".ruby-version"
80
137
  - ".travis.yml"
@@ -83,16 +140,28 @@ files:
83
140
  - README.md
84
141
  - Rakefile
85
142
  - lib/mercurius.rb
86
- - lib/mercurius/android.rb
87
- - lib/mercurius/apns/core.rb
143
+ - lib/mercurius/apns.rb
144
+ - lib/mercurius/apns/connection.rb
88
145
  - lib/mercurius/apns/notification.rb
89
- - lib/mercurius/apple.rb
90
- - lib/mercurius/gcm/core.rb
146
+ - lib/mercurius/apns/pem.rb
147
+ - lib/mercurius/apns/service.rb
148
+ - lib/mercurius/errors/pem_not_configured_error.rb
149
+ - lib/mercurius/errors/pem_not_found_error.rb
150
+ - lib/mercurius/errors/too_many_retries_error.rb
151
+ - lib/mercurius/gcm.rb
152
+ - lib/mercurius/gcm/connection.rb
91
153
  - lib/mercurius/gcm/notification.rb
154
+ - lib/mercurius/gcm/response.rb
155
+ - lib/mercurius/gcm/result.rb
156
+ - lib/mercurius/gcm/service.rb
92
157
  - lib/mercurius/version.rb
93
158
  - mercurius.gemspec
94
- - spec/lib/mercurius_spec.rb
159
+ - spec/lib/apns_service_spec.rb
160
+ - spec/lib/gcm_service_spec.rb
161
+ - spec/lib/notification_spec.rb
95
162
  - spec/spec_helper.rb
163
+ - spec/support/apns.pem
164
+ - spec/support/fake_socket.rb
96
165
  homepage: https://github.com/jrbeck/mercurius
97
166
  licenses: []
98
167
  metadata: {}
@@ -117,5 +186,9 @@ signing_key:
117
186
  specification_version: 4
118
187
  summary: Send push notifications to mobile devices through native services
119
188
  test_files:
120
- - spec/lib/mercurius_spec.rb
189
+ - spec/lib/apns_service_spec.rb
190
+ - spec/lib/gcm_service_spec.rb
191
+ - spec/lib/notification_spec.rb
121
192
  - spec/spec_helper.rb
193
+ - spec/support/apns.pem
194
+ - spec/support/fake_socket.rb
@@ -1,2 +0,0 @@
1
- require "mercurius/gcm/core"
2
- require "mercurius/gcm/notification"
@@ -1,128 +0,0 @@
1
- require 'socket'
2
- require 'openssl'
3
- require 'json'
4
-
5
- module APNS
6
- class Error < Exception; end
7
- class ConfigurationError < Error; end
8
-
9
- @host = 'gateway.sandbox.push.apple.com'
10
- @port = 2195
11
- @pem_path = nil
12
- @pem_password = nil
13
- @pem_data = nil
14
-
15
- @persistent = false
16
- @mutex = Mutex.new
17
- @retries = 3 # TODO: check if we really need this
18
-
19
- @sock = nil
20
- @ssl = nil
21
-
22
- class << self
23
- attr_accessor :host, :port, :pem_path, :pem_password, :pem_data
24
- end
25
-
26
- def self.start_persistence
27
- @persistent = true
28
- end
29
-
30
- def self.stop_persistence
31
- @persistent = false
32
- self.close_connection
33
- end
34
-
35
- def self.send_notification(device_token, message)
36
- notification = APNS::Notification.new(device_token, message)
37
- send_notifications([notification])
38
- end
39
-
40
- def self.send_notifications(notifications)
41
- @mutex.synchronize do
42
- with_connection do
43
- notifications.each do |n|
44
- @ssl.write(n.packaged_notification)
45
- end
46
- end
47
- end
48
- end
49
-
50
- def self.feedback
51
- sock, ssl = feedback_connection
52
- apns_feedback = []
53
-
54
- # read lines from the socket
55
- while line = ssl.read(38)
56
- line.strip!
57
- f = line.unpack('N1n1H140')
58
- apns_feedback << { timestamp: Time.at(f[0]), token: f[2] }
59
- end
60
-
61
- ssl.close
62
- sock.close
63
-
64
- apns_feedback
65
- end
66
-
67
- protected
68
-
69
- def self.with_connection
70
- attempts = 1
71
-
72
- begin
73
- open_connection if connection_closed?
74
- yield
75
- rescue StandardError, Errno::EPIPE
76
- raise Error.new("Failed after #{@retries} attempts.") unless attempts < @retries
77
- close_connection
78
- attempts += 1
79
- retry
80
- end
81
-
82
- close_connection unless @persistent
83
- end
84
-
85
- def self.open_connection
86
- @sock = TCPSocket.new(self.host, self.port)
87
- @ssl = OpenSSL::SSL::SSLSocket.new(@sock, context)
88
- @ssl.connect
89
- end
90
-
91
- def self.close_connection
92
- @ssl.close
93
- @ssl = nil
94
- @sock.close
95
- @sock = nil
96
- end
97
-
98
- def self.connection_closed?
99
- @ssl.nil? || @sock.nil? || @ssl.closed? || @sock.closed?
100
- end
101
-
102
- def self.feedback_connection
103
- fhost = self.host.gsub('gateway','feedback')
104
- sock = TCPSocket.new(fhost, 2196)
105
- ssl = OpenSSL::SSL::SSLSocket.new(sock, context)
106
- ssl.connect
107
- return sock, ssl
108
- end
109
-
110
- def self.context
111
- context = OpenSSL::SSL::SSLContext.new
112
- context.cert = OpenSSL::X509::Certificate.new(pem_data)
113
- context.key = OpenSSL::PKey::RSA.new(pem_data, pem_password)
114
- context
115
- end
116
-
117
- def self.pem_data
118
- return @pem_data if @pem_data
119
-
120
- if @pem_path
121
- raise ConfigurationError.new('The specified PEM file does not exist.') unless File.exist?(@pem_path)
122
- @pem_data = File.read(@pem_path)
123
- else
124
- raise ConfigurationError.new('PEM not configured properly.')
125
- end
126
- end
127
-
128
- end
@@ -1,2 +0,0 @@
1
- require "mercurius/apns/core"
2
- require "mercurius/apns/notification"
@@ -1,113 +0,0 @@
1
- require 'httparty'
2
- require 'json'
3
-
4
- module GCM
5
- include HTTParty
6
-
7
- @host = 'https://android.googleapis.com/gcm/send'
8
- @format = :json
9
- @key = nil
10
-
11
- class << self
12
- attr_accessor :host, :format, :key
13
-
14
- def key(identity = nil)
15
- if @key.is_a?(Hash)
16
- raise %{If your key is a hash of keys you'll need to pass a identifier to the notification!} if identity.nil?
17
- return @key[identity]
18
- else
19
- return @key
20
- end
21
- end
22
-
23
- def key_identities
24
- if @key.is_a?(Hash)
25
- return @key.keys
26
- else
27
- return nil
28
- end
29
- end
30
- end
31
-
32
- def self.send_notification(device_tokens, data = {}, options = {})
33
- n = GCM::Notification.new(device_tokens, data, options)
34
- self.send_notifications([n])
35
- end
36
-
37
- def self.send_notifications(notifications)
38
- responses = []
39
- notifications.each do |n|
40
- responses << self.prepare_and_send(n)
41
- end
42
- responses
43
- end
44
-
45
- private
46
-
47
- def self.prepare_and_send(n)
48
- if n.device_tokens.count < 1 || n.device_tokens.count > 1000
49
- raise "Number of device tokens must be between 1 and 1000"
50
- end
51
- if !n.collapse_key.nil? && n.time_to_live.nil?
52
- raise %q{If you are defining a "collapse key" you need a "time to live"}
53
- end
54
- if @key.is_a?(Hash) && n.identity.nil?
55
- raise %{If your key is a Hash of keys you'll need to pass a identifier to the notification!}
56
- end
57
-
58
- if self.format == :json
59
- self.send_push_as_json(n)
60
- elsif self.format == :text
61
- self.send_push_as_plain_text(n)
62
- else
63
- raise "Invalid format"
64
- end
65
- end
66
-
67
- def self.send_push_as_json(n)
68
- headers = {
69
- 'Authorization' => "key=#{ self.key(n.identity) }",
70
- 'Content-Type' => 'application/json',
71
- }
72
- body = {
73
- registration_ids: n.device_tokens,
74
- data: n.data,
75
- collapse_key: n.collapse_key,
76
- time_to_live: n.time_to_live,
77
- delay_while_idle: n.delay_while_idle
78
- }
79
- return self.send_to_server(headers, body.to_json)
80
- end
81
-
82
- def self.send_push_as_plain_text(n)
83
- raise "Still has to be done: http://developer.android.com/guide/google/gcm/gcm.html"
84
- headers = {
85
- # TODO: Aceitar key ser um hash
86
- 'Authorization' => "key=#{ self.key(n.identity) }",
87
- 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8',
88
- }
89
- return self.send_to_server(headers, body)
90
- end
91
-
92
- def self.send_to_server(headers, body)
93
- params = { headers: headers, body: body}
94
- response = self.post(self.host, params)
95
- build_response(response)
96
- end
97
-
98
- def self.build_response(response)
99
- case response.code
100
- when 200
101
- { response: 'success', body: JSON.parse(response.body), headers: response.headers, status_code: response.code }
102
- when 400
103
- { response: 'Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields.', status_code: response.code }
104
- when 401
105
- { response: 'There was an error authenticating the sender account.', status_code: response.code }
106
- when 500
107
- { response: 'There was an internal error in the GCM server while trying to process the request.', status_code: response.code }
108
- when 503
109
- { response: 'Server is temporarily unavailable.', status_code: response.code }
110
- end
111
- end
112
-
113
- end
@@ -1,148 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mercurius do
4
- describe "APNS" do
5
- it "should have an APNS object" do
6
- defined?(APNS).should_not be_false
7
- end
8
-
9
- it "should not forget the APNS default parameters" do
10
- APNS.host.should == "gateway.sandbox.push.apple.com"
11
- APNS.port.should == 2195
12
- APNS.pem_path.should be_equal(nil)
13
- APNS.pem_password.should be_equal(nil)
14
- end
15
-
16
- describe "Notifications" do
17
- describe "#==" do
18
- it "should properly equate objects without caring about object identity" do
19
- a = APNS::Notification.new("123", {:alert => "hi"})
20
- b = APNS::Notification.new("123", {:alert => "hi"})
21
- a.should eq(b)
22
- end
23
- end
24
- end
25
-
26
- describe '.send_notification' do
27
- let(:token) { 'token' }
28
- let(:message) { 'message' }
29
- let(:pem_data) { 'pem_data' }
30
- let(:cert) { double }
31
- let(:key) { double }
32
- let(:sock) { double(close: nil) }
33
- let(:ssl) { double(connect: nil, write: nil, close: nil) }
34
- let(:packaged) { 'packaged' }
35
-
36
- after do
37
- APNS.pem_path = nil
38
- APNS.pem_data = nil
39
- end
40
-
41
- before do
42
- allow(OpenSSL::X509::Certificate).to receive(:new).
43
- with(pem_data).and_return(cert)
44
- allow(OpenSSL::PKey::RSA).to receive(:new).
45
- with(pem_data, anything).and_return(key)
46
- allow(TCPSocket).to receive(:new).and_return(sock)
47
- allow(OpenSSL::SSL::SSLSocket).to receive(:new).and_return(ssl)
48
- end
49
-
50
- shared_examples 'notifications' do
51
- it 'notifications are sent' do
52
- expect(ssl).to have_received(:write).with(/"#{message}"/)
53
- end
54
- end
55
-
56
- context 'with pem setting' do
57
- context 'with an existing pem file' do
58
- let(:path) { '/good/path' }
59
-
60
- before do
61
- allow(File).to receive(:exist?).with(path).and_return(true)
62
- allow(File).to receive(:read).with(path).and_return(pem_data)
63
- end
64
-
65
- before { APNS.pem_path = '/good/path' }
66
- before { APNS.send_notification(token, message) }
67
-
68
- include_examples 'notifications'
69
- end
70
-
71
- context 'when the pem does not exist' do
72
- before { APNS.pem_path = '/bad/path' }
73
-
74
- it 'fails' do
75
- expect do
76
- APNS.send_notification(token, message)
77
- end.to raise_error(APNS::ConfigurationError, /does not exist/)
78
- end
79
- end
80
- end
81
-
82
- context 'with pem_data' do
83
- before { APNS.pem_data = pem_data }
84
- before { APNS.send_notification(token, message) }
85
-
86
- include_examples 'notifications'
87
- end
88
-
89
- context 'without pem or pem_data' do
90
- before { APNS.pem_path = nil }
91
-
92
- it 'fails' do
93
- expect do
94
- APNS.send_notification(token, message)
95
- end.to raise_error(APNS::ConfigurationError, /PEM not configured properly/)
96
- end
97
- end
98
- end
99
-
100
- end
101
-
102
- describe "GCM" do
103
- it "should have a GCM object" do
104
- defined?(GCM).should_not be_false
105
- end
106
-
107
- describe "Notifications" do
108
-
109
- before do
110
- @options = {:data => "dummy data"}
111
- end
112
-
113
- it "should allow only notifications with device_tokens as array" do
114
- n = GCM::Notification.new("id", @options)
115
- n.device_tokens.is_a?(Array).should be_true
116
-
117
- n.device_tokens = ["a" "b", "c"]
118
- n.device_tokens.is_a?(Array).should be_true
119
-
120
- n.device_tokens = "a"
121
- n.device_tokens.is_a?(Array).should be_true
122
- end
123
-
124
- it "should allow only notifications with data as hash with :data root" do
125
- n = GCM::Notification.new("id", { :data => "data" })
126
-
127
- n.data.is_a?(Hash).should be_true
128
- n.data.should == {:data => "data"}
129
-
130
- n.data = {:a => ["a", "b", "c"]}
131
- n.data.is_a?(Hash).should be_true
132
- n.data.should == {:a => ["a", "b", "c"]}
133
-
134
- n.data = {:a => "a"}
135
- n.data.is_a?(Hash).should be_true
136
- n.data.should == {:a => "a"}
137
- end
138
-
139
- describe "#==" do
140
- it "should properly equate objects without caring about object identity" do
141
- a = GCM::Notification.new("id", { :data => "data" })
142
- b = GCM::Notification.new("id", { :data => "data" })
143
- a.should eq(b)
144
- end
145
- end
146
- end
147
- end
148
- end