3 namespace Tests\Wallabag\ImportBundle\Import
;
5 use GuzzleHttp\Psr7\Response
;
6 use Http\Mock\Client
as HttpMockClient
;
7 use M6Web\Component\RedisMock\RedisMockFactory
;
8 use Monolog\Handler\TestHandler
;
10 use PHPUnit\Framework\TestCase
;
11 use Simpleue\Queue\RedisQueue
;
12 use Wallabag\CoreBundle\Entity\Config
;
13 use Wallabag\CoreBundle\Entity\Entry
;
14 use Wallabag\ImportBundle\Import\PocketImport
;
15 use Wallabag\ImportBundle\Redis\Producer
;
16 use Wallabag\UserBundle\Entity\User
;
18 class PocketImportTest
extends TestCase
23 protected $contentProxy;
24 protected $logHandler;
25 protected $tagsAssigner;
28 public function testInit()
30 $pocketImport = $this->getPocketImport();
32 $this->assertSame('Pocket', $pocketImport->getName());
33 $this->assertNotEmpty($pocketImport->getUrl());
34 $this->assertSame('import.pocket.description', $pocketImport->getDescription());
37 public function testOAuthRequest()
39 $httpMockClient = new HttpMockClient();
40 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['code' => 'wunderbar_code'])));
42 $pocketImport = $this->getPocketImport();
43 $pocketImport->setClient($httpMockClient);
45 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
47 $this->assertSame('wunderbar_code', $code);
50 public function testOAuthRequestBadResponse()
52 $httpMockClient = new HttpMockClient();
53 $httpMockClient->addResponse(new Response(403));
55 $pocketImport = $this->getPocketImport();
56 $pocketImport->setClient($httpMockClient);
58 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
60 $this->assertFalse($code);
62 $records = $this->logHandler
->getRecords();
63 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']);
64 $this->assertSame('ERROR', $records[0]['level_name']);
67 public function testOAuthAuthorize()
69 $httpMockClient = new HttpMockClient();
70 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['access_token' => 'wunderbar_token'])));
72 $pocketImport = $this->getPocketImport();
73 $pocketImport->setClient($httpMockClient);
75 $res = $pocketImport->authorize('wunderbar_code');
77 $this->assertTrue($res);
78 $this->assertSame('wunderbar_token', $pocketImport->getAccessToken());
81 public function testOAuthAuthorizeBadResponse()
83 $httpMockClient = new HttpMockClient();
84 $httpMockClient->addResponse(new Response(403));
86 $pocketImport = $this->getPocketImport();
87 $pocketImport->setClient($httpMockClient);
89 $res = $pocketImport->authorize('wunderbar_code');
91 $this->assertFalse($res);
93 $records = $this->logHandler
->getRecords();
94 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']);
95 $this->assertSame('ERROR', $records[0]['level_name']);
99 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
101 public function testImport()
103 $httpMockClient = new HttpMockClient();
104 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['access_token' => 'wunderbar_token'])));
105 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], <<<'JSON'
110 "item_id": "229279689",
111 "resolved_id": "229279689",
112 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
113 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
116 "time_added": "1473020899",
117 "time_updated": "1473020899",
119 "time_favorited": "0",
121 "resolved_title": "The Massive Ryder Cup Preview",
122 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
123 "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.",
128 "word_count": "3197",
131 "item_id": "229279689",
133 "src": "http://a.espncdn.com/combiner/i?img=/photo/2012/0927/grant_g_ryder_cr_640.jpg&w=640&h=360",
136 "credit": "Jamie Squire/Getty Images",
142 "item_id": "229279689",
144 "src": "http://www.youtube.com/v/Er34PbFkVGk?version=3&hl=en_US&rel=0",
153 "item_id": "1147652870",
157 "item_id": "1147652870",
163 "item_id": "229279689",
164 "resolved_id": "229279689",
165 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
166 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
169 "time_added": "1473020899",
170 "time_updated": "1473020899",
172 "time_favorited": "0",
174 "resolved_title": "The Massive Ryder Cup Preview",
175 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
176 "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.",
188 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
190 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
191 ->disableOriginalConstructor()
194 $entryRepo->expects($this->exactly(2))
195 ->method('findByUrlAndUserId')
196 ->will($this->onConsecutiveCalls(false, true));
199 ->expects($this->exactly(2))
200 ->method('getRepository')
201 ->willReturn($entryRepo);
204 ->expects($this->any())
206 ->with($this->callback(function ($persistedEntry) {
207 return $persistedEntry->isArchived() && $persistedEntry->isStarred();
210 $entry = new Entry($this->user
);
213 ->expects($this->once())
214 ->method('updateEntry')
215 ->willReturn($entry);
217 $pocketImport->setClient($httpMockClient);
218 $pocketImport->authorize('wunderbar_code');
220 $res = $pocketImport->import();
222 $this->assertTrue($res);
223 $this->assertSame(['skipped' => 1, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
227 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
229 public function testImportAndMarkAllAsRead()
231 $httpMockClient = new HttpMockClient();
232 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['access_token' => 'wunderbar_token'])));
233 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], <<<'JSON'
238 "item_id": "229279689",
239 "resolved_id": "229279689",
240 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
241 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
244 "time_added": "1473020899",
245 "time_updated": "1473020899",
247 "time_favorited": "0",
249 "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.",
256 "item_id": "229279689",
257 "resolved_id": "229279689",
258 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview/2",
259 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
262 "time_added": "1473020899",
263 "time_updated": "1473020899",
265 "time_favorited": "0",
267 "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.",
278 $pocketImport = $this->getPocketImport('ConsumerKey', 2);
280 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
281 ->disableOriginalConstructor()
284 $entryRepo->expects($this->exactly(2))
285 ->method('findByUrlAndUserId')
286 ->will($this->onConsecutiveCalls(false, false));
289 ->expects($this->exactly(2))
290 ->method('getRepository')
291 ->willReturn($entryRepo);
293 // check that every entry persisted are archived
295 ->expects($this->any())
297 ->with($this->callback(function ($persistedEntry) {
298 return $persistedEntry->isArchived();
301 $entry = new Entry($this->user
);
304 ->expects($this->exactly(2))
305 ->method('updateEntry')
306 ->willReturn($entry);
308 $pocketImport->setClient($httpMockClient);
309 $pocketImport->authorize('wunderbar_code');
311 $res = $pocketImport->setMarkAsRead(true)->import();
313 $this->assertTrue($res);
314 $this->assertSame(['skipped' => 0, 'imported' => 2, 'queued' => 0], $pocketImport->getSummary());
318 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
320 public function testImportWithRabbit()
322 $httpMockClient = new HttpMockClient();
326 "item_id": "229279689",
327 "resolved_id": "229279689",
328 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
329 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
332 "time_added": "1473020899",
333 "time_updated": "1473020899",
335 "time_favorited": "0",
337 "resolved_title": "The Massive Ryder Cup Preview",
338 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
339 "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.",
347 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['access_token' => 'wunderbar_token'])));
348 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], <<<JSON
358 $pocketImport = $this->getPocketImport();
360 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
361 ->disableOriginalConstructor()
364 $entryRepo->expects($this->never())
365 ->method('findByUrlAndUserId');
368 ->expects($this->never())
369 ->method('getRepository');
371 $entry = new Entry($this->user
);
374 ->expects($this->never())
375 ->method('updateEntry');
377 $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
378 ->disableOriginalConstructor()
381 $bodyAsArray = json_decode($body, true);
382 // because with just use `new User()` so it doesn't have an id
383 $bodyAsArray['userId'] = null;
386 ->expects($this->once())
388 ->with(json_encode($bodyAsArray));
390 $pocketImport->setClient($httpMockClient);
391 $pocketImport->setProducer($producer);
392 $pocketImport->authorize('wunderbar_code');
394 $res = $pocketImport->setMarkAsRead(true)->import();
396 $this->assertTrue($res);
397 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
401 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
403 public function testImportWithRedis()
405 $httpMockClient = new HttpMockClient();
409 "item_id": "229279689",
410 "resolved_id": "229279689",
411 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
412 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
415 "time_added": "1473020899",
416 "time_updated": "1473020899",
418 "time_favorited": "0",
420 "resolved_title": "The Massive Ryder Cup Preview",
421 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
422 "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.",
430 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['access_token' => 'wunderbar_token'])));
431 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], <<<JSON
441 $pocketImport = $this->getPocketImport();
443 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
444 ->disableOriginalConstructor()
447 $entryRepo->expects($this->never())
448 ->method('findByUrlAndUserId');
451 ->expects($this->never())
452 ->method('getRepository');
454 $entry = new Entry($this->user
);
457 ->expects($this->never())
458 ->method('updateEntry');
460 $factory = new RedisMockFactory();
461 $redisMock = $factory->getAdapter('Predis\Client', true);
463 $queue = new RedisQueue($redisMock, 'pocket');
464 $producer = new Producer($queue);
466 $pocketImport->setClient($httpMockClient);
467 $pocketImport->setProducer($producer);
468 $pocketImport->authorize('wunderbar_code');
470 $res = $pocketImport->setMarkAsRead(true)->import();
472 $this->assertTrue($res);
473 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
475 $this->assertNotEmpty($redisMock->lpop('pocket'));
478 public function testImportBadResponse()
480 $httpMockClient = new HttpMockClient();
482 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['access_token' => 'wunderbar_token'])));
483 $httpMockClient->addResponse(new Response(403));
485 $pocketImport = $this->getPocketImport();
486 $pocketImport->setClient($httpMockClient);
487 $pocketImport->authorize('wunderbar_code');
489 $res = $pocketImport->import();
491 $this->assertFalse($res);
493 $records = $this->logHandler
->getRecords();
494 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
495 $this->assertSame('ERROR', $records[0]['level_name']);
498 public function testImportWithExceptionFromGraby()
500 $httpMockClient = new HttpMockClient();
502 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['access_token' => 'wunderbar_token'])));
503 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], <<<'JSON'
510 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
518 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
520 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
521 ->disableOriginalConstructor()
524 $entryRepo->expects($this->once())
525 ->method('findByUrlAndUserId')
526 ->will($this->onConsecutiveCalls(false, true));
529 ->expects($this->once())
530 ->method('getRepository')
531 ->willReturn($entryRepo);
533 $entry = new Entry($this->user
);
536 ->expects($this->once())
537 ->method('updateEntry')
538 ->will($this->throwException(new \
Exception()));
540 $pocketImport->setClient($httpMockClient);
541 $pocketImport->authorize('wunderbar_code');
543 $res = $pocketImport->import();
545 $this->assertTrue($res);
546 $this->assertSame(['skipped' => 0, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
549 private function getPocketImport($consumerKey = 'ConsumerKey', $dispatched = 0)
551 $this->user
= new User();
553 $config = new Config($this->user
);
554 $config->setPocketConsumerKey('xxx');
556 $this->user
->setConfig($config);
558 $this->contentProxy
= $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
559 ->disableOriginalConstructor()
562 $this->tagsAssigner
= $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
563 ->disableOriginalConstructor()
566 $this->em
= $this->getMockBuilder('Doctrine\ORM\EntityManager')
567 ->disableOriginalConstructor()
570 $this->uow
= $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
571 ->disableOriginalConstructor()
575 ->expects($this->any())
576 ->method('getUnitOfWork')
577 ->willReturn($this->uow
);
580 ->expects($this->any())
581 ->method('getScheduledEntityInsertions')
584 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
585 ->disableOriginalConstructor()
589 ->expects($this->exactly($dispatched))
590 ->method('dispatch');
592 $pocket = new PocketImport($this->em
, $this->contentProxy
, $this->tagsAssigner
, $dispatcher);
593 $pocket->setUser($this->user
);
595 $this->logHandler
= new TestHandler();
596 $logger = new Logger('test', [$this->logHandler
]);
597 $pocket->setLogger($logger);