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;
26 protected $tagsAssigner;
29 private function getPocketImport($consumerKey = 'ConsumerKey', $dispatched = 0)
31 $this->user
= new User();
33 $config = new Config($this->user
);
34 $config->setPocketConsumerKey('xxx');
36 $this->user
->setConfig($config);
38 $this->contentProxy
= $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
39 ->disableOriginalConstructor()
42 $this->tagsAssigner
= $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
43 ->disableOriginalConstructor()
46 $this->em
= $this->getMockBuilder('Doctrine\ORM\EntityManager')
47 ->disableOriginalConstructor()
50 $this->uow
= $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
51 ->disableOriginalConstructor()
55 ->expects($this->any())
56 ->method('getUnitOfWork')
57 ->willReturn($this->uow
);
60 ->expects($this->any())
61 ->method('getScheduledEntityInsertions')
64 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
65 ->disableOriginalConstructor()
69 ->expects($this->exactly($dispatched))
72 $pocket = new PocketImport($this->em
, $this->contentProxy
, $this->tagsAssigner
, $dispatcher);
73 $pocket->setUser($this->user
);
75 $this->logHandler
= new TestHandler();
76 $logger = new Logger('test', [$this->logHandler
]);
77 $pocket->setLogger($logger);
82 public function testInit()
84 $pocketImport = $this->getPocketImport();
86 $this->assertEquals('Pocket', $pocketImport->getName());
87 $this->assertNotEmpty($pocketImport->getUrl());
88 $this->assertEquals('import.pocket.description', $pocketImport->getDescription());
91 public function testOAuthRequest()
93 $client = new Client();
96 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['code' => 'wunderbar_code']))),
99 $client->getEmitter()->attach($mock);
101 $pocketImport = $this->getPocketImport();
102 $pocketImport->setClient($client);
104 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
106 $this->assertEquals('wunderbar_code', $code);
109 public function testOAuthRequestBadResponse()
111 $client = new Client();
117 $client->getEmitter()->attach($mock);
119 $pocketImport = $this->getPocketImport();
120 $pocketImport->setClient($client);
122 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
124 $this->assertFalse($code);
126 $records = $this->logHandler
->getRecords();
127 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']);
128 $this->assertEquals('ERROR', $records[0]['level_name']);
131 public function testOAuthAuthorize()
133 $client = new Client();
136 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
139 $client->getEmitter()->attach($mock);
141 $pocketImport = $this->getPocketImport();
142 $pocketImport->setClient($client);
144 $res = $pocketImport->authorize('wunderbar_code');
146 $this->assertTrue($res);
147 $this->assertEquals('wunderbar_token', $pocketImport->getAccessToken());
150 public function testOAuthAuthorizeBadResponse()
152 $client = new Client();
158 $client->getEmitter()->attach($mock);
160 $pocketImport = $this->getPocketImport();
161 $pocketImport->setClient($client);
163 $res = $pocketImport->authorize('wunderbar_code');
165 $this->assertFalse($res);
167 $records = $this->logHandler
->getRecords();
168 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']);
169 $this->assertEquals('ERROR', $records[0]['level_name']);
173 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
175 public function testImport()
177 $client = new Client();
180 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
181 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
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.",
204 "word_count": "3197",
207 "item_id": "229279689",
209 "src": "http://a.espncdn.com/combiner/i?img=/photo/2012/0927/grant_g_ryder_cr_640.jpg&w=640&h=360",
212 "credit": "Jamie Squire/Getty Images",
218 "item_id": "229279689",
220 "src": "http://www.youtube.com/v/Er34PbFkVGk?version=3&hl=en_US&rel=0",
229 "item_id": "1147652870",
233 "item_id": "1147652870",
239 "item_id": "229279689",
240 "resolved_id": "229279689",
241 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
242 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
245 "time_added": "1473020899",
246 "time_updated": "1473020899",
248 "time_favorited": "0",
250 "resolved_title": "The Massive Ryder Cup Preview",
251 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
252 "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.",
264 $client->getEmitter()->attach($mock);
266 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
268 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
269 ->disableOriginalConstructor()
272 $entryRepo->expects($this->exactly(2))
273 ->method('findByUrlAndUserId')
274 ->will($this->onConsecutiveCalls(false, true));
277 ->expects($this->exactly(2))
278 ->method('getRepository')
279 ->willReturn($entryRepo);
281 $entry = new Entry($this->user
);
284 ->expects($this->once())
285 ->method('updateEntry')
286 ->willReturn($entry);
288 $pocketImport->setClient($client);
289 $pocketImport->authorize('wunderbar_code');
291 $res = $pocketImport->import();
293 $this->assertTrue($res);
294 $this->assertEquals(['skipped' => 1, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
298 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
300 public function testImportAndMarkAllAsRead()
302 $client = new Client();
305 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
306 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
311 "item_id": "229279689",
312 "resolved_id": "229279689",
313 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
314 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
317 "time_added": "1473020899",
318 "time_updated": "1473020899",
320 "time_favorited": "0",
322 "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.",
329 "item_id": "229279689",
330 "resolved_id": "229279689",
331 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview/2",
332 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
335 "time_added": "1473020899",
336 "time_updated": "1473020899",
338 "time_favorited": "0",
340 "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.",
351 $client->getEmitter()->attach($mock);
353 $pocketImport = $this->getPocketImport('ConsumerKey', 2);
355 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
356 ->disableOriginalConstructor()
359 $entryRepo->expects($this->exactly(2))
360 ->method('findByUrlAndUserId')
361 ->will($this->onConsecutiveCalls(false, false));
364 ->expects($this->exactly(2))
365 ->method('getRepository')
366 ->willReturn($entryRepo);
368 // check that every entry persisted are archived
370 ->expects($this->any())
372 ->with($this->callback(function ($persistedEntry) {
373 return $persistedEntry->isArchived();
376 $entry = new Entry($this->user
);
379 ->expects($this->exactly(2))
380 ->method('updateEntry')
381 ->willReturn($entry);
383 $pocketImport->setClient($client);
384 $pocketImport->authorize('wunderbar_code');
386 $res = $pocketImport->setMarkAsRead(true)->import();
388 $this->assertTrue($res);
389 $this->assertEquals(['skipped' => 0, 'imported' => 2, 'queued' => 0], $pocketImport->getSummary());
393 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
395 public function testImportWithRabbit()
397 $client = new Client();
401 "item_id": "229279689",
402 "resolved_id": "229279689",
403 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
404 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
407 "time_added": "1473020899",
408 "time_updated": "1473020899",
410 "time_favorited": "0",
412 "resolved_title": "The Massive Ryder Cup Preview",
413 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
414 "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.",
423 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
424 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
428 "229279690": '.$body.'
434 $client->getEmitter()->attach($mock);
436 $pocketImport = $this->getPocketImport();
438 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
439 ->disableOriginalConstructor()
442 $entryRepo->expects($this->never())
443 ->method('findByUrlAndUserId');
446 ->expects($this->never())
447 ->method('getRepository');
449 $entry = new Entry($this->user
);
452 ->expects($this->never())
453 ->method('updateEntry');
455 $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
456 ->disableOriginalConstructor()
459 $bodyAsArray = json_decode($body, true);
460 // because with just use `new User()` so it doesn't have an id
461 $bodyAsArray['userId'] = null;
464 ->expects($this->once())
466 ->with(json_encode($bodyAsArray));
468 $pocketImport->setClient($client);
469 $pocketImport->setProducer($producer);
470 $pocketImport->authorize('wunderbar_code');
472 $res = $pocketImport->setMarkAsRead(true)->import();
474 $this->assertTrue($res);
475 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
479 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
481 public function testImportWithRedis()
483 $client = new Client();
487 "item_id": "229279689",
488 "resolved_id": "229279689",
489 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
490 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
493 "time_added": "1473020899",
494 "time_updated": "1473020899",
496 "time_favorited": "0",
498 "resolved_title": "The Massive Ryder Cup Preview",
499 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
500 "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.",
509 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
510 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
514 "229279690": '.$body.'
520 $client->getEmitter()->attach($mock);
522 $pocketImport = $this->getPocketImport();
524 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
525 ->disableOriginalConstructor()
528 $entryRepo->expects($this->never())
529 ->method('findByUrlAndUserId');
532 ->expects($this->never())
533 ->method('getRepository');
535 $entry = new Entry($this->user
);
538 ->expects($this->never())
539 ->method('updateEntry');
541 $factory = new RedisMockFactory();
542 $redisMock = $factory->getAdapter('Predis\Client', true);
544 $queue = new RedisQueue($redisMock, 'pocket');
545 $producer = new Producer($queue);
547 $pocketImport->setClient($client);
548 $pocketImport->setProducer($producer);
549 $pocketImport->authorize('wunderbar_code');
551 $res = $pocketImport->setMarkAsRead(true)->import();
553 $this->assertTrue($res);
554 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
556 $this->assertNotEmpty($redisMock->lpop('pocket'));
559 public function testImportBadResponse()
561 $client = new Client();
564 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
568 $client->getEmitter()->attach($mock);
570 $pocketImport = $this->getPocketImport();
571 $pocketImport->setClient($client);
572 $pocketImport->authorize('wunderbar_code');
574 $res = $pocketImport->import();
576 $this->assertFalse($res);
578 $records = $this->logHandler
->getRecords();
579 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
580 $this->assertEquals('ERROR', $records[0]['level_name']);
583 public function testImportWithExceptionFromGraby()
585 $client = new Client();
588 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
589 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
596 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
603 $client->getEmitter()->attach($mock);
605 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
607 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
608 ->disableOriginalConstructor()
611 $entryRepo->expects($this->once())
612 ->method('findByUrlAndUserId')
613 ->will($this->onConsecutiveCalls(false, true));
616 ->expects($this->once())
617 ->method('getRepository')
618 ->willReturn($entryRepo);
620 $entry = new Entry($this->user
);
623 ->expects($this->once())
624 ->method('updateEntry')
625 ->will($this->throwException(new \
Exception()));
627 $pocketImport->setClient($client);
628 $pocketImport->authorize('wunderbar_code');
630 $res = $pocketImport->import();
632 $this->assertTrue($res);
633 $this->assertEquals(['skipped' => 0, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());