fcm 1.0.8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/spec/fcm_spec.rb CHANGED
@@ -1,547 +1,438 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe FCM do
4
- let(:send_url) { "#{FCM::BASE_URI}/fcm/send" }
5
- let(:group_notification_base_uri) { "#{FCM::GROUP_NOTIFICATION_BASE_URI}/gcm/notification" }
6
- let(:api_key) { "AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA" }
7
- let(:registration_id) { "42" }
8
- let(:registration_ids) { ["42"] }
9
- let(:key_name) { "appUser-Chris" }
10
- let(:project_id) { "123456789" } # https://developers.google.com/cloud-messaging/gcm#senderid
11
- let(:notification_key) { "APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ" }
12
- let(:valid_topic) { "TopicA" }
13
- let(:invalid_topic) { "TopicA$" }
14
- let(:valid_condition) { "'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)" }
15
- let(:invalid_condition) { "'TopicA' in topics and some other text ('TopicB' in topics || 'TopicC' in topics)" }
16
- let(:invalid_condition_topic) { "'TopicA$' in topics" }
17
-
18
- it "should raise an error if the api key is not provided" do
19
- expect { FCM.new }.to raise_error(ArgumentError)
4
+ let(:project_name) { 'test-project' }
5
+ let(:json_key_path) { 'path/to/json/key.json' }
6
+ let(:client) { FCM.new(json_key_path) }
7
+
8
+ let(:mock_token) { "access_token" }
9
+ let(:mock_headers) do
10
+ {
11
+ "Content-Type" => "application/json",
12
+ "Authorization" => "Bearer #{mock_token}",
13
+ }
20
14
  end
21
15
 
22
- it "should raise error if time_to_live is given" do
23
- # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#ttl
16
+ before do
17
+ allow(client).to receive(:json_key)
18
+
19
+ # Mock the Google::Auth::ServiceAccountCredentials
20
+ allow(Google::Auth::ServiceAccountCredentials).to receive(:make_creds).
21
+ and_return(double(fetch_access_token!: { 'access_token' => mock_token }))
24
22
  end
25
23
 
26
- describe "#send_v1" do
27
- pending "should send message"
24
+ it "should initialize" do
25
+ expect { client }.not_to raise_error
28
26
  end
29
27
 
30
- describe "sending notification" do
31
- let(:valid_request_body) do
32
- { registration_ids: registration_ids }
33
- end
34
- let(:valid_request_body_with_string) do
35
- { registration_ids: registration_id }
36
- end
37
- let(:valid_request_headers) do
38
- {
39
- "Content-Type" => "application/json",
40
- "Authorization" => "key=#{api_key}",
41
- }
28
+ describe "credentials path" do
29
+ it "can be a path to a file" do
30
+ fcm = FCM.new("README.md")
31
+ expect(fcm.__send__(:json_key).class).to eq(File)
42
32
  end
43
33
 
44
- let(:stub_fcm_send_request) do
45
- stub_request(:post, send_url).with(
46
- body: valid_request_body.to_json,
47
- headers: valid_request_headers,
48
- ).to_return(
49
- # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
50
- body: "{}",
51
- headers: {},
52
- status: 200,
53
- )
34
+ it "can be an IO object" do
35
+ fcm = FCM.new(StringIO.new("hey"))
36
+ expect(fcm.__send__(:json_key).class).to eq(StringIO)
54
37
  end
38
+ end
39
+
40
+ describe "#send_v1 or #send_notification_v1" do
41
+ let(:client) { FCM.new(json_key_path, project_name) }
42
+
43
+ let(:uri) { "#{FCM::BASE_URI_V1}#{project_name}/messages:send" }
44
+ let(:status_code) { 200 }
55
45
 
