3 namespace Tests\Wallabag\ImportBundle\Import
;
6 use GuzzleHttp\Message\Response
;
7 use GuzzleHttp\Stream\Stream
;
8 use GuzzleHttp\Subscriber\Mock
;
9 use M6Web\Component\RedisMock\RedisMockFactory
;
10 use Monolog\Handler\TestHandler
;
12 use Simpleue\Queue\RedisQueue
;
13 use Wallabag\CoreBundle\Entity\Config
;
14 use Wallabag\CoreBundle\Entity\Entry
;
15 use Wallabag\ImportBundle\Import\PocketImport
;
16 use Wallabag\ImportBundle\Redis\Producer
;
17 use Wallabag\UserBundle\Entity\User
;
19 class PocketImportTest
extends \PHPUnit_Framework_TestCase
24 protected $contentProxy;
25 protected $logHandler;
26 protected $tagsAssigner;
29 public function testInit()
31 $pocketImport = $this->getPocketImport();
33 $this->assertSame('Pocket', $pocketImport->getName());
34 $this->assertNotEmpty($pocketImport->getUrl());
35 $this->assertSame('import.pocket.description', $pocketImport->getDescription());
38 public function testOAuthRequest()
40 $client = new Client();
43 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['code' => 'wunderbar_code']))),
46 $client->getEmitter()->attach($mock);
48 $pocketImport = $this->getPocketImport();
49 $pocketImport->setClient($client);
51 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
53 $this->assertSame('wunderbar_code', $code);
56 public function testOAuthRequestBadResponse()
58 $client = new Client();
64 $client->getEmitter()->attach($mock);
66 $pocketImport = $this->getPocketImport();
67 $pocketImport->setClient($client);
69 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
71 $this->assertFalse($code);
73 $records = $this->logHandler
->getRecords();
74 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']);
75 $this->assertSame('ERROR', $records[0]['level_name']);
78 public function testOAuthAuthorize()
80 $client = new Client();
83 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
86 $client->getEmitter()->attach($mock);
88 $pocketImport = $this->getPocketImport();
89 $pocketImport->setClient($client);
91 $res = $pocketImport->authorize('wunderbar_code');
93 $this->assertTrue($res);
94 $this->assertSame('wunderbar_token', $pocketImport->getAccessToken());
97 public function testOAuthAuthorizeBadResponse()
99 $client = new Client();
105 $client->getEmitter()->attach($mock);
107 $pocketImport = $this->getPocketImport();
108 $pocketImport->setClient($client);
110 $res = $pocketImport->authorize('wunderbar_code');
112 $this->assertFalse($res);
114 $records = $this->logHandler
->getRecords();
115 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']);
116 $this->assertSame('ERROR', $records[0]['level_name']);
120 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
122 public function testImport()
124 $client = new Client();
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('
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",
139 "time_added": "1473020899",
140 "time_updated": "1473020899",
142 "time_favorited": "0",
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.",
151 "word_count": "3197",
154 "item_id": "229279689",
156 "src": "http://a.espncdn.com/combiner/i?img=/photo/2012/0927/grant_g_ryder_cr_640.jpg&w=640&h=360",
159 "credit": "Jamie Squire/Getty Images",
165 "item_id": "229279689",
167 "src": "http://www.youtube.com/v/Er34PbFkVGk?version=3&hl=en_US&rel=0",
176 "item_id": "1147652870",
180 "item_id": "1147652870",
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",
192 "time_added": "1473020899",
193 "time_updated": "1473020899",
195 "time_favorited": "0",
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.",
211 $client->getEmitter()->attach($mock);
213 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
215 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
216 ->disableOriginalConstructor()
219 $entryRepo->expects($this->exactly(2))
220 ->method('findByUrlAndUserId')
221 ->will($this->onConsecutiveCalls(false, true));
224 ->expects($this->exactly(2))
225 ->method('getRepository')
226 ->willReturn($entryRepo);
228 $entry = new Entry($this->user
);
231 ->expects($this->once())
232 ->method('updateEntry')
233 ->willReturn($entry);
235 $pocketImport->setClient($client);
236 $pocketImport->authorize('wunderbar_code');
238 $res = $pocketImport->import();
240 $this->assertTrue($res);
241 $this->assertSame(['skipped' => 1, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
245 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
247 public function testImportAndMarkAllAsRead()
249 $client = new Client();
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('
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",
264 "time_added": "1473020899",
265 "time_updated": "1473020899",
267 "time_favorited": "0",
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.",
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",
282 "time_added": "1473020899",
283 "time_updated": "1473020899",
285 "time_favorited": "0",
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.",
298 $client->getEmitter()->attach($mock);
300 $pocketImport = $this->getPocketImport('ConsumerKey', 2);
302 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
303 ->disableOriginalConstructor()
306 $entryRepo->expects($this->exactly(2))
307 ->method('findByUrlAndUserId')
308 ->will($this->onConsecutiveCalls(false, false));
311 ->expects($this->exactly(2))
312 ->method('getRepository')
313 ->willReturn($entryRepo);
315 // check that every entry persisted are archived
317 ->expects($this->any())
319 ->with($this->callback(function ($persistedEntry) {
320 return $persistedEntry->isArchived();
323 $entry = new Entry($this->user
);
326 ->expects($this->exactly(2))
327 ->method('updateEntry')
328 ->willReturn($entry);
330 $pocketImport->setClient($client);
331 $pocketImport->authorize('wunderbar_code');
333 $res = $pocketImport->setMarkAsRead(true)->import();
335 $this->assertTrue($res);
336 $this->assertSame(['skipped' => 0, 'imported' => 2, 'queued' => 0], $pocketImport->getSummary());
340 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
342 public function testImportWithRabbit()
344 $client = new Client();
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",
354 "time_added": "1473020899",
355 "time_updated": "1473020899",
357 "time_favorited": "0",
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.",
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('
375 "229279690": ' . $body . '
381 $client->getEmitter()->attach($mock);
383 $pocketImport = $this->getPocketImport();
385 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
386 ->disableOriginalConstructor()
389 $entryRepo->expects($this->never())
390 ->method('findByUrlAndUserId');
393 ->expects($this->never())
394 ->method('getRepository');
396 $entry = new Entry($this->user
);
399 ->expects($this->never())
400 ->method('updateEntry');
402 $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
403 ->disableOriginalConstructor()
406 $bodyAsArray = json_decode($body, true);
407 // because with just use `new User()` so it doesn't have an id
408 $bodyAsArray['userId'] = null;
411 ->expects($this->once())
413 ->with(json_encode($bodyAsArray));
415 $pocketImport->setClient($client);
416 $pocketImport->setProducer($producer);
417 $pocketImport->authorize('wunderbar_code');
419 $res = $pocketImport->setMarkAsRead(true)->import();
421 $this->assertTrue($res);
422 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
426 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
428 public function testImportWithRedis()
430 $client = new Client();
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",
440 "time_added": "1473020899",
441 "time_updated": "1473020899",
443 "time_favorited": "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.",
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('
461 "229279690": ' . $body . '
467 $client->getEmitter()->attach($mock);
469 $pocketImport = $this->getPocketImport();
471 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
472 ->disableOriginalConstructor()
475 $entryRepo->expects($this->never())
476 ->method('findByUrlAndUserId');
479 ->expects($this->never())
480 ->method('getRepository');
482 $entry = new Entry($this->user
);
485 ->expects($this->never())
486 ->method('updateEntry');
488 $factory = new RedisMockFactory();
489 $redisMock = $factory->getAdapter('Predis\Client', true);
491 $queue = new RedisQueue($redisMock, 'pocket');
492 $producer = new Producer($queue);
494 $pocketImport->setClient($client);
495 $pocketImport->setProducer($producer);
496 $pocketImport->authorize('wunderbar_code');
498 $res = $pocketImport->setMarkAsRead(true)->import();
500 $this->assertTrue($res);
501 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
503 $this->assertNotEmpty($redisMock->lpop('pocket'));
506 public function testImportBadResponse()
508 $client = new Client();
511 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
515 $client->getEmitter()->attach($mock);
517 $pocketImport = $this->getPocketImport();
518 $pocketImport->setClient($client);
519 $pocketImport->authorize('wunderbar_code');
521 $res = $pocketImport->import();
523 $this->assertFalse($res);
525 $records = $this->logHandler
->getRecords();
526 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
527 $this->assertSame('ERROR', $records[0]['level_name']);
530 public function testImportWithExceptionFromGraby()
532 $client = new Client();
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('
543 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
550 $client->getEmitter()->attach($mock);
552 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
554 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
555 ->disableOriginalConstructor()
558 $entryRepo->expects($this->once())
559 ->method('findByUrlAndUserId')
560 ->will($this->onConsecutiveCalls(false, true));
563 ->expects($this->once())
564 ->method('getRepository')
565 ->willReturn($entryRepo);
567 $entry = new Entry($this->user
);
570 ->expects($this->once())
571 ->method('updateEntry')
572 ->will($this->throwException(new \
Exception()));
574 $pocketImport->setClient($client);
575 $pocketImport->authorize('wunderbar_code');
577 $res = $pocketImport->import();
579 $this->assertTrue($res);
580 $this->assertSame(['skipped' => 0, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
583 private function getPocketImport($consumerKey = 'ConsumerKey', $dispatched = 0)
585 $this->user
= new User();
587 $config = new Config($this->user
);
588 $config->setPocketConsumerKey('xxx');
590 $this->user
->setConfig($config);
592 $this->contentProxy
= $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
593 ->disableOriginalConstructor()
596 $this->tagsAssigner
= $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
597 ->disableOriginalConstructor()
600 $this->em
= $this->getMockBuilder('Doctrine\ORM\EntityManager')
601 ->disableOriginalConstructor()
604 $this->uow
= $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
605 ->disableOriginalConstructor()
609 ->expects($this->any())
610 ->method('getUnitOfWork')
611 ->willReturn($this->uow
);
614 ->expects($this->any())
615 ->method('getScheduledEntityInsertions')
618 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
619 ->disableOriginalConstructor()
623 ->expects($this->exactly($dispatched))
624 ->method('dispatch');
626 $pocket = new PocketImport($this->em
, $this->contentProxy
, $this->tagsAssigner
, $dispatcher);
627 $pocket->setUser($this->user
);
629 $this->logHandler
= new TestHandler();
630 $logger = new Logger('test', [$this->logHandler
]);
631 $pocket->setLogger($logger);