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 PHPUnit\Framework\TestCase
;
13 use Simpleue\Queue\RedisQueue
;
14 use Wallabag\CoreBundle\Entity\Config
;
15 use Wallabag\CoreBundle\Entity\Entry
;
16 use Wallabag\ImportBundle\Import\PocketImport
;
17 use Wallabag\ImportBundle\Redis\Producer
;
18 use Wallabag\UserBundle\Entity\User
;
20 class PocketImportTest
extends TestCase
25 protected $contentProxy;
26 protected $logHandler;
27 protected $tagsAssigner;
30 public function testInit()
32 $pocketImport = $this->getPocketImport();
34 $this->assertSame('Pocket', $pocketImport->getName());
35 $this->assertNotEmpty($pocketImport->getUrl());
36 $this->assertSame('import.pocket.description', $pocketImport->getDescription());
39 public function testOAuthRequest()
41 $client = new Client();
44 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['code' => 'wunderbar_code']))),
47 $client->getEmitter()->attach($mock);
49 $pocketImport = $this->getPocketImport();
50 $pocketImport->setClient($client);
52 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
54 $this->assertSame('wunderbar_code', $code);
57 public function testOAuthRequestBadResponse()
59 $client = new Client();
65 $client->getEmitter()->attach($mock);
67 $pocketImport = $this->getPocketImport();
68 $pocketImport->setClient($client);
70 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
72 $this->assertFalse($code);
74 $records = $this->logHandler
->getRecords();
75 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']);
76 $this->assertSame('ERROR', $records[0]['level_name']);
79 public function testOAuthAuthorize()
81 $client = new Client();
84 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
87 $client->getEmitter()->attach($mock);
89 $pocketImport = $this->getPocketImport();
90 $pocketImport->setClient($client);
92 $res = $pocketImport->authorize('wunderbar_code');
94 $this->assertTrue($res);
95 $this->assertSame('wunderbar_token', $pocketImport->getAccessToken());
98 public function testOAuthAuthorizeBadResponse()
100 $client = new Client();
106 $client->getEmitter()->attach($mock);
108 $pocketImport = $this->getPocketImport();
109 $pocketImport->setClient($client);
111 $res = $pocketImport->authorize('wunderbar_code');
113 $this->assertFalse($res);
115 $records = $this->logHandler
->getRecords();
116 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']);
117 $this->assertSame('ERROR', $records[0]['level_name']);
121 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
123 public function testImport()
125 $client = new Client();
128 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
129 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
134 "item_id": "229279689",
135 "resolved_id": "229279689",
136 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
137 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
140 "time_added": "1473020899",
141 "time_updated": "1473020899",
143 "time_favorited": "0",
145 "resolved_title": "The Massive Ryder Cup Preview",
146 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
147 "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.",
152 "word_count": "3197",
155 "item_id": "229279689",
157 "src": "http://a.espncdn.com/combiner/i?img=/photo/2012/0927/grant_g_ryder_cr_640.jpg&w=640&h=360",
160 "credit": "Jamie Squire/Getty Images",
166 "item_id": "229279689",
168 "src": "http://www.youtube.com/v/Er34PbFkVGk?version=3&hl=en_US&rel=0",
177 "item_id": "1147652870",
181 "item_id": "1147652870",
187 "item_id": "229279689",
188 "resolved_id": "229279689",
189 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
190 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
193 "time_added": "1473020899",
194 "time_updated": "1473020899",
196 "time_favorited": "0",
198 "resolved_title": "The Massive Ryder Cup Preview",
199 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
200 "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.",
212 $client->getEmitter()->attach($mock);
214 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
216 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
217 ->disableOriginalConstructor()
220 $entryRepo->expects($this->exactly(2))
221 ->method('findByUrlAndUserId')
222 ->will($this->onConsecutiveCalls(false, true));
225 ->expects($this->exactly(2))
226 ->method('getRepository')
227 ->willReturn($entryRepo);
229 $entry = new Entry($this->user
);
232 ->expects($this->once())
233 ->method('updateEntry')
234 ->willReturn($entry);
236 $pocketImport->setClient($client);
237 $pocketImport->authorize('wunderbar_code');
239 $res = $pocketImport->import();
241 $this->assertTrue($res);
242 $this->assertSame(['skipped' => 1, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
246 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
248 public function testImportAndMarkAllAsRead()
250 $client = new Client();
253 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
254 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
259 "item_id": "229279689",
260 "resolved_id": "229279689",
261 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
262 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
265 "time_added": "1473020899",
266 "time_updated": "1473020899",
268 "time_favorited": "0",
270 "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.",
277 "item_id": "229279689",
278 "resolved_id": "229279689",
279 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview/2",
280 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
283 "time_added": "1473020899",
284 "time_updated": "1473020899",
286 "time_favorited": "0",
288 "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.",
299 $client->getEmitter()->attach($mock);
301 $pocketImport = $this->getPocketImport('ConsumerKey', 2);
303 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
304 ->disableOriginalConstructor()
307 $entryRepo->expects($this->exactly(2))
308 ->method('findByUrlAndUserId')
309 ->will($this->onConsecutiveCalls(false, false));
312 ->expects($this->exactly(2))
313 ->method('getRepository')
314 ->willReturn($entryRepo);
316 // check that every entry persisted are archived
318 ->expects($this->any())
320 ->with($this->callback(function ($persistedEntry) {
321 return $persistedEntry->isArchived();
324 $entry = new Entry($this->user
);
327 ->expects($this->exactly(2))
328 ->method('updateEntry')
329 ->willReturn($entry);
331 $pocketImport->setClient($client);
332 $pocketImport->authorize('wunderbar_code');
334 $res = $pocketImport->setMarkAsRead(true)->import();
336 $this->assertTrue($res);
337 $this->assertSame(['skipped' => 0, 'imported' => 2, 'queued' => 0], $pocketImport->getSummary());
341 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
343 public function testImportWithRabbit()
345 $client = new Client();
349 "item_id": "229279689",
350 "resolved_id": "229279689",
351 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
352 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
355 "time_added": "1473020899",
356 "time_updated": "1473020899",
358 "time_favorited": "0",
360 "resolved_title": "The Massive Ryder Cup Preview",
361 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
362 "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.",
371 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
372 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
376 "229279690": ' . $body . '
382 $client->getEmitter()->attach($mock);
384 $pocketImport = $this->getPocketImport();
386 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
387 ->disableOriginalConstructor()
390 $entryRepo->expects($this->never())
391 ->method('findByUrlAndUserId');
394 ->expects($this->never())
395 ->method('getRepository');
397 $entry = new Entry($this->user
);
400 ->expects($this->never())
401 ->method('updateEntry');
403 $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
404 ->disableOriginalConstructor()
407 $bodyAsArray = json_decode($body, true);
408 // because with just use `new User()` so it doesn't have an id
409 $bodyAsArray['userId'] = null;
412 ->expects($this->once())
414 ->with(json_encode($bodyAsArray));
416 $pocketImport->setClient($client);
417 $pocketImport->setProducer($producer);
418 $pocketImport->authorize('wunderbar_code');
420 $res = $pocketImport->setMarkAsRead(true)->import();
422 $this->assertTrue($res);
423 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
427 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
429 public function testImportWithRedis()
431 $client = new Client();
435 "item_id": "229279689",
436 "resolved_id": "229279689",
437 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
438 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
441 "time_added": "1473020899",
442 "time_updated": "1473020899",
444 "time_favorited": "0",
446 "resolved_title": "The Massive Ryder Cup Preview",
447 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
448 "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.",
457 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
458 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
462 "229279690": ' . $body . '
468 $client->getEmitter()->attach($mock);
470 $pocketImport = $this->getPocketImport();
472 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
473 ->disableOriginalConstructor()
476 $entryRepo->expects($this->never())
477 ->method('findByUrlAndUserId');
480 ->expects($this->never())
481 ->method('getRepository');
483 $entry = new Entry($this->user
);
486 ->expects($this->never())
487 ->method('updateEntry');
489 $factory = new RedisMockFactory();
490 $redisMock = $factory->getAdapter('Predis\Client', true);
492 $queue = new RedisQueue($redisMock, 'pocket');
493 $producer = new Producer($queue);
495 $pocketImport->setClient($client);
496 $pocketImport->setProducer($producer);
497 $pocketImport->authorize('wunderbar_code');
499 $res = $pocketImport->setMarkAsRead(true)->import();
501 $this->assertTrue($res);
502 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
504 $this->assertNotEmpty($redisMock->lpop('pocket'));
507 public function testImportBadResponse()
509 $client = new Client();
512 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
516 $client->getEmitter()->attach($mock);
518 $pocketImport = $this->getPocketImport();
519 $pocketImport->setClient($client);
520 $pocketImport->authorize('wunderbar_code');
522 $res = $pocketImport->import();
524 $this->assertFalse($res);
526 $records = $this->logHandler
->getRecords();
527 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
528 $this->assertSame('ERROR', $records[0]['level_name']);
531 public function testImportWithExceptionFromGraby()
533 $client = new Client();
536 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory(json_encode(['access_token' => 'wunderbar_token']))),
537 new Response(200, ['Content-Type' => 'application/json'], Stream
::factory('
544 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
551 $client->getEmitter()->attach($mock);
553 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
555 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
556 ->disableOriginalConstructor()
559 $entryRepo->expects($this->once())
560 ->method('findByUrlAndUserId')
561 ->will($this->onConsecutiveCalls(false, true));
564 ->expects($this->once())
565 ->method('getRepository')
566 ->willReturn($entryRepo);
568 $entry = new Entry($this->user
);
571 ->expects($this->once())
572 ->method('updateEntry')
573 ->will($this->throwException(new \
Exception()));
575 $pocketImport->setClient($client);
576 $pocketImport->authorize('wunderbar_code');
578 $res = $pocketImport->import();
580 $this->assertTrue($res);
581 $this->assertSame(['skipped' => 0, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
584 private function getPocketImport($consumerKey = 'ConsumerKey', $dispatched = 0)
586 $this->user
= new User();
588 $config = new Config($this->user
);
589 $config->setPocketConsumerKey('xxx');
591 $this->user
->setConfig($config);
593 $this->contentProxy
= $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
594 ->disableOriginalConstructor()
597 $this->tagsAssigner
= $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
598 ->disableOriginalConstructor()
601 $this->em
= $this->getMockBuilder('Doctrine\ORM\EntityManager')
602 ->disableOriginalConstructor()
605 $this->uow
= $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
606 ->disableOriginalConstructor()
610 ->expects($this->any())
611 ->method('getUnitOfWork')
612 ->willReturn($this->uow
);
615 ->expects($this->any())
616 ->method('getScheduledEntityInsertions')
619 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
620 ->disableOriginalConstructor()
624 ->expects($this->exactly($dispatched))
625 ->method('dispatch');
627 $pocket = new PocketImport($this->em
, $this->contentProxy
, $this->tagsAssigner
, $dispatcher);
628 $pocket->setUser($this->user
);
630 $this->logHandler
= new TestHandler();
631 $logger = new Logger('test', [$this->logHandler
]);
632 $pocket->setLogger($logger);