zero_push_woosh 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b79acd64d3607ad7c5e4b55e48cccdb4b3e2f738
4
+ data.tar.gz: 0b4d4685e5050b196e745ee9962f77223b93ce8b
5
+ SHA512:
6
+ metadata.gz: 11a6d6e212fab18168261ea0db70e7f18d78be02856df243b05ecd528d47bbf20e18e78726c93a0887a280a7f3d2a4cf34b79dc1a9c429d9e23a68349dfb37d3
7
+ data.tar.gz: ff22ab600fc3b85d1193adf776a259c03e82f7c71d907f758a8909e91d5c89368a0b582721cdb3c456b059b40ef3bb861d005260ffe3ab70a90e99b374c16d69
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.gem
2
+
3
+ spec/tmp
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ ---
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.1
7
+ - 2.2.0
8
+ - jruby-19mode
9
+ notifications:
10
+ email:
11
+ - adam.v.duke@gmail.com
12
+ - stefan.natchev@gmail.com
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ ## 2.5.1 (2015-01-30)
2
+ Increment the version due to the 2.5.0 tag pointing at the wrong commit.
3
+
4
+ ## 2.5.0 (2015-01-28)
5
+
6
+ Features:
7
+
8
+ * add endpoints `/devices`, `/device/{token}`, `/channels`, and `/channels/{channel_name}`
9
+ * add ability to configure with multiple device tokens.
10
+ * update http client to use JSON parameter encoding.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in zero_push_woosh.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,80 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ zero_push_woosh (1.0.0)
5
+ faraday (~> 0.9.0)
6
+ faraday_middleware (~> 0.9.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionpack (4.1.4)
12
+ actionview (= 4.1.4)
13
+ activesupport (= 4.1.4)
14
+ rack (~> 1.5.2)
15
+ rack-test (~> 0.6.2)
16
+ actionview (4.1.4)
17
+ activesupport (= 4.1.4)
18
+ builder (~> 3.1)
19
+ erubis (~> 2.7.0)
20
+ activesupport (4.1.4)
21
+ i18n (~> 0.6, >= 0.6.9)
22
+ json (~> 1.7, >= 1.7.7)
23
+ minitest (~> 5.1)
24
+ thread_safe (~> 0.1)
25
+ tzinfo (~> 1.1)
26
+ addressable (2.3.6)
27
+ builder (3.2.2)
28
+ coderay (1.1.0)
29
+ crack (0.4.2)
30
+ safe_yaml (~> 1.0.0)
31
+ erubis (2.7.0)
32
+ faraday (0.9.1)
33
+ multipart-post (>= 1.2, < 3)
34
+ faraday_middleware (0.9.2)
35
+ faraday (>= 0.7.4, < 0.10)
36
+ i18n (0.6.9)
37
+ json (1.8.1)
38
+ metaclass (0.0.4)
39
+ method_source (0.8.2)
40
+ minitest (5.3.5)
41
+ minitest-around (0.2.0)
42
+ minitest (~> 5.0)
43
+ mocha (1.1.0)
44
+ metaclass (~> 0.0.1)
45
+ multipart-post (2.0.0)
46
+ pry (0.9.12.4)
47
+ coderay (~> 1.0)
48
+ method_source (~> 0.8)
49
+ slop (~> 3.4)
50
+ rack (1.5.2)
51
+ rack-test (0.6.2)
52
+ rack (>= 1.0)
53
+ railties (4.1.4)
54
+ actionpack (= 4.1.4)
55
+ activesupport (= 4.1.4)
56
+ rake (>= 0.8.7)
57
+ thor (>= 0.18.1, < 2.0)
58
+ rake (10.3.2)
59
+ safe_yaml (1.0.4)
60
+ slop (3.4.7)
61
+ thor (0.19.1)
62
+ thread_safe (0.3.4)
63
+ tzinfo (1.2.1)
64
+ thread_safe (~> 0.1)
65
+ webmock (1.20.4)
66
+ addressable (>= 2.3.6)
67
+ crack (>= 0.3.2)
68
+
69
+ PLATFORMS
70
+ ruby
71
+
72
+ DEPENDENCIES
73
+ minitest (~> 5.3.5)
74
+ minitest-around (~> 0.2.0)
75
+ mocha (~> 1.1.0)
76
+ pry
77
+ railties (~> 4.1.4)
78
+ rake (~> 10.3.2)
79
+ webmock (~> 1.20.4)
80
+ zero_push_woosh!
data/LICENSE.md ADDED
@@ -0,0 +1,25 @@
1
+ ## License
2
+
3
+ Copyright (c) 2015 Symmetric Infinity LLC
4
+
5
+ MIT License
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining
8
+ a copy of this software and associated documentation files (the
9
+ "Software"), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # Important notice about this Gem
2
+
3
+ [ZeroPush has been acquired by Twitter](https://zeropush.com/acquisition) and will be shutting their doors on January 31, 2016. They have partnered with [PushWoosh](http://www.pushwoosh.com) to provide a ["code free" migration path](http://docs.pushwoosh.com/docs/zeropush-migration). This gem offers a bridge between the former ZeroPush API and mirror PushWoosh API. Please note there have been only two minor changes:
4
+
5
+ 1. This gem and its files have been renamed from zero_push to zero_push_woosh to mark the bridge between the two providers
6
+ 2. The ZeroPush API endpoint URL has been replaced by the PushWoosh bridge API endpoint url (i.e. https://zeropush.pushwoosh.com)
7
+
8
+ Otherwise, all of the code remain the same as before.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'zero_push_woosh'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install zero_push_woosh
23
+
24
+ ## Usage
25
+
26
+ ### Rails Generator
27
+ Generate the ZeroPushWoosh initializer if you are using Ruby on Rails.
28
+
29
+ $ rails g zero_push_woosh:install
30
+
31
+ ### API Client
32
+
33
+ The easiest way to use the API client is to set the server `auth_token` at the module level and call methods on the ZeroPushWoosh module. You can find the token on settings page for your app.
34
+
35
+ ```ruby
36
+ ZeroPushWoosh.auth_token = 'iosprod_your-server-token'
37
+ ZeroPushWoosh.notify(device_tokens: ['abcdef'], alert: 'hello, world', badge: '+1', info: {user_id: 1234})
38
+ ```
39
+
40
+ If your web application supports must support multiple mobile apps, you may configure it like this:
41
+
42
+ ```ruby
43
+ if Rails.env == 'development' #or ENV['RACK_ENV']
44
+ ZeroPushWoosh.auth_tokens = {
45
+ apns: 'iosdev_XYZ',
46
+ gcm: 'gcmdev_ABC',
47
+ }
48
+ else
49
+ ZeroPushWoosh.auth_tokens = {
50
+ apns: 'iosprod_XYZ',
51
+ gcm: 'gcmprod_ABC',
52
+ }
53
+ end
54
+ ```
55
+
56
+ You may then instantiate clients by calling the method that matches the auth token key:
57
+
58
+ ```ruby
59
+ ZeroPushWoosh.apns.broadcast( ... )
60
+ ZeroPushWoosh.gcm.broadcast( ... )
61
+ ```
62
+
63
+
64
+ Lastly, if you have many apps you may instantiate clients API Clients
65
+
66
+ ```ruby
67
+ client_1 = ZeroPushWoosh.client('iosprod_app-server-token-1')
68
+ client_1.broadcast(alert: 'hello, app1')
69
+
70
+ client_2 = ZeroPushWoosh.client('iosprod_app-server-token-2')
71
+ client_1.broadcast(alert: 'hello, app2')
72
+ ```
73
+
74
+ Methods supported by this gem and their parameters can be found in the [API Reference](https://zeropush.com/documentation/api_reference)
75
+
76
+ For more documentation, check our [Getting Started Guide with ZeroPushWoosh](https://zeropush.com/documentation)
77
+
78
+ ## Contributing
79
+
80
+ 1. Fork it
81
+ 1. Create your feature branch (`git checkout -b my-new-feature`)
82
+ 1. Write tests for your feature
83
+ 1. Commit your changes (`git commit -am 'Add some feature'`)
84
+ 1. Push to the branch (`git push origin my-new-feature`)
85
+ 1. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "rake/testtask"
2
+ require "bundler/gem_tasks"
3
+
4
+ task default: :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'lib' << 'spec'
8
+ t.test_files = Dir["spec/**/*_spec.rb"]
9
+ t.verbose = true
10
+ end
11
+
@@ -0,0 +1,24 @@
1
+ require 'rails/generators'
2
+
3
+ module ZeroPushWoosh
4
+ class InstallGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ def create_initializer_file
8
+ @production_token = ask 'Production auth_token:'
9
+ @development_token = ask 'Development auth_token:'
10
+ template('zero_push_woosh.rb', 'config/initializers/zero_push_woosh.rb')
11
+ end
12
+
13
+ private
14
+
15
+ def self.installation_message
16
+ 'Generates the initializer'
17
+ end
18
+
19
+ desc installation_message
20
+
21
+ end
22
+ end
23
+
24
+
@@ -0,0 +1,5 @@
1
+ if Rails.env.production?
2
+ ZeroPushWoosh.auth_token = '<%= @production_token %>'
3
+ else
4
+ ZeroPushWoosh.auth_token = '<%= @development_token %>'
5
+ end
@@ -0,0 +1,44 @@
1
+ require 'zero_push_woosh/version'
2
+ require 'zero_push_woosh/client'
3
+ require 'faraday'
4
+
5
+ module ZeroPushWoosh
6
+ class << self
7
+ extend Forwardable
8
+ attr_accessor :auth_token, :auth_tokens, :config
9
+
10
+ def_delegators :client,
11
+ :verify_credentials,
12
+ :notify,
13
+ :broadcast,
14
+ :subscribe,
15
+ :unsubscribe,
16
+ :register,
17
+ :unregister,
18
+ :set_badge,
19
+ :inactive_tokens,
20
+ :devices,
21
+ :device,
22
+ :set_device,
23
+ :update_device,
24
+ :channels,
25
+ :channel,
26
+ :delete_channel
27
+
28
+ def client(auth_token = self.auth_token)
29
+ ZeroPushWoosh::Client.new(auth_token)
30
+ end
31
+
32
+ def config
33
+ @config ||= {:http_adapter => Faraday.default_adapter, request_encoding: :json}
34
+ end
35
+
36
+ def method_missing(method, *params, &block)
37
+ if auth_tokens.is_a?(Hash) && auth_tokens.keys.include?(method)
38
+ self.client(auth_tokens[method])
39
+ else
40
+ super
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,268 @@
1
+ require 'zero_push_woosh/compatibility'
2
+ require 'faraday_middleware'
3
+
4
+ module ZeroPushWoosh
5
+ class Client
6
+ URL = 'https://zeropush.pushwoosh.com'.freeze
7
+
8
+ attr_accessor :auth_token
9
+
10
+ def initialize(auth_token)
11
+ self.auth_token = auth_token
12
+ self.extend(Compatibility)
13
+ end
14
+
15
+ # verifies credentials
16
+ #
17
+ # @return [Boolean]
18
+ def verify_credentials
19
+ response = http.get('/verify_credentials')
20
+ response.status == 200
21
+ end
22
+
23
+ # Sends a notification to the list of devices
24
+ #
25
+ # @param params [Hash]
26
+ #
27
+ # Example response
28
+ # {"sent_count":10,"inactive_tokens":[],"unregistered_tokens":["abc"]}
29
+ def notify(params)
30
+ http.post('/notify', params)
31
+ end
32
+
33
+ # Sends a notification to all of the devices registered with the ZeroPushWoosh backend
34
+ #
35
+ # @param params [Hash]
36
+ #
37
+ # Example response
38
+ # {"sent_count":10}
39
+ def broadcast(params)
40
+ http.post('/broadcast', params)
41
+ end
42
+
43
+ # Subscribes a device to a particular notification channel
44
+ #
45
+ # @param device_token [String]
46
+ # @param channel [String]
47
+ #
48
+ # Example response
49
+ # {"device_token":"abc", "channels":["foo"]}
50
+ def subscribe(device_token, channel)
51
+ http.post("/subscribe/#{channel}", device_token:device_token)
52
+ end
53
+
54
+ # Unsubscribes a device from a particular notification channel
55
+ #
56
+ # @param device_token [String]
57
+ # @param channel [String]
58
+ #
59
+ # Example response
60
+ # {"device_token":"abc", "channels":[]}
61
+ def unsubscribe(device_token, channel)
62
+ http.delete("/subscribe/#{channel}", device_token:device_token)
63
+ end
64
+
65
+ # Registers a device token with the ZeroPushWoosh backend
66
+ #
67
+ # @param device_token
68
+ #
69
+ # Example response
70
+ # {"message":"ok"}
71
+ def register(device_token, channel=nil)
72
+ params = {device_token: device_token}
73
+ params.merge!(channel: channel) unless channel.nil?
74
+ http.post('/register', params)
75
+ end
76
+
77
+ # Unregisters a device token that has previously been registered with
78
+ # ZeroPushWoosh
79
+ #
80
+ # @param device_token
81
+ #
82
+ # Example response
83
+ # {"message":"ok"}
84
+ def unregister(device_token)
85
+ http.delete('/unregister', device_token: device_token)
86
+ end
87
+
88
+ # Sets the badge for a particular device
89
+ #
90
+ # @param device_token
91
+ # @param badge
92
+ #
93
+ # Example response
94
+ # {"message":"ok"}
95
+ def set_badge(device_token, badge)
96
+ http.post('/set_badge', device_token: device_token, badge: badge)
97
+ end
98
+
99
+ # Returns a list of tokens that have been marked inactive
100
+ #
101
+ # Example response
102
+ # [
103
+ # {
104
+ # "device_token":"238b8cb09011850cb4bd544dfe0c8f5eeab73d7eeaae9bdca59076db4ae49947",
105
+ # "marked_inactive_at":"2013-07-17T01:27:53-04:00"
106
+ # },
107
+ # {
108
+ # "device_token":"8c97be6643eea2143322005bc4c44a1aee5e549bce5e2bb2116114f45484ddaf",
109
+ # "marked_inactive_at":"2013-07-17T01:27:50-04:00"
110
+ # }
111
+ # ]
112
+ def inactive_tokens(params = {page:1})
113
+ http.get('/inactive_tokens', params)
114
+ end
115
+
116
+ # Returns a paginated list of devices
117
+ # https://zeropush.com/documentation/api_reference#devices_index
118
+ #
119
+ # Example response
120
+ # [
121
+ # {
122
+ # "token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf",
123
+ # "active": true,
124
+ # "marked_inactive_at": null,
125
+ # "badge": 1
126
+ # },
127
+ # {
128
+ # "token": "234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf0",
129
+ # "active": true,
130
+ # "marked_inactive_at": null,
131
+ # "badge": 2
132
+ # }
133
+ # ]
134
+ def devices(params = {page:1})
135
+ http.get('/devices', params)
136
+ end
137
+
138
+ # Return detailed information about a device
139
+ # https://zeropush.com/documentation/api_reference#devices_show
140
+ #
141
+ # Example response
142
+ # {
143
+ # "token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf",
144
+ # "active": true,
145
+ # "marked_inactive_at": null,
146
+ # "badge": 1,
147
+ # "channels": [
148
+ # "testflight",
149
+ # "user@example.com"
150
+ # ]
151
+ # }
152
+ def device(token)
153
+ http.get("/devices/#{token}")
154
+ end
155
+
156
+ # Replace the channel subscriptions with a new set of channels. This will
157
+ # remove all previous subscriptions of the device. If you want to append a
158
+ # list of channels, use #update_device.
159
+ # https://zeropush.com/documentation/api_reference#devices_update_put
160
+ #
161
+ # @param token String token identifying the device
162
+ # @param channel_list String Comma separated list of channels
163
+ #
164
+ # Example Request
165
+ #
166
+ # ZeroPushWoosh.set_device(token, channel_list: 'player-1, game-256')
167
+ #
168
+ # Example Response
169
+ # {
170
+ # "token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf",
171
+ # "active": true,
172
+ # "marked_inactive_at": null,
173
+ # "badge": 1,
174
+ # "channels": [
175
+ # "player-1",
176
+ # "game-256"
177
+ # ]
178
+ # }
179
+ def set_device(token, params)
180
+ http.put("/devices/#{token}", params)
181
+ end
182
+
183
+ # Append the channel subscriptions with a set of new channels. If you want
184
+ # to replace the list of channels, use #set_device.
185
+ # https://zeropush.com/documentation/api_reference#devices_update_patch
186
+ #
187
+ # @param token String token identifying the device
188
+ # @param channel_list String Comma separated list of channels
189
+ #
190
+ # Example Request
191
+ #
192
+ # ZeroPushWoosh.update_device(token, channel_list: 'player-1, game-256')
193
+ #
194
+ # Example Response
195
+ # {
196
+ # "token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf",
197
+ # "active": true,
198
+ # "marked_inactive_at": null,
199
+ # "badge": 1,
200
+ # "channels": [
201
+ # "player-1",
202
+ # "game-256"
203
+ # ]
204
+ # }
205
+ def update_device(token, params)
206
+ http.patch("/devices/#{token}", params)
207
+ end
208
+
209
+ # Returns paginated list of channels
210
+ # https://zeropush.com/documentation/api_reference#channels_index
211
+ #
212
+ # Example Response:
213
+ # [
214
+ # "player-1",
215
+ # "player-2",
216
+ # "player-9",
217
+ # "game-256",
218
+ # "admins",
219
+ # "lobby"
220
+ # ]
221
+ def channels(params = {page:1})
222
+ http.get('/channels', params)
223
+ end
224
+
225
+ # Returns the list of device tokens for the given channel
226
+ # https://zeropush.com/documentation/api_reference#channels_show
227
+ #
228
+ # Example Response:
229
+ # {
230
+ # "channel": "player-1",
231
+ # "device_tokens": [
232
+ # "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf"
233
+ # ]
234
+ # }
235
+ def channel(channel_name)
236
+ http.get("/channels/#{channel_name}")
237
+ end
238
+
239
+ # Deletes a channels and unsubscribes all of the devices from it.
240
+ # https://zeropush.com/documentation/api_reference#channels_destroy
241
+ #
242
+ # {
243
+ # "channel": "player-1",
244
+ # "device_tokens": [
245
+ # "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf"
246
+ # ]
247
+ # }
248
+ def delete_channel(channel_name)
249
+ http.delete("/channels/#{channel_name}")
250
+ end
251
+
252
+ # Instantiate a new http client configured for making requests to the API
253
+ def http
254
+ Faraday.new(url: URL) do |c|
255
+ c.token_auth self.auth_token
256
+ c.request http_config[:request_encoding]
257
+ c.response :json, :content_type => /\bjson$/ # parse responses to JSON
258
+ c.adapter http_config[:http_adapter]
259
+ end
260
+ end
261
+ alias client http
262
+
263
+ protected
264
+ def http_config
265
+ @http_config ||= ZeroPushWoosh.config.dup
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,21 @@
1
+ module ZeroPushWoosh
2
+ module Compatibility
3
+ def warn_on_deprecated_parameters(params)
4
+ value = (params[:info] || params['info'] || params[:data] || params['data'])
5
+ if value.is_a?(String)
6
+ warn "[DEPRECATION] `info` or `data` encoded as a string will not be supported in version 3.0.0; Use a hash instead."
7
+ http_config[:request_encoding] = :url_encoded
8
+ end
9
+ end
10
+
11
+ def notify(params)
12
+ warn_on_deprecated_parameters(params)
13
+ super
14
+ end
15
+
16
+ def broadcast(params)
17
+ warn_on_deprecated_parameters(params)
18
+ super
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module ZeroPushWoosh
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ require 'rails/generators/test_case'
3
+ require 'generators/zero_push_woosh/install_generator'
4
+
5
+ class ZeroPushWoosh::GeneratorTest < Rails::Generators::TestCase
6
+ destination File.expand_path('../tmp', __FILE__)
7
+ tests ZeroPushWoosh::InstallGenerator
8
+ test 'it copies the initializer' do
9
+ production_token = 'production'
10
+ development_token = 'development'
11
+ ZeroPushWoosh::InstallGenerator.any_instance.stubs(:ask).returns(production_token).then.returns(development_token)
12
+
13
+ run_generator
14
+
15
+ assert_file 'config/initializers/zero_push_woosh.rb' do |initializer|
16
+ production_config = %Q|ZeroPushWoosh.auth_token = '#{production_token}'|
17
+ assert(initializer.include?(production_config), "The initializer doesn't include the production configuration")
18
+
19
+ development_config = %Q|ZeroPushWoosh.auth_token = '#{development_token}'|
20
+ assert(initializer.include?(development_config), "The initializer doesn't include the development configuration")
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/spec'
3
+ require 'webmock/minitest'
4
+ require 'zero_push_woosh'
5
+ require 'pry'
6
+
7
+ ENV['AUTH_TOKEN'] ||= 'test-token'
8
+
9
+ WebMock.enable!
@@ -0,0 +1,316 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+
4
+ describe ZeroPushWoosh::Client do
5
+
6
+ let(:auth_token){ ENV['AUTH_TOKEN'] }
7
+ let(:client){ ZeroPushWoosh.client(auth_token) }
8
+ let(:device_token) { 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }
9
+ before do
10
+ stub_request(:post, "https://zeropush.pushwoosh.com/register").
11
+ with(body: '{"device_token":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}', headers: {'Authorization'=>'Token token="test-token"', 'Content-Type'=>'application/json'}).
12
+ to_return(status: 200, body: '{"message":"ok"}', headers: {'Content-Type' => 'application/json'})
13
+
14
+ stub_request(:delete, "https://zeropush.pushwoosh.com/unregister?device_token=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").
15
+ with(headers: {'Authorization'=>"Token token=\"#{auth_token}\""}).
16
+ to_return(status: 200, body: '{"message":"ok"}', headers: {'Content-Type' => 'application/json'})
17
+ end
18
+
19
+ describe 'compatibility' do
20
+ it 'uses url_encoding if `info` or `data` params are strings' do
21
+ request = stub_request(:post, "https://zeropush.pushwoosh.com/notify").
22
+ with(body: {"info" => "{\"a\":1}"}, headers: {'Content-Type'=>'application/x-www-form-urlencoded'}).to_return(status: 200)
23
+ client.notify(info: JSON.dump({a: 1}))
24
+ assert_request_requested request
25
+ end
26
+ it 'uses JSON encoding if `info` or `data` params are hashes' do
27
+ request = stub_request(:post, "https://zeropush.pushwoosh.com/notify").
28
+ with(body: '{"info":{"a":1}}', headers: {'Content-Type' => 'application/json'}).to_return(status: 200)
29
+ client.notify(info: {a: 1})
30
+ assert_request_requested request
31
+ end
32
+ end
33
+
34
+ describe '#http' do
35
+ it 'instantiates a default http client' do
36
+ client.http.must_be_instance_of Faraday::Connection
37
+ client.http.headers['Authorization'].must_equal 'Token token="test-token"'
38
+ end
39
+ end
40
+
41
+ describe '#verify_credentials' do
42
+ it 'verifies credentials successfully' do
43
+ stub_request(:get, "https://zeropush.pushwoosh.com/verify_credentials").
44
+ with(headers: {'Authorization'=>'Token token="test-token"'}).
45
+ to_return(status: 200, body: '{"message": "authenticated"}', headers: {'Content-Type' => 'application/json'})
46
+
47
+ client.verify_credentials.must_equal true
48
+ end
49
+
50
+ it 'fails to verify credentials' do
51
+ stub_request(:get, "https://zeropush.pushwoosh.com/verify_credentials").
52
+ with(headers: {'Authorization'=>'Token token="not a valid token"'}).
53
+ to_return(status: 401, body: '{"error": "unauthorized"}', headers: {'Content-Type' => 'application/json'})
54
+
55
+ client = ZeroPushWoosh.client('not a valid token')
56
+ client.verify_credentials.must_equal false
57
+ end
58
+ end
59
+
60
+ describe '#notify' do
61
+ before do
62
+ stub_request(:post, "https://zeropush.pushwoosh.com/notify").
63
+ with(body: '{"device_tokens":["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"],"alert":"hi"}').
64
+ to_return(status: 200, body: '{"sent_count":1, "inactive_tokens":[], "unregistered_tokens":[]}', headers: {'Content-Type' => 'application/json'})
65
+ client.register(device_token)
66
+ end
67
+
68
+ after do
69
+ client.unregister(device_token)
70
+ end
71
+
72
+ let(:response){client.notify(device_tokens: [device_token], alert: 'hi')}
73
+
74
+ it 'returns a hash' do
75
+ response.body.class.must_equal Hash
76
+ end
77
+
78
+ it 'constructs the request' do
79
+ response.body['sent_count'].must_equal 1
80
+ response.body['inactive_tokens'].must_equal []
81
+ end
82
+ end
83
+
84
+ describe '#register' do
85
+ describe 'without a channel parameter' do
86
+ it 'returns a hash' do
87
+ client.register(device_token).body.class.must_equal Hash
88
+ end
89
+
90
+ it 'registers the device' do
91
+ client.register(device_token).body['message'].must_equal 'ok'
92
+ end
93
+ end
94
+
95
+ describe 'with a channel parameter' do
96
+ before do
97
+ stub_request(:post, "https://zeropush.pushwoosh.com/register").
98
+ with(body: '{"device_token":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","channel":"foo"}',
99
+ headers: {'Authorization'=>'Token token="test-token"', 'Content-Type'=>'application/json'}).
100
+ to_return(status: 200, body: '{"message":"ok"}', headers: {'Content-Type'=>'application/json'})
101
+ end
102
+ it 'returns a hash' do
103
+ client.register(device_token, 'foo').body.class.must_equal Hash
104
+ end
105
+
106
+ it 'registers the device' do
107
+ client.register(device_token, 'foo').body['message'].must_equal 'ok'
108
+ end
109
+ end
110
+ end
111
+
112
+ describe '#unregister' do
113
+ before do
114
+ client.register(device_token)
115
+ end
116
+
117
+ describe 'when the device has been registered' do
118
+ before do
119
+ stub_request(:delete, "https://zeropush.pushwoosh.com/unregister?device_token=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").
120
+ to_return(status: 200, body: '{"message":"ok"}', headers: {'Content-Type' => 'application/json'})
121
+ end
122
+
123
+ it 'returns a hash' do
124
+ client.unregister(device_token).body.class.must_equal Hash
125
+ end
126
+
127
+ it 'unregisters the device' do
128
+ client.unregister(device_token).body['message'].must_equal 'ok'
129
+ end
130
+ end
131
+ end
132
+
133
+ describe '#subscribe' do
134
+ before do
135
+ stub_request(:post, "https://zeropush.pushwoosh.com/subscribe/foo_channel").
136
+ with(body: '{"device_token":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}').
137
+ to_return(status: 200, body: '{"device_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","channels":["foo_channel"]}', headers: {'Content-Type' => 'application/json'})
138
+ end
139
+
140
+ let(:response){client.subscribe(device_token, 'foo_channel')}
141
+
142
+ it 'returns a hash' do
143
+ response.body.class.must_equal Hash
144
+ end
145
+
146
+ it 'subscribes a device to a channel' do
147
+ response.body['device_token'].must_equal device_token
148
+ response.body['channels'].must_include 'foo_channel'
149
+ end
150
+ end
151
+
152
+ describe '#unsubscribe' do
153
+ before do
154
+ stub_request(:delete, "https://zeropush.pushwoosh.com/subscribe/foo_channel?device_token=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").
155
+ to_return(status: 200, body: '{"device_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","channels":[]}', headers: {'Content-Type' => 'application/json'})
156
+ end
157
+
158
+ let(:response){client.unsubscribe(device_token, 'foo_channel')}
159
+
160
+ it 'returns a hash' do
161
+ response.body.class.must_equal Hash
162
+ end
163
+
164
+ it 'subscribes a device to a channel' do
165
+ response.body['device_token'].must_equal device_token
166
+ response.body['channels'].wont_include 'foo_channel'
167
+ end
168
+ end
169
+
170
+ describe '#broadcast' do
171
+ before do
172
+ stub_request(:post, "https://zeropush.pushwoosh.com/broadcast").
173
+ with(body: '{"alert":"hi"}').
174
+ to_return(status: 200, body: '{"sent_count":10}', headers: {'Content-Type' => 'application/json'})
175
+ end
176
+ let(:response){client.broadcast(alert:'hi')}
177
+
178
+ it 'returns a hash' do
179
+ response.body.class.must_equal Hash
180
+ end
181
+
182
+ it 'broadcasts a notification to all the devices' do
183
+ response.body['sent_count'].must_equal 10
184
+ end
185
+
186
+ it 'uses json encoding for custom data' do
187
+ request = stub_request(:post, "https://zeropush.pushwoosh.com/broadcast").
188
+ with(body: '{"data":{"alert":"hi","user_id":5}}', headers: {'Content-Type'=>'application/json'}).to_return(status: 200)
189
+ client.broadcast(data: {alert: "hi", user_id: 5})
190
+ assert_request_requested request
191
+ end
192
+ end
193
+
194
+ describe '#set_badge' do
195
+ before do
196
+ stub_request(:post, "https://zeropush.pushwoosh.com/set_badge").
197
+ with(body: '{"device_token":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","badge":10}').
198
+ to_return(status: 200, body: '{"message":"ok"}', headers: {'Content-Type'=>'application/json'})
199
+ end
200
+
201
+ let(:response){client.set_badge(device_token, 10)}
202
+
203
+ it 'returns a hash' do
204
+ response.body.class.must_equal Hash
205
+ end
206
+
207
+ it 'sets the device\'s badge' do
208
+ response.body['message'].must_equal 'ok'
209
+ end
210
+ end
211
+
212
+ describe '#inactive_tokens' do
213
+
214
+ let(:response){client.inactive_tokens}
215
+ before do
216
+ stub_request(:get, "https://zeropush.pushwoosh.com/inactive_tokens?page=1").
217
+ to_return(status: 200, body: '[{"device_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","marked_inactive_at": "2013-03-11T16:25:14-04:00"}]', headers: {'Content-Type'=>'application/json'})
218
+ end
219
+
220
+ it 'returns an array' do
221
+ response.body.class.must_equal Array
222
+ end
223
+
224
+ it 'gets a list of inactive tokens' do
225
+ response.body.count.must_equal 1
226
+ end
227
+ end
228
+
229
+ describe '#devices' do
230
+ let(:response){client.devices}
231
+ before do
232
+ stub_request(:get, "https://zeropush.pushwoosh.com/devices?page=1").
233
+ to_return(status: 200, body: '[]', headers: {'Content-Type' => 'application/json', 'Link' => '<https://zeropush.pushwoosh.com/devices?page=10&per_page=25>; rel="last",<https://zeropush.pushwoosh.com/devices?page=2&per_page=25>; rel="next"'})
234
+ end
235
+ it 'returns an array' do
236
+ response.body.class.must_equal Array
237
+ end
238
+ it 'has paginated results' do
239
+ response.headers["link"].must_equal '<https://zeropush.pushwoosh.com/devices?page=10&per_page=25>; rel="last",<https://zeropush.pushwoosh.com/devices?page=2&per_page=25>; rel="next"'
240
+ end
241
+ end
242
+
243
+ describe '#device' do
244
+ before do
245
+ stub_request(:get, "https://zeropush.pushwoosh.com/devices/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").
246
+ to_return(status: 200, body: '{
247
+ "token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf",
248
+ "active": true,
249
+ "marked_inactive_at": null,
250
+ "badge": 1,
251
+ "channels": [
252
+ "testflight",
253
+ "user@example.com"
254
+ ]
255
+ }', headers: {'Content-Type'=>'application/json'})
256
+ end
257
+ let(:response){client.device('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')}
258
+
259
+ it 'returns a device hash' do
260
+ response.body.class.must_equal Hash
261
+ response.body.keys.must_equal %w[token active marked_inactive_at badge channels]
262
+ end
263
+ end
264
+
265
+ describe '#channels' do
266
+ before do
267
+ stub_request(:get, "https://zeropush.pushwoosh.com/channels?page=1").
268
+ to_return(status: 200, body: '["player-1","foobar"]', headers: {'Content-Type'=>'application/json', 'Link' => '<https://zeropush.pushwoosh.com/channels?page=10&per_page=25>; rel="last",<https://zeropush.pushwoosh.com/channels?page=2&per_page=25>; rel="next"'})
269
+ end
270
+ let(:response){client.channels}
271
+ it 'returns an array' do
272
+ response.body.class.must_equal Array
273
+ end
274
+ it 'has paginated results' do
275
+ response.headers["link"].must_equal '<https://zeropush.pushwoosh.com/channels?page=10&per_page=25>; rel="last",<https://zeropush.pushwoosh.com/channels?page=2&per_page=25>; rel="next"'
276
+ end
277
+ end
278
+
279
+ describe '#channel' do
280
+ before do
281
+ stub_request(:get, 'https://zeropush.pushwoosh.com/channels/player-1').
282
+ to_return(status: 200, body:'{
283
+ "channel": "player-1",
284
+ "device_tokens": [
285
+ "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf"
286
+ ]
287
+ }', headers: {'Content-Type' => 'application/json'})
288
+ end
289
+
290
+ let(:response) { client.channel('player-1') }
291
+
292
+ it 'returns a channel hash' do
293
+ response.body.class.must_equal Hash
294
+ response.body.keys.must_equal %w[channel device_tokens]
295
+ end
296
+ end
297
+
298
+ describe '#delete_channel' do
299
+ before do
300
+ stub_request(:delete, 'https://zeropush.pushwoosh.com/channels/player-1').
301
+ to_return(status: 200, body:'{
302
+ "channel": "player-1",
303
+ "device_tokens": [
304
+ "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcedf"
305
+ ]
306
+ }', headers: {'Content-Type' => 'application/json'})
307
+ end
308
+
309
+ let(:response) { client.delete_channel('player-1') }
310
+
311
+ it 'returns a channel hash' do
312
+ response.body.class.must_equal Hash
313
+ response.body.keys.must_equal %w[channel device_tokens]
314
+ end
315
+ end
316
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe ZeroPushWoosh do
4
+ before do
5
+ ZeroPushWoosh.auth_token = ENV['AUTH_TOKEN'] || 'test_token'
6
+ end
7
+
8
+ describe 'using different auth_tokens' do
9
+ it 'accepts a hash of tokens' do
10
+ ZeroPushWoosh.auth_tokens = {
11
+ apns: 'test-apns-token',
12
+ gcm: 'test-gcm-token'
13
+ }
14
+ ZeroPushWoosh.apns.auth_token.must_equal 'test-apns-token'
15
+ ZeroPushWoosh.gcm.auth_token.must_equal 'test-gcm-token'
16
+ end
17
+ end
18
+
19
+ describe '.client' do
20
+ it 'returns a client instance' do
21
+ ZeroPushWoosh.client.class.must_equal ZeroPushWoosh::Client
22
+ end
23
+ end
24
+
25
+ describe 'methods the module responds to' do
26
+ [:verify_credentials, :notify, :broadcast, :subscribe, :unsubscribe, :register, :unregister, :set_badge, :inactive_tokens, :devices, :device, :set_device, :update_device, :channels, :channel, :delete_channel, :client].each do |method|
27
+ it "responds to #{method}" do
28
+ ZeroPushWoosh.respond_to?(method).must_equal(true)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'zero_push_woosh/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "zero_push_woosh"
8
+ gem.version = ZeroPushWoosh::VERSION
9
+ gem.authors = ["Stefan Natchev", "Adam Duke"]
10
+ gem.email = ["stefan.natchev@gmail.com", "adam.v.duke@gmail.com"]
11
+ gem.summary = %q{A gem for interacting with the ZeroPushWoosh API. (http://zeropush.com)}
12
+ gem.description = %q{ZeroPushWoosh is a simple service for sending iOS push notifications. (http://zeropush.com)}
13
+ gem.homepage = "https://zeropush.com"
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+ gem.required_ruby_version = '>= 1.9'
21
+
22
+ gem.add_dependency "faraday", "~> 0.9.0"
23
+ gem.add_dependency "faraday_middleware", "~> 0.9.0"
24
+
25
+ gem.add_development_dependency 'minitest', '~> 5.3.5'
26
+ gem.add_development_dependency 'minitest-around', '~> 0.2.0'
27
+ gem.add_development_dependency 'mocha', '~> 1.1.0'
28
+ gem.add_development_dependency 'rake', '~> 10.3.2'
29
+ gem.add_development_dependency 'railties', '~> 4.1.4'
30
+ gem.add_development_dependency 'pry'
31
+ gem.add_development_dependency 'webmock', '~> 1.20.4'
32
+ end
Binary file
metadata ADDED
@@ -0,0 +1,197 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zero_push_woosh
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Stefan Natchev
8
+ - Adam Duke
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-12-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 0.9.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.9.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: faraday_middleware
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 0.9.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.9.0
42
+ - !ruby/object:Gem::Dependency
43
+ name: minitest
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 5.3.5
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 5.3.5
56
+ - !ruby/object:Gem::Dependency
57
+ name: minitest-around
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: 0.2.0
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 0.2.0
70
+ - !ruby/object:Gem::Dependency
71
+ name: mocha
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: 1.1.0
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: 1.1.0
84
+ - !ruby/object:Gem::Dependency
85
+ name: rake
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: 10.3.2
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: 10.3.2
98
+ - !ruby/object:Gem::Dependency
99
+ name: railties
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: 4.1.4
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: 4.1.4
112
+ - !ruby/object:Gem::Dependency
113
+ name: pry
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: webmock
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: 1.20.4
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: 1.20.4
140
+ description: ZeroPushWoosh is a simple service for sending iOS push notifications.
141
+ (http://zeropush.com)
142
+ email:
143
+ - stefan.natchev@gmail.com
144
+ - adam.v.duke@gmail.com
145
+ executables: []
146
+ extensions: []
147
+ extra_rdoc_files: []
148
+ files:
149
+ - ".gitignore"
150
+ - ".travis.yml"
151
+ - CHANGELOG.md
152
+ - Gemfile
153
+ - Gemfile.lock
154
+ - LICENSE.md
155
+ - README.md
156
+ - Rakefile
157
+ - lib/generators/zero_push_woosh/install_generator.rb
158
+ - lib/generators/zero_push_woosh/templates/zero_push_woosh.rb
159
+ - lib/zero_push_woosh.rb
160
+ - lib/zero_push_woosh/client.rb
161
+ - lib/zero_push_woosh/compatibility.rb
162
+ - lib/zero_push_woosh/version.rb
163
+ - spec/generator_spec.rb
164
+ - spec/spec_helper.rb
165
+ - spec/zero_push_woosh_client_spec.rb
166
+ - spec/zero_push_woosh_spec.rb
167
+ - zero_push_woosh.gemspec
168
+ - zeropush-header.png
169
+ homepage: https://zeropush.com
170
+ licenses:
171
+ - MIT
172
+ metadata: {}
173
+ post_install_message:
174
+ rdoc_options: []
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '1.9'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ requirements: []
188
+ rubyforge_project:
189
+ rubygems_version: 2.4.7
190
+ signing_key:
191
+ specification_version: 4
192
+ summary: A gem for interacting with the ZeroPushWoosh API. (http://zeropush.com)
193
+ test_files:
194
+ - spec/generator_spec.rb
195
+ - spec/spec_helper.rb
196
+ - spec/zero_push_woosh_client_spec.rb
197
+ - spec/zero_push_woosh_spec.rb