56
- let(:stub_fcm_send_request_with_string) do
57
- stub_request(:post, send_url).with(
58
- body: valid_request_body_with_string.to_json,
59
- headers: valid_request_headers,
46
+ let(:stub_fcm_send_v1_request) do
47
+ stub_request(:post, uri).with(
48
+ body: { 'message' => send_v1_params }.to_json,
49
+ headers: mock_headers
60
50
  ).to_return(
51
+ # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
61
52
  body: "{}",
62
53
  headers: {},
63
- status: 200,
54
+ status: status_code,
64
55
  )
65
56
  end
66
57
 
67
- let(:stub_fcm_send_request_with_basic_auth) do
68
- uri = URI.parse(send_url)
69
- uri.user = "a"
70
- uri.password = "b"
71
- stub_request(:post, uri.to_s).to_return(body: "{}", headers: {}, status: 200)
58
+ before do
59
+ stub_fcm_send_v1_request
72
60
  end
73
61
 
74
- before(:each) do
75
- stub_fcm_send_request
76
- stub_fcm_send_request_with_string
77
- stub_fcm_send_request_with_basic_auth
78
- end
79
-
80
- it "should send notification using POST to FCM server" do
81
- fcm = FCM.new(api_key)
82
- fcm.send(registration_ids).should eq(response: "success", body: "{}", headers: {}, status_code: 200, canonical_ids: [], not_registered_ids: [])
83
- stub_fcm_send_request.should have_been_made.times(1)
84
- end
85
-
86
- it "should send notification using POST to FCM if id provided as string" do
87
- fcm = FCM.new(api_key)
88
- fcm.send(registration_id).should eq(response: "success", body: "{}", headers: {}, status_code: 200, canonical_ids: [], not_registered_ids: [])
89
- stub_fcm_send_request.should have_been_made.times(1)
90
- end
91
-
92
- context "send notification with data" do
93
- let!(:stub_with_data) do
94
- stub_request(:post, send_url)
95
- .with(body: '{"registration_ids":["42"],"data":{"score":"5x1","time":"15:10"}}',
96
- headers: valid_request_headers)
97
- .to_return(status: 200, body: "", headers: {})
98
- end
99
- before do
100
- end
101
- it "should send the data in a post request to fcm" do
102
- fcm = FCM.new(api_key)
103
- fcm.send(registration_ids, data: { score: "5x1", time: "15:10" })
104
- stub_with_data.should have_been_requested
62
+ shared_examples 'succesfuly send notification' do
63
+ it 'should send notification of HTTP V1 using POST to FCM server' do
64
+ client.send_v1(send_v1_params).should eq(
65
+ response: 'success', body: '{}', headers: {}, status_code: 200
66
+ )
67
+ stub_fcm_send_v1_request.should have_been_made.times(1)
105
68
  end
106
69
  end
107
70
 
108
- context "sending notification to a topic" do
109
- let!(:stub_with_valid_topic) do
110
- stub_request(:post, send_url)
111
- .with(body: '{"to":"/topics/TopicA","data":{"score":"5x1","time":"15:10"}}',
112
- headers: valid_request_headers)
113
- .to_return(status: 200, body: "", headers: {})
114
- end
115
- let!(:stub_with_invalid_topic) do
116
- stub_request(:post, send_url)
117
- .with(body: '{"condition":"/topics/TopicA$","data":{"score":"5x1","time":"15:10"}}',
118
- headers: valid_request_headers)
119
- .to_return(status: 200, body: "", headers: {})
71
+ describe 'send to token' do
72
+ let(:token) { '4sdsx' }
73
+ let(:send_v1_params) do
74
+ {
75
+ 'token' => token,
76
+ 'notification' => {
77
+ 'title' => 'Breaking News',
78
+ 'body' => 'New news story available.'
79
+ },
80
+ 'data' => {
81
+ 'story_id' => 'story_12345'
82
+ },
83
+ 'android' => {
84
+ 'notification' => {
85
+ 'click_action' => 'TOP_STORY_ACTIVITY',
86
+ 'body' => 'Check out the Top Story'
87
+ }
88
+ },
89
+ 'apns' => {
90
+ 'payload' => {
91
+ 'aps' => {
92
+ 'category' => 'NEW_MESSAGE_CATEGORY'
93
+ }
94
+ }
95
+ }
96
+ }
120
97
  end
121
98
 
122
- describe "#send_to_topic" do
123
- it "should send the data in a post request to fcm" do
124
- fcm = FCM.new(api_key)
125
- fcm.send_to_topic(valid_topic, data: { score: "5x1", time: "15:10" })
126
- stub_with_valid_topic.should have_been_requested
127
- end
99
+ include_examples 'succesfuly send notification'
128
100
 
129
- it "should not send to invalid topics" do
130
- fcm = FCM.new(api_key)
131
- fcm.send_to_topic(invalid_topic, data: { score: "5x1", time: "15:10" })
132
- stub_with_invalid_topic.should_not have_been_requested
133
- end
101
+ it 'includes all the response' do
102
+ response = client.send_v1(send_v1_params)
103
+ expect(response[:status_code]).to eq(status_code)
104
+ expect(response[:response]).to eq('success')
105
+ expect(response[:body]).to eq('{}')
106
+ expect(response[:headers]).to eq({})
107
+ expect(response[:canonical_ids]).to be_nil
108
+ expect(response[:not_registered_ids]).to be_nil
134
109
  end
135
110
  end
136
111
 
137
- context "sending notification to a topic condition" do
138
- let!(:stub_with_valid_condition) do
139
- stub_request(:post, send_url)
140
- .with(body: '{"condition":"\'TopicA\' in topics && (\'TopicB\' in topics || \'TopicC\' in topics)","data":{"score":"5x1","time":"15:10"}}',
141
- headers: valid_request_headers)
142
- .to_return(status: 200, body: "", headers: {})
143
- end
144
- let!(:stub_with_invalid_condition) do
145
- stub_request(:post, send_url)
146
- .with(body: '{"condition":"\'TopicA\' in topics and some other text (\'TopicB\' in topics || \'TopicC\' in topics)","data":{"score":"5x1","time":"15:10"}}',
147
- headers: valid_request_headers)
148
- .to_return(status: 200, body: "", headers: {})
149
- end
150
- let!(:stub_with_invalid_condition_topic) do
151
- stub_request(:post, send_url)
152
- .with(body: '{"condition":"\'TopicA$\' in topics","data":{"score":"5x1","time":"15:10"}}',
153
- headers: valid_request_headers)
154
- .to_return(status: 200, body: "", headers: {})
112
+ describe 'send to multiple tokens' do
113
+ let(:tokens) { ['4sdsx', '4sdsy'] }
114
+ let(:send_v1_params) do
115
+ {
116
+ 'token' => tokens,
117
+ 'notification' => {
118
+ 'title' => 'Breaking News',
119
+ 'body' => 'New news story available.'
120
+ }
121
+ }
155
122
  end
156
123
 
157
- describe "#send_to_topic_condition" do
158
- it "should send the data in a post request to fcm" do
159
- fcm = FCM.new(api_key)
160
- fcm.send_to_topic_condition(valid_condition, data: { score: "5x1", time: "15:10" })
161
- stub_with_valid_condition.should have_been_requested
162
- end
163
-
164
- it "should not send to invalid conditions" do
165
- fcm = FCM.new(api_key)
166
- fcm.send_to_topic_condition(invalid_condition, data: { score: "5x1", time: "15:10" })
167
- stub_with_invalid_condition.should_not have_been_requested
168
- end
169
-
170
- it "should not send to invalid topics in a condition" do
171
- fcm = FCM.new(api_key)
172
- fcm.send_to_topic_condition(invalid_condition_topic, data: { score: "5x1", time: "15:10" })
173
- stub_with_invalid_condition_topic.should_not have_been_requested
174
- end
175
- end
124
+ include_examples 'succesfuly send notification'
176
125
  end
177
126
 
178
- context "when send_notification responds with failure" do
179
- let(:mock_request_attributes) do
127
+ describe 'send to topic' do
128
+ let(:topic) { 'news' }
129
+ let(:send_v1_params) do
180
130
  {
181
- body: valid_request_body.to_json,
182
- headers: valid_request_headers,
131
+ 'topic' => topic,
132
+ 'notification' => {
133
+ 'title' => 'Breaking News',
134
+ 'body' => 'New news story available.'
135
+ }
183
136
  }
184
137
  end
185
138
 
186
- subject { FCM.new(api_key) }
187
-
188
- context "on failure code 400" do
189
- before do
190
- stub_request(:post, send_url).with(
191
- mock_request_attributes
192
- ).to_return(
193
- # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
194
- body: "{}",
195
- headers: {},
196
- status: 400,
197
- )
198
- end
199
- it "should not send notification due to 400" do
200
- subject.send(registration_ids).should eq(body: "{}",
201
- headers: {},
202
- response: "Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields.",
203
- status_code: 400)
204
- end
205
- end
139
+ include_examples 'succesfuly send notification'
206
140
 
207
- context "on failure code 401" do
208
- before do
209
- stub_request(:post, send_url).with(
210
- mock_request_attributes
211
- ).to_return(
212
- # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
213
- body: "{}",
214
- headers: {},
215
- status: 401,
216
- )
217
- end
141
+ context 'when topic is invalid' do
142
+ let(:topic) { '/topics/news$' }
218
143
 
219
- it "should not send notification due to 401" do
220
- subject.send(registration_ids).should eq(body: "{}",
221
- headers: {},
222
- response: "There was an error authenticating the sender account.",
223
- status_code: 401)
144
+ it 'should raise error' do
145
+ stub_fcm_send_v1_request.should_not have_been_requested
224
146
  end
225
147
  end
148
+ end
226
149
 
227
- context "on failure code 503" do
228
- before do
229
- stub_request(:post, send_url).with(
230
- mock_request_attributes
231
- ).to_return(
232
- # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
233
- body: "{}",
234
- headers: {},
235
- status: 503,
236
- )
237
- end
238
-
239
- it "should not send notification due to 503" do
240
- subject.send(registration_ids).should eq(body: "{}",
241
- headers: {},
242
- response: "Server is temporarily unavailable.",
243
- status_code: 503)
244
- end
150
+ describe 'send to condition' do
151
+ let(:condition) { "'foo' in topics" }
152
+ let(:send_v1_params) do
153
+ {
154
+ 'condition' => condition,
155
+ 'notification' => {
156
+ 'title' => 'Breaking News',
157
+ 'body' => 'New news story available.'
158
+ },
159
+ }
245
160
  end
246
161
 
247
- context "on failure code 5xx" do
248
- before do
249
- stub_request(:post, send_url).with(
250
- mock_request_attributes
251
- ).to_return(
252
- # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
253
- body: '{"body-key" => "Body value"}',
254
- headers: { "header-key" => "Header value" },
255
- status: 599,
256
- )
257
- end
258
-
259
- it "should not send notification due to 599" do
260
- subject.send(registration_ids).should eq(body: '{"body-key" => "Body value"}',
261
- headers: { "header-key" => "Header value" },
262
- response: "There was an internal error in the FCM server while trying to process the request.",
263
- status_code: 599)
264
- end
265
- end
162
+ include_examples 'succesfuly send notification'
266
163
  end
267
164
 
268
- context "when send_notification responds canonical_ids" do
269
- let(:mock_request_attributes) do
165
+ describe 'send to notification_key' do
166
+ let(:notification_key) { 'notification_key' }
167
+ let(:send_v1_params) do
270
168
  {
271
- body: valid_request_body.to_json,
272
- headers: valid_request_headers,
169
+ 'notification_key' => notification_key,
170
+ 'notification' => {
171
+ 'title' => 'Breaking News',
172
+ 'body' => 'New news story available.'
173
+ }
273
174
  }
274
175
  end
275
176
 
276
- let(:valid_response_body_with_canonical_ids) do
177
+ include_examples 'succesfuly send notification'
178
+ end
179
+
180
+ context 'when project_name is empty' do
181
+ let(:project_name) { '' }
182
+ let(:send_v1_params) do
277
183
  {
278
- failure: 0, canonical_ids: 1, results: [{ registration_id: "43", message_id: "0:1385025861956342%572c22801bb3" }],
184
+ 'token' => '4sdsx',
185
+ 'notification' => {
186
+ 'title' => 'Breaking News',
187
+ 'body' => 'New news story available.'
188
+ }
279
189
  }
280
190
  end
281
191
 
282
- subject { FCM.new(api_key) }
192
+ it 'should not send notification' do
193
+ client.send_v1(send_v1_params)
194
+ stub_fcm_send_v1_request.should_not have_been_requested
195
+ end
196
+ end
283
197
 
284
- before do
285
- stub_request(:post, send_url).with(
286
- mock_request_attributes
287
- ).to_return(
288
- # ref: https://firebase.google.com/docs/cloud-messaging/http-server-ref#interpret-downstream
289
- body: valid_response_body_with_canonical_ids.to_json,
290
- headers: {},
291
- status: 200,
292
- )
198
+ describe 'error handling' do
199
+ let(:send_v1_params) do
200
+ {
201
+ 'token' => '4sdsx',
202
+ 'notification' => {
203
+ 'title' => 'Breaking News',
204
+ 'body' => 'New news story available.'
205
+ }
206
+ }
293
207
  end
294
208
 
295
- it "should contain canonical_ids" do
296
- response = subject.send(registration_ids)
209
+ context 'when status_code is 400' do
210
+ let(:status_code) { 400 }
297
211
 
298
- response.should eq(headers: {},
299
- canonical_ids: [{ old: "42", new: "43" }],
300
- not_registered_ids: [],
301
- status_code: 200,
302
- response: "success",
303
- body: '{"failure":0,"canonical_ids":1,"results":[{"registration_id":"43","message_id":"0:1385025861956342%572c22801bb3"}]}')
212
+ it 'should raise error' do
213
+ response = client.send_v1(send_v1_params)
214
+ expect(response[:status_code]).to eq(status_code)
215
+ expect(response[:response]).to include('Only applies for JSON requests')
216
+ end
304
217
  end
305
- end
306
218
 
307
- context "when send_notification responds with NotRegistered" do
308
- subject { FCM.new(api_key) }
219
+ context 'when status_code is 401' do
220
+ let(:status_code) { 401 }
309
221
 
310
- let(:mock_request_attributes) do
311
- {
312
- body: valid_request_body.to_json,
313
- headers: valid_request_headers,
314
- }
222
+ it 'should raise error' do
223
+ response = client.send_v1(send_v1_params)
224
+ expect(response[:status_code]).to eq(status_code)
225
+ expect(response[:response]).to include('There was an error authenticating')
226
+ end
315
227
  end
316
228
 
317
- let(:valid_response_body_with_not_registered_ids) do
318
- {
319
- canonical_ids: 0, failure: 1, results: [{ error: "NotRegistered" }],
320
- }
321
- end
229
+ context 'when status_code is 500' do
230
+ let(:status_code) { 500 }
322
231
 
323
- before do
324
- stub_request(:post, send_url).with(
325
- mock_request_attributes
326
- ).to_return(
327
- body: valid_response_body_with_not_registered_ids.to_json,
328
- headers: {},
329
- status: 200,
330
- )
232
+ it 'should raise error' do
233
+ response = client.send_v1(send_v1_params)
234
+ expect(response[:status_code]).to eq(status_code)
235
+ expect(response[:response]).to include('There was an internal error')
236
+ end
331
237
  end
332
238
 
333
- it "should contain not_registered_ids" do
334
- response = subject.send(registration_ids)
335
- response.should eq(
336
- headers: {},
337
- canonical_ids: [],
338
- not_registered_ids: registration_ids,
339
- status_code: 200,
340
- response: "success",
341
- body: '{"canonical_ids":0,"failure":1,"results":[{"error":"NotRegistered"}]}',
342
- )
239
+ context 'when status_code is 503' do
240
+ let(:status_code) { 503 }
241
+
242
+ it 'should raise error' do
243
+ response = client.send_v1(send_v1_params)
244
+ expect(response[:status_code]).to eq(status_code)
245
+ expect(response[:response]).to include('Server is temporarily unavailable')
246
+ end
343
247
  end
344
248
  end
345
249
  end
346
250
 
347
- describe "sending group notifications" do
348
- # TODO: refactor to should_behave_like
349
- let(:valid_request_headers) do
251
+ describe '#send_to_topic' do
252
+ let(:client) { FCM.new(json_key_path, project_name) }
253
+
254
+ let(:uri) { "#{FCM::BASE_URI_V1}#{project_name}/messages:send" }
255
+
256
+ let(:topic) { 'news' }
257
+ let(:params) do
350
258
  {
351
- "Authorization" => "key=#{api_key}",
352
- "Content-Type" => "application/json",
353
- "Project-Id" => project_id,
354
- }
259
+ 'topic' => topic
260
+ }.merge(options)
355
261
  end
