fcm-ruby-push-notifications 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +37 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +19 -0
  5. data/CHANGELOG.md +32 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE +22 -0
  8. data/README.md +82 -0
  9. data/Rakefile +12 -0
  10. data/examples/apns.rb +27 -0
  11. data/examples/gcm.rb +25 -0
  12. data/examples/mpns.rb +22 -0
  13. data/examples/wns.rb +25 -0
  14. data/gemfiles/Gemfile-legacy +8 -0
  15. data/lib/ruby-push-notifications.rb +7 -0
  16. data/lib/ruby-push-notifications/apns.rb +44 -0
  17. data/lib/ruby-push-notifications/apns/apns_connection.rb +70 -0
  18. data/lib/ruby-push-notifications/apns/apns_notification.rb +91 -0
  19. data/lib/ruby-push-notifications/apns/apns_pusher.rb +84 -0
  20. data/lib/ruby-push-notifications/apns/apns_results.rb +30 -0
  21. data/lib/ruby-push-notifications/fcm.rb +8 -0
  22. data/lib/ruby-push-notifications/fcm/fcm_connection.rb +60 -0
  23. data/lib/ruby-push-notifications/fcm/fcm_error.rb +17 -0
  24. data/lib/ruby-push-notifications/fcm/fcm_notification.rb +31 -0
  25. data/lib/ruby-push-notifications/fcm/fcm_pusher.rb +29 -0
  26. data/lib/ruby-push-notifications/fcm/fcm_request.rb +28 -0
  27. data/lib/ruby-push-notifications/fcm/fcm_response.rb +89 -0
  28. data/lib/ruby-push-notifications/fcm/fcm_result.rb +52 -0
  29. data/lib/ruby-push-notifications/gcm.rb +6 -0
  30. data/lib/ruby-push-notifications/gcm/gcm_connection.rb +54 -0
  31. data/lib/ruby-push-notifications/gcm/gcm_error.rb +17 -0
  32. data/lib/ruby-push-notifications/gcm/gcm_notification.rb +31 -0
  33. data/lib/ruby-push-notifications/gcm/gcm_pusher.rb +35 -0
  34. data/lib/ruby-push-notifications/gcm/gcm_response.rb +89 -0
  35. data/lib/ruby-push-notifications/gcm/gcm_result.rb +52 -0
  36. data/lib/ruby-push-notifications/mpns.rb +5 -0
  37. data/lib/ruby-push-notifications/mpns/mpns_connection.rb +87 -0
  38. data/lib/ruby-push-notifications/mpns/mpns_notification.rb +94 -0
  39. data/lib/ruby-push-notifications/mpns/mpns_pusher.rb +33 -0
  40. data/lib/ruby-push-notifications/mpns/mpns_response.rb +82 -0
  41. data/lib/ruby-push-notifications/mpns/mpns_result.rb +182 -0
  42. data/lib/ruby-push-notifications/notification_results_manager.rb +14 -0
  43. data/lib/ruby-push-notifications/wns.rb +6 -0
  44. data/lib/ruby-push-notifications/wns/wns_access.rb +82 -0
  45. data/lib/ruby-push-notifications/wns/wns_connection.rb +97 -0
  46. data/lib/ruby-push-notifications/wns/wns_notification.rb +101 -0
  47. data/lib/ruby-push-notifications/wns/wns_pusher.rb +32 -0
  48. data/lib/ruby-push-notifications/wns/wns_response.rb +83 -0
  49. data/lib/ruby-push-notifications/wns/wns_result.rb +208 -0
  50. data/ruby-push-notifications.gemspec +28 -0
  51. data/spec/factories.rb +17 -0
  52. data/spec/factories/notifications.rb +30 -0
  53. data/spec/ruby-push-notifications/apns/apns_connection_spec.rb +92 -0
  54. data/spec/ruby-push-notifications/apns/apns_notification_spec.rb +42 -0
  55. data/spec/ruby-push-notifications/apns/apns_pusher_spec.rb +295 -0
  56. data/spec/ruby-push-notifications/gcm/gcm_connection_spec.rb +46 -0
  57. data/spec/ruby-push-notifications/gcm/gcm_notification_spec.rb +37 -0
  58. data/spec/ruby-push-notifications/gcm/gcm_pusher_spec.rb +45 -0
  59. data/spec/ruby-push-notifications/gcm/gcm_response_spec.rb +82 -0
  60. data/spec/ruby-push-notifications/mpns/mpns_connection_spec.rb +46 -0
  61. data/spec/ruby-push-notifications/mpns/mpns_notification_spec.rb +53 -0
  62. data/spec/ruby-push-notifications/mpns/mpns_pusher_spec.rb +59 -0
  63. data/spec/ruby-push-notifications/mpns/mpns_response_spec.rb +64 -0
  64. data/spec/ruby-push-notifications/wns/wns_access_spec.rb +76 -0
  65. data/spec/ruby-push-notifications/wns/wns_connection_spec.rb +53 -0
  66. data/spec/ruby-push-notifications/wns/wns_notification_spec.rb +177 -0
  67. data/spec/ruby-push-notifications/wns/wns_pusher_spec.rb +58 -0
  68. data/spec/ruby-push-notifications/wns/wns_response_spec.rb +65 -0
  69. data/spec/spec_helper.rb +23 -0
  70. data/spec/support/dummy.pem +44 -0
  71. data/spec/support/factory_girl.rb +5 -0
  72. data/spec/support/results_shared_examples.rb +31 -0
  73. metadata +249 -0
