messagebus_ruby_apn_api 1.0.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/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm use ruby-1.9.2-p180-patched@messagebus_ruby_api --create
2
+
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'activesupport'
4
+
5
+ group :test, :development do
6
+ gem 'rspec', '2.5.0'
7
+ gem 'rr', '1.0.2'
8
+ gem 'fakeweb'
9
+ end
10
+
11
+ # Specify your gem's dependencies in messagebus.gemspec
12
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,64 @@
1
+ = Message Bus Ruby APN API
2
+
3
+ == Installation
4
+
5
+ gem install messagebus_ruby_apn_api
6
+
7
+ == Basic Use
8
+
9
+ === Start by requiring MessabusApi:
10
+
11
+ require 'messagebus_ruby_apn_api'
12
+
13
+ === Then create an instance of the Messagebus class with your account information
14
+
15
+ client = MessagebusApnApi::Messagebus.new("<INSERT_YOUR_API_KEY>")
16
+
17
+ === Sending a single notification
18
+
19
+ ==== Create Required Parameters
20
+
21
+ params = { :userName => 'apitest1@messagebus.com',
22
+ :alert => 'Hello push notification world.',
23
+ :platform => Messagebus::PLATFORM_IOS,
24
+ :customFields => {}
25
+ }
26
+
27
+ ==== Send the message
28
+
29
+ client.add_apn_message(params)
30
+
31
+ == Examples
32
+
33
+ The provided examples illustrate how to:
34
+ - send a single notification to a registered device
35
+ - register a device
36
+
37
+ == SSL Certificates
38
+
39
+ If you encounter SSL certificate problems, use the cacert_info() method to specify a
40
+ cacert.pem file (remember to specify the full path).
41
+
42
+ The curl site has an up to date version of the file:
43
+
44
+ http://curl.haxx.se/ca/cacert.pem
45
+
46
+ == Tests
47
+ To run the tests, issue the following command from the root of the project:
48
+ bundle exec rspec spec/messagebus_ruby_apn_api/client_spec.rb
49
+
50
+ == License
51
+ Copyright 2012 Mail Bypass, Inc.
52
+
53
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
54
+ except in compliance with the License. You may obtain a copy of the License at
55
+
56
+ http://www.apache.org/licenses/LICENSE-2.0
57
+
58
+ Unless required by applicable law or agreed to in writing, software distributed under the
59
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
60
+ either express or implied. See the License for the specific language governing permissions
61
+ and limitations under the License.
62
+
63
+ == More info
64
+ Contact Message Bus if you have questions or problems (https://www.messagebus.com/contact)
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,23 @@
1
+ # Copyright 2012 Mail Bypass, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ # not use this file except in compliance with the License. You may obtain
5
+ # a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+ # License for the specific language governing permissions and limitations
13
+ # under the License.
14
+
15
+ dir = File.dirname(__FILE__)
16
+
17
+ require 'net/https'
18
+ require 'uri'
19
+ require 'cgi'
20
+
21
+ require "#{dir}/messagebus_ruby_apn_api/errors"
22
+ require "#{dir}/messagebus_ruby_apn_api/messagebus"
23
+ require "#{dir}/messagebus_ruby_apn_api/version"
@@ -0,0 +1,37 @@
1
+ # Copyright 2012 Mail Bypass, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ # not use this file except in compliance with the License. You may obtain
5
+ # a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+ # License for the specific language governing permissions and limitations
13
+ # under the License.
14
+
15
+ module MessagebusApi
16
+
17
+ class APIParameterError < StandardError
18
+ def initialize(problematic_parameter="")
19
+ super("missing or malformed parameter #{problematic_parameter}")
20
+ end
21
+ end
22
+
23
+ class BadAPIKeyError < StandardError
24
+ end
25
+
26
+ class MissingFileError <StandardError
27
+ end
28
+
29
+ class RemoteServerError < StandardError
30
+ attr_reader :result
31
+ def initialize(message, result={})
32
+ super(message)
33
+ @result = result
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,283 @@
1
+ # Copyright 2012 Mail Bypass, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ # not use this file except in compliance with the License. You may obtain
5
+ # a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+ # License for the specific language governing permissions and limitations
13
+ # under the License.
14
+ require 'json'
15
+
16
+ require 'json'
17
+
18
+ module MessagebusApnApi
19
+ DEFAULT_API_APN_ENDPOINT_STRING = 'https://apn.messagebus.com'
20
+
21
+ class Messagebus
22
+
23
+ PLATFORM_IOS = 'ios'
24
+ PLATFORM_ANDROID = 'android'
25
+
26
+ attr_writer :send_common_info
27
+
28
+ def initialize(api_key)
29
+ @api_key = api_key
30
+ init_http_connection(domain)
31
+
32
+ @msg_buffer_size = 20
33
+ @msg_buffer = []
34
+ @msg_buffer_flushed = false
35
+
36
+ @register_buffer_size = 20
37
+ @register_buffer = []
38
+ @register_buffer_flushed = false
39
+
40
+ @send_common_info = {}
41
+ @results = base_response_params
42
+ @rest_endpoints = define_rest_endpoints
43
+ @rest_http_errors = define_rest_http_errors
44
+ end
45
+
46
+ def results
47
+ @results
48
+ end
49
+
50
+ def send_buffer_size=(size)
51
+ @msg_buffer_size = size if (size >= 1 && size <= 100)
52
+ end
53
+
54
+ def send_buffer_size
55
+ @msg_buffer_size
56
+ end
57
+
58
+ def send_flushed?
59
+ @msg_buffer_flushed
60
+ end
61
+
62
+ def register_buffer_size=(size)
63
+ @register_buffer_size = size if (size >= 1 && size <= 100)
64
+ end
65
+
66
+ def register_buffer_size
67
+ @register_buffer_size
68
+ end
69
+
70
+ def register_flushed?
71
+ @register_buffer_flushed
72
+ end
73
+
74
+ def api_version
75
+ make_api_get_call(@rest_endpoints[:version])
76
+ end
77
+
78
+ def add_apn_send(params, app_key, flush_buffer = false)
79
+ @msg_buffer << base_apn_send_params.merge!(params)
80
+
81
+ @msg_buffer_flushed = false
82
+ if flush_buffer || @msg_buffer.size >= @msg_buffer_size
83
+ apn_send_flush(app_key)
84
+ end
85
+ return
86
+ end
87
+
88
+ def apn_send_flush(app_key)
89
+ if (@msg_buffer.size==0)
90
+ @results=@empty_send_results
91
+ return
92
+ end
93
+
94
+ endpoint = @rest_endpoints[:apn_send].gsub("%KEY%", app_key)
95
+
96
+ json = json_apn_send_from_list(@msg_buffer)
97
+ if (@last_init_time < Time.now.utc - 60)
98
+ init_http_connection(domain)
99
+ end
100
+ @results=make_api_post_call(endpoint, json)
101
+ @msg_buffer.clear
102
+
103
+ @msg_buffer_flushed = true
104
+ return
105
+ end
106
+
107
+ def add_apn_register(params, app_key, flush_buffer = false)
108
+ @register_buffer << base_apn_register_params.merge!(params)
109
+
110
+ @register_buffer_flushed = false
111
+ if flush_buffer || @register_buffer.size >= @register_buffer_size
112
+ apn_register_flush(app_key)
113
+ end
114
+ return
115
+ end
116
+
117
+ def apn_register_flush(app_key)
118
+ if (@register_buffer.size==0)
119
+ @results=@empty_send_results
120
+ return
121
+ end
122
+
123
+ endpoint = @rest_endpoints[:apn_register].gsub("%KEY%", app_key)
124
+
125
+ json = json_apn_register_from_list(@register_buffer)
126
+ if (@last_init_time < Time.now.utc - 60)
127
+ init_http_connection(domain)
128
+ end
129
+ @results=make_api_post_call(endpoint, json)
130
+ @register_buffer.clear
131
+ @register_buffer_flushed = true
132
+ return
133
+ end
134
+
135
+ def get_apn_apps
136
+ path = @rest_endpoints[:apn_apps]
137
+ @results = make_api_get_call(path)
138
+ @results
139
+ end
140
+
141
+ def cacert_info(cert_file)
142
+ @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
143
+ if !File.exists?(cert_file)
144
+ raise MessagebusApi::MissingFileError.new("Unable to read file #{cert_file}")
145
+ end
146
+ @http.ca_file = File.join(cert_file)
147
+ end
148
+
149
+ private
150
+
151
+ def init_http_connection(target_server)
152
+ if (@http and @http.started?)
153
+ @http.finish
154
+ end
155
+ @last_init_time = Time.now.utc
156
+ endpoint_url = URI.parse(target_server)
157
+ @http = Net::HTTP.new(endpoint_url.host, endpoint_url.port)
158
+ @http.use_ssl = true
159
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
160
+ @http
161
+ end
162
+
163
+ def domain
164
+ DEFAULT_API_APN_ENDPOINT_STRING
165
+ end
166
+
167
+ def common_http_headers
168
+ {'User-Agent' => MessagebusApi::Info.get_user_agent, 'X-MessageBus-Key' => @api_key}
169
+ end
170
+
171
+ def rest_post_headers
172
+ {"Content-Type" => "application/json; charset=utf-8"}
173
+ end
174
+
175
+ def json_apn_send_from_list(messages)
176
+ {:messages => messages}.to_json
177
+ end
178
+
179
+ def json_apn_register_from_list(users)
180
+ {:users => users}.to_json
181
+ end
182
+
183
+ def make_api_post_call(path, data)
184
+ headers = common_http_headers.merge(rest_post_headers)
185
+ response = @http.request_post(path, data, headers)
186
+ check_response(response)
187
+ end
188
+
189
+ def make_api_get_call(path)
190
+ headers = common_http_headers
191
+ response = @http.request_get(path, headers)
192
+ check_response(response)
193
+ end
194
+
195
+ def check_response(response, symbolize_names=true)
196
+ case response
197
+ when Net::HTTPSuccess
198
+ begin
199
+ return JSON.parse(response.body, :symbolize_names => symbolize_names)
200
+ rescue JSON::ParserError => e
201
+ raise MessagebusApi::RemoteServerError.new("JSON parsing error. Response started with #{response.body.slice(0..9)}")
202
+ end
203
+ when Net::HTTPClientError, Net::HTTPServerError
204
+ if (response.body && response.body.size > 0)
205
+ result = begin
206
+ JSON.parse(response.body, :symbolize_names => symbolize_names)
207
+ rescue JSON::ParserError
208
+ nil
209
+ end
210
+ raise MessagebusApi::RemoteServerError.new("#{response.code.to_s}:#{rest_http_error_message(response.code.to_s)}")
211
+ else
212
+ raise MessagebusApi::RemoteServerError.new("#{response.code.to_s}:#{rest_http_error_message(response.code.to_s)}")
213
+ end
214
+ else
215
+ raise "Unexpected HTTP Response: #{response.class.name}"
216
+ end
217
+ raise "Could not determine response"
218
+ end
219
+
220
+ def rest_http_error?(status_code)
221
+ @rest_http_errors.key?(status_code)
222
+ end
223
+
224
+ def rest_http_error_message(status_code)
225
+ message = "Unknown Error Code"
226
+ message = @rest_http_errors[status_code] if rest_http_error?(status_code)
227
+ message
228
+ end
229
+
230
+ def define_rest_endpoints
231
+ {
232
+ :apn_register => "/api/v3/app/%KEY%/register",
233
+ :apn_send => "/api/v3/app/%KEY%/send",
234
+ :apn_apps => "/api/v3/apps",
235
+ :version => "/api/version"
236
+ }
237
+ end
238
+
239
+ def define_rest_http_errors
240
+ {
241
+ "400" => "Invalid Request",
242
+ "401" => "Unauthorized-Missing API Key",
243
+ "403" => "Unauthorized-Invalid API Key",
244
+ "404" => "Incorrect URL",
245
+ "405" => "Method not allowed",
246
+ "406" => "Format not acceptable",
247
+ "408" => "Request Timeout",
248
+ "409" => "Conflict",
249
+ "410" => "Object missing or deleted",
250
+ "413" => "Too many messages in request",
251
+ "415" => "POST JSON data invalid",
252
+ "422" => "Unprocessable Entity",
253
+ "500" => "Internal Server Error",
254
+ "501" => "Not Implemented",
255
+ "503" => "Service Unavailable",
256
+ "507" => "Insufficient Storage"
257
+ }
258
+ end
259
+
260
+ def base_apn_register_params
261
+ {
262
+ :userName => '',
263
+ :deviceToken => '',
264
+ :platform => ''
265
+ }
266
+ end
267
+
268
+ def base_apn_send_params
269
+ {
270
+ :userName => '',
271
+ :alert => '',
272
+ :platform => '',
273
+ :customFields => {}
274
+ }
275
+ end
276
+
277
+ def base_response_params
278
+ {:statusCode => 0,
279
+ :statusMessage => "",
280
+ :statusTime => "1970-01-01T00:00:00.000Z"}
281
+ end
282
+ end
283
+ end
@@ -0,0 +1,27 @@
1
+ # Copyright 2012 Mail Bypass, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ # not use this file except in compliance with the License. You may obtain
5
+ # a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+ # License for the specific language governing permissions and limitations
13
+ # under the License.
14
+
15
+ module MessagebusApi
16
+ VERSION = "1.0.0"
17
+
18
+ class Info
19
+ @@ClientVersion = MessagebusApi::VERSION
20
+ @@RubyVersion = RUBY_VERSION
21
+ @@UserAgent = "MessagebusAPI:#{@@ClientVersion}-Ruby:#{@@RubyVersion}";
22
+
23
+ def self.get_user_agent
24
+ return @@UserAgent
25
+ end
26
+ end
27
+ end
@@ -0,0 +1 @@
1
+ # THIS IS ONLY FOR TESTING
@@ -0,0 +1,319 @@
1
+ # Copyright 2012 Mail Bypass, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ # not use this file except in compliance with the License. You may obtain
5
+ # a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+ # License for the specific language governing permissions and limitations
13
+ # under the License.
14
+
15
+
16
+ dir = File.dirname(__FILE__)
17
+ require "#{dir}/../spec_helper"
18
+
19
+ class MessagebusTest < MessagebusApnApi::Messagebus
20
+ attr_accessor :last_init_time
21
+ end
22
+
23
+ describe MessagebusApnApi::Messagebus do
24
+ attr_reader :client, :api_key, :required_params
25
+
26
+
27
+
28
+ def default_apn_send_params
29
+ {
30
+ :userName => 'mark@example.com',
31
+ :alert => 'Message Bus application push',
32
+ :platform => 'ios',
33
+ :customFields => ["badge"=>"23"]
34
+ }
35
+ end
36
+
37
+ def default_apn_register_params
38
+ {
39
+ :userName => 'mark@messagebus.com',
40
+ :deviceToken => '835012e8d4640406818e8c7',
41
+ :platform => 'ios'
42
+ }
43
+ end
44
+
45
+ def create_success_result(num_result)
46
+ list=[]
47
+ num_result.times do
48
+ list << @success_message
49
+ end
50
+
51
+ success_result = {
52
+ "statusMessage" => "OK",
53
+ "successCount" => num_result,
54
+ "failureCount" => 0,
55
+ "results" => list
56
+ }
57
+ success_result
58
+ end
59
+
60
+ def create_results_array
61
+ results = {
62
+ "statusMessage" => "OK",
63
+ "results" => []
64
+ }
65
+ results
66
+ end
67
+
68
+ def json_parse(data)
69
+ JSON.parse(data, :symbolize_names => true)
70
+ end
71
+
72
+ before do
73
+ FakeWeb.allow_net_connect = false
74
+
75
+ @app_key = 'test_key'
76
+ @api_key = "7215ee9c7d9dc229d2921a40e899ec5f"
77
+ @client = MessagebusTest.new(@api_key)
78
+ @success_message={
79
+ "status" => 200,
80
+ "messageId" => "abcdefghijklmnopqrstuvwxyz012345"
81
+ }
82
+ @simple_success_result = create_success_result(1)
83
+ @apn_endpoint = "https://apn.messagebus.com/api/v3/"
84
+ end
85
+
86
+ describe "messagebus object set up correctly" do
87
+ it "has correct headers set for api calls" do
88
+ client = MessagebusApnApi::Messagebus.new(@api_key)
89
+ end
90
+ end
91
+
92
+ describe "add cacert file to http communications" do
93
+ it "raises error if cert file does not exist" do
94
+ client = MessagebusApnApi::Messagebus.new(@api_key)
95
+ cert_file_path = File.join(File.dirname(__FILE__), "nofile.pem")
96
+ expect do
97
+ client.cacert_info(cert_file_path)
98
+ end.should raise_error
99
+ end
100
+
101
+ it "accepts a cert file that exists" do
102
+ client = MessagebusApnApi::Messagebus.new(@api_key)
103
+ cert_file_path = File.join(File.dirname(__FILE__), "cacert.pem")
104
+ expect do
105
+ client.cacert_info(cert_file_path)
106
+ end.should_not raise_error
107
+ end
108
+ end
109
+
110
+ describe "#add_apn_send" do
111
+ it "buffered send that adds to empty buffer" do
112
+ client.add_apn_send(default_apn_send_params, @app_key)
113
+ client.send_flushed?.should be_false
114
+ end
115
+ it "buffered send that adds to empty buffer and sends with flush_buffer flag" do
116
+ expected_request="#{@apn_endpoint}app/#{@app_key}/send"
117
+ FakeWeb.register_uri(:post, expected_request, :body => json_valid_apn_send)
118
+ client.add_apn_send(default_apn_send_params, @app_key, true)
119
+ client.send_flushed?.should be_true
120
+ end
121
+ it "should have user-agent and x-messagebus-key set in request headers" do
122
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/send", :body => json_valid_apn_send)
123
+ client.add_apn_send(default_apn_send_params, @app_key, true)
124
+ client.send_flushed?.should be_true
125
+
126
+ FakeWeb.last_request.get_fields("X-MessageBus-Key").should_not be_nil
127
+ FakeWeb.last_request.get_fields("User-Agent").should_not be_nil
128
+ FakeWeb.last_request.get_fields("Content-Type").should_not be_nil
129
+ end
130
+ it "buffered send that adds to a buffer and auto-flushes" do
131
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/send", :body => create_success_result(client.send_buffer_size).to_json)
132
+ (client.send_buffer_size-1).times do |idx|
133
+ client.add_apn_send(default_apn_send_params, @app_key)
134
+ client.send_flushed?.should be_false
135
+ end
136
+ client.add_apn_send(default_apn_send_params, @app_key)
137
+ client.send_flushed?.should be_true
138
+ client.results[:results].size.should == client.send_buffer_size
139
+
140
+ end
141
+ end
142
+
143
+ describe "#apn_app_register" do
144
+ it "buffered register that adds to empty buffer" do
145
+ client.add_apn_register(default_apn_register_params, @app_key)
146
+ client.register_flushed?.should be_false
147
+ end
148
+ it "buffered register that adds to empty buffer and registers with flush_buffer flag" do
149
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/register", :body => json_valid_apn_register)
150
+ client.add_apn_register(default_apn_register_params, @app_key, true)
151
+ client.register_flushed?.should be_true
152
+ end
153
+ it "should have user-agent and x-messagebus-key set in request headers" do
154
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/register", :body => json_valid_apn_register)
155
+ client.add_apn_register(default_apn_register_params, @app_key, true)
156
+ client.register_flushed?.should be_true
157
+
158
+ FakeWeb.last_request.get_fields("X-MessageBus-Key").should_not be_nil
159
+ FakeWeb.last_request.get_fields("User-Agent").should_not be_nil
160
+ FakeWeb.last_request.get_fields("Content-Type").should_not be_nil
161
+ end
162
+ it "buffered register that adds to a buffer and auto-flushes" do
163
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/register", :body => create_success_result(client.register_buffer_size).to_json)
164
+ (client.send_buffer_size-1).times do |idx|
165
+ client.add_apn_register(default_apn_register_params, @app_key)
166
+ client.register_flushed?.should be_false
167
+ end
168
+ client.add_apn_register(default_apn_register_params, @app_key)
169
+ client.register_flushed?.should be_true
170
+ client.results[:results].size.should == client.register_buffer_size
171
+ end
172
+ end
173
+
174
+ describe "#apn_send_flush" do
175
+ it "apn send flush called on empty buffer" do
176
+ client.apn_send_flush(@app_key)
177
+ client.send_flushed?.should be_false
178
+ end
179
+
180
+ it "apn send flush called on partially filled buffer" do
181
+ message_count = 9
182
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/send", :body => create_success_result(message_count).to_json)
183
+ (message_count).times do |idx|
184
+ client.add_apn_send(default_apn_send_params, @app_key)
185
+ client.send_flushed?.should be_false
186
+ end
187
+ client.apn_send_flush(@app_key)
188
+ client.send_flushed?.should be_true
189
+ client.results[:results].size.should == message_count
190
+ end
191
+
192
+ it "doesnt reset connection if under a minute old" do
193
+ current_init_time=client.last_init_time
194
+ current_init_time.should be > Time.now.utc-5
195
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/send", :body => create_success_result(1).to_json)
196
+ client.add_apn_send(default_apn_send_params, @app_key)
197
+ client.apn_send_flush(@app_key)
198
+ client.send_flushed?.should be_true
199
+ client.results[:results].size.should == 1
200
+ client.last_init_time.should == current_init_time
201
+ end
202
+
203
+ it "resets connection if over a minute old" do
204
+ client.last_init_time=Time.now.utc-60
205
+ current_init_time=client.last_init_time
206
+ current_init_time.should be < Time.now.utc-59
207
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/send", :body => create_success_result(1).to_json)
208
+ client.add_apn_send(default_apn_send_params, @app_key)
209
+ client.apn_send_flush(@app_key)
210
+ client.send_flushed?.should be_true
211
+ client.results[:results].size.should == 1
212
+ client.last_init_time.should be > current_init_time
213
+ end
214
+ end
215
+
216
+ describe "#send_buffer_size=" do
217
+ it "can set the buffer size" do
218
+ client.send_buffer_size=(10)
219
+ client.send_buffer_size.should == 10
220
+ end
221
+
222
+ it "cannot set an invalid buffer size" do
223
+ default_buffer_size = 20
224
+ client.send_buffer_size=(-1)
225
+ client.send_buffer_size.should == default_buffer_size
226
+
227
+ client.send_buffer_size=(0)
228
+ client.send_buffer_size.should == default_buffer_size
229
+
230
+ client.send_buffer_size=(101)
231
+ client.send_buffer_size.should == default_buffer_size
232
+
233
+ client.send_buffer_size=(1)
234
+ client.send_buffer_size.should == 1
235
+
236
+ client.send_buffer_size=(100)
237
+ client.send_buffer_size.should == 100
238
+ end
239
+ end
240
+
241
+ describe "#apn_register_flush" do
242
+ it "apn register flush called on empty buffer" do
243
+ client.apn_register_flush(@app_key)
244
+ client.register_flushed?.should be_false
245
+ end
246
+
247
+ it "apn register flush called on partially filled buffer" do
248
+ message_count = 9
249
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/register", :body => create_success_result(message_count).to_json)
250
+ (message_count).times do |idx|
251
+ client.add_apn_register(default_apn_register_params, @app_key)
252
+ client.register_flushed?.should be_false
253
+ end
254
+ client.apn_register_flush(@app_key)
255
+ client.register_flushed?.should be_true
256
+ client.results[:results].size.should == message_count
257
+ end
258
+
259
+ it "doesnt reset connection if under a minute old" do
260
+ current_init_time=client.last_init_time
261
+ current_init_time.should be > Time.now.utc-5
262
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/register", :body => create_success_result(1).to_json)
263
+ client.add_apn_register(default_apn_register_params, @app_key)
264
+ client.apn_register_flush(@app_key)
265
+ client.register_flushed?.should be_true
266
+ client.results[:results].size.should == 1
267
+ client.last_init_time.should == current_init_time
268
+ end
269
+
270
+ it "resets connection if over a minute old" do
271
+ client.last_init_time=Time.now.utc-60
272
+ current_init_time=client.last_init_time
273
+ current_init_time.should be < Time.now.utc-59
274
+ FakeWeb.register_uri(:post, "#{@apn_endpoint}app/#{@app_key}/register", :body => create_success_result(1).to_json)
275
+ client.add_apn_register(default_apn_register_params, @app_key)
276
+ client.apn_register_flush(@app_key)
277
+ client.register_flushed?.should be_true
278
+ client.results[:results].size.should == 1
279
+ client.last_init_time.should be > current_init_time
280
+ end
281
+ end
282
+
283
+ describe "#register_buffer_size=" do
284
+ it "can set the buffer size" do
285
+ client.register_buffer_size=(10)
286
+ client.register_buffer_size.should == 10
287
+ end
288
+
289
+ it "cannot set an invalid buffer size" do
290
+ default_buffer_size = 20
291
+ client.register_buffer_size=(-1)
292
+ client.register_buffer_size.should == default_buffer_size
293
+
294
+ client.register_buffer_size=(0)
295
+ client.register_buffer_size.should == default_buffer_size
296
+
297
+ client.register_buffer_size=(101)
298
+ client.register_buffer_size.should == default_buffer_size
299
+
300
+ client.register_buffer_size=(1)
301
+ client.register_buffer_size.should == 1
302
+
303
+ client.register_buffer_size=(100)
304
+ client.register_buffer_size.should == 100
305
+ end
306
+ end
307
+
308
+
309
+ describe "#get_apn_apps" do
310
+ it "can return a list of apps with name and app key" do
311
+ FakeWeb.register_uri(:get, "#{@apn_endpoint}apps", :body => json_valid_apn_apps)
312
+ expect do
313
+ response = client.get_apn_apps
314
+ FakeWeb.last_request.body.should be_nil
315
+ response.should == json_parse(json_valid_apn_apps)
316
+ end.should_not raise_error
317
+ end
318
+ end
319
+ end
@@ -0,0 +1,19 @@
1
+ # Copyright 2012 Mail Bypass, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ # not use this file except in compliance with the License. You may obtain
5
+ # a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+ # License for the specific language governing permissions and limitations
13
+ # under the License.
14
+
15
+ class Hash
16
+ def without(key)
17
+ self.dup.tap{|hash| hash.delete(key)}
18
+ end
19
+ end
@@ -0,0 +1,42 @@
1
+ # Copyright 2012 Mail Bypass, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ # not use this file except in compliance with the License. You may obtain
5
+ # a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+ # License for the specific language governing permissions and limitations
13
+ # under the License.
14
+
15
+ dir = File.dirname(__FILE__)
16
+
17
+ require 'rubygems'
18
+ require 'fakeweb'
19
+ require 'rr'
20
+ require 'json'
21
+
22
+ require "#{dir}/spec_core_extensions"
23
+ require "#{dir}/../lib/messagebus_ruby_apn_api"
24
+
25
+ def json_valid_apn_send
26
+ json = <<JAVASCRIPT
27
+ {"statusCode":202,"statusMessage":"","statusTime":"2011-09-19T22:40:45.123Z","successCount":1,"failureCount":0,"results":[{"userName":"mark@messagebus.com","registrationStatus":"0"}]}
28
+ JAVASCRIPT
29
+ json
30
+ end
31
+
32
+ def json_valid_apn_register
33
+ json = <<JAVASCRIPT
34
+ {"statusCode":202,"statusMessage":"","statusTime":"2011-09-19T22:40:45.123Z","successCount":1,"failureCount":0,"results":[{"userName":"mark@messagebus.com","platform":"ios","messageStatus":0}]}
35
+ JAVASCRIPT
36
+ end
37
+
38
+ def json_valid_apn_apps
39
+ json = <<JAVASCRIPT
40
+ {"statusCode":202, "statusMessage":"", "statusTime":"2011-09-19T22:40:45.123Z","results":[{"appName":"Sample App","appKey":"<app key>"}]}
41
+ JAVASCRIPT
42
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: messagebus_ruby_apn_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Message Bus dev team
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-02 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: ! 'Allows you to use the Message Bus API '
15
+ email:
16
+ - messagebus@googlegroups.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/messagebus_ruby_apn_api/errors.rb
22
+ - lib/messagebus_ruby_apn_api/messagebus.rb
23
+ - lib/messagebus_ruby_apn_api/version.rb
24
+ - lib/messagebus_ruby_apn_api.rb
25
+ - spec/messagebus_ruby_apn_api/cacert.pem
26
+ - spec/messagebus_ruby_apn_api/messagebus_spec.rb
27
+ - spec/spec_core_extensions.rb
28
+ - spec/spec_helper.rb
29
+ - README.rdoc
30
+ - Gemfile
31
+ - Rakefile
32
+ - .rvmrc
33
+ homepage: ''
34
+ licenses:
35
+ - APACHE2
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project: messagebus_ruby_apn_api
54
+ rubygems_version: 1.8.15
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: Send application push notifications through the Message Bus service
58
+ test_files:
59
+ - spec/messagebus_ruby_apn_api/cacert.pem
60
+ - spec/messagebus_ruby_apn_api/messagebus_spec.rb
61
+ - spec/spec_core_extensions.rb
62
+ - spec/spec_helper.rb