356
- let(:valid_response_body) do
357
- { notification_key: "APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ" }
358
- end
359
-
360
- let(:default_valid_request_body) do
262
+ let(:options) do
361
263
  {
362
- registration_ids: registration_ids,
363
- operation: "create",
364
- notification_key_name: key_name,
264
+ 'data' => {
265
+ 'story_id' => 'story_12345'
266
+ }
365
267
  }
366
268
  end
367
269
 
368
- subject { FCM.new(api_key) }
270
+ let(:stub_fcm_send_to_topic_request) do
271
+ stub_request(:post, uri).with(
272
+ body: { 'message' => params }.to_json,
273
+ headers: mock_headers
274
+ ).to_return(
275
+ body: "{}",
276
+ headers: {},
277
+ status: 200,
278
+ )
279
+ end
369
280
 
370
- # ref: https://firebase.google.com/docs/cloud-messaging/notifications#managing-device-groups-on-the-app-server
371
- context "create" do
372
- let(:valid_request_body) do
373
- default_valid_request_body.merge({
374
- operation: "create",
375
- })
376
- end
281
+ before do
282
+ stub_fcm_send_to_topic_request
283
+ end
377
284
 
378
- let(:mock_request_attributes) do
379
- {
380
- body: valid_request_body.to_json,
381
- headers: valid_request_headers,
382
- }
383
- end
285
+ it 'should send notification to topic using POST to FCM server' do
286
+ client.send_to_topic(topic, options).should eq(
287
+ response: 'success', body: '{}', headers: {}, status_code: 200
288
+ )
289
+ stub_fcm_send_to_topic_request.should have_been_made.times(1)
290
+ end
384
291
 
