pushpad 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](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
|