@@ -0,0 +1,46 @@
1
+
2
+ module RubyPushNotifications
3
+ module GCM
4
+ describe GCMConnection do
5
+
6
+ describe '::post' do
7
+
8
+ let(:body) { 'abc' }
9
+ let(:key) { 'def' }
10
+ let(:response) { JSON.dump a: 1 }
11
+
12
+ before do
13
+ stub_request(:post, 'https://android.googleapis.com/gcm/send').
14
+ to_return status: [200, 'OK'], body: response
15
+ end
16
+
17
+ it 'runs the right request' do
18
+ GCMConnection.post body, key
19
+
20
+ expect(WebMock).
21
+ to have_requested(:post, 'https://android.googleapis.com/gcm/send').
22
+ with(body: body, headers: { 'Content-Type' => 'application/json', 'Authorization' => "key=#{key}" }).
23
+ once
24
+ end
25
+
26
+ context 'when :url option is present' do
27
+ it 'posts data to a custom GCM endpoint' do
28
+ stub_request(:post, 'https://example.com/gcm/send').
29
+ to_return status: [200, 'OK'], body: response
30
+
31
+ GCMConnection.post body, key, url: 'https://example.com/gcm/send'
32
+
33
+ expect(WebMock).
34
+ to have_requested(:post, 'https://example.com/gcm/send').
35
+ with(body: body, headers: { 'Content-Type' => 'application/json', 'Authorization' => "key=#{key}" }).
36
+ once
37
+ end
38
+ end
39
+
40
+ it 'returns the response encapsulated in a GCMResponse object' do
41
+ expect(GCMConnection.post body, key).to eq GCMResponse.new(200, response)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,37 @@
1
+
2
+ module RubyPushNotifications
3
+ module GCM
4
+ describe GCMNotification do
5
+
6
+ let(:registration_ids) { %w(a b c) }
7
+ let(:data) { { a: 1 } }
8
+ let(:notification) { build :gcm_notification, registration_ids: registration_ids, data: data }
9
+
10
+ it 'builds the right gcm json' do
11
+ expect(notification.as_gcm_json).to eq JSON.dump(
12
+ registration_ids: registration_ids,
13
+ data: data
14
+ )
15
+ end
16
+
17
+ it 'validates the registration_ids format'
18
+
19
+ # According to https://developer.android.com/google/gcm/server-ref.html#table1
20
+ it 'validates the data'
21
+
22
+ it_behaves_like 'a proper results manager' do
23
+ let(:success_count) { 2 }
24
+ let(:failures_count) { 1 }
25
+ let(:canonical_id) { 'abcd' }
26
+ let(:individual_results) { [GCMCanonicalIDResult.new(canonical_id)] }
27
+ let(:results) do
28
+ GCMResponse.new 200, JSON.dump(
29
+ success: success_count, failure: failures_count, results: [
30
+ registration_id: canonical_id
31
+ ]
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,45 @@
1
+
2
+ module RubyPushNotifications
3
+ module GCM
4
+ describe GCMPusher do
5
+
6
+ let(:gcm_key) { 'gcm key' }
7
+ let(:pusher) { GCMPusher.new gcm_key }
8
+
9
+ describe '#push' do
10
+
11
+ let(:notif1) { build :gcm_notification }
12
+ let(:notif2) { build :gcm_notification }
13
+ let(:response) { JSON.dump a: 1 }
14
+
15
+ before do
16
+ stub_request(:post, 'https://android.googleapis.com/gcm/send').
17
+ to_return status: [200, 'OK'], body: response
18
+ end
19
+
20
+ it 'submits every notification' do
21
+ pusher.push [notif1, notif2]
22
+
23
+ expect(WebMock).
24
+ to have_requested(:post, 'https://android.googleapis.com/gcm/send').
25
+ with(body: notif1.as_gcm_json, headers: { 'Content-Type' => 'application/json', 'Authorization' => "key=#{gcm_key}" }).
26
+ once
27
+
28
+ expect(WebMock).
29
+ to have_requested(:post, 'https://android.googleapis.com/gcm/send').
30
+ with(body: notif2.as_gcm_json, headers: { 'Content-Type' => 'application/json', 'Authorization' => "key=#{gcm_key}" }).
31
+ once
32
+ end
33
+
34
+ it 'sets results to notifications' do
35
+ expect do
36
+ pusher.push [notif1, notif2]
37
+ end.to change { [notif1, notif2].map &:results }.from([nil, nil]).to [GCMResponse.new(200, response)]*2
38
+ end
39
+
40
+ it 'splits notifications with more than 1000 destinations in parts'
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,82 @@
1
+
2
+ module RubyPushNotifications
3
+ module GCM
4
+ describe GCMResponse do
5
+
6
+ describe 'success' do
7
+
8
+ let(:successful_messages) { 3 }
9
+ let(:failed_messages) { 1 }
10
+ let(:canonical_ids) { 2 }
11
+ let(:body) { JSON.dump(
12
+ multicast_id: 123456789,
13
+ success: successful_messages,
14
+ failure: failed_messages,
15
+ canonical_ids: canonical_ids,
16
+ results: [
17
+ { message_id: 1,
18
+ registration_id: 'new_reg_id' },
19
+ { message_id: 2,
20
+ registration_id: 'new_reg_id_2' },
21
+ { message_id: 3 },
22
+ { message_id: 4,
23
+ error: 'NotRegistered' }
24
+ ]
25
+ ) }
26
+
27
+ let(:response) { GCMResponse.new 200, body }
28
+
29
+ it 'parses the number of successfully processed notifications' do
30
+ expect(response.success).to eq successful_messages
31
+ end
32
+
33
+ it 'parses the number of failed messages' do
34
+ expect(response.failed).to eq failed_messages
35
+ end
36
+
37
+ it 'parses the number of canonical ids received' do
38
+ expect(response.canonical_ids).to eq canonical_ids
39
+ end
40
+
41
+ it 'parses the results' do
42
+ expect(response.results).to eq [GCMCanonicalIDResult.new('new_reg_id'), GCMCanonicalIDResult.new('new_reg_id_2'), GCMResultOK.new, GCMResultError.new('NotRegistered')]
43
+ end
44
+ end
45
+
46
+ describe 'errors' do
47
+ let(:dummy_response_body) { 'dummy response body' }
48
+ describe '400 Bad Request error code' do
49
+ it 'raises a MalformedGCMJSONError' do
50
+ expect do
51
+ GCMResponse.new 400, dummy_response_body
52
+ end.to raise_error MalformedGCMJSONError, dummy_response_body
53
+ end
54
+ end
55
+
56
+ describe '401 Unauthorized error code' do
57
+ it 'raises a GCMAuthError' do
58
+ expect do
59
+ GCMResponse.new 401, dummy_response_body
60
+ end.to raise_error GCMAuthError, dummy_response_body
61
+ end
62
+ end
63
+
64
+ describe '500 Internal Server Error error code' do
65
+ it 'raises a GCMInternalError' do
66
+ expect do
67
+ GCMResponse.new 500, dummy_response_body
68
+ end.to raise_error GCMInternalError, dummy_response_body
69
+ end
70
+ end
71
+
72
+ describe '302 Found error code' do
73
+ it 'raises a UnexpectedGCMResponseError' do
74
+ expect do
75
+ GCMResponse.new 302, dummy_response_body
76
+ end.to raise_error UnexpectedGCMResponseError, '302'
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,46 @@
1
+
2
+ module RubyPushNotifications
3
+ module MPNS
4
+ describe MPNSConnection do
5
+
6
+ describe '::post' do
7
+
8
+ let(:body) { 'abc' }
9
+ let(:headers) {
10
+ {
11
+ 'x-notificationstatus' => 'Received',
12
+ 'x-deviceconnectionstatus' => 'Connected',
13
+ 'x-subscriptionstatus' => 'Active'
14
+ }
15
+ }
16
+ let(:device_urls) { [generate(:mpns_device_url)] }
17
+ let(:toast_data) { { title: 'Title', message: 'Hello MPNS World!', type: :toast } }
18
+ let(:toast_notification) { build :mpns_notification, device_urls: device_urls, data: toast_data }
19
+
20
+ before do
21
+ stub_request(:post, %r{s.notify.live.net}).
22
+ to_return status: [200, 'OK'], body: body, headers: headers
23
+ end
24
+
25
+ it 'runs the right request' do
26
+ MPNSConnection.post toast_notification
27
+
28
+ expect(WebMock).
29
+ to have_requested(:post, toast_notification.device_urls[0]).
30
+ with(body: toast_notification.as_mpns_xml, headers: { 'Content-Type' => 'text/xml', 'X-NotificationClass' => '2', 'X-WindowsPhone-Target' => :toast}).
31
+ once
32
+ end
33
+
34
+ it 'returns the response encapsulated in a Hash object' do
35
+ responses = [
36
+ { device_url: toast_notification.device_urls[0],
37
+ headers: headers,
38
+ code: 200
39
+ }
40
+ ]
41
+ expect(MPNSConnection.post toast_notification).to eq MPNSResponse.new(responses)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,53 @@
1
+
2
+ module RubyPushNotifications
3
+ module MPNS
4
+ describe MPNSNotification do
5
+
6
+ let(:device_urls) { %w(a b c) }
7
+ let(:raw_notification) { build :mpns_notification }
8
+ let(:toast_data) { { title: 'Title', message: 'Hello MPNS World!', type: :toast } }
9
+ let(:toast_notification) { build :mpns_notification, device_urls: device_urls, data: toast_data }
10
+ let(:tile_data) { { count: 1, title: 'Hello MPNS World!', type: :tile } }
11
+ let(:tile_notification) { build :mpns_notification, device_urls: device_urls, data: tile_data }
12
+
13
+ it 'builds the right mpns raw xml' do
14
+ xml = '<?xml version="1.0" encoding="UTF-8"?>'
15
+ xml << '<root><value1>hello</value1></root>'
16
+ expect(raw_notification.as_mpns_xml).to eq xml
17
+ end
18
+
19
+ it 'builds the right mpns toast xml' do
20
+ xml = '<?xml version="1.0" encoding="UTF-8"?>'
21
+ xml << '<wp:Notification xmlns:wp="WPNotification"><wp:Toast>'
22
+ xml << '<wp:Text1>Title</wp:Text1>'
23
+ xml << '<wp:Text2>Hello MPNS World!</wp:Text2>'
24
+ xml << '</wp:Toast></wp:Notification>'
25
+ expect(toast_notification.as_mpns_xml).to eq xml
26
+ end
27
+
28
+ it 'builds the right mpns tile xml' do
29
+ xml = '<?xml version="1.0" encoding="UTF-8"?>'
30
+ xml << '<wp:Notification xmlns:wp="WPNotification"><wp:Tile>'
31
+ xml << '<wp:Count>1</wp:Count>'
32
+ xml << '<wp:Title>Hello MPNS World!</wp:Title>'
33
+ xml << '</wp:Tile></wp:Notification>'
34
+ expect(tile_notification.as_mpns_xml).to eq xml
35
+ end
36
+
37
+ it 'validates the mpns format'
38
+
39
+ it 'validates the data'
40
+
41
+ it_behaves_like 'a proper results manager' do
42
+ let(:notification) { build :mpns_notification }
43
+ let(:success_count) { 1 }
44
+ let(:failures_count) { 0 }
45
+ let(:device_url) { generate :mpns_device_url }
46
+ let(:individual_results) { [MPNSResultOK.new(device_url, {})] }
47
+ let(:results) do
48
+ MPNSResponse.new [{ code: 200, device_url: device_url, headers: {} }]
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,59 @@
1
+
2
+ module RubyPushNotifications
3
+ module MPNS
4
+ describe MPNSPusher do
5
+
6
+ let(:pusher) { MPNSPusher.new }
7
+
8
+ describe '#push' do
9
+
10
+ let(:device_urls) { [generate(:mpns_device_url)] }
11
+ let(:notif1) { build :mpns_notification, device_urls: ['http://s.notify.live.net/1'], data: { message: { value1: 'hello' } } }
12
+ let(:notif2) { build :mpns_notification, device_urls: ['http://s.notify.live.net/1'], data: { message: { value1: 'hello' } } }
13
+ let(:raw_notification) { build :mpns_notification }
14
+ let(:toast_data) { { title: 'Title', message: 'Hello MPNS World!', type: :toast } }
15
+ let(:toast_notification) { build :mpns_notification, device_urls: device_urls, data: toast_data }
16
+ let(:tile_data) { { count: 1, title: 'Hello MPNS World!', type: :tile } }
17
+ let(:tile_notification) { build :mpns_notification, device_urls: device_urls, data: tile_data }
18
+ let(:headers) {
19
+ {
20
+ 'x-notificationstatus' => 'Received',
21
+ 'x-deviceconnectionstatus' => 'Connected',
22
+ 'x-subscriptionstatus' => 'Active'
23
+ }
24
+ }
25
+ let(:response) { [ { device_url: 'http://s.notify.live.net/1', headers: headers, code: 200 } ]}
26
+
27
+ before do
28
+ stub_request(:post, %r{s.notify.live.net}).
29
+ to_return status: [200, 'OK'], headers: headers
30
+ end
31
+
32
+ it 'submits every notification' do
33
+ pusher.push [raw_notification, toast_notification, tile_notification]
34
+ expect(WebMock).
35
+ to have_requested(:post, raw_notification.device_urls[0]).
36
+ with(body: raw_notification.as_mpns_xml, headers: { 'Content-Type' => 'text/xml', 'X-NotificationClass' => '3'}).
37
+ once
38
+
39
+ expect(WebMock).
40
+ to have_requested(:post, toast_notification.device_urls[0]).
41
+ with(body: toast_notification.as_mpns_xml, headers: { 'Content-Type' => 'text/xml', 'X-NotificationClass' => '2', 'X-WindowsPhone-Target' => :toast}).
42
+ once
43
+
44
+ expect(WebMock).
45
+ to have_requested(:post, tile_notification.device_urls[0]).
46
+ with(body: tile_notification.as_mpns_xml, headers: { 'Content-Type' => 'text/xml', 'X-NotificationClass' => '1', 'X-WindowsPhone-Target' => 'token'}).
47
+ once
48
+ end
49
+
50
+ it 'sets results to notifications' do
51
+ expect do
52
+ pusher.push [notif1, notif2]
53
+ end.to change { [notif1, notif2].map &:results }.from([nil, nil]).to [MPNSResponse.new(response)]*2
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,64 @@
1
+
2
+ module RubyPushNotifications
3
+ module MPNS
4
+ describe MPNSResponse do
5
+
6
+ describe 'success' do
7
+
8
+ let(:successful_messages) { 2 }
9
+ let(:failed_messages) { 6 }
10
+ let(:headers) {
11
+ {
12
+ 'x-notificationstatus' => 'Received',
13
+ 'x-deviceconnectionstatus' => 'Connected',
14
+ 'x-subscriptionstatus' => 'Active'
15
+ }
16
+ }
17
+
18
+ let(:responses) {
19
+ [
20
+ { device_url: '1', headers: headers, code: 200 },
21
+ { device_url: '2', headers: headers, code: 200 },
22
+ { device_url: '3', code: 400 },
23
+ { device_url: '4', code: 401 },
24
+ { device_url: '5', headers: headers, code: 404 },
25
+ { device_url: '6', headers: headers, code: 406 },
26
+ { device_url: '7', headers: headers, code: 412 },
27
+ { device_url: '8', code: 503 }
28
+ ]
29
+ }
30
+
31
+ let(:response) { MPNSResponse.new responses }
32
+ let(:result) { MPNSResultOK.new '1', headers }
33
+
34
+ it 'parses the number of successfully processed notifications' do
35
+ expect(response.success).to eq successful_messages
36
+ end
37
+
38
+ it 'parses the number of failed messages' do
39
+ expect(response.failed).to eq failed_messages
40
+ end
41
+
42
+ it 'parses the results' do
43
+ expect(response.results).to eq [
44
+ MPNSResultOK.new('1', headers),
45
+ MPNSResultOK.new('2', headers),
46
+ MalformedMPNSResultError.new('3'),
47
+ MPNSAuthError.new('4'),
48
+ MPNSInvalidError.new('5', headers),
49
+ MPNSLimitError.new('6', headers),
50
+ MPNSPreConditionError.new('7', headers),
51
+ MPNSInternalError.new('8')
52
+ ]
53
+ end
54
+
55
+ it 'parses headers to result attributes' do
56
+ expect(result.notification_status).to eq 'Received'
57
+ expect(result.device_connection_status).to eq 'Connected'
58
+ expect(result.subscription_status).to eq 'Active'
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+ 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