385
- before do
386
- stub_request(:post, group_notification_base_uri).with(
387
- mock_request_attributes
388
- ).to_return(
389
- body: valid_response_body.to_json,
390
- headers: {},
391
- status: 200,
392
- )
393
- end
292
+ context 'when topic is invalid' do
293
+ let(:topic) { '/topics/news$' }
394
294
 
395
- it "should send a post request" do
396
- response = subject.create(key_name, project_id, registration_ids)
397
- response.should eq(
398
- headers: {},
399
- status_code: 200,
400
- response: "success",
401
- body: valid_response_body.to_json,
402
- )
403
- end
404
- end # create context
405
-
406
- context "add" do
407
- let(:valid_request_body) do
408
- default_valid_request_body.merge({
409
- operation: "add",
410
- notification_key: notification_key,
411
- })
412
- end
413
-
414
- let(:mock_request_attributes) do
415
- {
416
- body: valid_request_body.to_json,
417
- headers: valid_request_headers,
418
- }
295
+ it 'should raise error' do
296
+ client.send_to_topic(topic, options)
297
+ stub_fcm_send_to_topic_request.should_not have_been_requested
419
298
  end
299
+ end
300
+ end
420
301
 
421
- before do
422
- stub_request(:post, group_notification_base_uri).with(
423
- mock_request_attributes
424
- ).to_return(
425
- body: valid_response_body.to_json,
426
- headers: {},
427
- status: 200,
428
- )
429
- end
302
+ describe "#send_to_topic_condition" do
303
+ let(:client) { FCM.new(json_key_path, project_name) }
430
304
 
