pushpad 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/README.md +74 -2
- data/Rakefile +5 -0
- data/lib/pushpad/notification.rb +120 -0
- data/lib/pushpad/request.rb +56 -0
- data/lib/pushpad/subscription.rb +52 -0
- data/lib/pushpad.rb +4 -73
- data/pushpad.gemspec +13 -0
- data/spec/pushpad/notification_spec.rb +360 -0
- data/spec/pushpad/request_spec.rb +78 -0
- data/spec/pushpad/subscription_spec.rb +85 -0
- data/spec/pushpad_spec.rb +0 -118
- metadata +24 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72937e2f8f9f8340e2c8a503a413a13f5cce90cd
|
4
|
+
data.tar.gz: b296e7b4007accf9d7d8729b31c1f0180fa465a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85de1abb940f431332c41280c5a47983e93b29999c25877c4eef01e913b2517f208a13804110294d904399f4f348f7899fc10817fa3e95d85436e85a908532fd
|
7
|
+
data.tar.gz: 7c3230b40848571ce581498286364eee8e86388519b1cf82df37cfd54bf45074930196752021ec985b09a2072370632cc5c56c629ac7a298f17f7604fd824f2b
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# Pushpad - Web Push Notifications Service
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/pushpad/pushpad-ruby.svg?branch=master)](https://travis-ci.org/pushpad/pushpad-ruby)
|
2
4
|
|
3
5
|
[Pushpad](https://pushpad.xyz) is a service for sending push notifications from your web app. It supports the **Push API** (Chrome, Firefox, Opera) and **APNs** (Safari).
|
4
6
|
|
@@ -109,13 +111,83 @@ notification.broadcast
|
|
109
111
|
|
110
112
|
If no user with that id has subscribed to push notifications, that id is simply ignored.
|
111
113
|
|
112
|
-
The methods above return an hash:
|
114
|
+
The methods above return an hash:
|
113
115
|
|
114
116
|
- `"id"` is the id of the notification on Pushpad
|
115
117
|
- `"scheduled"` is the estimated reach of the notification (i.e. the number of devices to which the notification will be sent, which can be different from the number of users, since a user may receive notifications on multiple devices)
|
116
118
|
- `"uids"` (`deliver_to` only) are the user IDs that will be actually reached by the notification because they are subscribed to your notifications. For example if you send a notification to `['uid1', 'uid2', 'uid3']`, but only `'uid1'` is subscribed, you will get `['uid1']` in response. Note that if a user has unsubscribed after the last notification sent to him, he may still be reported for one time as subscribed (this is due to [the way](http://blog.pushpad.xyz/2016/05/the-push-api-and-its-wild-unsubscription-mechanism/) the W3C Push API works).
|
117
119
|
|
120
|
+
The `id` and `scheduled_count` attribute are also stored on the notification object:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
|
124
|
+
notification.deliver_to user
|
125
|
+
|
126
|
+
notification.id # => 1000
|
127
|
+
notification.scheduled_count # => 5
|
128
|
+
```
|
129
|
+
|
130
|
+
## Getting push notification data
|
131
|
+
|
132
|
+
You can retrieve data for past notifications:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
notification = Pushpad::Notification.find(42)
|
136
|
+
|
137
|
+
# get basic attributes
|
138
|
+
notification.id # => 42
|
139
|
+
notification.title # => "Foo Bar",
|
140
|
+
notification.body # => "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
141
|
+
notification.target_url # => "http://example.com",
|
142
|
+
notification.ttl # => 604800,
|
143
|
+
notification.require_interaction # => false,
|
144
|
+
notification.icon_url # => "http://example.com/assets/icon.png",
|
145
|
+
|
146
|
+
# `created_at` is a `Time` instance
|
147
|
+
notification.created_at.utc.to_s # => "2016-07-06 10:09:14 UTC",
|
148
|
+
|
149
|
+
# get statistics
|
150
|
+
notification.scheduled_count # => 1
|
151
|
+
notification.successfully_sent_count # => 4,
|
152
|
+
notification.opened_count # => 2
|
153
|
+
```
|
154
|
+
|
155
|
+
Or for mutliple notifications of a project at once:
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
notifications = Pushpad::Notification.find_all(project_id: 5)
|
159
|
+
|
160
|
+
# same attributes as for single notification in example above
|
161
|
+
notifications[0].id # => 42
|
162
|
+
notifications[0].title # => "Foo Bar",
|
163
|
+
```
|
164
|
+
|
165
|
+
If `Pushpad.project_id` is defined, the `project_id` option can be
|
166
|
+
omitted.
|
167
|
+
|
168
|
+
The REST API paginates the result set. You can pass a `page` parameter
|
169
|
+
to get the full list in multiple requests.
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
notifications = Pushpad::Notification.find_all(project_id: 5, page: 2)
|
173
|
+
```
|
174
|
+
|
175
|
+
## Getting subscription count
|
176
|
+
|
177
|
+
You can retrieve the number of subscriptions for a given project,
|
178
|
+
optionally filtered by `tags` or `uids`:
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
Pushpad::Subscription.count(project_id: 5) # => 100
|
182
|
+
Pushpad::Subscription.count(project_id: 5, uids: ['user1']) # => 2
|
183
|
+
Pushpad::Subscription.count(project_id: 5, tags: ['sports']) # => 10
|
184
|
+
Pushpad::Subscription.count(project_id: 5, tags: 'sports && travel') # => 5
|
185
|
+
Pushpad::Subscription.count(project_id: 5, uids: ['user1'], tags: 'sports && travel') # => 1
|
186
|
+
```
|
187
|
+
|
188
|
+
If `Pushpad.project_id` is defined, the `project_id` option can be
|
189
|
+
omitted.
|
190
|
+
|
118
191
|
## License
|
119
192
|
|
120
193
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
121
|
-
|
data/Rakefile
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require "json"
|
2
|
+
require "time"
|
3
|
+
|
4
|
+
module Pushpad
|
5
|
+
class Notification
|
6
|
+
class DeliveryError < RuntimeError
|
7
|
+
end
|
8
|
+
|
9
|
+
class FindError < RuntimeError
|
10
|
+
end
|
11
|
+
|
12
|
+
class ReadonlyError < RuntimeError
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :body, :title, :target_url, :icon_url, :ttl, :require_interaction
|
16
|
+
attr_reader :id, :created_at, :scheduled_count, :successfully_sent_count, :opened_count
|
17
|
+
|
18
|
+
def initialize(options)
|
19
|
+
@id = options[:id]
|
20
|
+
@created_at = options[:created_at] && Time.parse(options[:created_at])
|
21
|
+
@scheduled_count = options[:scheduled_count]
|
22
|
+
@successfully_sent_count = options[:successfully_sent_count]
|
23
|
+
@opened_count = options[:opened_count]
|
24
|
+
|
25
|
+
@body = options[:body]
|
26
|
+
@title = options[:title]
|
27
|
+
@target_url = options[:target_url]
|
28
|
+
@icon_url = options[:icon_url]
|
29
|
+
@ttl = options[:ttl]
|
30
|
+
@require_interaction = options[:require_interaction]
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.find(id)
|
34
|
+
response = Request.get("https://pushpad.xyz/notifications/#{id}")
|
35
|
+
|
36
|
+
unless response.code == "200"
|
37
|
+
raise FindError, "Response #{response.code} #{response.message}: #{response.body}"
|
38
|
+
end
|
39
|
+
|
40
|
+
new(JSON.parse(response.body, symbolize_names: true)).readonly!
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.find_all(options = {})
|
44
|
+
project_id = options[:project_id] || Pushpad.project_id
|
45
|
+
raise "You must set project_id" unless project_id
|
46
|
+
|
47
|
+
query_parameters = {}
|
48
|
+
query_parameters[:page] = options[:page] if options.key?(:page)
|
49
|
+
|
50
|
+
response = Request.get("https://pushpad.xyz/projects/#{project_id}/notifications",
|
51
|
+
query_parameters: query_parameters)
|
52
|
+
|
53
|
+
unless response.code == "200"
|
54
|
+
raise FindError, "Response #{response.code} #{response.message}: #{response.body}"
|
55
|
+
end
|
56
|
+
|
57
|
+
JSON.parse(response.body, symbolize_names: true).map do |attributes|
|
58
|
+
new(attributes).readonly!
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def readonly!
|
63
|
+
@readonly = true
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def broadcast(options = {})
|
68
|
+
deliver req_body(nil, options[:tags]), options
|
69
|
+
end
|
70
|
+
|
71
|
+
def deliver_to(users, options = {})
|
72
|
+
uids = if users.respond_to?(:ids)
|
73
|
+
users.ids
|
74
|
+
elsif users.respond_to?(:collect)
|
75
|
+
users.collect {|u| u.respond_to?(:id) ? u.id : u }
|
76
|
+
else
|
77
|
+
[users.respond_to?(:id) ? users.id : users]
|
78
|
+
end
|
79
|
+
deliver req_body(uids, options[:tags]), options
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def deliver(req_body, options = {})
|
85
|
+
if @readonly
|
86
|
+
raise(ReadonlyError,
|
87
|
+
"Notifications fetched with `find` or `find_all` cannot be delivered again.")
|
88
|
+
end
|
89
|
+
|
90
|
+
project_id = options[:project_id] || Pushpad.project_id
|
91
|
+
raise "You must set project_id" unless project_id
|
92
|
+
|
93
|
+
endpoint = "https://pushpad.xyz/projects/#{project_id}/notifications"
|
94
|
+
response = Request.post(endpoint, req_body)
|
95
|
+
|
96
|
+
unless response.code == "201"
|
97
|
+
raise DeliveryError, "Response #{response.code} #{response.message}: #{response.body}"
|
98
|
+
end
|
99
|
+
|
100
|
+
JSON.parse(response.body).tap do |attributes|
|
101
|
+
@id = attributes["id"]
|
102
|
+
@scheduled_count = attributes["scheduled"]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def req_body(uids = nil, tags = nil)
|
107
|
+
notification_params = { "body" => self.body }
|
108
|
+
notification_params["title"] = self.title if self.title
|
109
|
+
notification_params["target_url"] = self.target_url if self.target_url
|
110
|
+
notification_params["icon_url"] = self.icon_url if self.icon_url
|
111
|
+
notification_params["ttl"] = self.ttl if self.ttl
|
112
|
+
notification_params["require_interaction"] = self.require_interaction unless self.require_interaction.nil?
|
113
|
+
|
114
|
+
body = { "notification" => notification_params }
|
115
|
+
body["uids"] = uids if uids
|
116
|
+
body["tags"] = tags if tags
|
117
|
+
body.to_json
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "net/http"
|
3
|
+
|
4
|
+
module Pushpad
|
5
|
+
module Request
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def head(endpoint, options = {})
|
9
|
+
perform(Net::HTTP::Head, endpoint, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def get(endpoint, options = {})
|
13
|
+
perform(Net::HTTP::Get, endpoint, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def post(endpoint, body, options = {})
|
17
|
+
perform(Net::HTTP::Post, endpoint, options) do |request|
|
18
|
+
request.body = body
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def perform(method, endpoint, options)
|
25
|
+
uri = URI.parse(endpoint)
|
26
|
+
request = method.new(path_and_query(uri, options[:query_parameters]), headers)
|
27
|
+
|
28
|
+
yield request if block_given?
|
29
|
+
|
30
|
+
https(uri, request)
|
31
|
+
end
|
32
|
+
|
33
|
+
def path_and_query(uri, query_parameters)
|
34
|
+
[uri.path, query(query_parameters)].compact.join("?")
|
35
|
+
end
|
36
|
+
|
37
|
+
def query(parameters)
|
38
|
+
parameters && !parameters.empty? ? URI.encode_www_form(parameters) : nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def https(uri, request)
|
42
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |https|
|
43
|
+
https.request(request)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def headers
|
48
|
+
raise "You must set Pushpad.auth_token" unless Pushpad.auth_token
|
49
|
+
{
|
50
|
+
"Authorization" => %(Token token="#{Pushpad.auth_token}"),
|
51
|
+
"Content-Type" => "application/json;charset=UTF-8",
|
52
|
+
"Accept" => "application/json"
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Pushpad
|
2
|
+
class Subscription
|
3
|
+
class CountError < RuntimeError
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.count(options = {})
|
7
|
+
CountQuery.new(options).perform
|
8
|
+
end
|
9
|
+
|
10
|
+
class CountQuery
|
11
|
+
attr_reader :options
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def perform
|
18
|
+
project_id = options[:project_id] || Pushpad.project_id
|
19
|
+
raise "You must set project_id" unless project_id
|
20
|
+
|
21
|
+
endpoint = "https://pushpad.xyz/projects/#{project_id}/subscriptions"
|
22
|
+
response = Request.head(endpoint, query_parameters: query_parameters)
|
23
|
+
|
24
|
+
unless response.code == "200"
|
25
|
+
raise CountError, "Response #{response.code} #{response.message}: #{response.body}"
|
26
|
+
end
|
27
|
+
|
28
|
+
response["X-Total-Count"].to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def query_parameters
|
34
|
+
[uid_query_parameters, tag_query_parameters].flatten(1)
|
35
|
+
end
|
36
|
+
|
37
|
+
def uid_query_parameters
|
38
|
+
options.fetch(:uids, []).map { |uid| ["uids[]", uid] }
|
39
|
+
end
|
40
|
+
|
41
|
+
def tag_query_parameters
|
42
|
+
tags = options.fetch(:tags, [])
|
43
|
+
|
44
|
+
if tags.is_a?(String)
|
45
|
+
[["tags", tags]]
|
46
|
+
else
|
47
|
+
tags.map { |tag| ["tags[]", tag] }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/pushpad.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
require 'net/http'
|
2
1
|
require 'openssl'
|
3
|
-
|
2
|
+
|
3
|
+
require "pushpad/request"
|
4
|
+
require "pushpad/notification"
|
5
|
+
require "pushpad/subscription"
|
4
6
|
|
5
7
|
module Pushpad
|
6
8
|
@@auth_token = nil
|
@@ -38,75 +40,4 @@ module Pushpad
|
|
38
40
|
uid_signature = self.signature_for(uid.to_s)
|
39
41
|
"#{self.path(options)}?uid=#{uid}&uid_signature=#{uid_signature}"
|
40
42
|
end
|
41
|
-
|
42
|
-
class Notification
|
43
|
-
class DeliveryError < RuntimeError
|
44
|
-
end
|
45
|
-
|
46
|
-
attr_accessor :body, :title, :target_url, :icon_url, :ttl, :require_interaction
|
47
|
-
|
48
|
-
def initialize(options)
|
49
|
-
self.body = options[:body]
|
50
|
-
self.title = options[:title]
|
51
|
-
self.target_url = options[:target_url]
|
52
|
-
self.icon_url = options[:icon_url]
|
53
|
-
self.ttl = options[:ttl]
|
54
|
-
self.require_interaction = options[:require_interaction]
|
55
|
-
end
|
56
|
-
|
57
|
-
def broadcast(options = {})
|
58
|
-
deliver req_body(nil, options[:tags]), options
|
59
|
-
end
|
60
|
-
|
61
|
-
def deliver_to(users, options = {})
|
62
|
-
uids = if users.respond_to?(:ids)
|
63
|
-
users.ids
|
64
|
-
elsif users.respond_to?(:collect)
|
65
|
-
users.collect {|u| u.respond_to?(:id) ? u.id : u }
|
66
|
-
else
|
67
|
-
[users.respond_to?(:id) ? users.id : users]
|
68
|
-
end
|
69
|
-
deliver req_body(uids, options[:tags]), options
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
def deliver(req_body, options = {})
|
75
|
-
project_id = options[:project_id] || Pushpad.project_id
|
76
|
-
raise "You must set project_id" unless project_id
|
77
|
-
endpoint = "https://pushpad.xyz/projects/#{project_id}/notifications"
|
78
|
-
uri = URI.parse(endpoint)
|
79
|
-
https = Net::HTTP.new(uri.host, uri.port)
|
80
|
-
https.use_ssl = true
|
81
|
-
req = Net::HTTP::Post.new(uri.path, req_headers)
|
82
|
-
req.body = req_body
|
83
|
-
res = https.request(req)
|
84
|
-
raise DeliveryError, "Response #{res.code} #{res.message}: #{res.body}" unless res.code == '201'
|
85
|
-
JSON.parse(res.body)
|
86
|
-
end
|
87
|
-
|
88
|
-
def req_headers
|
89
|
-
raise "You must set Pushpad.auth_token" unless Pushpad.auth_token
|
90
|
-
{
|
91
|
-
'Authorization' => 'Token token="' + Pushpad.auth_token + '"',
|
92
|
-
'Content-Type' => 'application/json;charset=UTF-8',
|
93
|
-
'Accept' => 'application/json'
|
94
|
-
}
|
95
|
-
end
|
96
|
-
|
97
|
-
def req_body(uids = nil, tags = nil)
|
98
|
-
notification_params = { "body" => self.body }
|
99
|
-
notification_params["title"] = self.title if self.title
|
100
|
-
notification_params["target_url"] = self.target_url if self.target_url
|
101
|
-
notification_params["icon_url"] = self.icon_url if self.icon_url
|
102
|
-
notification_params["ttl"] = self.ttl if self.ttl
|
103
|
-
notification_params["require_interaction"] = self.require_interaction unless self.require_interaction.nil?
|
104
|
-
|
105
|
-
body = { "notification" => notification_params }
|
106
|
-
body["uids"] = uids if uids
|
107
|
-
body["tags"] = tags if tags
|
108
|
-
body.to_json
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
43
|
end
|
data/pushpad.gemspec
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = "pushpad"
|
3
|
+
spec.version = '0.6.0'
|
4
|
+
spec.authors = ["Pushpad"]
|
5
|
+
spec.email = ["support@pushpad.xyz"]
|
6
|
+
spec.summary = "Web push notifications for Chrome, Firefox and Safari using Pushpad."
|
7
|
+
spec.homepage = "https://pushpad.xyz"
|
8
|
+
spec.license = "MIT"
|
9
|
+
spec.files = `git ls-files`.split("\n")
|
10
|
+
spec.test_files = `git ls-files -- spec/*`.split("\n")
|
11
|
+
spec.add_development_dependency "rspec"
|
12
|
+
spec.add_development_dependency "webmock"
|
13
|
+
end
|
@@ -0,0 +1,360 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Pushpad
|
4
|
+
describe Notification do
|
5
|
+
let!(:auth_token) { Pushpad.auth_token = "abc123" }
|
6
|
+
let!(:project_id) { Pushpad.project_id = 123 }
|
7
|
+
let(:notification) { Pushpad::Notification.new body: "Example message" }
|
8
|
+
|
9
|
+
def stub_notification_get(attributes)
|
10
|
+
stub_request(:get, "https://pushpad.xyz/notifications/#{attributes[:id]}").
|
11
|
+
to_return(status: 200, body: attributes.to_json)
|
12
|
+
end
|
13
|
+
|
14
|
+
def stub_failing_notification_get(notification_id)
|
15
|
+
stub_request(:get, "https://pushpad.xyz/notifications/#{notification_id}").
|
16
|
+
to_return(status: 404)
|
17
|
+
end
|
18
|
+
|
19
|
+
def stub_notifications_get(options)
|
20
|
+
stub_request(:get, "https://pushpad.xyz/projects/#{options[:project_id]}/notifications").
|
21
|
+
with(query: hash_including(options.fetch(:query, {}))).
|
22
|
+
to_return(status: 200, body: options[:list].to_json)
|
23
|
+
end
|
24
|
+
|
25
|
+
def stub_failing_notifications_get(options)
|
26
|
+
stub_request(:get, "https://pushpad.xyz/projects/#{options[:project_id]}/notifications").
|
27
|
+
to_return(status: 403)
|
28
|
+
end
|
29
|
+
|
30
|
+
def stub_notification_post(project_id, params = {}, response_body = "{}")
|
31
|
+
stub_request(:post, "https://pushpad.xyz/projects/#{project_id}/notifications").
|
32
|
+
with(body: hash_including(params)).
|
33
|
+
to_return(status: 201, body: response_body)
|
34
|
+
end
|
35
|
+
|
36
|
+
def stub_failing_notification_post(project_id)
|
37
|
+
stub_request(:post, "https://pushpad.xyz/projects/#{project_id}/notifications").
|
38
|
+
to_return(status: 403)
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".new" do
|
42
|
+
it "allows delivering notifications even if an id attribute is supplied" do
|
43
|
+
stub_notification_post(project_id)
|
44
|
+
|
45
|
+
expect {
|
46
|
+
Notification.new(id: "ignored").broadcast
|
47
|
+
}.not_to raise_error
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".find" do
|
52
|
+
it "returns notification with attributes from json response" do
|
53
|
+
attributes = {
|
54
|
+
id: 5,
|
55
|
+
title: "Foo Bar",
|
56
|
+
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
57
|
+
target_url: "http://example.com",
|
58
|
+
created_at: "2016-07-06T10:09:14.835Z",
|
59
|
+
ttl: 604800,
|
60
|
+
require_interaction: false,
|
61
|
+
icon_url: "https://example.com/assets/icon.png",
|
62
|
+
scheduled_count: 2,
|
63
|
+
successfully_sent_count: 4,
|
64
|
+
opened_count: 1
|
65
|
+
}
|
66
|
+
stub_notification_get(attributes)
|
67
|
+
|
68
|
+
notification = Notification.find(5)
|
69
|
+
|
70
|
+
attributes.delete(:created_at)
|
71
|
+
expect(notification).to have_attributes(attributes)
|
72
|
+
expect(notification.created_at.utc.to_s).to eq(Time.utc(2016, 7, 6, 10, 9, 14.835).to_s)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "fails with FindError if response status code is not 200" do
|
76
|
+
stub_failing_notification_get(5)
|
77
|
+
|
78
|
+
expect {
|
79
|
+
Notification.find(5)
|
80
|
+
}.to raise_error(Notification::FindError)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "returns notification that fails with ReadonlyError when calling deliver_to" do
|
84
|
+
stub_notification_get(id: 5)
|
85
|
+
|
86
|
+
notification = Notification.find(5)
|
87
|
+
|
88
|
+
expect {
|
89
|
+
notification.deliver_to(100)
|
90
|
+
}.to raise_error(Notification::ReadonlyError)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns notification that fails with ReadonlyError when calling broadcast" do
|
94
|
+
stub_notification_get(id: 5)
|
95
|
+
|
96
|
+
notification = Notification.find(5)
|
97
|
+
|
98
|
+
expect {
|
99
|
+
notification.broadcast
|
100
|
+
}.to raise_error(Notification::ReadonlyError)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe ".find_all" do
|
105
|
+
it "returns notifications of project with attributes from json response" do
|
106
|
+
attributes = {
|
107
|
+
id: 5,
|
108
|
+
title: "Foo Bar",
|
109
|
+
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
110
|
+
target_url: "http://example.com",
|
111
|
+
created_at: "2016-07-06T10:09:14.835Z",
|
112
|
+
ttl: 604800,
|
113
|
+
require_interaction: false,
|
114
|
+
icon_url: "https://example.com/assets/icon.png",
|
115
|
+
scheduled_count: 2,
|
116
|
+
successfully_sent_count: 4,
|
117
|
+
opened_count: 1
|
118
|
+
}
|
119
|
+
stub_notifications_get(project_id: 10, list: [attributes])
|
120
|
+
|
121
|
+
notifications = Notification.find_all(project_id: 10)
|
122
|
+
|
123
|
+
attributes.delete(:created_at)
|
124
|
+
expect(notifications[0]).to have_attributes(attributes)
|
125
|
+
expect(notifications[0].created_at.utc.to_s).to eq(Time.utc(2016, 7, 6, 10, 9, 14.835).to_s)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "falls back to global project id" do
|
129
|
+
attributes = { id: 5 }
|
130
|
+
stub_notifications_get(project_id: 10, list: [attributes])
|
131
|
+
|
132
|
+
Pushpad.project_id = 10
|
133
|
+
notifications = Notification.find_all
|
134
|
+
|
135
|
+
expect(notifications[0]).to have_attributes(attributes)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "fails with helpful error message when project_id is missing" do
|
139
|
+
Pushpad.project_id = nil
|
140
|
+
|
141
|
+
expect {
|
142
|
+
Notification.find_all
|
143
|
+
}.to raise_error(/must set project_id/)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "allows passing page parameter for pagination" do
|
147
|
+
attributes = { id: 5 }
|
148
|
+
stub_notifications_get(project_id: 10, list: [attributes], query: { page: "3" })
|
149
|
+
|
150
|
+
notifications = Notification.find_all(project_id: 10, page: 3)
|
151
|
+
|
152
|
+
expect(notifications[0]).to have_attributes(attributes)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "fails with FindError if response status code is not 200" do
|
156
|
+
stub_failing_notifications_get(project_id: 10)
|
157
|
+
|
158
|
+
expect {
|
159
|
+
Notification.find_all(project_id: 10)
|
160
|
+
}.to raise_error(Notification::FindError)
|
161
|
+
end
|
162
|
+
|
163
|
+
it "returns notifications that fail with ReadonlyError when calling deliver_to" do
|
164
|
+
stub_notifications_get(project_id: 10, list: [{ id: 5 }])
|
165
|
+
|
166
|
+
notifications = Notification.find_all(project_id: 10)
|
167
|
+
|
168
|
+
expect {
|
169
|
+
notifications[0].deliver_to(100)
|
170
|
+
}.to raise_error(Notification::ReadonlyError)
|
171
|
+
end
|
172
|
+
|
173
|
+
it "returns notifications that fail with ReadonlyError when calling broadcast" do
|
174
|
+
stub_notifications_get(project_id: 10, list: [{ id: 5 }])
|
175
|
+
|
176
|
+
notifications = Notification.find_all(project_id: 10)
|
177
|
+
|
178
|
+
expect {
|
179
|
+
notifications[0].broadcast
|
180
|
+
}.to raise_error(Notification::ReadonlyError)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
shared_examples "delivery method" do |method|
|
185
|
+
it "fails with DeliveryError if response status code is not 201" do
|
186
|
+
stub_failing_notification_post(project_id)
|
187
|
+
|
188
|
+
expect {
|
189
|
+
method.call(notification)
|
190
|
+
}.to raise_error(Notification::DeliveryError)
|
191
|
+
end
|
192
|
+
|
193
|
+
it "sets id and scheduled_count from json response" do
|
194
|
+
response_body = {
|
195
|
+
"id" => 3,
|
196
|
+
"scheduled" => 5
|
197
|
+
}.to_json
|
198
|
+
stub_notification_post(project_id, {}, response_body)
|
199
|
+
|
200
|
+
method.call(notification)
|
201
|
+
|
202
|
+
expect(notification).to have_attributes(id: 3, scheduled_count: 5)
|
203
|
+
end
|
204
|
+
|
205
|
+
it "overrides id on subsequent calls" do
|
206
|
+
id_counter = 0
|
207
|
+
response_body = lambda do |*|
|
208
|
+
id_counter += 1
|
209
|
+
|
210
|
+
{
|
211
|
+
"id" => id_counter,
|
212
|
+
"scheduled" => 5
|
213
|
+
}.to_json
|
214
|
+
end
|
215
|
+
stub_notification_post(project_id, {}, response_body)
|
216
|
+
|
217
|
+
method.call(notification)
|
218
|
+
method.call(notification)
|
219
|
+
method.call(notification)
|
220
|
+
|
221
|
+
expect(notification.id).to eq(3)
|
222
|
+
end
|
223
|
+
|
224
|
+
it "returns raw json response" do
|
225
|
+
response = {
|
226
|
+
"id" => 4,
|
227
|
+
"scheduled" => 5,
|
228
|
+
"uids" => ["uid0", "uid1"]
|
229
|
+
}
|
230
|
+
stub_notification_post(project_id, {}, response.to_json)
|
231
|
+
|
232
|
+
result = method.call(notification)
|
233
|
+
|
234
|
+
expect(result).to eq(response)
|
235
|
+
end
|
236
|
+
|
237
|
+
it "fails with helpful error message when project_id is missing" do
|
238
|
+
Pushpad.project_id = nil
|
239
|
+
|
240
|
+
expect {
|
241
|
+
method.call(notification)
|
242
|
+
}.to raise_error(/must set project_id/)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe "#deliver_to" do
|
247
|
+
include_examples "delivery method", lambda { |notification|
|
248
|
+
notification.deliver_to(100)
|
249
|
+
}
|
250
|
+
|
251
|
+
shared_examples "notification params" do
|
252
|
+
it "includes the params in the request" do
|
253
|
+
req = stub_notification_post project_id, notification: notification_params
|
254
|
+
notification.deliver_to [123, 456]
|
255
|
+
expect(req).to have_been_made.once
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context "a notification with just the required params" do
|
260
|
+
let(:notification_params) do
|
261
|
+
{ body: "Example message" }
|
262
|
+
end
|
263
|
+
let(:notification) { Pushpad::Notification.new body: notification_params[:body] }
|
264
|
+
include_examples "notification params"
|
265
|
+
end
|
266
|
+
|
267
|
+
context "a notification with all the optional params" do
|
268
|
+
let(:notification_params) do
|
269
|
+
{
|
270
|
+
body: "Example message",
|
271
|
+
title: "Website Name",
|
272
|
+
target_url: "http://example.com",
|
273
|
+
icon_url: "http://example.com/assets/icon.png",
|
274
|
+
ttl: 604800,
|
275
|
+
require_interaction: true
|
276
|
+
}
|
277
|
+
end
|
278
|
+
let(:notification) { Pushpad::Notification.new notification_params }
|
279
|
+
include_examples "notification params"
|
280
|
+
end
|
281
|
+
|
282
|
+
context "with a scalar as a param" do
|
283
|
+
it "reaches only that uid" do
|
284
|
+
req = stub_notification_post project_id, uids: [100]
|
285
|
+
notification.deliver_to(100)
|
286
|
+
expect(req).to have_been_made.once
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
context "with an array as a param" do
|
291
|
+
it "reaches only those uids" do
|
292
|
+
req = stub_notification_post project_id, uids: [123, 456]
|
293
|
+
notification.deliver_to([123, 456])
|
294
|
+
expect(req).to have_been_made.once
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
context "with uids and tags" do
|
299
|
+
it "filters audience by uids and tags" do
|
300
|
+
req = stub_notification_post project_id, uids: [123, 456], tags: ["tag1"]
|
301
|
+
notification.deliver_to([123, 456], tags: ["tag1"])
|
302
|
+
expect(req).to have_been_made.once
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe "#broadcast" do
|
308
|
+
include_examples "delivery method", lambda { |notification|
|
309
|
+
notification.broadcast
|
310
|
+
}
|
311
|
+
|
312
|
+
shared_examples "notification params" do
|
313
|
+
it "includes the params in the request" do
|
314
|
+
req = stub_notification_post project_id, notification: notification_params
|
315
|
+
notification.broadcast
|
316
|
+
expect(req).to have_been_made.once
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
context "a notification with just the required params" do
|
321
|
+
let(:notification_params) do
|
322
|
+
{ body: "Example message" }
|
323
|
+
end
|
324
|
+
let(:notification) { Pushpad::Notification.new body: notification_params[:body] }
|
325
|
+
include_examples "notification params"
|
326
|
+
end
|
327
|
+
|
328
|
+
context "a notification with all the optional params" do
|
329
|
+
let(:notification_params) do
|
330
|
+
{
|
331
|
+
body: "Example message",
|
332
|
+
title: "Website Name",
|
333
|
+
target_url: "http://example.com",
|
334
|
+
icon_url: "http://example.com/assets/icon.png",
|
335
|
+
ttl: 604800,
|
336
|
+
require_interaction: true
|
337
|
+
}
|
338
|
+
end
|
339
|
+
let(:notification) { Pushpad::Notification.new notification_params }
|
340
|
+
include_examples "notification params"
|
341
|
+
end
|
342
|
+
|
343
|
+
context "without params" do
|
344
|
+
it "reaches everyone" do
|
345
|
+
req = stub_notification_post project_id, {}
|
346
|
+
notification.broadcast
|
347
|
+
expect(req).to have_been_made.once
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
context "with tags" do
|
352
|
+
it "filters audience by tags" do
|
353
|
+
req = stub_notification_post project_id, tags: ["tag1", "tag2"]
|
354
|
+
notification.broadcast tags: ["tag1", "tag2"]
|
355
|
+
expect(req).to have_been_made.once
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Pushpad
|
4
|
+
describe Request do
|
5
|
+
describe ".head" do
|
6
|
+
it "passes auth_token in authorization header" do
|
7
|
+
stub_request(:any, /pushpad.xyz/)
|
8
|
+
|
9
|
+
Pushpad.auth_token = "abc123"
|
10
|
+
Request.head("https://pushpad.xyz/example")
|
11
|
+
|
12
|
+
expect(a_request(:head, "https://pushpad.xyz/example").
|
13
|
+
with(headers: { "Authorization" => 'Token token="abc123"' })).to have_been_made
|
14
|
+
end
|
15
|
+
|
16
|
+
it "supports passing query parameters" do
|
17
|
+
stub_request(:any, /pushpad.xyz/)
|
18
|
+
|
19
|
+
Pushpad.auth_token = "abc123"
|
20
|
+
Request.head("https://pushpad.xyz/example", query_parameters: [["some", "value"]])
|
21
|
+
|
22
|
+
expect(a_request(:head, "https://pushpad.xyz/example?some=value")).to have_been_made
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".get" do
|
27
|
+
it "passes auth_token in authorization header" do
|
28
|
+
stub_request(:any, /pushpad.xyz/)
|
29
|
+
|
30
|
+
Pushpad.auth_token = "abc123"
|
31
|
+
Request.get("https://pushpad.xyz/example")
|
32
|
+
|
33
|
+
expect(a_request(:get, "https://pushpad.xyz/example").
|
34
|
+
with(headers: { "Authorization" => 'Token token="abc123"' })).to have_been_made
|
35
|
+
end
|
36
|
+
|
37
|
+
it "supports passing query parameters" do
|
38
|
+
stub_request(:any, /pushpad.xyz/)
|
39
|
+
|
40
|
+
Pushpad.auth_token = "abc123"
|
41
|
+
Request.get("https://pushpad.xyz/example", query_parameters: [["some", "value"]])
|
42
|
+
|
43
|
+
expect(a_request(:get, "https://pushpad.xyz/example?some=value")).to have_been_made
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe ".post" do
|
48
|
+
it "passes auth_token in authorization header" do
|
49
|
+
stub_request(:any, /pushpad.xyz/)
|
50
|
+
|
51
|
+
Pushpad.auth_token = "abc123"
|
52
|
+
Request.post("https://pushpad.xyz/example", '{"some": "value"}')
|
53
|
+
|
54
|
+
expect(a_request(:post, "https://pushpad.xyz/example").
|
55
|
+
with(headers: { "Authorization" => 'Token token="abc123"' })).to have_been_made
|
56
|
+
end
|
57
|
+
|
58
|
+
it "passes request body" do
|
59
|
+
stub_request(:any, /pushpad.xyz/)
|
60
|
+
|
61
|
+
Pushpad.auth_token = "abc123"
|
62
|
+
Request.post("https://pushpad.xyz/example", '{"some": "value"}')
|
63
|
+
|
64
|
+
expect(a_request(:post, "https://pushpad.xyz/example").
|
65
|
+
with(body: '{"some": "value"}')).to have_been_made
|
66
|
+
end
|
67
|
+
|
68
|
+
it "supports passing query parameters" do
|
69
|
+
stub_request(:any, /pushpad.xyz/)
|
70
|
+
|
71
|
+
Pushpad.auth_token = "abc123"
|
72
|
+
Request.post("https://pushpad.xyz/example", "{}", query_parameters: [["some", "value"]])
|
73
|
+
|
74
|
+
expect(a_request(:post, "https://pushpad.xyz/example?some=value")).to have_been_made
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Pushpad
|
4
|
+
describe Subscription do
|
5
|
+
def stub_subscriptions_head(options)
|
6
|
+
stub_request(:head, "https://pushpad.xyz/projects/#{options[:project_id]}/subscriptions").
|
7
|
+
with(query: hash_including(options.fetch(:query, {}))).
|
8
|
+
to_return(status: 200,
|
9
|
+
headers: { "X-Total-Count" => options.fetch(:total_count, 10) })
|
10
|
+
end
|
11
|
+
|
12
|
+
def stub_failing_subscriptions_head(options)
|
13
|
+
stub_request(:head, "https://pushpad.xyz/projects/#{options[:project_id]}/subscriptions").
|
14
|
+
to_return(status: 503)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe ".count" do
|
18
|
+
it "returns value from X-Total-Count header" do
|
19
|
+
stub_subscriptions_head(project_id: 5, total_count: 100)
|
20
|
+
|
21
|
+
result = Subscription.count(project_id: 5)
|
22
|
+
|
23
|
+
expect(result).to eq(100)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "falls back to global project_id" do
|
27
|
+
request = stub_subscriptions_head(project_id: 5, total_count: 100)
|
28
|
+
|
29
|
+
Pushpad.project_id = 5
|
30
|
+
Subscription.count
|
31
|
+
|
32
|
+
expect(request).to have_been_made.once
|
33
|
+
end
|
34
|
+
|
35
|
+
it "fails with helpful error message when project_id is missing" do
|
36
|
+
Pushpad.project_id = nil
|
37
|
+
|
38
|
+
expect {
|
39
|
+
Subscription.count
|
40
|
+
}.to raise_error(/must set project_id/)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "allows passing uids" do
|
44
|
+
request = stub_subscriptions_head(project_id: 5, query: { uids: ["uid0", "uid1"] })
|
45
|
+
|
46
|
+
Subscription.count(project_id: 5, uids: ["uid0", "uid1"])
|
47
|
+
|
48
|
+
expect(request).to have_been_made.once
|
49
|
+
end
|
50
|
+
|
51
|
+
it "allows passing tags" do
|
52
|
+
request = stub_subscriptions_head(project_id: 5, query: { tags: ["sports", "travel"] })
|
53
|
+
|
54
|
+
Subscription.count(project_id: 5, tags: ["sports", "travel"])
|
55
|
+
|
56
|
+
expect(request).to have_been_made.once
|
57
|
+
end
|
58
|
+
|
59
|
+
it "allows passing tags as boolean expression" do
|
60
|
+
request = stub_subscriptions_head(project_id: 5, query: { tags: "sports || travel" })
|
61
|
+
|
62
|
+
Subscription.count(project_id: 5, tags: "sports || travel")
|
63
|
+
|
64
|
+
expect(request).to have_been_made.once
|
65
|
+
end
|
66
|
+
|
67
|
+
it "allows passing tags and uids" do
|
68
|
+
request = stub_subscriptions_head(project_id: 5,
|
69
|
+
query: { tags: ["sports", "travel"], uids: ["uid0"] })
|
70
|
+
|
71
|
+
Subscription.count(project_id: 5, tags: ["sports", "travel"], uids: ["uid0"])
|
72
|
+
|
73
|
+
expect(request).to have_been_made.once
|
74
|
+
end
|
75
|
+
|
76
|
+
it "fails with CountError if response status code is not 200" do
|
77
|
+
stub_failing_subscriptions_head(project_id: 5)
|
78
|
+
|
79
|
+
expect {
|
80
|
+
Subscription.count(project_id: 5)
|
81
|
+
}.to raise_error(Subscription::CountError)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/spec/pushpad_spec.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Pushpad do
|
4
|
-
let!(:auth_token) { Pushpad.auth_token = 'abc123' }
|
5
|
-
let!(:project_id) { Pushpad.project_id = 123 }
|
6
|
-
let(:notification) { Pushpad::Notification.new body: "Example message" }
|
7
|
-
|
8
4
|
describe "#auth_token=" do
|
9
5
|
it "sets the Pushpad auth token globally" do
|
10
6
|
Pushpad.auth_token = 'abc123'
|
@@ -25,118 +21,4 @@ describe Pushpad do
|
|
25
21
|
expect(signature).to eq '27fbe136f5a4aa0b6be74c0e18fa8ce81ad91b60'
|
26
22
|
end
|
27
23
|
end
|
28
|
-
|
29
|
-
def stub_notification_post project_id, params
|
30
|
-
stub_request(:post, "https://pushpad.xyz/projects/#{project_id}/notifications").
|
31
|
-
with(body: hash_including(params)).
|
32
|
-
to_return(status: 201, body: '{}')
|
33
|
-
end
|
34
|
-
|
35
|
-
describe "#deliver_to" do
|
36
|
-
|
37
|
-
shared_examples 'notification params' do
|
38
|
-
it "includes the params in the request" do
|
39
|
-
req = stub_notification_post project_id, notification: notification_params
|
40
|
-
notification.deliver_to [123, 456]
|
41
|
-
expect(req).to have_been_made.once
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context "a notification with just the required params" do
|
46
|
-
let(:notification_params) do
|
47
|
-
{ body: "Example message" }
|
48
|
-
end
|
49
|
-
let(:notification) { Pushpad::Notification.new body: notification_params[:body] }
|
50
|
-
include_examples 'notification params'
|
51
|
-
end
|
52
|
-
|
53
|
-
context "a notification with all the optional params" do
|
54
|
-
let(:notification_params) do
|
55
|
-
{
|
56
|
-
body: "Example message",
|
57
|
-
title: "Website Name",
|
58
|
-
target_url: "http://example.com",
|
59
|
-
icon_url: "http://example.com/assets/icon.png",
|
60
|
-
ttl: 604800,
|
61
|
-
require_interaction: true
|
62
|
-
}
|
63
|
-
end
|
64
|
-
let(:notification) { Pushpad::Notification.new notification_params }
|
65
|
-
include_examples 'notification params'
|
66
|
-
end
|
67
|
-
|
68
|
-
context "with a scalar as a param" do
|
69
|
-
it "reaches only that uid" do
|
70
|
-
req = stub_notification_post project_id, uids: [100]
|
71
|
-
notification.deliver_to(100)
|
72
|
-
expect(req).to have_been_made.once
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
context "with an array as a param" do
|
77
|
-
it "reaches only those uids" do
|
78
|
-
req = stub_notification_post project_id, uids: [123, 456]
|
79
|
-
notification.deliver_to([123, 456])
|
80
|
-
expect(req).to have_been_made.once
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
context "with uids and tags" do
|
85
|
-
it "filters audience by uids and tags" do
|
86
|
-
req = stub_notification_post project_id, uids: [123, 456], tags: ['tag1']
|
87
|
-
notification.deliver_to([123, 456], tags: ['tag1'])
|
88
|
-
expect(req).to have_been_made.once
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
describe "#broadcast" do
|
94
|
-
|
95
|
-
shared_examples 'notification params' do
|
96
|
-
it "includes the params in the request" do
|
97
|
-
req = stub_notification_post project_id, notification: notification_params
|
98
|
-
notification.broadcast
|
99
|
-
expect(req).to have_been_made.once
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context "a notification with just the required params" do
|
104
|
-
let(:notification_params) do
|
105
|
-
{ body: "Example message" }
|
106
|
-
end
|
107
|
-
let(:notification) { Pushpad::Notification.new body: notification_params[:body] }
|
108
|
-
include_examples 'notification params'
|
109
|
-
end
|
110
|
-
|
111
|
-
context "a notification with all the optional params" do
|
112
|
-
let(:notification_params) do
|
113
|
-
{
|
114
|
-
body: "Example message",
|
115
|
-
title: "Website Name",
|
116
|
-
target_url: "http://example.com",
|
117
|
-
icon_url: "http://example.com/assets/icon.png",
|
118
|
-
ttl: 604800,
|
119
|
-
require_interaction: true
|
120
|
-
}
|
121
|
-
end
|
122
|
-
let(:notification) { Pushpad::Notification.new notification_params }
|
123
|
-
include_examples 'notification params'
|
124
|
-
end
|
125
|
-
|
126
|
-
context "without params" do
|
127
|
-
it "reaches everyone" do
|
128
|
-
req = stub_notification_post project_id, {}
|
129
|
-
notification.broadcast
|
130
|
-
expect(req).to have_been_made.once
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
context "with tags" do
|
135
|
-
it "filters audience by tags" do
|
136
|
-
req = stub_notification_post project_id, tags: ['tag1', 'tag2']
|
137
|
-
notification.broadcast tags: ['tag1', 'tag2']
|
138
|
-
expect(req).to have_been_made.once
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
24
|
end
|
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pushpad
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pushpad
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: webmock
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
description:
|
@@ -45,10 +45,21 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
+
- .gitignore
|
49
|
+
- .rspec
|
50
|
+
- .travis.yml
|
48
51
|
- Gemfile
|
49
52
|
- LICENSE.txt
|
50
53
|
- README.md
|
54
|
+
- Rakefile
|
51
55
|
- lib/pushpad.rb
|
56
|
+
- lib/pushpad/notification.rb
|
57
|
+
- lib/pushpad/request.rb
|
58
|
+
- lib/pushpad/subscription.rb
|
59
|
+
- pushpad.gemspec
|
60
|
+
- spec/pushpad/notification_spec.rb
|
61
|
+
- spec/pushpad/request_spec.rb
|
62
|
+
- spec/pushpad/subscription_spec.rb
|
52
63
|
- spec/pushpad_spec.rb
|
53
64
|
- spec/spec_helper.rb
|
54
65
|
homepage: https://pushpad.xyz
|
@@ -61,20 +72,23 @@ require_paths:
|
|
61
72
|
- lib
|
62
73
|
required_ruby_version: !ruby/object:Gem::Requirement
|
63
74
|
requirements:
|
64
|
-
- -
|
75
|
+
- - '>='
|
65
76
|
- !ruby/object:Gem::Version
|
66
77
|
version: '0'
|
67
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
79
|
requirements:
|
69
|
-
- -
|
80
|
+
- - '>='
|
70
81
|
- !ruby/object:Gem::Version
|
71
82
|
version: '0'
|
72
83
|
requirements: []
|
73
84
|
rubyforge_project:
|
74
|
-
rubygems_version: 2.
|
85
|
+
rubygems_version: 2.0.14.1
|
75
86
|
signing_key:
|
76
87
|
specification_version: 4
|
77
88
|
summary: Web push notifications for Chrome, Firefox and Safari using Pushpad.
|
78
89
|
test_files:
|
79
|
-
- spec/
|
90
|
+
- spec/pushpad/notification_spec.rb
|
91
|
+
- spec/pushpad/request_spec.rb
|
92
|
+
- spec/pushpad/subscription_spec.rb
|
80
93
|
- spec/pushpad_spec.rb
|
94
|
+
- spec/spec_helper.rb
|