3 namespace Tests\Wallabag\ImportBundle\Import
;
5 use Wallabag\UserBundle\Entity\User
;
6 use Wallabag\CoreBundle\Entity\Entry
;
7 use Wallabag\CoreBundle\Entity\Config
;
8 use Wallabag\ImportBundle\Import\PocketImport
;
10 use GuzzleHttp\Subscriber\Mock
;
11 use GuzzleHttp\Message\Response
;
12 use GuzzleHttp\Stream\Stream
;
13 use Wallabag\ImportBundle\Redis\Producer
;
15 use Monolog\Handler\TestHandler
;
16 use Simpleue\Queue\RedisQueue
;
17 use M6Web\Component\RedisMock\RedisMockFactory
;
19 class PocketImportTest
extends \PHPUnit_Framework_TestCase
24 protected $contentProxy;
25 protected $logHandler;
27 private function getPocketImport($consumerKey = 'ConsumerKey', $dispatched = 0)
29 $this->user
= new User();
31 $config = new Config($this->user
);
32 $config->setPocketConsumerKey('xxx');
34 $this->user
->setConfig($config);
36 $this->contentProxy
= $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
37 ->disableOriginalConstructor()
40 $this->em
= $this->getMockBuilder('Doctrine\ORM\EntityManager')
41 ->disableOriginalConstructor()
44 $this->uow
= $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
45 ->disableOriginalConstructor()
49 ->expects($this->any())
50 ->method('getUnitOfWork')
51 ->willReturn($this->uow
);
54 ->expects($this->any())
55 ->method('getScheduledEntityInsertions')
58 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
59 ->disableOriginalConstructor()
63 ->expects($this->exactly($dispatched))
66 $pocket = new PocketImport($this->em
, $this->contentProxy
, $dispatcher);
67 $pocket->setUser($this->user
);
69 $this->logHandler
= new TestHandler();
70 $logger = new Logger('test', [$this->logHandler
]);
71 $pocket->setLogger($logger);
76 public function testInit()
78 $pocketImport = $this->getPocketImport();
80 $this->assertEquals('Pocket', $pocketImport->getName());
81 $this->assertNotEmpty($pocketImport->getUrl());
82 $this->assertEquals('import.pocket.description', $pocketImport->getDescription());
85 public function testOAuthRequest()
87 $client = new Client();
90 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['code' => 'wunderbar_code']))),
93 $client->getEmitter()->attach($mock);
95 $pocketImport = $this->getPocketImport();
96 $pocketImport->setClient($client);
98 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
100 $this->assertEquals('wunderbar_code', $code);
103 public function testOAuthRequestBadResponse()
105 $client = new Client();
111 $client->getEmitter()->attach($mock);
113 $pocketImport = $this->getPocketImport();
114 $pocketImport->setClient($client);
116 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
118 $this->assertFalse($code);
120 $records = $this->logHandler
->getRecords();
121 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']);
122 $this->assertEquals('ERROR', $records[0]['level_name']);
125 public function testOAuthAuthorize()
127 $client = new Client();
130 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
133 $client->getEmitter()->attach($mock);
135 $pocketImport = $this->getPocketImport();
136 $pocketImport->setClient($client);
138 $res = $pocketImport->authorize('wunderbar_code');
140 $this->assertTrue($res);
141 $this->assertEquals('wunderbar_token', $pocketImport->getAccessToken());
144 public function testOAuthAuthorizeBadResponse()
146 $client = new Client();
152 $client->getEmitter()->attach($mock);
154 $pocketImport = $this->getPocketImport();
155 $pocketImport->setClient($client);
157 $res = $pocketImport->authorize('wunderbar_code');
159 $this->assertFalse($res);
161 $records = $this->logHandler
->getRecords();
162 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']);
163 $this->assertEquals('ERROR', $records[0]['level_name']);
167 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
169 public function testImport()
171 $client = new Client();
174 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
175 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
180 "item_id": "229279689",
181 "resolved_id": "229279689",
182 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
183 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
186 "time_added": "1473020899",
187 "time_updated": "1473020899",
189 "time_favorited": "0",
191 "resolved_title": "The Massive Ryder Cup Preview",
192 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
193 "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.",
198 "word_count": "3197",
201 "item_id": "229279689",
203 "src": "http://a.espncdn.com/combiner/i?img=/photo/2012/0927/grant_g_ryder_cr_640.jpg&w=640&h=360",
206 "credit": "Jamie Squire/Getty Images",
212 "item_id": "229279689",
214 "src": "http://www.youtube.com/v/Er34PbFkVGk?version=3&hl=en_US&rel=0",
223 "item_id": "1147652870",
227 "item_id": "1147652870",
233 "item_id": "229279689",
234 "resolved_id": "229279689",
235 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
236 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
239 "time_added": "1473020899",
240 "time_updated": "1473020899",
242 "time_favorited": "0",
244 "resolved_title": "The Massive Ryder Cup Preview",
245 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
246 "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.",
258 $client->getEmitter()->attach($mock);
260 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
262 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
263 ->disableOriginalConstructor()
266 $entryRepo->expects($this->exactly(2))
267 ->method('findByUrlAndUserId')
268 ->will($this->onConsecutiveCalls(false, true));
271 ->expects($this->exactly(2))
272 ->method('getRepository')
273 ->willReturn($entryRepo);
275 $entry = new Entry($this->user
);
278 ->expects($this->once())
279 ->method('updateEntry')
280 ->willReturn($entry);
282 $pocketImport->setClient($client);
283 $pocketImport->authorize('wunderbar_code');
285 $res = $pocketImport->import();
287 $this->assertTrue($res);
288 $this->assertEquals(['skipped' => 1, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
292 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
294 public function testImportAndMarkAllAsRead()
296 $client = new Client();
299 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
300 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
305 "item_id": "229279689",
306 "resolved_id": "229279689",
307 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
308 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
311 "time_added": "1473020899",
312 "time_updated": "1473020899",
314 "time_favorited": "0",
316 "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.",
323 "item_id": "229279689",
324 "resolved_id": "229279689",
325 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview/2",
326 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
329 "time_added": "1473020899",
330 "time_updated": "1473020899",
332 "time_favorited": "0",
334 "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.",
345 $client->getEmitter()->attach($mock);
347 $pocketImport = $this->getPocketImport('ConsumerKey', 2);
349 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
350 ->disableOriginalConstructor()
353 $entryRepo->expects($this->exactly(2))
354 ->method('findByUrlAndUserId')
355 ->will($this->onConsecutiveCalls(false, false));
358 ->expects($this->exactly(2))
359 ->method('getRepository')
360 ->willReturn($entryRepo);
362 // check that every entry persisted are archived
364 ->expects($this->any())
366 ->with($this->callback(function ($persistedEntry) {
367 return $persistedEntry->isArchived();
370 $entry = new Entry($this->user
);
373 ->expects($this->exactly(2))
374 ->method('updateEntry')
375 ->willReturn($entry);
377 $pocketImport->setClient($client);
378 $pocketImport->authorize('wunderbar_code');
380 $res = $pocketImport->setMarkAsRead(true)->import();
382 $this->assertTrue($res);
383 $this->assertEquals(['skipped' => 0, 'imported' => 2, 'queued' => 0], $pocketImport->getSummary());
387 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
389 public function testImportWithRabbit()
391 $client = new Client();
395 "item_id": "229279689",
396 "resolved_id": "229279689",
397 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
398 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
401 "time_added": "1473020899",
402 "time_updated": "1473020899",
404 "time_favorited": "0",
406 "resolved_title": "The Massive Ryder Cup Preview",
407 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
408 "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.",
417 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
418 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
422 "229279690": '.$body.'
428 $client->getEmitter()->attach($mock);
430 $pocketImport = $this->getPocketImport();
432 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
433 ->disableOriginalConstructor()
436 $entryRepo->expects($this->never())
437 ->method('findByUrlAndUserId');
440 ->expects($this->never())
441 ->method('getRepository');
443 $entry = new Entry($this->user
);
446 ->expects($this->never())
447 ->method('updateEntry');
449 $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
450 ->disableOriginalConstructor()
453 $bodyAsArray = json_decode($body, true);
454 // because with just use `new User()` so it doesn't have an id
455 $bodyAsArray['userId'] = null;
458 ->expects($this->once())
460 ->with(json_encode($bodyAsArray));
462 $pocketImport->setClient($client);
463 $pocketImport->setProducer($producer);
464 $pocketImport->authorize('wunderbar_code');
466 $res = $pocketImport->setMarkAsRead(true)->import();
468 $this->assertTrue($res);
469 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
473 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
475 public function testImportWithRedis()
477 $client = new Client();
481 "item_id": "229279689",
482 "resolved_id": "229279689",
483 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
484 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
487 "time_added": "1473020899",
488 "time_updated": "1473020899",
490 "time_favorited": "0",
492 "resolved_title": "The Massive Ryder Cup Preview",
493 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
494 "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.",
503 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
504 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
508 "229279690": '.$body.'
514 $client->getEmitter()->attach($mock);
516 $pocketImport = $this->getPocketImport();
518 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
519 ->disableOriginalConstructor()
522 $entryRepo->expects($this->never())
523 ->method('findByUrlAndUserId');
526 ->expects($this->never())
527 ->method('getRepository');
529 $entry = new Entry($this->user
);
532 ->expects($this->never())
533 ->method('updateEntry');
535 $factory = new RedisMockFactory();
536 $redisMock = $factory->getAdapter('Predis\Client', true);
538 $queue = new RedisQueue($redisMock, 'pocket');
539 $producer = new Producer($queue);
541 $pocketImport->setClient($client);
542 $pocketImport->setProducer($producer);
543 $pocketImport->authorize('wunderbar_code');
545 $res = $pocketImport->setMarkAsRead(true)->import();
547 $this->assertTrue($res);
548 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
550 $this->assertNotEmpty($redisMock->lpop('pocket'));
553 public function testImportBadResponse()
555 $client = new Client();
558 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
562 $client->getEmitter()->attach($mock);
564 $pocketImport = $this->getPocketImport();
565 $pocketImport->setClient($client);
566 $pocketImport->authorize('wunderbar_code');
568 $res = $pocketImport->import();
570 $this->assertFalse($res);
572 $records = $this->logHandler
->getRecords();
573 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
574 $this->assertEquals('ERROR', $records[0]['level_name']);
577 public function testImportWithExceptionFromGraby()
579 $client = new Client();
582 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
583 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
590 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
597 $client->getEmitter()->attach($mock);
599 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
601 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
602 ->disableOriginalConstructor()
605 $entryRepo->expects($this->once())
606 ->method('findByUrlAndUserId')
607 ->will($this->onConsecutiveCalls(false, true));
610 ->expects($this->once())
611 ->method('getRepository')
612 ->willReturn($entryRepo);
614 $entry = new Entry($this->user
);
617 ->expects($this->once())
618 ->method('updateEntry')
619 ->will($this->throwException(new \
Exception()));
621 $pocketImport->setClient($client);
622 $pocketImport->authorize('wunderbar_code');
624 $res = $pocketImport->import();
626 $this->assertTrue($res);
627 $this->assertEquals(['skipped' => 0, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());