fcm 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 566f06986ceeeb5c1feb04bd49988c7d1a1698ed
4
+ data.tar.gz: 60daa74b40a83b9536a54db75b04d8b02b1526f0
5
+ SHA512:
6
+ metadata.gz: 6c58de63c80e324d3425278ebebe22c617be80d2514a8d0a6944bda90a3c6bd06d2de3bb4afd137e1528fc363f97eb8e8671f3e0f7cf73a71381a0a75f60e107
7
+ data.tar.gz: aaf37a387be61be0dbb3a094404204dfcb433549c68757dd4863ea97dbf80be236dcbd7706e298ac5148643af217aa76ad73a7e6eef14a06e009adbb650b2aba
@@ -0,0 +1,50 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # jeweler generated
15
+ pkg
16
+
17
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
18
+ #
19
+ # * Create a file at ~/.gitignore
20
+ # * Include files you want ignored
21
+ # * Run: git config --global core.excludesfile ~/.gitignore
22
+ #
23
+ # After doing this, these files will be ignored in all your git projects,
24
+ # saving you from having to 'pollute' every project you touch with them
25
+ #
26
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
27
+ #
28
+ # For MacOS:
29
+ #
30
+ .DS_Store
31
+ #
32
+ # For TextMate
33
+ #*.tmproj
34
+ #tmtags
35
+ #
36
+ # For emacs:
37
+ #*~
38
+ #\#*
39
+ #.\#*
40
+ #
41
+ # For vim:
42
+ #*.swp
43
+
44
+ bin
45
+ cache
46
+ gems
47
+ specifications
48
+ Gemfile.lock
49
+ .rvmrc
50
+ spec/reports
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 2.1.9
5
+ - 2.2.5
6
+ - 2.3.1
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+ gem 'rake'
5
+ gem 'rspec'
6
+ gem 'webmock'
7
+ gem 'ci_reporter_rspec'
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 Kashif Rasul and Shoaib Burq
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,128 @@
1
+ # Firebase Cloud Messaging (FCM) for Android and iOS
2
+ [![Gem Version](https://badge.fury.io/rb/fcm.svg)](http://badge.fury.io/rb/fcm) [![Build Status](https://secure.travis-ci.org/spacialdb/fcm.png?branch=master)](http://travis-ci.org/spacialdb/fcm)
3
+
4
+ The FCM gem lets your ruby backend send notifications to Android and iOS devices via [
5
+ Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/).
6
+
7
+ ##Installation
8
+
9
+ $ gem install fcm
10
+
11
+ or in your `Gemfile` just include it:
12
+
13
+ ```ruby
14
+ gem 'fcm'
15
+ ```
16
+
17
+ ##Requirements
18
+
19
+ For Android you will need a device running 2.3 (or newer) that also have the Google Play Store app installed, or an emulator running Android 2.3 with Google APIs. iOS devices are also supported.
20
+
21
+ One of the following, tested Ruby versions:
22
+
23
+ * `2.0.0`
24
+ * `2.1.9`
25
+ * `2.2.5`
26
+ * `2.3.1`
27
+
28
+ ##Usage
29
+
30
+ For your server to send a message to one or more devices, you must first initialise a new `FCM` class with your Firebase server Api key, and then call the `send` method on this and give it 1 or more (up to 1000) registration tokens as an array of strings. You can also optionally send further [HTTP message parameters](https://firebase.google.com/docs/cloud-messaging/http-server-ref) like `data` or `time_to_live` etc. as a hash via the second optional argument to `send`.
31
+
32
+ Example sending notifications:
33
+
34
+ ```ruby
35
+ require 'fcm'
36
+
37
+ fcm = FCM.new("my_api_key")
38
+ # you can set option parameters in here
39
+ # - all options are pass to HTTParty method arguments
40
+ # - ref: https://github.com/jnunemaker/httparty/blob/master/lib/httparty.rb#L29-L60
41
+ # fcm = FCM.new("my_api_key", timeout: 3)
42
+
43
+ registration_ids= ["12", "13"] # an array of one or more client registration tokens
44
+ options = {data: {score: "123"}, collapse_key: "updated_score"}
45
+ response = fcm.send(registration_ids, options)
46
+ ```
47
+
48
+ Currently `response` is just a hash containing the response `body`, `headers` and `status`. Check [here](https://firebase.google.com/docs/cloud-messaging/server#response) to see how to interpret the responses.
49
+
50
+ ## Device Group Messaging
51
+
52
+ With [device group messaging](https://firebase.google.com/docs/cloud-messaging/notifications), you can send a single message to multiple instance of an app running on devices belonging to a group. Typically, "group" refers a set of different devices that belong to a single user. However, a group could also represent a set of devices where the app instance functions in a highly correlated manner. To use this feature, you will first need an initialised `FCM` class.
53
+
54
+ ### Generate a Notification Key for device group
55
+ Then you will need a notification key which you can create for a particular `key_name` which needs to be uniquely named per app in case you have multiple apps for the same `project_id`. This ensures that notifications only go to the intended target app. The `create` method will do this and return the token `notification_key`, that represents the device group, in the response:
56
+
57
+ ```ruby
58
+ response = fcm.create(key_name: "appUser-Chris",
59
+ project_id: "my_project_id",
60
+ registration_ids:["4", "8", "15", "16", "23", "42"])
61
+ ```
62
+
63
+ ### Send to Notification Key
64
+ Now you can send a message to a particular `notification_key` via the `send_with_notification_key` method. This allows the server to send a single data to multiple app instances (typically on multiple devices) owned by a single user (instead of sending to some registration tokens). Note: the maximum number of members allowed for a `notification_key` is 20.
65
+
66
+ ```ruby
67
+ response = fcm.send_with_notification_key("notification_key", {
68
+ data: {score: "3x1"},
69
+ collapse_key: "updated_score"})
70
+ ```
71
+
72
+ ### Add/Remove Registration Tokens
73
+
74
+ You can also add/remove registration Tokens to/from a particular `notification_key` of some `project_id`. For example:
75
+
76
+ ```ruby
77
+ response = fcm.add(key_name: "appUser-Chris",
78
+ project_id: "my_project_id",
79
+ notification_key:"appUser-Chris-key",
80
+ registration_ids:["7", "3"])
81
+
82
+ response = fcm.remove(key_name: "appUser-Chris",
83
+ project_id: "my_project_id",
84
+ notification_key:"appUser-Chris-key",
85
+ registration_ids:["8", "15"])
86
+ ```
87
+
88
+ ## Send Messages to Topics
89
+
90
+ FCM [topic messaging](https://firebase.google.com/docs/cloud-messaging/topic-messaging) allows your app server to send a message to multiple devices that have opted in to a particular topic. Based on the publish/subscribe model, topic messaging supports unlimited subscriptions per app. Sending to a topic is very similar to sending to an individual device or to a user group, in the sense that you can use the `fcm.send_with_notification_key()` method where the `noticiation_key` matches the regular expression `"/topics/[a-zA-Z0-9-_.~%]+"`:
91
+
92
+ ```ruby
93
+ response = fcm.send_with_notification_key("/topics/yourTopic", {
94
+ data: {message: "This is a FCM Topic Message!"})
95
+ ```
96
+
97
+ Or you can use the helper:
98
+
99
+ ```ruby
100
+ response = fcm.send_to_topic("yourTopic", {
101
+ data: {message: "This is a FCM Topic Message!"})
102
+ ```
103
+
104
+ ## Mobile Clients
105
+
106
+ You can find a guide to implement an Android Client app to receive notifications here: [Set up a FCM Client App on Android](https://firebase.google.com/docs/cloud-messaging/android/client).
107
+
108
+ The guide to set up an iOS app to get notifications is here: [Setting up a FCM Client App on iOS](https://firebase.google.com/docs/cloud-messaging/ios/client).
109
+
110
+ ## ChangeLog
111
+
112
+ ### 0.0.1
113
+
114
+ * Initial version.
115
+
116
+
117
+ ##MIT License
118
+
119
+ * Copyright (c) 2016 Kashif Rasul and Shoaib Burq. See LICENSE.txt for details.
120
+
121
+ ##Many thanks to all the contributors
122
+
123
+ * [Contributors](https://github.com/spacialdb/fcm/contributors)
124
+
125
+ ## Donations
126
+ We accept tips through [Gratipay](https://gratipay.com/spacialdb/).
127
+
128
+ [![Gratipay](https://img.shields.io/gratipay/spacialdb.svg)](https://www.gittip.com/spacialdb/)
@@ -0,0 +1,15 @@
1
+ require 'rspec/core/rake_task'
2
+ require "bundler/gem_tasks"
3
+ require "rake/tasklib"
4
+ require 'ci/reporter/rake/rspec'
5
+
6
+ RSpec::Core::RakeTask.new(:spec => ["ci:setup:rspec"]) do |t|
7
+ t.pattern = 'spec/**/*_spec.rb'
8
+ end
9
+
10
+ RSpec::Core::RakeTask.new(:spec) do |spec|
11
+ spec.pattern = 'spec/**/*_spec.rb'
12
+ spec.rspec_opts = ['--format documentation']
13
+ end
14
+
15
+ task :default => :spec
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "fcm"
6
+ s.version = "0.0.1"
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Kashif Rasul", "Shoaib Burq"]
9
+ s.email = ["kashif@spacialdb.com", "shoaib@spacialdb.com"]
10
+ s.homepage = "https://github.com/spacialdb/fcm"
11
+ s.summary = %q{Reliably deliver messages and notifications via FCM}
12
+ s.description = %q{fcm provides ruby bindings to Firebase Cloud Messaging (FCM) a cross-platform messaging solution that lets you reliably deliver messages and notifications at no cost to Android, iOS or Web browsers.}
13
+ s.license = "MIT"
14
+
15
+ s.required_ruby_version = '>= 2.0.0'
16
+
17
+ s.rubyforge_project = "fcm"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+
24
+ s.add_dependency('httparty')
25
+ s.add_dependency('json')
26
+ end
@@ -0,0 +1,179 @@
1
+ require 'httparty'
2
+ require 'cgi'
3
+ require 'json'
4
+
5
+ class FCM
6
+ include HTTParty
7
+ base_uri 'https://fcm.googleapis.com/fcm'
8
+ default_timeout 30
9
+ format :json
10
+
11
+ attr_accessor :timeout, :api_key
12
+
13
+ def initialize(api_key, client_options = {})
14
+ @api_key = api_key
15
+ @client_options = client_options
16
+ end
17
+
18
+ # {
19
+ # "collapse_key": "score_update",
20
+ # "time_to_live": 108,
21
+ # "delay_while_idle": true,
22
+ # "registration_ids": ["4", "8", "15", "16", "23", "42"],
23
+ # "data" : {
24
+ # "score": "5x1",
25
+ # "time": "15:10"
26
+ # }
27
+ # }
28
+ # fcm = FCM.new("API_KEY")
29
+ # fcm.send(registration_ids: ["4sdsx", "8sdsd"], {data: {score: "5x1"}})
30
+ def send_notification(registration_ids, options = {})
31
+ post_body = build_post_body(registration_ids, options)
32
+
33
+ params = {
34
+ body: post_body.to_json,
35
+ headers: {
36
+ 'Authorization' => "key=#{@api_key}",
37
+ 'Content-Type' => 'application/json'
38
+ }
39
+ }
40
+ response = self.class.post('/send', params.merge(@client_options))
41
+ build_response(response, registration_ids)
42
+ end
43
+ alias send send_notification
44
+
45
+ def create_notification_key(key_name, project_id, registration_ids = [])
46
+ post_body = build_post_body(registration_ids, operation: 'create',
47
+ notification_key_name: key_name)
48
+
49
+ params = {
50
+ body: post_body.to_json,
51
+ headers: {
52
+ 'Content-Type' => 'application/json',
53
+ 'project_id' => project_id,
54
+ 'Authorization' => "key=#{@api_key}"
55
+ }
56
+ }
57
+
58
+ response = self.class.post('/notification', params.merge(@client_options))
59
+ build_response(response)
60
+ end
61
+ alias create create_notification_key
62
+
63
+ def add_registration_ids(key_name, project_id, notification_key, registration_ids)
64
+ post_body = build_post_body(registration_ids, operation: 'add',
65
+ notification_key_name: key_name,
66
+ notification_key: notification_key)
67
+
68
+ params = {
69
+ body: post_body.to_json,
70
+ headers: {
71
+ 'Content-Type' => 'application/json',
72
+ 'project_id' => project_id,
73
+ 'Authorization' => "key=#{@api_key}"
74
+ }
75
+ }
76
+
77
+ response = self.class.post('/notification', params.merge(@client_options))
78
+ build_response(response)
79
+ end
80
+ alias add add_registration_ids
81
+
82
+ def remove_registration_ids(key_name, project_id, notification_key, registration_ids)
83
+ post_body = build_post_body(registration_ids, operation: 'remove',
84
+ notification_key_name: key_name,
85
+ notification_key: notification_key)
86
+
87
+ params = {
88
+ body: post_body.to_json,
89
+ headers: {
90
+ 'Content-Type' => 'application/json',
91
+ 'project_id' => project_id,
92
+ 'Authorization' => "key=#{@api_key}"
93
+ }
94
+ }
95
+
96
+ response = self.class.post('/notification', params.merge(@client_options))
97
+ build_response(response)
98
+ end
99
+ alias remove remove_registration_ids
100
+
101
+ def send_with_notification_key(notification_key, options = {})
102
+ body = { to: notification_key }.merge(options)
103
+
104
+ params = {
105
+ body: body.to_json,
106
+ headers: {
107
+ 'Authorization' => "key=#{@api_key}",
108
+ 'Content-Type' => 'application/json'
109
+ }
110
+ }
111
+ response = self.class.post('/send', params.merge(@client_options))
112
+ build_response(response)
113
+ end
114
+
115
+ def send_to_topic(topic, options = {})
116
+ if topic =~ /[a-zA-Z0-9\-_.~%]+/
117
+ send_with_notification_key('/topics/' + topic, options)
118
+ end
119
+ end
120
+
121
+ private
122
+
123
+ def build_post_body(registration_ids, options = {})
124
+ { registration_ids: registration_ids }.merge(options)
125
+ end
126
+
127
+ def build_response(response, registration_ids = [])
128
+ body = response.body || {}
129
+ response_hash = { body: body, headers: response.headers, status_code: response.code }
130
+ case response.code
131
+ when 200
132
+ response_hash[:response] = 'success'
133
+ body = JSON.parse(body) unless body.empty?
134
+ response_hash[:canonical_ids] = build_canonical_ids(body, registration_ids) unless registration_ids.empty?
135
+ response_hash[:not_registered_ids] = build_not_registered_ids(body, registration_ids) unless registration_ids.empty?
136
+ when 400
137
+ response_hash[:response] = 'Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields.'
138
+ when 401
139
+ response_hash[:response] = 'There was an error authenticating the sender account.'
140
+ when 503
141
+ response_hash[:response] = 'Server is temporarily unavailable.'
142
+ when 500..599
143
+ response_hash[:response] = 'There was an internal error in the FCM server while trying to process the request.'
144
+ end
145
+ response_hash
146
+ end
147
+
148
+ def build_canonical_ids(body, registration_ids)
149
+ canonical_ids = []
150
+ unless body.empty?
151
+ if body['canonical_ids'] > 0
152
+ body['results'].each_with_index do |result, index|
153
+ canonical_ids << { old: registration_ids[index], new: result['registration_id'] } if has_canonical_id?(result)
154
+ end
155
+ end
156
+ end
157
+ canonical_ids
158
+ end
159
+
160
+ def build_not_registered_ids(body, registration_id)
161
+ not_registered_ids = []
162
+ unless body.empty?
163
+ if body['failure'] > 0
164
+ body['results'].each_with_index do |result, index|
165
+ not_registered_ids << registration_id[index] if is_not_registered?(result)
166
+ end
167
+ end
168
+ end
169
+ not_registered_ids
170
+ end
171
+
172
+ def has_canonical_id?(result)
173
+ !result['registration_id'].nil?
174
+ end
175
+
176
+ def is_not_registered?(result)
177
+ result['error'] == 'NotRegistered'
178
+ end
179
+ end
@@ -0,0 +1,241 @@
1
+ require 'spec_helper'
2
+
3
+ describe FCM do
4
+ let(:send_url) { "#{FCM.base_uri}/send" }
5
+
6
+ it 'should raise an error if the api key is not provided' do
7
+ expect { FCM.new }.to raise_error
8
+ end
9
+
10
+ it 'should raise error if time_to_live is given' do
11
+ # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#ttl
12
+ end
13
+
14
+ describe 'sending notification' do
15
+ let(:api_key) { 'AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA' }
16
+ let(:registration_ids) { ['42'] }
17
+ let(:valid_request_body) do
18
+ { registration_ids: registration_ids }
19
+ end
20
+ let(:valid_request_headers) do
21
+ {
22
+ 'Content-Type' => 'application/json',
23
+ 'Authorization' => "key=#{api_key}"
24
+ }
25
+ end
26
+
27
+ let(:stub_fcm_send_request) do
28
+ stub_request(:post, send_url).with(
29
+ body: valid_request_body.to_json,
30
+ headers: valid_request_headers
31
+ ).to_return(
32
+ # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
33
+ body: '{}',
34
+ headers: {},
35
+ status: 200
36
+ )
37
+ end
38
+
39
+ let(:stub_fcm_send_request_with_basic_auth) do
40
+ uri = URI.parse(send_url)
41
+ uri.user = 'a'
42
+ uri.password = 'b'
43
+ stub_request(:post, uri.to_s).to_return(body: '{}', headers: {}, status: 200)
44
+ end
45
+
46
+ before(:each) do
47
+ stub_fcm_send_request
48
+ stub_fcm_send_request_with_basic_auth
49
+ end
50
+
51
+ it 'should send notification using POST to FCM server' do
52
+ fcm = FCM.new(api_key)
53
+ fcm.send(registration_ids).should eq(response: 'success', body: '{}', headers: {}, status_code: 200, canonical_ids: [], not_registered_ids: [])
54
+ stub_fcm_send_request.should have_been_made.times(1)
55
+ end
56
+
57
+ context 'send notification with data' do
58
+ let!(:stub_with_data) do
59
+ stub_request(:post, send_url)
60
+ .with(body: '{"registration_ids":["42"],"data":{"score":"5x1","time":"15:10"}}',
61
+ headers: valid_request_headers)
62
+ .to_return(status: 200, body: '', headers: {})
63
+ end
64
+ before do
65
+ end
66
+ it 'should send the data in a post request to fcm' do
67
+ fcm = FCM.new(api_key)
68
+ fcm.send(registration_ids, data: { score: '5x1', time: '15:10' })
69
+ stub_with_data.should have_been_requested
70
+ end
71
+ end
72
+
73
+ context 'when send_notification responds with failure' do
74
+ let(:mock_request_attributes) do
75
+ {
76
+ body: valid_request_body.to_json,
77
+ headers: valid_request_headers
78
+ }
79
+ end
80
+
81
+ subject { FCM.new(api_key) }
82
+
83
+ context 'on failure code 400' do
84
+ before do
85
+ stub_request(:post, send_url).with(
86
+ mock_request_attributes
87
+ ).to_return(
88
+ # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
89
+ body: '{}',
90
+ headers: {},
91
+ status: 400
92
+ )
93
+ end
94
+ it 'should not send notification due to 400' do
95
+ subject.send(registration_ids).should eq(body: '{}',
96
+ headers: {},
97
+ response: 'Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields.',
98
+ status_code: 400)
99
+ end
100
+ end
101
+
102
+ context 'on failure code 401' do
103
+ before do
104
+ stub_request(:post, send_url).with(
105
+ mock_request_attributes
106
+ ).to_return(
107
+ # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
108
+ body: '{}',
109
+ headers: {},
110
+ status: 401
111
+ )
112
+ end
113
+
114
+ it 'should not send notification due to 401' do
115
+ subject.send(registration_ids).should eq(body: '{}',
116
+ headers: {},
117
+ response: 'There was an error authenticating the sender account.',
118
+ status_code: 401)
119
+ end
120
+ end
121
+
122
+ context 'on failure code 503' do
123
+ before do
124
+ stub_request(:post, send_url).with(
125
+ mock_request_attributes
126
+ ).to_return(
127
+ # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
128
+ body: '{}',
129
+ headers: {},
130
+ status: 503
131
+ )
132
+ end
133
+
134
+ it 'should not send notification due to 503' do
135
+ subject.send(registration_ids).should eq(body: '{}',
136
+ headers: {},
137
+ response: 'Server is temporarily unavailable.',
138
+ status_code: 503)
139
+ end
140
+ end
141
+
142
+ context 'on failure code 5xx' do
143
+ before do
144
+ stub_request(:post, send_url).with(
145
+ mock_request_attributes
146
+ ).to_return(
147
+ # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
148
+ body: '{"body-key" => "Body value"}',
149
+ headers: { 'header-key' => 'Header value' },
150
+ status: 599
151
+ )
152
+ end
153
+
154
+ it 'should not send notification due to 599' do
155
+ subject.send(registration_ids).should eq(body: '{"body-key" => "Body value"}',
156
+ headers: { 'header-key' => ['Header value'] },
157
+ response: 'There was an internal error in the FCM server while trying to process the request.',
158
+ status_code: 599)
159
+ end
160
+ end
161
+ end
162
+
163
+ context 'when send_notification responds canonical_ids' do
164
+ let(:mock_request_attributes) do
165
+ {
166
+ body: valid_request_body.to_json,
167
+ headers: valid_request_headers
168
+ }
169
+ end
170
+
171
+ let(:valid_response_body_with_canonical_ids) do
172
+ {
173
+ failure: 0, canonical_ids: 1, results: [{ registration_id: '43', message_id: '0:1385025861956342%572c22801bb3' }]
174
+ }
175
+ end
176
+
177
+ subject { FCM.new(api_key) }
178
+
179
+ before do
180
+ stub_request(:post, send_url).with(
181
+ mock_request_attributes
182
+ ).to_return(
183
+ # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
184
+ body: valid_response_body_with_canonical_ids.to_json,
185
+ headers: {},
186
+ status: 200
187
+ )
188
+ end
189
+
190
+ it 'should contain canonical_ids' do
191
+ response = subject.send(registration_ids)
192
+
193
+ response.should eq(headers: {},
194
+ canonical_ids: [{ old: '42', new: '43' }],
195
+ not_registered_ids: [],
196
+ status_code: 200,
197
+ response: 'success',
198
+ body: '{"failure":0,"canonical_ids":1,"results":[{"registration_id":"43","message_id":"0:1385025861956342%572c22801bb3"}]}')
199
+ end
200
+ end
201
+
202
+ context 'when send_notification responds with NotRegistered' do
203
+ subject { FCM.new(api_key) }
204
+
205
+ let(:mock_request_attributes) do
206
+ {
207
+ body: valid_request_body.to_json,
208
+ headers: valid_request_headers
209
+ }
210
+ end
211
+
212
+ let(:valid_response_body_with_not_registered_ids) do
213
+ {
214
+ canonical_ids: 0, failure: 1, results: [{ error: 'NotRegistered' }]
215
+ }
216
+ end
217
+
218
+ before do
219
+ stub_request(:post, send_url).with(
220
+ mock_request_attributes
221
+ ).to_return(
222
+ body: valid_response_body_with_not_registered_ids.to_json,
223
+ headers: {},
224
+ status: 200
225
+ )
226
+ end
227
+
228
+ it 'should contain not_registered_ids' do
229
+ response = subject.send(registration_ids)
230
+ response.should eq(
231
+ headers: {},
232
+ canonical_ids: [],
233
+ not_registered_ids: registration_ids,
234
+ status_code: 200,
235
+ response: 'success',
236
+ body: '{"canonical_ids":0,"failure":1,"results":[{"error":"NotRegistered"}]}'
237
+ )
238
+ end
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'webmock/rspec'
4
+
5
+ require 'fcm'
6
+
7
+ RSpec.configure do |config|
8
+ config.run_all_when_everything_filtered = true
9
+ config.expect_with :rspec do |c|
10
+ c.syntax = [:should, :expect]
11
+ end
12
+ # config.filter_run :focus
13
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fcm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kashif Rasul
8
+ - Shoaib Burq
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-05-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: json
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ description: fcm provides ruby bindings to Firebase Cloud Messaging (FCM) a cross-platform
43
+ messaging solution that lets you reliably deliver messages and notifications at
44
+ no cost to Android, iOS or Web browsers.
45
+ email:
46
+ - kashif@spacialdb.com
47
+ - shoaib@spacialdb.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - ".gitignore"
53
+ - ".rspec"
54
+ - ".travis.yml"
55
+ - Gemfile
56
+ - LICENSE.txt
57
+ - README.md
58
+ - Rakefile
59
+ - fcm.gemspec
60
+ - lib/fcm.rb
61
+ - spec/fcm_spec.rb
62
+ - spec/spec_helper.rb
63
+ homepage: https://github.com/spacialdb/fcm
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 2.0.0
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project: fcm
83
+ rubygems_version: 2.6.4
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Reliably deliver messages and notifications via FCM
87
+ test_files:
88
+ - spec/fcm_spec.rb
89
+ - spec/spec_helper.rb