129
largeNotificationsBody = `
139
"id": "recipient_id",
142
"created_time": "2014-07-12T09:51:57+0000",
143
"updated_time": "2014-07-12T09:51:57+0000",
144
"title": "Sender posted on your timeline: \"The message...\"",
145
"link": "http://www.facebook.com/recipient/posts/id",
154
"id": "notif_1105650586_80600069",
160
"id": "recipient_id",
163
"created_time": "2014-07-08T06:17:52+0000",
164
"updated_time": "2014-07-08T06:17:52+0000",
165
"title": "Sender2's birthday was on July 7.",
166
"link": "http://www.facebook.com/profile.php?id=xxx&ref=brem",
169
"namespace": "superkarma",
170
"id": "329122197162272"
185
"id": "recipient_id",
188
"created_time": "2014-07-12T09:51:57+0000",
189
"updated_time": "2014-07-12T09:51:57+0000",
190
"title": "Sender posted on your timeline: \"The message...\"",
191
"link": "http://www.facebook.com/recipient/posts/id",
206
"id": "recipient_id",
209
"created_time": "2014-07-08T06:17:52+0000",
210
"updated_time": "2014-07-08T06:17:52+0000",
211
"title": "Sender2's birthday was on July 7.",
212
"link": "http://www.facebook.com/profile.php?id=xxx&ref=brem",
215
"namespace": "superkarma",
216
"id": "329122197162272"
222
"previous": "https://graph.facebook.com/v2.0/recipient/notifications?limit=5000&since=1405158717&__paging_token=enc_AewDzwIQmWOwPNO-36GaZsaJAog8l93HQ7uLEO-gp1Tb6KCiolXfzMCcGY2KjrJJsDJXdDmNJObICr5dewfMZgGs",
223
"next": "https://graph.facebook.com/v2.0/recipient/notifications?limit=5000&until=1404705077&__paging_token=enc_Aewlhut5DQyhqtLNr7pLCMlYU012t4XY7FOt7cooz4wsWIWi-Jqz0a0IDnciJoeLu2vNNQkbtOpCmEmsVsN4hkM4"
236
"id": "445809168892281",
237
"updated_time": "2014-08-25T18:39:32+0000",
241
"id": "445809168892281_1408991972",
243
"id": "346217352202239",
244
"name": "Pollod Magnifico"
246
"message": "Hola mundo!",
247
"created_time": "2014-08-25T18:39:32+0000"
251
"previous": "https://graph.facebook.com/v2.0/445809168892281/comments?limit=1&since=1408991972&__paging_token=enc_Aew2kKJXEXzdm9k89DvLYz_y8nYxUbvElWcn6h_pKMRsoAPTPpkU7-AsGhkcYF6M1qbomOnFJf9ckL5J3hTltLFq",
252
"next": "https://graph.facebook.com/v2.0/445809168892281/comments?limit=1&until=1408991972&__paging_token=enc_Aewlixpk4h4Vq79-W1ixrTM6ONbsMUDrcj0vLABs34tbhWarfpQLf818uoASWNDEpQO4XEXh5HbgHpcCqnuNVEOR"
259
"id": "445809168892282",
260
"updated_time": "2014-08-25T18:39:32+0000",
264
"id": "445809168892282_1408991973",
266
"id": "346217352202239",
267
"name": "Pollitod Magnifico"
270
"created_time": "2014-08-25T18:39:32+0000"
274
"previous": "https://graph.facebook.com/v2.0/445809168892281/comments?limit=1&since=1408991972&__paging_token=enc_Aew2kKJXEXzdm9k89DvLYz_y8nYxUbvElWcn6h_pKMRsoAPTPpkU7-AsGhkcYF6M1qbomOnFJf9ckL5J3hTltLFq",
275
"next": "https://graph.facebook.com/v2.0/445809168892281/comments?limit=1&until=1408991972&__paging_token=enc_Aewlixpk4h4Vq79-W1ixrTM6ONbsMUDrcj0vLABs34tbhWarfpQLf818uoASWNDEpQO4XEXh5HbgHpcCqnuNVEOR"
282
"id": "445809168892283",
283
"updated_time": "2014-08-25T18:39:32+0000",
287
"id": "445809168892282_1408991973",
289
"id": "346217352202240",
293
"created_time": "2014-08-25T18:39:32+0000"
297
"previous": "https://graph.facebook.com/v2.0/445809168892281/comments?limit=1&since=1408991972&__paging_token=enc_Aew2kKJXEXzdm9k89DvLYz_y8nYxUbvElWcn6h_pKMRsoAPTPpkU7-AsGhkcYF6M1qbomOnFJf9ckL5J3hTltLFq",
298
"next": "https://graph.facebook.com/v2.0/445809168892281/comments?limit=1&until=1408991972&__paging_token=enc_Aewlixpk4h4Vq79-W1ixrTM6ONbsMUDrcj0vLABs34tbhWarfpQLf818uoASWNDEpQO4XEXh5HbgHpcCqnuNVEOR"
306
"previous": "https://graph.facebook.com/v2.0/270128826512416/inbox?fields=unread,unseen,comments.limit(1)&limit=25&since=1408991972&__paging_token=enc_Aey99ACSOyZqN_7I-yWLnY8K3dqu4wVsx-Th3kMHMTMQ5VPbQRPgCQiJps0II1QAXDAVzHplqPS8yNgq8Zs_G2aK",
307
"next": "https://graph.facebook.com/v2.0/270128826512416/inbox?fields=unread,unseen,comments.limit(1)&limit=25&until=1408991972&__paging_token=enc_AewjHkk10NNjRCXJCoaP5hyf22kw-htwxsDaVOiLY-IiXxB99sKNGlfFFmkcG-VeMGUETI2agZGR_1IWP5W4vyPL"
312
"updated_time": "2014-08-25T19:05:49+0000"
127
func (s S) TestParseNotifications(c *C) {
318
func (s *S) SetUpTest(c *C) {
319
s.tempDir = c.MkDir()
320
plugins.XdgDataFind = func(a string) (string, error) {
321
return filepath.Join(s.tempDir, a), nil
323
plugins.XdgDataEnsure = func(a string) (string, error) {
324
p := filepath.Join(s.tempDir, a)
326
if _, err := os.Stat(base); err != nil {
327
os.MkdirAll(base, 0700)
333
func (s *S) TearDownTest(c *C) {
334
plugins.XdgDataFind = xdg.Data.Find
335
plugins.XdgDataEnsure = xdg.Data.Find
338
func (s *S) TestParseNotifications(c *C) {
128
339
resp := &http.Response{
129
340
StatusCode: http.StatusOK,
130
341
Body: closeWrapper{bytes.NewReader([]byte(notificationsBody))},
137
348
c.Check(messages[0].Notification.Card.Body, Equals, "Sender posted on your timeline: \"The message...\"")
138
349
c.Check(messages[1].Notification.Card.Summary, Equals, "Sender2")
139
350
c.Check(messages[1].Notification.Card.Body, Equals, "Sender2's birthday was on July 7.")
140
c.Check(p.lastUpdate, Equals, timeStamp("2014-07-12T09:51:57+0000"))
143
func (s S) TestIgnoreOldNotifications(c *C) {
351
c.Check(p.state.LastUpdate, Equals, timeStamp("2014-07-12T09:51:57+0000"))
354
func (s *S) TestParseLotsOfNotifications(c *C) {
355
resp := &http.Response{
356
StatusCode: http.StatusOK,
357
Body: closeWrapper{bytes.NewReader([]byte(largeNotificationsBody))},
360
messages, err := p.parseResponse(resp)
362
c.Assert(len(messages), Equals, 3)
363
c.Check(messages[0].Notification.Card.Summary, Equals, "Sender")
364
c.Check(messages[0].Notification.Card.Body, Equals, "Sender posted on your timeline: \"The message...\"")
365
c.Check(messages[1].Notification.Card.Summary, Equals, "Sender2")
366
c.Check(messages[1].Notification.Card.Body, Equals, "Sender2's birthday was on July 7.")
367
c.Check(messages[2].Notification.Card.Summary, Equals, "Multiple more notifications")
368
c.Check(messages[2].Notification.Card.Body, Equals, "From Sender3, Sender2")
369
c.Check(p.state.LastUpdate, Equals, timeStamp("2014-07-12T09:51:57+0000"))
372
func (s *S) TestIgnoreOldNotifications(c *C) {
144
373
resp := &http.Response{
145
374
StatusCode: http.StatusOK,
146
375
Body: closeWrapper{bytes.NewReader([]byte(notificationsBody))},
148
p := &fbPlugin{lastUpdate: "2014-07-08T06:17:52+0000"}
377
p := &fbPlugin{state: fbState{LastUpdate: "2014-07-08T06:17:52+0000"}}
149
378
messages, err := p.parseResponse(resp)
150
379
c.Assert(err, IsNil)
151
380
c.Assert(len(messages), Equals, 1)
152
381
c.Check(messages[0].Notification.Card.Summary, Equals, "Sender")
153
382
c.Check(messages[0].Notification.Card.Body, Equals, "Sender posted on your timeline: \"The message...\"")
154
c.Check(p.lastUpdate, Equals, timeStamp("2014-07-12T09:51:57+0000"))
383
c.Check(p.state.LastUpdate, Equals, timeStamp("2014-07-12T09:51:57+0000"))
157
func (s S) TestErrorResponse(c *C) {
386
func (s *S) TestParseResponseErrorResponse(c *C) {
158
387
resp := &http.Response{
159
388
StatusCode: http.StatusBadRequest,
160
389
Body: closeWrapper{bytes.NewReader([]byte(errorBody))},
168
397
c.Check(graphErr.Code, Equals, 2500)
171
func (s S) TestTokenExpiredErrorResponse(c *C) {
400
func (s *S) TestDecodeResponseErrorResponse(c *C) {
401
resp := &http.Response{
402
StatusCode: http.StatusBadRequest,
403
Body: closeWrapper{bytes.NewReader([]byte(errorBody))},
406
var result notificationDoc
407
err := p.decodeResponse(resp, &result)
408
c.Check(result, DeepEquals, notificationDoc{})
409
c.Assert(err, Not(IsNil))
410
graphErr := err.(*GraphError)
411
c.Check(graphErr.Message, Equals, "Unknown path components: /xyz")
412
c.Check(graphErr.Code, Equals, 2500)
415
func (s *S) TestDecodeResponseErrorResponseFails(c *C) {
416
resp := &http.Response{
417
StatusCode: http.StatusBadRequest,
418
Body: closeWrapper{bytes.NewReader([]byte("hola" + errorBody))},
421
var result notificationDoc
422
err := p.decodeResponse(resp, &result)
423
c.Check(result, DeepEquals, notificationDoc{})
424
c.Assert(err, NotNil)
425
jsonErr := err.(*json.SyntaxError)
426
c.Check(jsonErr.Offset, Equals, int64(1))
429
func (s *S) TestTokenExpiredErrorResponse(c *C) {
172
430
resp := &http.Response{
173
431
StatusCode: http.StatusBadRequest,
174
432
Body: closeWrapper{bytes.NewReader([]byte(tokenExpiredErrorBody))},
178
436
c.Check(notifications, IsNil)
179
437
c.Assert(err, Equals, plugins.ErrTokenExpired)
440
func (s *S) TestParseInbox(c *C) {
441
resp := &http.Response{
442
StatusCode: http.StatusOK,
443
Body: closeWrapper{bytes.NewReader([]byte(inboxBody))},
446
messages, err := p.parseInboxResponse(resp)
448
c.Assert(len(messages), Equals, 3)
449
c.Check(messages[0].Notification.Card.Summary, Equals, "Pollod Magnifico")
450
c.Check(messages[0].Notification.Card.Body, Equals, "Hola mundo!")
451
c.Check(messages[1].Notification.Card.Summary, Equals, "Pollitod Magnifico")
452
c.Check(messages[1].Notification.Card.Body, Equals, "Hola!")
453
c.Check(messages[2].Notification.Card.Summary, Equals, "Multiple more messages")
454
c.Check(messages[2].Notification.Card.Body, Equals, "From Pollitod Magnifico, A Friend")
455
c.Check(p.state.LastInboxUpdate, Equals, timeStamp("2014-08-25T18:39:32+0000"))
458
func (s *S) TestDecodeResponse(c *C) {
459
resp := &http.Response{
460
StatusCode: http.StatusOK,
461
Body: closeWrapper{bytes.NewReader([]byte(inboxBody))},
465
err := p.decodeResponse(resp, &doc)
467
c.Check(len(doc.Data), Equals, 3)
470
func (s *S) TestDecodeResponseFails(c *C) {
471
resp := &http.Response{
472
StatusCode: http.StatusOK,
473
Body: closeWrapper{bytes.NewReader([]byte("hola" + inboxBody))},
477
err := p.decodeResponse(resp, &doc)
478
c.Assert(err, NotNil)
479
jsonErr := err.(*json.SyntaxError)
480
c.Check(jsonErr.Offset, Equals, int64(1))
483
func (s *S) TestFilterNotifications(c *C) {
484
resp := &http.Response{
485
StatusCode: http.StatusOK,
486
Body: closeWrapper{bytes.NewReader([]byte(inboxBody))},
490
p.decodeResponse(resp, &doc)
492
notifications := p.filterNotifications(&doc, &state.LastInboxUpdate)
493
c.Check(notifications, HasLen, 3)
494
// check if the lastInboxUpdate is updated
495
c.Check(state.LastInboxUpdate, Equals, timeStamp("2014-08-25T18:39:32+0000"))
498
func (s *S) TestBuildPushMessages(c *C) {
499
resp := &http.Response{
500
StatusCode: http.StatusOK,
501
Body: closeWrapper{bytes.NewReader([]byte(inboxBody))},
504
p := &fbPlugin{state: state, accountId: 32}
506
p.decodeResponse(resp, &doc)
507
notifications := p.filterNotifications(&doc, &p.state.LastInboxUpdate)
508
pushMsgs := p.buildPushMessages(notifications, &doc, doc.size(), doc.size())
509
c.Check(pushMsgs, HasLen, doc.size())
512
func (s *S) TestBuildPushMessagesConsolidate(c *C) {
513
resp := &http.Response{
514
StatusCode: http.StatusOK,
515
Body: closeWrapper{bytes.NewReader([]byte(inboxBody))},
518
p := &fbPlugin{state: state, accountId: 32}
520
p.decodeResponse(resp, &doc)
521
notifications := p.filterNotifications(&doc, &p.state.LastInboxUpdate)
522
max := doc.size() - 2
523
pushMsgs := p.buildPushMessages(notifications, &doc, max, max)
524
// we should get max + 1 messages
525
c.Check(pushMsgs, HasLen, max+1)
528
func (s *S) TestStateFromStorageInitialState(c *C) {
529
state, err := stateFromStorage(32)
531
c.Check(state.LastUpdate, Equals, timeStamp(""))
532
c.Check(state.LastInboxUpdate, Equals, timeStamp(""))
535
func (s *S) TestStateFromStoragePersist(c *C) {
536
filePath := filepath.Join(s.tempDir, "facebook.test/facebook-32.json")
537
state, err := stateFromStorage(32)
539
state.LastInboxUpdate = timeStamp("2014-08-25T18:39:32+0000")
540
state.LastUpdate = timeStamp("2014-08-25T18:39:33+0000")
541
err = state.persist(32)
543
jsonData, err := ioutil.ReadFile(filePath)
545
var data map[string]string
546
json.Unmarshal(jsonData, &data)
547
c.Check(data["last_inbox_update"], Equals, "2014-08-25T18:39:32+0000")
548
c.Check(data["last_notification_update"], Equals, "2014-08-25T18:39:33+0000")
551
func (s *S) TestStateFromStoragePersistFails(c *C) {
552
state := fbState{LastInboxUpdate: "2014-08-25T18:39:32+0000", LastUpdate: "2014-08-25T18:39:33+0000"}
553
plugins.XdgDataEnsure = plugins.XdgDataFind
554
err := state.persist(32)
558
func (s *S) TestStateFromStorage(c *C) {
559
state := fbState{LastInboxUpdate: "2014-08-25T18:39:32+0000", LastUpdate: "2014-08-25T18:39:33+0000"}
560
err := state.persist(32)
562
newState, err := stateFromStorage(32)
564
c.Check(newState.LastUpdate, Equals, timeStamp("2014-08-25T18:39:33+0000"))
565
c.Check(newState.LastInboxUpdate, Equals, timeStamp("2014-08-25T18:39:32+0000"))
567
state = fbState{LastInboxUpdate: "yesterday", LastUpdate: "2014-08-25T18:39:33+0000"}
569
_, err = stateFromStorage(32)
571
state = fbState{LastInboxUpdate: "2014-08-25T18:39:33+0000", LastUpdate: "today"}
573
_, err = stateFromStorage(32)
577
func (s *S) TestNew(c *C) {
578
state := fbState{LastInboxUpdate: "2014-08-25T18:39:32+0000", LastUpdate: "2014-08-25T18:39:33+0000"}
582
c.Check(fb.state, DeepEquals, state)
584
state = fbState{LastInboxUpdate: "hola", LastUpdate: "mundo"}
588
c.Check(fb.state, DeepEquals, state)
591
func (s *S) TestApplicationId(c *C) {
592
expected := plugins.ApplicationId("com.ubuntu.developer.webapps.webapp-facebook_webapp-facebook")
594
c.Check(p.ApplicationId(), Equals, expected)