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,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="{&quot;var1&quot;:&quot;value1&quot;,&quot;var2&quot;:&quot;value2&quot;}">'
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
@@ -0,0 +1,58 @@
1
+ module RubyPushNotifications
2
+ module WNS
3
+ describe WNSPusher do
4
+ let(:access_token) { 'token' }
5
+ let(:pusher) { WNSPusher.new(access_token) }
6
+
7
+ describe '#push' do
8
+ let(:device_urls) { [generate(:wns_device_url)] }
9
+ let(:notifications) { build_list(:wns_notification, 2, device_urls: ['http://hk2.notify.windows.com/1'], data: { message: { value1: 'hello' } }).to_a }
10
+ let(:raw_notification) { build :wns_notification }
11
+ let(:toast_data) { { title: 'Title', message: 'Hello WNS World!', type: :toast } }
12
+ let(:toast_notification) { build :wns_notification, device_urls: device_urls, data: toast_data }
13
+ let(:tile_data) { { message: 'Hello WNS World!', image: 'http://image.com/image.jpg', type: :tile } }
14
+ let(:tile_notification) { build :wns_notification, device_urls: device_urls, data: tile_data }
15
+ let(:badge_data) { { value: 10, type: :badge } }
16
+ let(:badge_notification) { build :wns_notification, device_urls: device_urls, data: badge_data }
17
+
18
+ let(:headers) {
19
+ {
20
+ 'x-wns-notificationstatus' => 'Received',
21
+ 'x-wns-deviceconnectionstatus' => 'Connected',
22
+ 'x-wns-status' => 'Received'
23
+ }
24
+ }
25
+ let(:wns_connection) { RubyPushNotifications::WNS::WNSConnection }
26
+ let(:response) { [ { device_url: 'http://hk2.notify.windows.com/1', headers: headers, code: 200 } ]}
27
+
28
+ before do
29
+ stub_request(:post, %r{hk2.notify.windows.com}).
30
+ to_return status: [200, 'OK'], headers: headers
31
+ end
32
+
33
+ it 'submits every notification' do
34
+ pusher.push [raw_notification, toast_notification, tile_notification, badge_notification]
35
+ %i(raw toast tile badge).each do |push_type|
36
+ headers = {
37
+ wns_connection::CONTENT_TYPE_HEADER => wns_connection::CONTENT_TYPE[push_type],
38
+ wns_connection::X_WNS_TYPE_HEADER => wns_connection::WP_TARGETS[push_type],
39
+ wns_connection::CONTENT_LENGTH_HEADER => public_send("#{push_type}_notification").as_wns_xml.length.to_s,
40
+ wns_connection::AUTHORIZATION_HEADER => "Bearer #{access_token}",
41
+ wns_connection::REQUEST_FOR_STATUS_HEADER => 'true'
42
+ }
43
+ expect(WebMock).
44
+ to have_requested(:post, public_send("#{push_type}_notification").device_urls[0]).
45
+ with(body: public_send("#{push_type}_notification").as_wns_xml, headers: headers).
46
+ once
47
+ end
48
+ end
49
+
50
+ it 'sets results to notifications' do
51
+ expect do
52
+ pusher.push notifications
53
+ end.to change { notifications.map(&:results) }.from([nil, nil]).to [WNSResponse.new(response)] * 2
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,65 @@
1
+ module RubyPushNotifications
2
+ module WNS
3
+ describe WNSResponse do
4
+
5
+ describe 'success' do
6
+
7
+ let(:successful_messages) { 2 }
8
+ let(:failed_messages) { 7 }
9
+ let(:headers) {
10
+ {
11
+ 'x-wns-notificationstatus' => 'Received',
12
+ 'x-wns-deviceconnectionstatus' => 'Connected',
13
+ 'x-wns-status' => 'Received'
14
+ }
15
+ }
16
+
17
+ let(:responses) {
18
+ [
19
+ { device_url: '1', headers: headers, code: 200 },
20
+ { device_url: '2', headers: headers, code: 200 },
21
+ { device_url: '3', code: 400 },
22
+ { device_url: '4', code: 401 },
23
+ { device_url: '5', headers: headers, code: 404 },
24
+ { device_url: '6', headers: headers, code: 406 },
25
+ { device_url: '7', headers: headers, code: 412 },
26
+ { device_url: '8', code: 503 },
27
+ { device_url: '9', headers: headers, code: 410 }
28
+ ]
29
+ }
30
+
31
+ let(:response) { WNSResponse.new responses }
32
+ let(:result) { WNSResultOK.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
+ WNSResultOK.new('1', headers),
45
+ WNSResultOK.new('2', headers),
46
+ MalformedWNSResultError.new('3'),
47
+ WNSAuthError.new('4'),
48
+ WNSInvalidError.new('5', headers),
49
+ WNSLimitError.new('6', headers),
50
+ WNSPreConditionError.new('7', headers),
51
+ WNSInternalError.new('8'),
52
+ WNSExpiredError.new('9', headers)
53
+ ]
54
+ end
55
+
56
+ it 'parses headers to result attributes' do
57
+ expect(result.notification_status).to eq 'Received'
58
+ expect(result.device_connection_status).to eq 'Connected'
59
+ expect(result.status).to eq 'Received'
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,23 @@
1
+
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+
5
+ require 'rubygems'
6
+ require 'bundler'
7
+ Bundler.setup
8
+ Bundler.require :defaults, :development
9
+ require 'webmock/rspec'
10
+
11
+ require 'ruby-push-notifications'
12
+
13
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
14
+
15
+ def apns_binary(json, token, id)
16
+ json = JSON.dump(json) if json.is_a?(Hash)
17
+ [
18
+ 2, 56+json.bytesize, 1, 32, token, 2, json.bytesize, json,
19
+ 3, 4, id, 4, 4, (Time.now + RubyPushNotifications::APNS::APNSNotification::WEEKS_4).to_i, 5, 1, 10
20
+ ].pack 'cNcnH64cna*cnNcnNcnc'
21
+ end
22
+
23
+ WebMock.disable_net_connect!(:allow => "codeclimate.com")
@@ -0,0 +1,44 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICsDCCAhmgAwIBAgIJALwzrJEIBOaeMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
3
+ BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
4
+ aWRnaXRzIFB0eSBMdGQwHhcNMTEwOTMwMTUyNjM2WhcNMjEwOTI3MTUyNjM2WjBF
5
+ MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
6
+ ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
7
+ gQC88Ckwru9VR2p2KJ1WQyqesLzr95taNbhkYfsd0j8Tl0MGY5h+dczCaMQz0YY3
8
+ xHXuU5yAQQTZjiks+D3KA3cx+iKDf2p1q77oXxQcx5CkrXBWTaX2oqVtHm3aX23B
9
+ AIORGuPk00b4rT3cld7VhcEFmzRNbyI0EqLMAxIwceUKSQIDAQABo4GnMIGkMB0G
10
+ A1UdDgQWBBSGmOdvSXKXclic5UOKPW35JLMEEjB1BgNVHSMEbjBsgBSGmOdvSXKX
11
+ clic5UOKPW35JLMEEqFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUt
12
+ U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJALwzrJEI
13
+ BOaeMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAcPfWn49pgAX54ji5
14
+ SiUPFFNCuQGSSTHh2I+TMrs1G1Mb3a0X1dV5CNLRyXyuVxsqhiM/H2veFnTz2Q4U
15
+ wdY/kPxE19Auwcz9AvCkw7ol1LIlLfJvBzjzOjEpZJNtkXTx8ROSooNrDeJl3HyN
16
+ cciS5hf80XzIFqwhzaVS9gmiyM8=
17
+ -----END CERTIFICATE-----
18
+ -----BEGIN RSA PRIVATE KEY-----
19
+ MIIEogIBAAKCAQEA6Lr0lAvQrywXhMnXpJaTBL6edduZUY20piiT82Vasere343B
20
+ wcQFUMwGV9CrjSeOMI9jN/0PEw5ZJ5s4AwqYePxy3K05t6MV5UrDx6na7POfUOmC
21
+ sfp+KgURY4jQUtOvbHeXr4CjXiMEOJcTTuRaiqy24tjcwkNsHW4/QRyZ1BdKI+8H
22
+ x9HqpdwaVn2rCx36ZVukMUqv6y7m8QkDog02oLrneYQy8oMaVwkIcxNxFJzVqobN
23
+ SDGXH2Wdh7usoF8P3PD+EuzCgCeP/kqLym4BYXp6tzJj3hT/85xxpsOjIulLuubK
24
+ wJz9hngJ/C14DBjXjUmkN38R7XEkR3jvp0K09wIDAQABAoIBAF0irEwu6kWf/I18
25
+ hRrt00obyqhZyGKVtgykwoiuJauCpSgY0q5rdsEd1RABhxXHFaUjTM6ULBsxK8ao
26
+ 3GKDM/9+76yWejmeP13ybKUTuXQIDuK/gDkfiKviOVI+5zeuVU6wEXj/nuFGXCMV
27
+ enmg8wb6FXp01Ou9NaAVhaTWAE2afOQSZnI52NUNdV8qvic7+CXpq/W5A/eRIR9v
28
+ aGaEzglyXPq3N8LUEjqx5abFijCT3fcLwvO2yOs8gxVhwrS0cr30JXnRxqmEghk9
29
+ GsHyJvUyIEz2BFuzJ8sd0xVgej5wxPcdPcmVnGPGYZ/l+tSSw8XaXqmiBhPEElaa
30
+ wBET0qECgYEA/aJrYviMbKzS0FuTLNVjEM/Zj60xgVMSZZ9GOqrm4nyIkxFLHmGC
31
+ rnfeLiAnT0FlCZlO2vA71vXj8dNbhWSxD8EOCvu/oCcAJc0rmkmOgPIRrQMGcd7I
32
+ s3RbT0ZykuX+JW2SlnMWIPPW4QK5MXfqNux42J/6jC/q0iaeGNPBC9ECgYEA6uaf
33
+ +YdIHgEYkgn8WjY3i8rX98QmXL9565nFmQe7RmzBZrzFLyKd7FjxjYIz1hk+CfFS
34
+ jhMb4WNdeVvV8AVPTiTHomCxdVasfadfadsfdPFCHbkbizenFJf0DNx14qe7eSds
35
+ 2gQSZ3eTD7XdFNxqwF1dvPXPtDbVBa8SHlijDkcCgYB1tX4e9Xi+Ksq/tfAsu295
36
+ auzuOBOkkDgWf3+pVI1IiUEc98aj998dNzYes/9qUdAhT0wAYcNztLQwE8YCt0NR
37
+ K2hoAoPhQJhZ8skMlpyTDUTUxXWlPR5p4lNKDEi6EhELr7l7Jzga3O9Zh9kIsz04
38
+ djBzYHN3wfk5xIBUx1ltMQKBgBMA8XRIg4cZ45j9AdNyi2/dyzcaQVhDjWOIHzpQ
39
+ K9B4v/TF1NYJYOlcEL64B+WMST6YrWsdFKZZWZiV22r9ovrZcuUqGXE7PMgpXGcE
40
+ jZZZTlYFQbszl2rNGEtqEodxtnMIw3+n0K1aOSWOOwKTCnfhldHRuSoFPZqmHTsj
41
+ RJ3FAoGAXpx+ulBu99kOxOWWofmP7ff9DF3doF+Jmjwo6KdOAIq++74hNRgYCIKM
42
+ X+4TSnmu8qBOt++r+EaBgxb+m+36iQxJRhU25ggzlA97v7n7KSxdyt7OLCe5zXP5
43
+ iiMWAO+qJD6ZyHlzVz0wwu3nAvkhjTxQ2c3+7xjUwCZK1lXjvvM=
44
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,5 @@
1
+ RSpec.configure do |config|
2
+ config.include FactoryGirl::Syntax::Methods
3
+ end
4
+
5
+ FactoryGirl.find_definitions
@@ -0,0 +1,31 @@
1
+ shared_examples 'right results' do |success, failed, individual_results|
2
+ it 'has the expected success value' do
3
+ expect(notification.success).to eq success
4
+ end
5
+
6
+ it 'has the expected failed value' do
7
+ expect(notification.failed).to eq failed
8
+ end
9
+
10
+ it 'has the expected individual_results' do
11
+ expect(notification.individual_results).to eq individual_results
12
+ end
13
+ end
14
+
15
+ shared_examples 'a proper results manager' do
16
+ describe 'results management' do
17
+ before { notification.results = results }
18
+
19
+ it 'gives the success count' do
20
+ expect(notification.success).to eq success_count
21
+ end
22
+
23
+ it 'gives the failures count' do
24
+ expect(notification.failed).to eq failures_count
25
+ end
26
+
27
+ it 'gives the individual results' do
28
+ expect(notification.individual_results).to eq individual_results
29
+ end
30
+ end
31
+ end