]> git.immae.eu Git - github/wallabag/wallabag.git/blame - tests/Wallabag/ImportBundle/Import/PocketImportTest.php
Add a real configuration for CS-Fixer
[github/wallabag/wallabag.git] / tests / Wallabag / ImportBundle / Import / PocketImportTest.php
CommitLineData
7ec2897e
JB
1<?php
2
23634d5d 3namespace Tests\Wallabag\ImportBundle\Import;
7ec2897e 4
7ec2897e 5use GuzzleHttp\Client;
7ec2897e
JB
6use GuzzleHttp\Message\Response;
7use GuzzleHttp\Stream\Stream;
f808b016
JB
8use GuzzleHttp\Subscriber\Mock;
9use M6Web\Component\RedisMock\RedisMockFactory;
252ebd60 10use Monolog\Handler\TestHandler;
f808b016 11use Monolog\Logger;
b3437d58 12use Simpleue\Queue\RedisQueue;
f808b016
JB
13use Wallabag\CoreBundle\Entity\Config;
14use Wallabag\CoreBundle\Entity\Entry;
15use Wallabag\ImportBundle\Import\PocketImport;
16use Wallabag\ImportBundle\Redis\Producer;
17use Wallabag\UserBundle\Entity\User;
252ebd60 18
7ec2897e
JB
19class PocketImportTest extends \PHPUnit_Framework_TestCase
20{
21 protected $token;
22 protected $user;
7ec2897e 23 protected $em;
252ebd60
JB
24 protected $contentProxy;
25 protected $logHandler;
6bc6fb1f
TC
26 protected $tagsAssigner;
27 protected $uow;
7ec2897e 28
7ec2897e
JB
29 public function testInit()
30 {
31 $pocketImport = $this->getPocketImport();
32
f808b016 33 $this->assertSame('Pocket', $pocketImport->getName());
7019c7cf 34 $this->assertNotEmpty($pocketImport->getUrl());
f808b016 35 $this->assertSame('import.pocket.description', $pocketImport->getDescription());
7ec2897e
JB
36 }
37
38 public function testOAuthRequest()
39 {
40 $client = new Client();
41
42 $mock = new Mock([
252ebd60 43 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['code' => 'wunderbar_code']))),
7ec2897e
JB
44 ]);
45
46 $client->getEmitter()->attach($mock);
47
48 $pocketImport = $this->getPocketImport();
49 $pocketImport->setClient($client);
50
252ebd60 51 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
7ec2897e 52
f808b016 53 $this->assertSame('wunderbar_code', $code);
252ebd60
JB
54 }
55
56 public function testOAuthRequestBadResponse()
57 {
58 $client = new Client();
59
60 $mock = new Mock([
61 new Response(403),
62 ]);
63
64 $client->getEmitter()->attach($mock);
65
66 $pocketImport = $this->getPocketImport();
67 $pocketImport->setClient($client);
68
69 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
70
71 $this->assertFalse($code);
72
73 $records = $this->logHandler->getRecords();
74 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']);
f808b016 75 $this->assertSame('ERROR', $records[0]['level_name']);
7ec2897e
JB
76 }
77
78 public function testOAuthAuthorize()
79 {
80 $client = new Client();
81
82 $mock = new Mock([
252ebd60 83 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
7ec2897e
JB
84 ]);
85
86 $client->getEmitter()->attach($mock);
87
88 $pocketImport = $this->getPocketImport();
89 $pocketImport->setClient($client);
90
252ebd60 91 $res = $pocketImport->authorize('wunderbar_code');
7ec2897e 92
252ebd60 93 $this->assertTrue($res);
f808b016 94 $this->assertSame('wunderbar_token', $pocketImport->getAccessToken());
7ec2897e
JB
95 }
96
252ebd60
JB
97 public function testOAuthAuthorizeBadResponse()
98 {
99 $client = new Client();
100
101 $mock = new Mock([
102 new Response(403),
103 ]);
104
105 $client->getEmitter()->attach($mock);
106
107 $pocketImport = $this->getPocketImport();
108 $pocketImport->setClient($client);
109
110 $res = $pocketImport->authorize('wunderbar_code');
111
112 $this->assertFalse($res);
113
114 $records = $this->logHandler->getRecords();
115 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']);
f808b016 116 $this->assertSame('ERROR', $records[0]['level_name']);
252ebd60
JB
117 }
118
119 /**
120 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
121 */
7ec2897e
JB
122 public function testImport()
123 {
124 $client = new Client();
125
126 $mock = new Mock([
252ebd60
JB
127 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
128 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
129 {
130 "status": 1,
131 "list": {
132 "229279689": {
133 "item_id": "229279689",
134 "resolved_id": "229279689",
135 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
136 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
137 "favorite": "1",
138 "status": "1",
7f753117
JB
139 "time_added": "1473020899",
140 "time_updated": "1473020899",
141 "time_read": "0",
142 "time_favorited": "0",
143 "sort_id": 0,
252ebd60
JB
144 "resolved_title": "The Massive Ryder Cup Preview",
145 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
146 "excerpt": "The list of things I love about the Ryder Cup is so long that it could fill a (tedious) novel, and golf fans can probably guess most of them.",
147 "is_article": "1",
7f753117 148 "is_index": "0",
252ebd60
JB
149 "has_video": "1",
150 "has_image": "1",
151 "word_count": "3197",
152 "images": {
153 "1": {
154 "item_id": "229279689",
155 "image_id": "1",
156 "src": "http://a.espncdn.com/combiner/i?img=/photo/2012/0927/grant_g_ryder_cr_640.jpg&w=640&h=360",
157 "width": "0",
158 "height": "0",
159 "credit": "Jamie Squire/Getty Images",
160 "caption": ""
161 }
162 },
163 "videos": {
164 "1": {
165 "item_id": "229279689",
166 "video_id": "1",
167 "src": "http://www.youtube.com/v/Er34PbFkVGk?version=3&hl=en_US&rel=0",
168 "width": "420",
169 "height": "315",
170 "type": "1",
171 "vid": "Er34PbFkVGk"
172 }
173 },
174 "tags": {
175 "grantland": {
176 "item_id": "1147652870",
177 "tag": "grantland"
178 },
179 "Ryder Cup": {
180 "item_id": "1147652870",
181 "tag": "Ryder Cup"
182 }
183 }
184 },
185 "229279690": {
186 "item_id": "229279689",
187 "resolved_id": "229279689",
188 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
189 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
190 "favorite": "1",
191 "status": "1",
7f753117
JB
192 "time_added": "1473020899",
193 "time_updated": "1473020899",
194 "time_read": "0",
195 "time_favorited": "0",
196 "sort_id": 1,
252ebd60
JB
197 "resolved_title": "The Massive Ryder Cup Preview",
198 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
199 "excerpt": "The list of things I love about the Ryder Cup is so long that it could fill a (tedious) novel, and golf fans can probably guess most of them.",
200 "is_article": "1",
7f753117 201 "is_index": "0",
252ebd60
JB
202 "has_video": "0",
203 "has_image": "0",
204 "word_count": "3197"
205 }
206 }
207 }
208 ')),
209 ]);
210
211 $client->getEmitter()->attach($mock);
212
7816eb62 213 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
252ebd60
JB
214
215 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
216 ->disableOriginalConstructor()
217 ->getMock();
218
219 $entryRepo->expects($this->exactly(2))
78833672 220 ->method('findByUrlAndUserId')
252ebd60
JB
221 ->will($this->onConsecutiveCalls(false, true));
222
252ebd60 223 $this->em
c2656f96 224 ->expects($this->exactly(2))
252ebd60 225 ->method('getRepository')
c2656f96 226 ->willReturn($entryRepo);
252ebd60 227
79d0e38e 228 $entry = new Entry($this->user);
252ebd60
JB
229
230 $this->contentProxy
231 ->expects($this->once())
232 ->method('updateEntry')
233 ->willReturn($entry);
234
235 $pocketImport->setClient($client);
236 $pocketImport->authorize('wunderbar_code');
237
238 $res = $pocketImport->import();
239
240 $this->assertTrue($res);
f808b016 241 $this->assertSame(['skipped' => 1, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
252ebd60
JB
242 }
243
79d0e38e
JB
244 /**
245 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
246 */
247 public function testImportAndMarkAllAsRead()
248 {
249 $client = new Client();
250
251 $mock = new Mock([
252 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
253 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
254 {
255 "status": 1,
256 "list": {
257 "229279689": {
258 "item_id": "229279689",
259 "resolved_id": "229279689",
260 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
261 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
262 "favorite": "1",
263 "status": "1",
7f753117
JB
264 "time_added": "1473020899",
265 "time_updated": "1473020899",
266 "time_read": "0",
267 "time_favorited": "0",
268 "sort_id": 0,
79d0e38e
JB
269 "excerpt": "The list of things I love about the Ryder Cup is so long that it could fill a (tedious) novel, and golf fans can probably guess most of them.",
270 "is_article": "1",
271 "has_video": "1",
272 "has_image": "1",
273 "word_count": "3197"
274 },
275 "229279690": {
276 "item_id": "229279689",
277 "resolved_id": "229279689",
278 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview/2",
279 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
280 "favorite": "1",
281 "status": "0",
7f753117
JB
282 "time_added": "1473020899",
283 "time_updated": "1473020899",
284 "time_read": "0",
285 "time_favorited": "0",
286 "sort_id": 1,
79d0e38e
JB
287 "excerpt": "The list of things I love about the Ryder Cup is so long that it could fill a (tedious) novel, and golf fans can probably guess most of them.",
288 "is_article": "1",
289 "has_video": "0",
290 "has_image": "0",
291 "word_count": "3197"
292 }
293 }
294 }
295 ')),
296 ]);
297
298 $client->getEmitter()->attach($mock);
299
7816eb62 300 $pocketImport = $this->getPocketImport('ConsumerKey', 2);
79d0e38e
JB
301
302 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
303 ->disableOriginalConstructor()
304 ->getMock();
305
306 $entryRepo->expects($this->exactly(2))
307 ->method('findByUrlAndUserId')
308 ->will($this->onConsecutiveCalls(false, false));
309
310 $this->em
311 ->expects($this->exactly(2))
312 ->method('getRepository')
313 ->willReturn($entryRepo);
314
315 // check that every entry persisted are archived
316 $this->em
317 ->expects($this->any())
318 ->method('persist')
cebb4223 319 ->with($this->callback(function ($persistedEntry) {
79d0e38e
JB
320 return $persistedEntry->isArchived();
321 }));
322
323 $entry = new Entry($this->user);
324
325 $this->contentProxy
326 ->expects($this->exactly(2))
327 ->method('updateEntry')
328 ->willReturn($entry);
329
330 $pocketImport->setClient($client);
331 $pocketImport->authorize('wunderbar_code');
332
333 $res = $pocketImport->setMarkAsRead(true)->import();
334
335 $this->assertTrue($res);
f808b016 336 $this->assertSame(['skipped' => 0, 'imported' => 2, 'queued' => 0], $pocketImport->getSummary());
79d0e38e
JB
337 }
338
13470c35
JB
339 /**
340 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
341 */
342 public function testImportWithRabbit()
343 {
344 $client = new Client();
345
346 $body = <<<'JSON'
347{
348 "item_id": "229279689",
349 "resolved_id": "229279689",
350 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
351 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
352 "favorite": "1",
353 "status": "1",
7f753117
JB
354 "time_added": "1473020899",
355 "time_updated": "1473020899",
356 "time_read": "0",
357 "time_favorited": "0",
358 "sort_id": 0,
13470c35
JB
359 "resolved_title": "The Massive Ryder Cup Preview",
360 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
361 "excerpt": "The list of things I love about the Ryder Cup is so long that it could fill a (tedious) novel, and golf fans can probably guess most of them.",
362 "is_article": "1",
363 "has_video": "0",
364 "has_image": "0",
365 "word_count": "3197"
366}
367JSON;
368
369 $mock = new Mock([
370 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
371 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
372 {
373 "status": 1,
374 "list": {
f808b016 375 "229279690": ' . $body . '
13470c35
JB
376 }
377 }
378 ')),
379 ]);
380
381 $client->getEmitter()->attach($mock);
382
383 $pocketImport = $this->getPocketImport();
384
385 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
386 ->disableOriginalConstructor()
387 ->getMock();
388
389 $entryRepo->expects($this->never())
390 ->method('findByUrlAndUserId');
391
392 $this->em
393 ->expects($this->never())
394 ->method('getRepository');
395
396 $entry = new Entry($this->user);
397
398 $this->contentProxy
399 ->expects($this->never())
400 ->method('updateEntry');
401
402 $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
403 ->disableOriginalConstructor()
404 ->getMock();
405
406 $bodyAsArray = json_decode($body, true);
407 // because with just use `new User()` so it doesn't have an id
408 $bodyAsArray['userId'] = null;
409
410 $producer
411 ->expects($this->once())
412 ->method('publish')
413 ->with(json_encode($bodyAsArray));
414
415 $pocketImport->setClient($client);
b3437d58 416 $pocketImport->setProducer($producer);
13470c35
JB
417 $pocketImport->authorize('wunderbar_code');
418
419 $res = $pocketImport->setMarkAsRead(true)->import();
420
421 $this->assertTrue($res);
f808b016 422 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
13470c35
JB
423 }
424
b3437d58
JB
425 /**
426 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
427 */
428 public function testImportWithRedis()
429 {
430 $client = new Client();
431
432 $body = <<<'JSON'
433{
434 "item_id": "229279689",
435 "resolved_id": "229279689",
436 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
437 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
438 "favorite": "1",
439 "status": "1",
440 "time_added": "1473020899",
441 "time_updated": "1473020899",
442 "time_read": "0",
443 "time_favorited": "0",
444 "sort_id": 0,
445 "resolved_title": "The Massive Ryder Cup Preview",
446 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
447 "excerpt": "The list of things I love about the Ryder Cup is so long that it could fill a (tedious) novel, and golf fans can probably guess most of them.",
448 "is_article": "1",
449 "has_video": "0",
450 "has_image": "0",
451 "word_count": "3197"
452}
453JSON;
454
455 $mock = new Mock([
456 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
457 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
458 {
459 "status": 1,
460 "list": {
f808b016 461 "229279690": ' . $body . '
b3437d58
JB
462 }
463 }
464 ')),
465 ]);
466
467 $client->getEmitter()->attach($mock);
468
469 $pocketImport = $this->getPocketImport();
470
471 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
472 ->disableOriginalConstructor()
473 ->getMock();
474
475 $entryRepo->expects($this->never())
476 ->method('findByUrlAndUserId');
477
478 $this->em
479 ->expects($this->never())
480 ->method('getRepository');
481
482 $entry = new Entry($this->user);
483
484 $this->contentProxy
485 ->expects($this->never())
486 ->method('updateEntry');
487
488 $factory = new RedisMockFactory();
489 $redisMock = $factory->getAdapter('Predis\Client', true);
490
491 $queue = new RedisQueue($redisMock, 'pocket');
492 $producer = new Producer($queue);
493
494 $pocketImport->setClient($client);
495 $pocketImport->setProducer($producer);
496 $pocketImport->authorize('wunderbar_code');
497
498 $res = $pocketImport->setMarkAsRead(true)->import();
499
500 $this->assertTrue($res);
f808b016 501 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
b3437d58
JB
502
503 $this->assertNotEmpty($redisMock->lpop('pocket'));
504 }
505
252ebd60
JB
506 public function testImportBadResponse()
507 {
508 $client = new Client();
509
510 $mock = new Mock([
511 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
512 new Response(403),
7ec2897e
JB
513 ]);
514
515 $client->getEmitter()->attach($mock);
516
517 $pocketImport = $this->getPocketImport();
518 $pocketImport->setClient($client);
252ebd60
JB
519 $pocketImport->authorize('wunderbar_code');
520
521 $res = $pocketImport->import();
7ec2897e 522
252ebd60 523 $this->assertFalse($res);
7ec2897e 524
252ebd60
JB
525 $records = $this->logHandler->getRecords();
526 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
f808b016 527 $this->assertSame('ERROR', $records[0]['level_name']);
7ec2897e 528 }
19d9efab
JB
529
530 public function testImportWithExceptionFromGraby()
531 {
532 $client = new Client();
533
534 $mock = new Mock([
535 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
536 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
537 {
538 "status": 1,
539 "list": {
540 "229279689": {
59b97fae
JB
541 "status": "1",
542 "favorite": "1",
19d9efab
JB
543 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
544 }
545 }
546 }
547 ')),
548 ]);
549
550 $client->getEmitter()->attach($mock);
551
7816eb62 552 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
19d9efab
JB
553
554 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
555 ->disableOriginalConstructor()
556 ->getMock();
557
558 $entryRepo->expects($this->once())
559 ->method('findByUrlAndUserId')
560 ->will($this->onConsecutiveCalls(false, true));
561
562 $this->em
563 ->expects($this->once())
564 ->method('getRepository')
565 ->willReturn($entryRepo);
566
567 $entry = new Entry($this->user);
568
569 $this->contentProxy
570 ->expects($this->once())
571 ->method('updateEntry')
572 ->will($this->throwException(new \Exception()));
573
574 $pocketImport->setClient($client);
575 $pocketImport->authorize('wunderbar_code');
576
577 $res = $pocketImport->import();
578
579 $this->assertTrue($res);
f808b016
JB
580 $this->assertSame(['skipped' => 0, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
581 }
582
583 private function getPocketImport($consumerKey = 'ConsumerKey', $dispatched = 0)
584 {
585 $this->user = new User();
586
587 $config = new Config($this->user);
588 $config->setPocketConsumerKey('xxx');
589
590 $this->user->setConfig($config);
591
592 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
593 ->disableOriginalConstructor()
594 ->getMock();
595
596 $this->tagsAssigner = $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
597 ->disableOriginalConstructor()
598 ->getMock();
599
600 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
601 ->disableOriginalConstructor()
602 ->getMock();
603
604 $this->uow = $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
605 ->disableOriginalConstructor()
606 ->getMock();
607
608 $this->em
609 ->expects($this->any())
610 ->method('getUnitOfWork')
611 ->willReturn($this->uow);
612
613 $this->uow
614 ->expects($this->any())
615 ->method('getScheduledEntityInsertions')
616 ->willReturn([]);
617
618 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
619 ->disableOriginalConstructor()
620 ->getMock();
621
622 $dispatcher
623 ->expects($this->exactly($dispatched))
624 ->method('dispatch');
625
626 $pocket = new PocketImport($this->em, $this->contentProxy, $this->tagsAssigner, $dispatcher);
627 $pocket->setUser($this->user);
628
629 $this->logHandler = new TestHandler();
630 $logger = new Logger('test', [$this->logHandler]);
631 $pocket->setLogger($logger);
632
633 return $pocket;
19d9efab 634 }
7ec2897e 635}