ruby-push-notifications 1.1.0 → 1.2.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/CHANGELOG.md +5 -0
- data/README.md +3 -2
- data/examples/wns.rb +25 -0
- data/lib/ruby-push-notifications.rb +1 -0
- data/lib/ruby-push-notifications/wns.rb +6 -0
- data/lib/ruby-push-notifications/wns/wns_access.rb +82 -0
- data/lib/ruby-push-notifications/wns/wns_connection.rb +97 -0
- data/lib/ruby-push-notifications/wns/wns_notification.rb +101 -0
- data/lib/ruby-push-notifications/wns/wns_pusher.rb +32 -0
- data/lib/ruby-push-notifications/wns/wns_response.rb +83 -0
- data/lib/ruby-push-notifications/wns/wns_result.rb +208 -0
- data/ruby-push-notifications.gemspec +1 -1
- data/spec/factories.rb +3 -1
- data/spec/factories/notifications.rb +7 -0
- data/spec/ruby-push-notifications/wns/wns_access_spec.rb +76 -0
- data/spec/ruby-push-notifications/wns/wns_connection_spec.rb +53 -0
- data/spec/ruby-push-notifications/wns/wns_notification_spec.rb +177 -0
- data/spec/ruby-push-notifications/wns/wns_pusher_spec.rb +58 -0
- data/spec/ruby-push-notifications/wns/wns_response_spec.rb +65 -0
- metadata +21 -5
- data/.hound.yml +0 -2
- data/.ruby-style.yml +0 -1063
@@ -0,0 +1,208 @@
|
|
1
|
+
module RubyPushNotifications
|
2
|
+
module WNS
|
3
|
+
# Class that encapsulates the result of a single sent notification to a single
|
4
|
+
# Device URL
|
5
|
+
# https://msdn.microsoft.com/en-us/library/windows/apps/hh465435.aspx#WNSResponseCodes
|
6
|
+
class WNSResult
|
7
|
+
# @return [String]. Receiver WNS device URL.
|
8
|
+
attr_accessor :device_url
|
9
|
+
|
10
|
+
# @private X-WNS-NotificationStatus HTTP Header string
|
11
|
+
X_NOTIFICATION_STATUS = 'x-wns-notificationstatus'
|
12
|
+
|
13
|
+
# @private X-WNS-DeviceConnectionStatus HTTP Header string
|
14
|
+
X_DEVICE_CONNECTION_STATUS = 'x-wns-deviceconnectionstatus'
|
15
|
+
|
16
|
+
# @private X-SubscriptionStatus HTTP Header string
|
17
|
+
X_STATUS = 'x-wns-status'
|
18
|
+
end
|
19
|
+
|
20
|
+
# Indicates that the notification was successfully sent to the corresponding
|
21
|
+
# device URL
|
22
|
+
class WNSResultOK < WNSResult
|
23
|
+
# @return [String]. The status of the notification received
|
24
|
+
# by the Windows Notification Service.
|
25
|
+
attr_accessor :notification_status
|
26
|
+
|
27
|
+
# @return [String]. The connection status of the device.
|
28
|
+
attr_accessor :device_connection_status
|
29
|
+
|
30
|
+
# @return [String]. Notification status.
|
31
|
+
attr_accessor :status
|
32
|
+
|
33
|
+
def initialize(device_url, headers)
|
34
|
+
@device_url = device_url
|
35
|
+
@notification_status = headers[X_NOTIFICATION_STATUS]
|
36
|
+
@device_connection_status = headers[X_DEVICE_CONNECTION_STATUS]
|
37
|
+
@status = headers[X_STATUS]
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
(other.is_a?(WNSResultOK) &&
|
42
|
+
device_url == other.device_url &&
|
43
|
+
notification_status == other.notification_status &&
|
44
|
+
device_connection_status == other.device_connection_status &&
|
45
|
+
status == other.status) || super(other)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# This error occurs when the cloud service sends a notification
|
50
|
+
# request with a bad XML document or malformed notification URI.
|
51
|
+
class MalformedWNSResultError < WNSResult
|
52
|
+
def initialize(device_url)
|
53
|
+
@device_url = device_url
|
54
|
+
end
|
55
|
+
|
56
|
+
def ==(other)
|
57
|
+
(other.is_a?(MalformedWNSResultError) &&
|
58
|
+
device_url == other.device_url) || super(other)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Sending this notification is unauthorized.
|
63
|
+
class WNSAuthError < WNSResult
|
64
|
+
def initialize(device_url)
|
65
|
+
@device_url = device_url
|
66
|
+
end
|
67
|
+
|
68
|
+
def ==(other)
|
69
|
+
(other.is_a?(WNSAuthError) &&
|
70
|
+
device_url == other.device_url) || super(other)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Notification is invalid and is not present on the Push Notification Service.
|
75
|
+
class WNSInvalidError < WNSResult
|
76
|
+
# @return [String]. The status of the notification received
|
77
|
+
# by the Windows Notification Service.
|
78
|
+
attr_accessor :notification_status
|
79
|
+
|
80
|
+
# @return [String]. The connection status of the device.
|
81
|
+
attr_accessor :device_connection_status
|
82
|
+
|
83
|
+
# @return [String]. Notification status.
|
84
|
+
attr_accessor :status
|
85
|
+
|
86
|
+
def initialize(device_url, headers)
|
87
|
+
@device_url = device_url
|
88
|
+
@notification_status = headers[X_NOTIFICATION_STATUS]
|
89
|
+
@device_connection_status = headers[X_DEVICE_CONNECTION_STATUS]
|
90
|
+
@status = headers[X_STATUS]
|
91
|
+
end
|
92
|
+
|
93
|
+
def ==(other)
|
94
|
+
(other.is_a?(WNSInvalidError) &&
|
95
|
+
device_url == other.device_url &&
|
96
|
+
notification_status == other.notification_status &&
|
97
|
+
device_connection_status == other.device_connection_status &&
|
98
|
+
status == other.status) || super(other)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# This error occurs when an unauthenticated cloud service has reached
|
103
|
+
# the per-day throttling limit for a subscription,
|
104
|
+
# or when a cloud service (authenticated or unauthenticated)
|
105
|
+
# has sent too many notifications per second.
|
106
|
+
class WNSLimitError < WNSResult
|
107
|
+
# @return [String]. The status of the notification received
|
108
|
+
# by the Windows Notification Service.
|
109
|
+
attr_accessor :notification_status
|
110
|
+
|
111
|
+
# @return [String]. The connection status of the device.
|
112
|
+
attr_accessor :device_connection_status
|
113
|
+
|
114
|
+
# @return [String]. Notification status.
|
115
|
+
attr_accessor :status
|
116
|
+
|
117
|
+
def initialize(device_url, headers)
|
118
|
+
@device_url = device_url
|
119
|
+
@notification_status = headers[X_NOTIFICATION_STATUS]
|
120
|
+
@device_connection_status = headers[X_DEVICE_CONNECTION_STATUS]
|
121
|
+
@status = headers[X_STATUS]
|
122
|
+
end
|
123
|
+
|
124
|
+
def ==(other)
|
125
|
+
(other.is_a?(WNSLimitError) &&
|
126
|
+
device_url == other.device_url &&
|
127
|
+
notification_status == other.notification_status &&
|
128
|
+
device_connection_status == other.device_connection_status &&
|
129
|
+
status == other.status) || super(other)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# The device is in a disconnected state.
|
134
|
+
class WNSPreConditionError < WNSResult
|
135
|
+
# @return [String]. The status of the notification received
|
136
|
+
# by the Windows Notification Service.
|
137
|
+
attr_accessor :notification_status
|
138
|
+
|
139
|
+
# @return [String]. The connection status of the device.
|
140
|
+
attr_accessor :device_connection_status
|
141
|
+
|
142
|
+
def initialize(device_url, headers)
|
143
|
+
@device_url = device_url
|
144
|
+
@notification_status = headers[X_NOTIFICATION_STATUS]
|
145
|
+
@device_connection_status = headers[X_DEVICE_CONNECTION_STATUS]
|
146
|
+
end
|
147
|
+
|
148
|
+
def ==(other)
|
149
|
+
(other.is_a?(WNSPreConditionError) &&
|
150
|
+
device_url == other.device_url &&
|
151
|
+
notification_status == other.notification_status &&
|
152
|
+
device_connection_status == other.device_connection_status) || super(other)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# The device is in a disconnected state.
|
157
|
+
class WNSExpiredError < WNSResult
|
158
|
+
# @return [String]. The status of the notification received
|
159
|
+
# by the Windows Notification Service.
|
160
|
+
attr_accessor :notification_status
|
161
|
+
|
162
|
+
# @return [String]. The connection status of the device.
|
163
|
+
attr_accessor :device_connection_status
|
164
|
+
|
165
|
+
# @return [String]. Notification status.
|
166
|
+
attr_accessor :status
|
167
|
+
|
168
|
+
def initialize(device_url, headers)
|
169
|
+
@device_url = device_url
|
170
|
+
@notification_status = headers[X_NOTIFICATION_STATUS]
|
171
|
+
@device_connection_status = headers[X_DEVICE_CONNECTION_STATUS]
|
172
|
+
@status = 'Expired'.freeze
|
173
|
+
end
|
174
|
+
|
175
|
+
def ==(other)
|
176
|
+
(other.is_a?(WNSExpiredError) &&
|
177
|
+
device_url == other.device_url &&
|
178
|
+
notification_status == other.notification_status &&
|
179
|
+
device_connection_status == other.device_connection_status &&
|
180
|
+
status == other.status) || super(other)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# The Push Notification Service is unable to process the request.
|
185
|
+
class WNSInternalError < WNSResult
|
186
|
+
def initialize(device_url)
|
187
|
+
@device_url = device_url
|
188
|
+
end
|
189
|
+
|
190
|
+
def ==(other)
|
191
|
+
(other.is_a?(WNSInternalError) &&
|
192
|
+
device_url == other.device_url) || super(other)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Unknow Error
|
197
|
+
class WNSResultError < WNSResult
|
198
|
+
def initialize(device_url)
|
199
|
+
@device_url = device_url
|
200
|
+
end
|
201
|
+
|
202
|
+
def ==(other)
|
203
|
+
(other.is_a?(WNSResultError) &&
|
204
|
+
device_url == other.device_url) || super(other)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
Gem::Specification.new do |spec|
|
3
3
|
spec.name = "ruby-push-notifications"
|
4
|
-
spec.version = "1.
|
4
|
+
spec.version = "1.2.0"
|
5
5
|
spec.authors = ['Carlos Alonso']
|
6
6
|
spec.email = ['info@mrcalonso.com']
|
7
7
|
spec.summary = %q{iOS, Android and Windows Phone Push Notifications made easy!}
|
data/spec/factories.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
FactoryGirl.define do
|
3
2
|
sequence :apns_token do |i|
|
4
3
|
"ce8be627 2e43e855 16033e24 b4c28922 0eeda487 9c477160 b2545e95 b68b596#{i}"
|
@@ -12,4 +11,7 @@ FactoryGirl.define do
|
|
12
11
|
"http://s.notify.live.net/u/1/bn1/HmQAAACP-0esPuxBSkzBNNXH4W0lV3lK-stEw6eRfpXX39uYbM7IwehXOTO9pRBjaaGECWOdD_7x5j5U4w4iXG4hGxer/d2luZG93c3Bob25lZGVmYXVsdA/EMDhx32Q5BG0DWnZpuVX1g/kRFAu0-jnhMQ-HG94rXzrbb0wQk#{i}"
|
13
12
|
end
|
14
13
|
|
14
|
+
sequence :wns_device_url do |i|
|
15
|
+
"https://hk2.notify.windows.com/?token=AwYAAABe%2bpjShu%2fzcVaaf1NPm%2b2dpiosm7RnmBJGMVkBDiYNXpAEp0mETldEu8axFoamgwb%2fdKCuNSfGGDHZ3RcaO2fcNGfxC6Y4Yp3xTFkDOhv5kNfgSXef7pSP0uwueIpqbWI%3d#{i}"
|
16
|
+
end
|
15
17
|
end
|
@@ -20,4 +20,11 @@ FactoryGirl.define do
|
|
20
20
|
initialize_with { new device_urls, data }
|
21
21
|
end
|
22
22
|
|
23
|
+
factory :wns_notification, class: 'RubyPushNotifications::WNS::WNSNotification' do
|
24
|
+
device_urls { [generate(:wns_device_url)] }
|
25
|
+
data message: { value1: 'hello' }
|
26
|
+
|
27
|
+
initialize_with { new device_urls, data }
|
28
|
+
end
|
29
|
+
|
23
30
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module RubyPushNotifications
|
2
|
+
module WNS
|
3
|
+
describe WNSAccess do
|
4
|
+
describe '::access_token' do
|
5
|
+
let(:sid) { 'sid' }
|
6
|
+
let(:secret) { 'secret' }
|
7
|
+
|
8
|
+
context 'when service return status OK' do
|
9
|
+
let(:body) {
|
10
|
+
"{\"token_type\":\"bearer\",\"access_token\":\"real_access_token\",\"expires_in\":86400}"
|
11
|
+
}
|
12
|
+
before do
|
13
|
+
stub_request(:post, "https://login.live.com/accesstoken.srf").
|
14
|
+
to_return status: [200, 'OK'], body: body
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns correct response' do
|
18
|
+
response = OpenStruct.new(
|
19
|
+
status_code: 200,
|
20
|
+
status: 'OK',
|
21
|
+
error: nil,
|
22
|
+
error_description: nil,
|
23
|
+
access_token: 'real_access_token',
|
24
|
+
token_ttl: 86400
|
25
|
+
)
|
26
|
+
expect(WNSAccess.new(sid, secret).get_token.response).to eq(response)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when service return an error' do
|
31
|
+
context 'when bad credentials' do
|
32
|
+
let(:body) {
|
33
|
+
"{\"error\":\"invalid_client\",\"error_description\":\"Invalid client id\"}"
|
34
|
+
}
|
35
|
+
before do
|
36
|
+
stub_request(:post, "https://login.live.com/accesstoken.srf").
|
37
|
+
to_return status: [400, 'Bad Request'], body: body
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns correct response' do
|
41
|
+
response = OpenStruct.new(
|
42
|
+
status_code: 400,
|
43
|
+
status: 'Bad Request',
|
44
|
+
error: 'invalid_client',
|
45
|
+
error_description: 'Invalid client id',
|
46
|
+
access_token: nil,
|
47
|
+
token_ttl: nil
|
48
|
+
)
|
49
|
+
expect(WNSAccess.new(sid, secret).get_token.response).to eq(response)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when bad request' do
|
54
|
+
let(:body) { '' }
|
55
|
+
before do
|
56
|
+
stub_request(:post, "https://login.live.com/accesstoken.srf").
|
57
|
+
to_return status: [500, 'Internal Server Error'], body: body
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'returns correct response' do
|
61
|
+
response = OpenStruct.new(
|
62
|
+
status_code: 500,
|
63
|
+
status: 'Internal Server Error',
|
64
|
+
error: nil,
|
65
|
+
error_description: nil,
|
66
|
+
access_token: nil,
|
67
|
+
token_ttl: nil
|
68
|
+
)
|
69
|
+
expect(WNSAccess.new(sid, secret).get_token.response).to eq(response)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module RubyPushNotifications
|
2
|
+
module WNS
|
3
|
+
describe WNSConnection do
|
4
|
+
|
5
|
+
describe '::post' do
|
6
|
+
let(:body) { 'abc' }
|
7
|
+
let(:headers) {
|
8
|
+
{
|
9
|
+
'x-wns-notificationstatus' => 'Received',
|
10
|
+
'x-wns-deviceconnectionstatus' => 'Connected',
|
11
|
+
'x-wns-status' => 'Received'
|
12
|
+
}
|
13
|
+
}
|
14
|
+
let(:push_types) { RubyPushNotifications::WNS::WNSConnection::WP_TARGETS }
|
15
|
+
let(:access_token) { 'token' }
|
16
|
+
let(:device_urls) { [generate(:wns_device_url)] }
|
17
|
+
let(:toast_data) { { title: 'Title', message: 'Hello WNS World!', type: :toast } }
|
18
|
+
let(:toast_notification) { build :wns_notification, device_urls: device_urls, data: toast_data }
|
19
|
+
let(:wns_connection) { RubyPushNotifications::WNS::WNSConnection }
|
20
|
+
|
21
|
+
before do
|
22
|
+
stub_request(:post, %r{hk2.notify.windows.com}).
|
23
|
+
to_return status: [200, 'OK'], body: body, headers: headers
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'runs the right request' do
|
27
|
+
WNSConnection.post toast_notification, access_token
|
28
|
+
headers = {
|
29
|
+
wns_connection::CONTENT_TYPE_HEADER => wns_connection::CONTENT_TYPE[:toast],
|
30
|
+
wns_connection::X_WNS_TYPE_HEADER => wns_connection::WP_TARGETS[:toast],
|
31
|
+
wns_connection::CONTENT_LENGTH_HEADER => toast_notification.as_wns_xml.length.to_s,
|
32
|
+
wns_connection::AUTHORIZATION_HEADER => "Bearer #{access_token}",
|
33
|
+
wns_connection::REQUEST_FOR_STATUS_HEADER => 'true'
|
34
|
+
}
|
35
|
+
expect(WebMock).
|
36
|
+
to have_requested(:post, toast_notification.device_urls[0]).
|
37
|
+
with(body: toast_notification.as_wns_xml, headers: headers).
|
38
|
+
once
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns the response encapsulated in a Hash object' do
|
42
|
+
responses = [
|
43
|
+
{ device_url: toast_notification.device_urls[0],
|
44
|
+
headers: headers,
|
45
|
+
code: 200
|
46
|
+
}
|
47
|
+
]
|
48
|
+
expect(WNSConnection.post toast_notification, access_token).to eq WNSResponse.new(responses)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
module RubyPushNotifications
|
2
|
+
module WNS
|
3
|
+
describe WNSNotification do
|
4
|
+
let(:device_urls) { %w(a b c) }
|
5
|
+
let(:raw_data) { { message: { title: 'Title', message: 'Hello WNS World!'} } }
|
6
|
+
let(:raw_notification) { build :wns_notification, data: raw_data }
|
7
|
+
let(:toast_data) { { title: 'Title', message: 'Hello WNS World!', type: :toast } }
|
8
|
+
let(:toast_notification) { build :wns_notification, device_urls: device_urls, data: toast_data }
|
9
|
+
let(:tile_data) { { message: 'Hello WNS World!', image: 'http://image.com/image.jpg', type: :tile } }
|
10
|
+
let(:tile_notification) { build :wns_notification, device_urls: device_urls, data: tile_data }
|
11
|
+
let(:badge_data) { { value: 10, type: :badge } }
|
12
|
+
let(:badge_notification) { build :wns_notification, device_urls: device_urls, data: badge_data }
|
13
|
+
|
14
|
+
describe 'raw xml' do
|
15
|
+
it 'builds the right wns raw xml' do
|
16
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
17
|
+
xml << '<root><title>Title</title><message>Hello WNS World!</message></root>'
|
18
|
+
expect(raw_notification.as_wns_xml).to eq xml
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'without message' do
|
22
|
+
let(:raw_data) { {} }
|
23
|
+
|
24
|
+
it 'builds the right wns raw xml' do
|
25
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
26
|
+
xml << '<root></root>'
|
27
|
+
expect(raw_notification.as_wns_xml).to eq xml
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'badge xml' do
|
33
|
+
it 'builds the right wns badge xml' do
|
34
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
35
|
+
xml << '<badge value="10"/>'
|
36
|
+
expect(badge_notification.as_wns_xml).to eq xml
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'without value' do
|
40
|
+
let(:badge_data) { { type: :badge } }
|
41
|
+
|
42
|
+
it 'builds the right wns badge xml' do
|
43
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
44
|
+
xml << '<badge value=""/>'
|
45
|
+
expect(badge_notification.as_wns_xml).to eq xml
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'toast xml' do
|
51
|
+
it 'builds the right wns toast xml' do
|
52
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
53
|
+
xml << '<toast>'
|
54
|
+
xml << '<visual>'
|
55
|
+
xml << '<binding template="ToastText02">'
|
56
|
+
xml << '<text id="1">Title</text>'
|
57
|
+
xml << '<text id="2">Hello WNS World!</text>'
|
58
|
+
xml << '</binding>'
|
59
|
+
xml << '</visual>'
|
60
|
+
xml << '</toast>'
|
61
|
+
expect(toast_notification.as_wns_xml).to eq xml
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when params present' do
|
65
|
+
let(:toast_data) { super().merge(param: { var1: 'value1', var2: 'value2'}) }
|
66
|
+
|
67
|
+
it 'builds the right wns toast xml' do
|
68
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
69
|
+
xml << '<toast launch="{"var1":"value1","var2":"value2"}">'
|
70
|
+
xml << '<visual>'
|
71
|
+
xml << '<binding template="ToastText02">'
|
72
|
+
xml << '<text id="1">Title</text>'
|
73
|
+
xml << '<text id="2">Hello WNS World!</text>'
|
74
|
+
xml << '</binding>'
|
75
|
+
xml << '</visual>'
|
76
|
+
xml << '</toast>'
|
77
|
+
expect(toast_notification.as_wns_xml).to eq xml
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when template present' do
|
82
|
+
let(:toast_data) { super().merge(template: 'custom_template') }
|
83
|
+
|
84
|
+
it 'builds the right wns toast xml' do
|
85
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
86
|
+
xml << '<toast>'
|
87
|
+
xml << '<visual>'
|
88
|
+
xml << '<binding template="custom_template">'
|
89
|
+
xml << '<text id="1">Title</text>'
|
90
|
+
xml << '<text id="2">Hello WNS World!</text>'
|
91
|
+
xml << '</binding>'
|
92
|
+
xml << '</visual>'
|
93
|
+
xml << '</toast>'
|
94
|
+
expect(toast_notification.as_wns_xml).to eq xml
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'without title and message' do
|
99
|
+
let(:toast_data) { { type: :toast } }
|
100
|
+
|
101
|
+
it 'builds the right wns toast xml' do
|
102
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
103
|
+
xml << '<toast>'
|
104
|
+
xml << '<visual>'
|
105
|
+
xml << '<binding template="ToastText02">'
|
106
|
+
xml << '<text id="1"></text>'
|
107
|
+
xml << '<text id="2"></text>'
|
108
|
+
xml << '</binding>'
|
109
|
+
xml << '</visual>'
|
110
|
+
xml << '</toast>'
|
111
|
+
expect(toast_notification.as_wns_xml).to eq xml
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'toast xml' do
|
117
|
+
it 'builds the right wns tile xml' do
|
118
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
119
|
+
xml << '<tile>'
|
120
|
+
xml << '<visual>'
|
121
|
+
xml << '<binding template="TileWideImageAndText01">'
|
122
|
+
xml << '<image src="http://image.com/image.jpg"/>'
|
123
|
+
xml << '<text>Hello WNS World!</text>'
|
124
|
+
xml << '</binding>'
|
125
|
+
xml << '</visual>'
|
126
|
+
xml << '</tile>'
|
127
|
+
expect(tile_notification.as_wns_xml).to eq xml
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'when template present' do
|
131
|
+
let(:tile_data) { super().merge(template: 'custom_template') }
|
132
|
+
|
133
|
+
it 'builds the right wns toast xml' do
|
134
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
135
|
+
xml << '<tile>'
|
136
|
+
xml << '<visual>'
|
137
|
+
xml << '<binding template="custom_template">'
|
138
|
+
xml << '<image src="http://image.com/image.jpg"/>'
|
139
|
+
xml << '<text>Hello WNS World!</text>'
|
140
|
+
xml << '</binding>'
|
141
|
+
xml << '</visual>'
|
142
|
+
xml << '</tile>'
|
143
|
+
expect(tile_notification.as_wns_xml).to eq xml
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'without image and message' do
|
148
|
+
let(:tile_data) { { type: :tile } }
|
149
|
+
|
150
|
+
it 'builds the right wns toast xml' do
|
151
|
+
xml = '<?xml version="1.0" encoding="UTF-8"?>'
|
152
|
+
xml << '<tile>'
|
153
|
+
xml << '<visual>'
|
154
|
+
xml << '<binding template="TileWideImageAndText01">'
|
155
|
+
xml << '<image src=""/>'
|
156
|
+
xml << '<text></text>'
|
157
|
+
xml << '</binding>'
|
158
|
+
xml << '</visual>'
|
159
|
+
xml << '</tile>'
|
160
|
+
expect(tile_notification.as_wns_xml).to eq xml
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
it_behaves_like 'a proper results manager' do
|
166
|
+
let(:notification) { build :wns_notification }
|
167
|
+
let(:success_count) { 1 }
|
168
|
+
let(:failures_count) { 0 }
|
169
|
+
let(:device_url) { generate :wns_device_url }
|
170
|
+
let(:individual_results) { [WNSResultOK.new(device_url, {})] }
|
171
|
+
let(:results) do
|
172
|
+
WNSResponse.new [{ code: 200, device_url: device_url, headers: {} }]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|