ruby-push-notifications 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|