431
- it "should send a post request" do
432
- response = subject.add(key_name, project_id, notification_key, registration_ids)
433
- response.should eq(
434
- headers: {},
435
- status_code: 200,
436
- response: "success",
437
- body: valid_response_body.to_json,
438
- )
439
- end
440
- end # add context
441
-
442
- context "remove" do
443
- let(:valid_request_body) do
444
- default_valid_request_body.merge({
445
- operation: "remove",
446
- notification_key: notification_key,
447
- })
448
- end
305
+ let(:uri) { "#{FCM::BASE_URI_V1}#{project_name}/messages:send" }
449
306
 
450
- let(:mock_request_attributes) do
451
- {
452
- body: valid_request_body.to_json,
453
- headers: valid_request_headers,
307
+ let(:topic_condition) { "'foo' in topics" }
308
+ let(:params) do
309
+ {
310
+ 'condition' => topic_condition
311
+ }.merge(options)
312
+ end
313
+ let(:options) do
314
+ {
315
+ 'data' => {
316
+ 'story_id' => 'story_12345'
454
317
  }
455
- end
318
+ }
319
+ end
456
320
 
457
- before do
458
- stub_request(:post, group_notification_base_uri).with(
459
- mock_request_attributes
460
- ).to_return(
461
- body: valid_response_body.to_json,
462
- headers: {},
463
- status: 200,
464
- )
465
- end
321
+ let(:stub_fcm_send_to_topic_condition_request) do
322
+ stub_request(:post, uri).with(
323
+ body: { 'message' => params }.to_json,
324
+ headers: mock_headers
325
+ ).to_return(
326
+ body: "{}",
327
+ headers: {},
328
+ status: 200,
329
+ )
330
+ end
466
331
 
467
- it "should send a post request" do
468
- response = subject.remove(key_name, project_id, notification_key, registration_ids)
469
- response.should eq(
470
- headers: {},
471
- status_code: 200,
472
- response: "success",
473
- body: valid_response_body.to_json,
474
- )
475
- end
476
- end # remove context
477
- end
332
+ before do
333
+ stub_fcm_send_to_topic_condition_request
334
+ end
478
335
 
479
- describe "#recover_notification_key" do
480
- it "sends a 'retrieve notification key' request" do
481
- uri = "#{FCM::GROUP_NOTIFICATION_BASE_URI}/gcm/notification"
482
- endpoint = stub_request(:get, uri).with(
483
- headers: {
484
- "Content-Type" => "application/json",
485
- "Authorization" => "key=TEST_SERVER_KEY",
486
- "project_id" => "TEST_PROJECT_ID",
487
- },
488
- query: { notification_key_name: "TEST_KEY_NAME" },
336
+ it 'should send notification to topic_condition using POST to FCM server' do
337
+ client.send_to_topic_condition(topic_condition, options).should eq(
338
+ response: 'success', body: '{}', headers: {}, status_code: 200
489
339
  )
490
- client = FCM.new("TEST_SERVER_KEY")
340
+ stub_fcm_send_to_topic_condition_request.should have_been_made.times(1)
341
+ end
491
342
 
492
- client.recover_notification_key("TEST_KEY_NAME", "TEST_PROJECT_ID")
343
+ context 'when topic_condition is invalid' do
344
+ let(:topic_condition) { "'foo' in topics$" }
493
345
 
494
- expect(endpoint).to have_been_requested
346
+ it 'should raise error' do
347
+ client.send_to_topic_condition(topic_condition, options)
348
+ stub_fcm_send_to_topic_condition_request.should_not have_been_requested
349
+ end
495
350
  end
496
351
  end
497
352
 
498
- describe "subscribing to a topic" do
499
- # TODO
500
- end
501
-
502
- describe 'getting instance info' do
503
- subject(:get_info) { client.get_instance_id_info(registration_id, options) }
353
+ describe "#get_instance_id_info" do
354
+ subject(:get_info) { client.get_instance_id_info(registration_token, options) }
504
355
 
505
356
  let(:options) { nil }
506
- let(:client) { FCM.new('TEST_SERVER_KEY') }
507
357
  let(:base_uri) { "#{FCM::INSTANCE_ID_API}/iid/info" }
508
- let(:uri) { "#{base_uri}/#{registration_id}" }
509
- let(:mock_request_attributes) do
510
- { headers: {
511
- 'Authorization' => 'key=TEST_SERVER_KEY',
512
- 'Content-Type' => 'application/json'
513
- } }
514
- end
358
+ let(:uri) { "#{base_uri}/#{registration_token}" }
359
+ let(:registration_token) { "42" }
515
360
 
516
361
  context 'without options' do
517
362
  it 'calls info endpoint' do
518
- endpoint = stub_request(:get, uri).with(mock_request_attributes)
363
+ endpoint = stub_request(:get, uri).with(headers: mock_headers)
519
364
  get_info
520
365
  expect(endpoint).to have_been_requested
521
366
  end
522
367
  end
523
368
 
524
369
  context 'with detail option' do
525
- let(:uri) { "#{base_uri}/#{registration_id}?details=true" }
370
+ let(:uri) { "#{base_uri}/#{registration_token}?details=true" }
526
371
  let(:options) { { details: true } }
527
372
 
528
373
  it 'calls info endpoint' do
529
- endpoint = stub_request(:get, uri).with(mock_request_attributes)
374
+ endpoint = stub_request(:get, uri).with(headers: mock_headers)
530
375
  get_info
531
376
  expect(endpoint).to have_been_requested
532
377
  end
533
378
  end
534
379
  end
535
380
 
536
- describe "credentials path" do
537
- it "can be a path to a file" do
538
- fcm = FCM.new("test", "README.md")
539
- expect(fcm.__send__(:json_key).class).to eq(File)
381
+ describe "topic subscriptions" do
382
+ let(:topic) { 'news' }
383
+ let(:registration_token) { "42" }
384
+ let(:registration_token_2) { "43" }
385
+ let(:registration_tokens) { [registration_token, registration_token_2] }
386
+
387
+ describe "#topic_subscription" do
388
+ subject(:subscribe) { client.topic_subscription(topic, registration_token) }
389
+
390
+ let(:uri) { "#{FCM::INSTANCE_ID_API}/iid/v1/#{registration_token}/rel/topics/#{topic}" }
391
+
392
+ it 'subscribes to a topic' do
393
+ endpoint = stub_request(:post, uri).with(headers: mock_headers)
394
+ subscribe
395
+ expect(endpoint).to have_been_requested
396
+ end
540
397
  end
541
398
 
542
- it "can be an IO object" do
543
- fcm = FCM.new("test", StringIO.new("hey"))
544
- expect(fcm.__send__(:json_key).class).to eq(StringIO)
399
+ describe "#topic_unsubscription" do
400
+ subject(:unsubscribe) { client.topic_unsubscription(topic, registration_token) }
401
+
402
+ let(:uri) { "#{FCM::INSTANCE_ID_API}/iid/v1:batchRemove" }
403
+ let(:params) { { to: "/topics/#{topic}", registration_tokens: [registration_token] } }
404
+
405
+ it 'unsubscribes from a topic' do
406
+ endpoint = stub_request(:post, uri).with(body: params.to_json, headers: mock_headers)
407
+ unsubscribe
408
+ expect(endpoint).to have_been_requested
409
+ end
410
+ end
411
+
412
+ describe "#batch_topic_subscription" do
413
+ subject(:batch_subscribe) { client.batch_topic_subscription(topic, registration_tokens) }
414
+
415
+ let(:uri) { "#{FCM::INSTANCE_ID_API}/iid/v1:batchAdd" }
416
+ let(:params) { { to: "/topics/#{topic}", registration_tokens: registration_tokens } }
417
+
418
+ it 'subscribes to a topic' do
419
+ endpoint = stub_request(:post, uri).with(body: params.to_json, headers: mock_headers)
420
+ batch_subscribe
421
+ expect(endpoint).to have_been_requested
422
+ end
423
+ end
424
+
425
+ describe "#batch_topic_unsubscription" do
426
+ subject(:batch_unsubscribe) { client.batch_topic_unsubscription(topic, registration_tokens) }
427
+
428
+ let(:uri) { "#{FCM::INSTANCE_ID_API}/iid/v1:batchRemove" }
429
+ let(:params) { { to: "/topics/#{topic}", registration_tokens: registration_tokens } }
430
+
431
+ it 'unsubscribes from a topic' do
432
+ endpoint = stub_request(:post, uri).with(body: params.to_json, headers: mock_headers)
433
+ batch_unsubscribe
434
+ expect(endpoint).to have_been_requested
435
+ end
545
436
  end
546
437
  end
547
438
  end