mercurius 0.1.5 → 0.1.6
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.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/lib/mercurius.rb +2 -0
- data/lib/mercurius/apns/connection.rb +0 -2
- data/lib/mercurius/apns/notification.rb +10 -10
- data/lib/mercurius/apns/pem.rb +0 -2
- data/lib/mercurius/apns/service.rb +0 -2
- data/lib/mercurius/errors/invalid_apns_mode_error.rb +0 -2
- data/lib/mercurius/errors/pem_not_configured_error.rb +1 -3
- data/lib/mercurius/errors/pem_not_found_error.rb +1 -3
- data/lib/mercurius/errors/too_many_retries_error.rb +0 -2
- data/lib/mercurius/gcm/notification.rb +6 -20
- data/lib/mercurius/gcm/response.rb +33 -27
- data/lib/mercurius/gcm/response_collection.rb +28 -0
- data/lib/mercurius/gcm/result.rb +14 -15
- data/lib/mercurius/gcm/result_collection.rb +33 -0
- data/lib/mercurius/gcm/service.rb +17 -18
- data/lib/mercurius/version.rb +1 -1
- data/mercurius.gemspec +1 -1
- data/spec/lib/gcm_notification_spec.rb +2 -8
- data/spec/lib/gcm_response_spec.rb +74 -17
- data/spec/lib/gcm_result_collection_spec.rb +32 -0
- data/spec/lib/gcm_result_spec.rb +43 -7
- data/spec/lib/gcm_service_spec.rb +38 -19
- data/spec/lib/testing_spec.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ab94d197c802c11b53e6fc8dc34090237b456af
|
4
|
+
data.tar.gz: 4dbcf381ccc7185f1cb27514ac24ff3d80bf8332
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 098bd1d77a6e27e53e52cc873aeee6b8428569d47fbf855af51cd2624ab0470c7cfede9e0dc8b1e092100e779d78c6d0843751bacbba837e332102b2351e77f7
|
7
|
+
data.tar.gz: fee9b5c35b361e65a8d4496e9127f5627b2078ab249349477b9827fe24855125c0664bf66fc5946735d2a7fc7539eb87d9856cfd3d8f8904724c5165b08f21a3
|
data/README.md
CHANGED
@@ -28,14 +28,14 @@ Create the service with:
|
|
28
28
|
|
29
29
|
Now create the notification that you wish to send:
|
30
30
|
|
31
|
-
gcm_notification = GCM::Notification.new(alert: 'Hey')
|
31
|
+
gcm_notification = GCM::Notification.new(data: { alert: 'Hey' })
|
32
32
|
|
33
33
|
You can deliver the gcm_notification in the following manners:
|
34
34
|
|
35
|
-
gcm_service.deliver gcm_notification, 'token123'
|
36
|
-
gcm_service.deliver gcm_notification, 'token123', 'token456'
|
37
|
-
|
38
|
-
gcm_service.deliver gcm_notification,
|
35
|
+
gcm_service.deliver gcm_notification, 'token123' # single recipient
|
36
|
+
gcm_service.deliver gcm_notification, 'token123', 'token456' # multiple recipients
|
37
|
+
gcm_service.deliver gcm_notification, ['token123', 'token456'] # multiple recipients
|
38
|
+
gcm_service.deliver gcm_notification, topic: 'topic123' # topic delivery
|
39
39
|
|
40
40
|
## APNS
|
41
41
|
|
data/bin/rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rake' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rake', 'rake')
|
data/bin/rspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'rspec' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('rspec-core', 'rspec')
|
data/lib/mercurius.rb
CHANGED
@@ -23,4 +23,6 @@ require 'mercurius/gcm/connection'
|
|
23
23
|
require 'mercurius/gcm/notification'
|
24
24
|
require 'mercurius/gcm/service'
|
25
25
|
require 'mercurius/gcm/response'
|
26
|
+
require 'mercurius/gcm/response_collection'
|
27
|
+
require 'mercurius/gcm/result_collection'
|
26
28
|
require 'mercurius/gcm/result'
|
@@ -34,13 +34,11 @@ module APNS
|
|
34
34
|
end
|
35
35
|
|
36
36
|
private
|
37
|
-
|
38
37
|
def ssl_context_for_pem(pem)
|
39
38
|
context = OpenSSL::SSL::SSLContext.new
|
40
39
|
context.cert = OpenSSL::X509::Certificate.new(pem.data)
|
41
40
|
context.key = OpenSSL::PKey::RSA.new(pem.data, pem.password)
|
42
41
|
context
|
43
42
|
end
|
44
|
-
|
45
43
|
end
|
46
44
|
end
|
@@ -26,16 +26,6 @@ module APNS
|
|
26
26
|
[0, 0, 32, package_device_token(device_token), 0, packaged_message.bytesize, packaged_message].pack("ccca*cca*")
|
27
27
|
end
|
28
28
|
|
29
|
-
def package_device_token(device_token)
|
30
|
-
[device_token.gsub(/[\s|<|>]/,'')].pack('H*')
|
31
|
-
end
|
32
|
-
|
33
|
-
def packaged_message
|
34
|
-
{ aps: payload }.to_json.gsub(/\\u([\da-fA-F]{4})/) do |m|
|
35
|
-
[$1].pack("H*").unpack("n*").pack("U*")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
29
|
def ==(that)
|
40
30
|
attributes == that.attributes
|
41
31
|
end
|
@@ -44,5 +34,15 @@ module APNS
|
|
44
34
|
packaged_message.bytesize <= MAX_PAYLOAD_BYTES
|
45
35
|
end
|
46
36
|
|
37
|
+
private
|
38
|
+
def package_device_token(device_token)
|
39
|
+
[device_token.gsub(/[\s|<|>]/,'')].pack('H*')
|
40
|
+
end
|
41
|
+
|
42
|
+
def packaged_message
|
43
|
+
{ aps: payload }.to_json.gsub(/\\u([\da-fA-F]{4})/) do |m|
|
44
|
+
[$1].pack("H*").unpack("n*").pack("U*")
|
45
|
+
end
|
46
|
+
end
|
47
47
|
end
|
48
48
|
end
|
data/lib/mercurius/apns/pem.rb
CHANGED
@@ -1,36 +1,22 @@
|
|
1
1
|
module GCM
|
2
2
|
class Notification
|
3
3
|
include ActiveModel::Model
|
4
|
-
|
5
|
-
def self.special_attrs
|
6
|
-
[:collapse_key, :time_to_live, :delay_while_idle, :dry_run, :notification]
|
7
|
-
end
|
8
|
-
|
9
|
-
attr_accessor :data
|
10
|
-
attr_accessor *special_attrs
|
11
|
-
# validate delay_while_idle is true/false
|
12
|
-
# validate ttl is integer in seconds
|
4
|
+
attr_accessor :attributes
|
13
5
|
|
14
6
|
def initialize(attributes = {})
|
15
7
|
@attributes = attributes
|
16
|
-
super @attributes.slice(*self.class.special_attrs).merge(data: @attributes.except(*self.class.special_attrs))
|
17
8
|
end
|
18
9
|
|
19
10
|
def to_h
|
20
|
-
|
21
|
-
notification: notification,
|
22
|
-
data: data,
|
23
|
-
collapse_key: collapse_key,
|
24
|
-
time_to_live: time_to_live,
|
25
|
-
delay_while_idle: delay_while_idle,
|
26
|
-
dry_run: dry_run
|
27
|
-
}
|
28
|
-
|
29
|
-
hash.reject { |k, v| v.nil? }
|
11
|
+
@attributes
|
30
12
|
end
|
31
13
|
|
32
14
|
def ==(that)
|
33
15
|
attributes == that.attributes
|
34
16
|
end
|
17
|
+
|
18
|
+
def method_missing(method, *args, &block)
|
19
|
+
@attributes.fetch(method) { super }
|
20
|
+
end
|
35
21
|
end
|
36
22
|
end
|
@@ -1,49 +1,55 @@
|
|
1
1
|
module GCM
|
2
2
|
class Response
|
3
|
-
attr_reader :response, :
|
4
|
-
|
5
|
-
|
6
|
-
200 => 'Success',
|
7
|
-
400 => 'The request could not be parsed as JSON or it contained invalid fields',
|
8
|
-
401 => 'There was an error authenticating the sender account',
|
9
|
-
500 => 'There was an internal error in the GCM server',
|
10
|
-
503 => 'GCM server is temporarily unavailable',
|
11
|
-
default: 'Unknown error'
|
12
|
-
}
|
13
|
-
|
14
|
-
def initialize(response, device_tokens)
|
3
|
+
attr_reader :response, :tokens
|
4
|
+
|
5
|
+
def initialize(response, tokens = [])
|
15
6
|
@response = response
|
16
|
-
@
|
7
|
+
@tokens = tokens
|
17
8
|
end
|
18
9
|
|
19
10
|
def status
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def message
|
24
|
-
MESSAGES.fetch(status, MESSAGES[:default])
|
11
|
+
response.status
|
25
12
|
end
|
26
13
|
|
27
14
|
def success?
|
28
|
-
|
15
|
+
response.success?
|
29
16
|
end
|
30
17
|
|
31
|
-
def
|
18
|
+
def fail?
|
32
19
|
!success?
|
33
20
|
end
|
34
21
|
|
35
|
-
def
|
36
|
-
|
22
|
+
def results
|
23
|
+
@_results ||= begin
|
24
|
+
results = to_h.fetch 'results', []
|
25
|
+
results.map!.with_index do |attributes, i|
|
26
|
+
GCM::Result.new attributes, tokens[i]
|
27
|
+
end
|
28
|
+
ResultCollection.new(results)
|
29
|
+
end
|
37
30
|
end
|
38
31
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
32
|
+
def error
|
33
|
+
case status
|
34
|
+
when 401
|
35
|
+
'Authentication error with GCM. Check the server whitelist and the validity of your project key.'
|
36
|
+
when 400
|
37
|
+
'Invalid JSON was sent to GCM.'
|
38
|
+
when 500..599
|
39
|
+
'GCM Internal server error.'
|
40
|
+
else
|
41
|
+
nil
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
def
|
46
|
-
|
45
|
+
def retry_after
|
46
|
+
response.headers['Retry-After']
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_h
|
50
|
+
JSON.parse response.body
|
51
|
+
rescue JSON::ParserError
|
52
|
+
{}
|
47
53
|
end
|
48
54
|
end
|
49
55
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module GCM
|
2
|
+
class ResponseCollection
|
3
|
+
attr_reader :recommendations
|
4
|
+
|
5
|
+
def initialize(notification, responses = [])
|
6
|
+
@responses = responses
|
7
|
+
@notification = notification
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](index)
|
11
|
+
@responses[index]
|
12
|
+
end
|
13
|
+
|
14
|
+
def <<(response)
|
15
|
+
@responses.concat Array(response).flatten
|
16
|
+
end
|
17
|
+
|
18
|
+
def results
|
19
|
+
out = GCM::ResultCollection.new
|
20
|
+
@responses.map do |response|
|
21
|
+
response.results.each do |result|
|
22
|
+
out << result
|
23
|
+
end
|
24
|
+
end
|
25
|
+
out
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/mercurius/gcm/result.rb
CHANGED
@@ -1,30 +1,29 @@
|
|
1
1
|
module GCM
|
2
2
|
class Result
|
3
|
-
|
3
|
+
include ActiveModel::Model
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
@responses = []
|
8
|
-
end
|
5
|
+
attr_accessor :message_id, :registration_id, :error
|
6
|
+
attr_reader :token
|
9
7
|
|
10
|
-
def
|
11
|
-
|
8
|
+
def initialize(attributes, token)
|
9
|
+
super attributes
|
10
|
+
@token = token
|
12
11
|
end
|
13
12
|
|
14
|
-
def
|
15
|
-
|
13
|
+
def success?
|
14
|
+
message_id.present?
|
16
15
|
end
|
17
16
|
|
18
|
-
def
|
19
|
-
|
17
|
+
def fail?
|
18
|
+
!success?
|
20
19
|
end
|
21
20
|
|
22
|
-
def
|
23
|
-
|
21
|
+
def canonical_id
|
22
|
+
registration_id
|
24
23
|
end
|
25
24
|
|
26
|
-
def
|
27
|
-
|
25
|
+
def has_canonical_id?
|
26
|
+
canonical_id.present?
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module GCM
|
2
|
+
class ResultCollection
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(results = [])
|
6
|
+
@results = results
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](index)
|
10
|
+
@results[index]
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
@results.each &block
|
15
|
+
end
|
16
|
+
|
17
|
+
def succeeded
|
18
|
+
@results.select &:success?
|
19
|
+
end
|
20
|
+
|
21
|
+
def failed
|
22
|
+
@results.select &:fail?
|
23
|
+
end
|
24
|
+
|
25
|
+
def with_canonical_ids
|
26
|
+
@results.select &:has_canonical_id?
|
27
|
+
end
|
28
|
+
|
29
|
+
def <<(result)
|
30
|
+
@results << result
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -2,8 +2,7 @@ module GCM
|
|
2
2
|
class Service
|
3
3
|
include ActiveModel::Model
|
4
4
|
|
5
|
-
|
6
|
-
MAX_DEVICES_AT_ONCE = 999
|
5
|
+
BATCH_SIZE = 999
|
7
6
|
|
8
7
|
attr_accessor :host, :key
|
9
8
|
attr_reader :connection, :attempts
|
@@ -16,27 +15,27 @@ module GCM
|
|
16
15
|
@attempts = 0
|
17
16
|
end
|
18
17
|
|
19
|
-
def deliver(notification, *
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
result.process_response connection.write(payload), tokens
|
25
|
-
end
|
26
|
-
result
|
27
|
-
end
|
28
|
-
|
29
|
-
def deliver_topic(notification, topic)
|
30
|
-
GCM::Result.new(notification).tap do |result|
|
31
|
-
result.process_response connection.write(notification.to_h.merge(to: topic)), [topic]
|
32
|
-
end
|
18
|
+
def deliver(notification, *tokens, topic: nil)
|
19
|
+
responses = GCM::ResponseCollection.new(notification)
|
20
|
+
responses << deliver_to_tokens(notification, tokens)
|
21
|
+
responses << deliver_to_topic(notification, topic) if topic
|
22
|
+
responses
|
33
23
|
end
|
34
24
|
|
35
25
|
private
|
26
|
+
def each_batch_of_tokens(tokens, batch_size: BATCH_SIZE, &block)
|
27
|
+
Array(tokens).flatten.compact.each_slice(batch_size)
|
28
|
+
end
|
36
29
|
|
37
|
-
def
|
38
|
-
|
30
|
+
def deliver_to_tokens(notification, tokens)
|
31
|
+
each_batch_of_tokens(tokens).map do |tokens|
|
32
|
+
payload = notification.to_h.merge registration_ids: tokens
|
33
|
+
GCM::Response.new(connection.write(payload), tokens)
|
34
|
+
end
|
39
35
|
end
|
40
36
|
|
37
|
+
def deliver_to_topic(notification, topic)
|
38
|
+
GCM::Response.new connection.write(notification.to_h.merge(to: topic))
|
39
|
+
end
|
41
40
|
end
|
42
41
|
end
|
data/lib/mercurius/version.rb
CHANGED
data/mercurius.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
|
19
19
|
s.files = `git ls-files`.split("\n")
|
20
20
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
-
s.executables = `git ls-files --
|
21
|
+
s.executables = `git ls-files -- exe/*`.split("\n").map{ |f| File.basename(f) }
|
22
22
|
|
23
23
|
s.require_paths = ["lib"]
|
24
24
|
s.required_ruby_version = '~> 2.0'
|
@@ -1,17 +1,11 @@
|
|
1
1
|
describe GCM::Notification do
|
2
2
|
describe 'with attributes' do
|
3
|
-
it '
|
3
|
+
it 'delegates methods to the attributes hash' do
|
4
4
|
notification = GCM::Notification.new({ collapse_key: 'some_key', time_to_live: 123, delay_while_idle: true, dry_run: true })
|
5
5
|
expect(notification.collapse_key).to eq 'some_key'
|
6
6
|
expect(notification.time_to_live).to eq 123
|
7
7
|
expect(notification.delay_while_idle).to eq true
|
8
8
|
expect(notification.dry_run).to eq true
|
9
9
|
end
|
10
|
-
|
11
|
-
it 'should move other attributes to data' do
|
12
|
-
notification = GCM::Notification.new({ message: 'hello', dry_run: true})
|
13
|
-
expect(notification.dry_run).to eq true
|
14
|
-
expect(notification.data).to eq({ message: 'hello' })
|
15
|
-
end
|
16
10
|
end
|
17
|
-
end
|
11
|
+
end
|
@@ -1,25 +1,82 @@
|
|
1
1
|
describe GCM::Response do
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
allow(subject).to receive(:response_body) { OpenStruct.new canonical_ids: 1 }
|
6
|
-
expect(subject.has_canonical_ids?).to be_truthy
|
2
|
+
class FakeResponse < Struct.new(:hash, :success)
|
3
|
+
def body; hash.to_json; end
|
4
|
+
def success?; success; end
|
7
5
|
end
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
let(:json) { Hash.new }
|
8
|
+
let(:success) { true }
|
9
|
+
let(:tokens) { ['token123', 'token456'] }
|
10
|
+
|
11
|
+
let(:response) do
|
12
|
+
GCM::Response.new FakeResponse.new(json, success), tokens
|
12
13
|
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
describe '#results' do
|
16
|
+
let(:json) do
|
17
|
+
{
|
18
|
+
multicast_id: 108, success: 2, failure: 1, canonical_ids: 1, results: [
|
19
|
+
{ message_id: '1' },
|
20
|
+
{ message_id: '2', registration_id: 'canonicalToken456' },
|
21
|
+
{ error: 'DeviceMessageRateExceeded' }
|
22
|
+
]
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns an array of the results in a response' do
|
27
|
+
expect(response.results.count).to eq 3
|
28
|
+
expect(response.results[0].message_id).to eq '1'
|
29
|
+
expect(response.results[0].token).to eq 'token123'
|
30
|
+
expect(response.results[1].message_id).to eq '2'
|
31
|
+
expect(response.results[1].token).to eq 'token456'
|
32
|
+
expect(response.results[1].canonical_id).to eq 'canonicalToken456'
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'ResultCollection#succeeded' do
|
36
|
+
subject { response.results.succeeded }
|
37
|
+
|
38
|
+
it 'returns only the successful results' do
|
39
|
+
expect(subject.count).to eq 2
|
40
|
+
expect(subject[0].message_id).to eq '1'
|
41
|
+
expect(subject[1].message_id).to eq '2'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'ResultCollection#failed' do
|
46
|
+
subject { response.results.failed }
|
47
|
+
|
48
|
+
it 'returns only the failed results' do
|
49
|
+
expect(subject.count).to eq 1
|
50
|
+
expect(subject[0].error).to eq 'DeviceMessageRateExceeded'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'ResultCollection#with_canonical_ids' do
|
55
|
+
subject { response.results.with_canonical_ids }
|
56
|
+
|
57
|
+
it 'returns only the results with canonical ids' do
|
58
|
+
expect(subject.count).to eq 1
|
59
|
+
expect(subject[0].token).to eq 'token456'
|
60
|
+
expect(subject[0].canonical_id).to eq 'canonicalToken456'
|
61
|
+
end
|
62
|
+
end
|
17
63
|
end
|
18
64
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
65
|
+
describe '#success?' do
|
66
|
+
context 'Faraday response is successful' do
|
67
|
+
let(:success) { true }
|
68
|
+
|
69
|
+
it 'returns true' do
|
70
|
+
expect(response).to be_success
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'Faraday response is not successful' do
|
75
|
+
let(:success) { false }
|
76
|
+
|
77
|
+
it 'returns false' do
|
78
|
+
expect(response).to_not be_success
|
79
|
+
end
|
80
|
+
end
|
24
81
|
end
|
25
|
-
end
|
82
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
describe GCM::ResultCollection do
|
2
|
+
subject do
|
3
|
+
GCM::ResultCollection.new [
|
4
|
+
GCM::Result.new({ message_id: '1' }, 'token123'),
|
5
|
+
GCM::Result.new({ message_id: '2', registration_id: 'canonicalToken456' }, 'token456'),
|
6
|
+
GCM::Result.new({ error: 'DeviceMessageRateExceeded' }, nil)
|
7
|
+
]
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#succeeded' do
|
11
|
+
it 'returns only the successful results' do
|
12
|
+
expect(subject.succeeded.count).to eq 2
|
13
|
+
expect(subject.succeeded[0].message_id).to eq '1'
|
14
|
+
expect(subject.succeeded[1].message_id).to eq '2'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#failed' do
|
19
|
+
it 'returns only the failed results' do
|
20
|
+
expect(subject.failed.count).to eq 1
|
21
|
+
expect(subject.failed[0].error).to eq 'DeviceMessageRateExceeded'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#with_canonical_ids' do
|
26
|
+
it 'returns only the results with canonical ids' do
|
27
|
+
expect(subject.with_canonical_ids.count).to eq 1
|
28
|
+
expect(subject.with_canonical_ids[0].token).to eq 'token456'
|
29
|
+
expect(subject.with_canonical_ids[0].canonical_id).to eq 'canonicalToken456'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/spec/lib/gcm_result_spec.rb
CHANGED
@@ -1,13 +1,49 @@
|
|
1
1
|
describe GCM::Result do
|
2
|
-
|
2
|
+
describe '#canonical_id' do
|
3
|
+
it 'returns the registration_id from the GCM response JSON' do
|
4
|
+
result = GCM::Result.new({ message_id: '1:08', registration_id: 'canonicalToken123' }, nil)
|
5
|
+
expect(result.canonical_id).to eq 'canonicalToken123'
|
6
|
+
end
|
3
7
|
|
4
|
-
|
5
|
-
|
6
|
-
|
8
|
+
it 'returns nil if no canonical ID is given by GCM' do
|
9
|
+
result = GCM::Result.new({ message_id: '1:08' }, nil)
|
10
|
+
expect(result.canonical_id).to be_nil
|
11
|
+
end
|
7
12
|
end
|
8
13
|
|
9
|
-
|
10
|
-
|
11
|
-
|
14
|
+
describe '#has_canonical_id?' do
|
15
|
+
it 'returns true when canonical_id is given by GCM' do
|
16
|
+
result = GCM::Result.new({ message_id: '1:08', registration_id: 'canonicalToken123' }, nil)
|
17
|
+
expect(result.has_canonical_id?).to be_truthy
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns false when canonical_id is not given by GCM' do
|
21
|
+
result = GCM::Result.new({ message_id: '1:08' }, nil)
|
22
|
+
expect(result.has_canonical_id?).to be_falsey
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#success?' do
|
27
|
+
it 'returns true when the message is sent and returned with a message id' do
|
28
|
+
result = GCM::Result.new({ message_id: '1:08' }, nil)
|
29
|
+
expect(result).to be_success
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns false otherwise' do
|
33
|
+
result = GCM::Result.new({ error: 'DeviceMessageRateExceeded' }, nil)
|
34
|
+
expect(result).to_not be_success
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#error' do
|
39
|
+
it 'returns the error from GCM' do
|
40
|
+
result = GCM::Result.new({ error: 'DeviceMessageRateExceeded' }, nil)
|
41
|
+
expect(result.error).to eq 'DeviceMessageRateExceeded'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns nil when there is no error' do
|
45
|
+
result = GCM::Result.new({ message_id: '1:08' }, nil)
|
46
|
+
expect(result.error).to be_nil
|
47
|
+
end
|
12
48
|
end
|
13
49
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
describe GCM::Service do
|
2
2
|
let(:service) { GCM::Service.new }
|
3
|
-
let(:message) { GCM::Notification.new(alert: 'Hey') }
|
3
|
+
let(:message) { GCM::Notification.new(data: { alert: 'Hey' }) }
|
4
4
|
|
5
5
|
it 'should default to the GCM module configs' do
|
6
6
|
expect(service.host).to eq GCM.host
|
@@ -34,7 +34,7 @@ describe GCM::Service do
|
|
34
34
|
expect(WebMock).to have_requested(:post, %r[android.googleapis.com/gcm/send]).
|
35
35
|
with(body: { data: { alert: 'Hey' }, registration_ids: tokens.take(999) })
|
36
36
|
expect(WebMock).to have_requested(:post, %r[android.googleapis.com/gcm/send]).
|
37
|
-
with(body: { data: { alert: 'Hey' }, registration_ids: [
|
37
|
+
with(body: { data: { alert: 'Hey' }, registration_ids: ['token1000'] })
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -43,7 +43,7 @@ describe GCM::Service do
|
|
43
43
|
let(:message) { { notification: { title: 'hello', body: 'world' } } }
|
44
44
|
|
45
45
|
it 'sends a notification to a topic' do
|
46
|
-
service.
|
46
|
+
service.deliver message, topic: '/topics/global'
|
47
47
|
expect(WebMock).to have_requested(:post, %r[android.googleapis.com/gcm/send]).
|
48
48
|
with(body: message.merge(to: '/topics/global'))
|
49
49
|
end
|
@@ -54,28 +54,47 @@ describe GCM::Service do
|
|
54
54
|
before { stub_request :post, %r[android.googleapis.com/gcm/send] }
|
55
55
|
|
56
56
|
it 'processes a 200 response' do
|
57
|
-
|
58
|
-
expect(
|
59
|
-
expect(
|
60
|
-
expect(
|
57
|
+
responses = service.deliver message, 'token123'
|
58
|
+
expect(responses[0].status).to eq 200
|
59
|
+
expect(responses[0].success?).to eq true
|
60
|
+
expect(responses.results.failed).to eq []
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
|
65
|
-
|
64
|
+
describe 'failure' do
|
65
|
+
context 401 do
|
66
|
+
before { stub_request(:post, %r[android.googleapis.com/gcm/send]).to_return(status: 401) }
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
expect(result.failed_device_tokens).to eq ['token123']
|
68
|
+
it 'has a meaningful message from #error' do
|
69
|
+
responses = service.deliver message, 'token123'
|
70
|
+
expect(responses[0].error).to match /Authentication error/
|
71
|
+
end
|
72
72
|
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
context 400 do
|
75
|
+
before { stub_request(:post, %r[android.googleapis.com/gcm/send]).to_return(status: 400) }
|
76
|
+
|
77
|
+
it 'has a meaningful message from #error' do
|
78
|
+
responses = service.deliver message, 'token123'
|
79
|
+
expect(responses[0].error).to match /Invalid JSON/
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 500..599 do
|
84
|
+
before do
|
85
|
+
stub_request(:post, %r[android.googleapis.com/gcm/send]).
|
86
|
+
to_return status: 500, headers: { 'Retry-After' => '120' }
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'has a meaningful message from #error' do
|
90
|
+
responses = service.deliver message, 'token123'
|
91
|
+
expect(responses[0].error).to match /GCM Internal server error/
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'returns the Retry-After header from GCM' do
|
95
|
+
responses = service.deliver message, 'token123'
|
96
|
+
expect(responses[0].retry_after).to eq '120'
|
97
|
+
end
|
79
98
|
end
|
80
99
|
end
|
81
100
|
|
data/spec/lib/testing_spec.rb
CHANGED
@@ -18,7 +18,7 @@ describe 'Test mode' do
|
|
18
18
|
|
19
19
|
context 'GCM' do
|
20
20
|
let(:service) { GCM::MockService.new }
|
21
|
-
let(:message) { GCM::Notification.new(alert: 'Hey') }
|
21
|
+
let(:message) { GCM::Notification.new(data: { alert: 'Hey' }) }
|
22
22
|
|
23
23
|
it 'returns the deliveries sent to GCM' do
|
24
24
|
result = service.deliver message, 'token123'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mercurius
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
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-
|
11
|
+
date: 2015-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -139,6 +139,8 @@ files:
|
|
139
139
|
- LICENSE
|
140
140
|
- README.md
|
141
141
|
- Rakefile
|
142
|
+
- bin/rake
|
143
|
+
- bin/rspec
|
142
144
|
- lib/mercurius.rb
|
143
145
|
- lib/mercurius/apns.rb
|
144
146
|
- lib/mercurius/apns/connection.rb
|
@@ -153,7 +155,9 @@ files:
|
|
153
155
|
- lib/mercurius/gcm/connection.rb
|
154
156
|
- lib/mercurius/gcm/notification.rb
|
155
157
|
- lib/mercurius/gcm/response.rb
|
158
|
+
- lib/mercurius/gcm/response_collection.rb
|
156
159
|
- lib/mercurius/gcm/result.rb
|
160
|
+
- lib/mercurius/gcm/result_collection.rb
|
157
161
|
- lib/mercurius/gcm/service.rb
|
158
162
|
- lib/mercurius/testing.rb
|
159
163
|
- lib/mercurius/testing/base.rb
|
@@ -167,6 +171,7 @@ files:
|
|
167
171
|
- spec/lib/apns_spec.rb
|
168
172
|
- spec/lib/gcm_notification_spec.rb
|
169
173
|
- spec/lib/gcm_response_spec.rb
|
174
|
+
- spec/lib/gcm_result_collection_spec.rb
|
170
175
|
- spec/lib/gcm_result_spec.rb
|
171
176
|
- spec/lib/gcm_service_spec.rb
|
172
177
|
- spec/lib/testing_spec.rb
|
@@ -202,6 +207,7 @@ test_files:
|
|
202
207
|
- spec/lib/apns_spec.rb
|
203
208
|
- spec/lib/gcm_notification_spec.rb
|
204
209
|
- spec/lib/gcm_response_spec.rb
|
210
|
+
- spec/lib/gcm_result_collection_spec.rb
|
205
211
|
- spec/lib/gcm_result_spec.rb
|
206
212
|
- spec/lib/gcm_service_spec.rb
|
207
213
|
- spec/lib/testing_spec.rb
|