]> git.immae.eu Git - github/wallabag/wallabag.git/blame - tests/Wallabag/ImportBundle/Import/PocketImportTest.php
Use httplug
[github/wallabag/wallabag.git] / tests / Wallabag / ImportBundle / Import / PocketImportTest.php
CommitLineData
7ec2897e
JB
1<?php
2
23634d5d 3namespace Tests\Wallabag\ImportBundle\Import;
7ec2897e 4
bf9ace06 5use Http\Mock\Client as HttpMockClient;
6use GuzzleHttp\Psr7\Response;
f808b016 7use M6Web\Component\RedisMock\RedisMockFactory;
252ebd60 8use Monolog\Handler\TestHandler;
f808b016 9use Monolog\Logger;
bd91bd5c 10use PHPUnit\Framework\TestCase;
b3437d58 11use Simpleue\Queue\RedisQueue;
f808b016
JB
12use Wallabag\CoreBundle\Entity\Config;
13use Wallabag\CoreBundle\Entity\Entry;
14use Wallabag\ImportBundle\Import\PocketImport;
15use Wallabag\ImportBundle\Redis\Producer;
16use Wallabag\UserBundle\Entity\User;
252ebd60 17
bd91bd5c 18class PocketImportTest extends TestCase
7ec2897e
JB
19{
20 protected $token;
21 protected $user;
7ec2897e 22 protected $em;
252ebd60
JB
23 protected $contentProxy;
24 protected $logHandler;
6bc6fb1f
TC
25 protected $tagsAssigner;
26 protected $uow;
7ec2897e 27
7ec2897e
JB
28 public function testInit()
29 {
30 $pocketImport = $this->getPocketImport();
31
f808b016 32 $this->assertSame('Pocket', $pocketImport->getName());
7019c7cf 33 $this->assertNotEmpty($pocketImport->getUrl());
f808b016 34 $this->assertSame('import.pocket.description', $pocketImport->getDescription());
7ec2897e
JB
35 }
36
37 public function testOAuthRequest()
38 {
bf9ace06 39 $httpMockClient = new HttpMockClient();
40 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['code' => 'wunderbar_code'])));
7ec2897e
JB
41
42 $pocketImport = $this->getPocketImport();
bf9ace06 43 $pocketImport->setClient($httpMockClient);
7ec2897e 44
252ebd60 45 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
7ec2897e 46
f808b016 47 $this->assertSame('wunderbar_code', $code);
252ebd60
JB
48 }
49
50 public function testOAuthRequestBadResponse()
51 {
bf9ace06 52 $httpMockClient = new HttpMockClient();
53 $httpMockClient->addResponse(new Response(403));
252ebd60
JB
54
55 $pocketImport = $this->getPocketImport();
bf9ace06 56 $pocketImport->setClient($httpMockClient);
252ebd60
JB
57
58 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
59
60 $this->assertFalse($code);
61
62 $records = $this->logHandler->getRecords();
63 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']);
f808b016 64 $this->assertSame('ERROR', $records[0]['level_name']);
7ec2897e
JB
65 }
66
67 public function testOAuthAuthorize()
68 {
bf9ace06 69 $httpMockClient = new HttpMockClient();
70 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['access_token' => 'wunderbar_token'])));
7ec2897e
JB
71
72 $pocketImport = $this->getPocketImport();
bf9ace06 73 $pocketImport->setClient($httpMockClient);
7ec2897e 74
252ebd60 75 $res = $pocketImport->authorize('wunderbar_code');
7ec2897e 76
252ebd60 77 $this->assertTrue($res);
f808b016 78 $this->assertSame('wunderbar_token', $pocketImport->getAccessToken());
7ec2897e
JB
79 }
80
252ebd60
JB
81 public function testOAuthAuthorizeBadResponse()
82 {
bf9ace06 83 $httpMockClient = new HttpMockClient();
84 $httpMockClient->addResponse(new Response(403));
252ebd60
JB
85
86 $pocketImport = $this->getPocketImport();
bf9ace06 87 $pocketImport->setClient($httpMockClient);
252ebd60
JB
88
89 $res = $pocketImport->authorize('wunderbar_code');
90
91 $this->assertFalse($res);
92
93 $records = $this->logHandler->getRecords();
94 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']);
f808b016 95 $this->assertSame('ERROR', $records[0]['level_name']);
252ebd60
JB
96 }
97
98 /**
99 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
100 */
7ec2897e
JB
101 public function testImport()
102 {
bf9ace06 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'
106 {
107 "status": 1,
108 "list": {
109 "229279689": {
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",
114 "favorite": "1",
115 "status": "1",
116 "time_added": "1473020899",
117 "time_updated": "1473020899",
118 "time_read": "0",
119 "time_favorited": "0",
120 "sort_id": 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.",
124 "is_article": "1",
125 "is_index": "0",
126 "has_video": "1",
127 "has_image": "1",
128 "word_count": "3197",
129 "images": {
130 "1": {
131 "item_id": "229279689",
132 "image_id": "1",
133 "src": "http://a.espncdn.com/combiner/i?img=/photo/2012/0927/grant_g_ryder_cr_640.jpg&w=640&h=360",
134 "width": "0",
135 "height": "0",
136 "credit": "Jamie Squire/Getty Images",
137 "caption": ""
252ebd60
JB
138 }
139 },
bf9ace06 140 "videos": {
141 "1": {
142 "item_id": "229279689",
143 "video_id": "1",
144 "src": "http://www.youtube.com/v/Er34PbFkVGk?version=3&hl=en_US&rel=0",
145 "width": "420",
146 "height": "315",
147 "type": "1",
148 "vid": "Er34PbFkVGk"
149 }
150 },
151 "tags": {
152 "grantland": {
153 "item_id": "1147652870",
154 "tag": "grantland"
155 },
156 "Ryder Cup": {
157 "item_id": "1147652870",
158 "tag": "Ryder Cup"
159 }
252ebd60 160 }
bf9ace06 161 },
162 "229279690": {
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",
167 "favorite": "1",
168 "status": "1",
169 "time_added": "1473020899",
170 "time_updated": "1473020899",
171 "time_read": "0",
172 "time_favorited": "0",
173 "sort_id": 1,
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.",
177 "is_article": "1",
178 "is_index": "0",
179 "has_video": "0",
180 "has_image": "0",
181 "word_count": "3197"
252ebd60
JB
182 }
183 }
bf9ace06 184 }
185JSON
186));
252ebd60 187
7816eb62 188 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
252ebd60
JB
189
190 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
191 ->disableOriginalConstructor()
192 ->getMock();
193
194 $entryRepo->expects($this->exactly(2))
78833672 195 ->method('findByUrlAndUserId')
252ebd60
JB
196 ->will($this->onConsecutiveCalls(false, true));
197
252ebd60 198 $this->em
c2656f96 199 ->expects($this->exactly(2))
252ebd60 200 ->method('getRepository')
c2656f96 201 ->willReturn($entryRepo);
252ebd60 202
8d082488
JB
203 $this->em
204 ->expects($this->any())
205 ->method('persist')
206 ->with($this->callback(function ($persistedEntry) {
207 return $persistedEntry->isArchived() && $persistedEntry->isStarred();
208 }));
209
79d0e38e 210 $entry = new Entry($this->user);
252ebd60
JB
211
212 $this->contentProxy
213 ->expects($this->once())
214 ->method('updateEntry')
215 ->willReturn($entry);
216
bf9ace06 217 $pocketImport->setClient($httpMockClient);
252ebd60
JB
218 $pocketImport->authorize('wunderbar_code');
219
220 $res = $pocketImport->import();
221
222 $this->assertTrue($res);
f808b016 223 $this->assertSame(['skipped' => 1, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
252ebd60
JB
224 }
225
79d0e38e
JB
226 /**
227 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
228 */
229 public function testImportAndMarkAllAsRead()
230 {
bf9ace06 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'
234 {
235 "status": 1,
236 "list": {
237 "229279689": {
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",
242 "favorite": "1",
243 "status": "1",
244 "time_added": "1473020899",
245 "time_updated": "1473020899",
246 "time_read": "0",
247 "time_favorited": "0",
248 "sort_id": 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.",
250 "is_article": "1",
251 "has_video": "1",
252 "has_image": "1",
253 "word_count": "3197"
254 },
255 "229279690": {
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",
260 "favorite": "1",
261 "status": "0",
262 "time_added": "1473020899",
263 "time_updated": "1473020899",
264 "time_read": "0",
265 "time_favorited": "0",
266 "sort_id": 1,
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.",
268 "is_article": "1",
269 "has_video": "0",
270 "has_image": "0",
271 "word_count": "3197"
79d0e38e
JB
272 }
273 }
bf9ace06 274 }
275JSON
276));
79d0e38e 277
7816eb62 278 $pocketImport = $this->getPocketImport('ConsumerKey', 2);
79d0e38e
JB
279
280 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
281 ->disableOriginalConstructor()
282 ->getMock();
283
284 $entryRepo->expects($this->exactly(2))
285 ->method('findByUrlAndUserId')
286 ->will($this->onConsecutiveCalls(false, false));
287
288 $this->em
289 ->expects($this->exactly(2))
290 ->method('getRepository')
291 ->willReturn($entryRepo);
292
293 // check that every entry persisted are archived
294 $this->em
295 ->expects($this->any())
296 ->method('persist')
cebb4223 297 ->with($this->callback(function ($persistedEntry) {
79d0e38e
JB
298 return $persistedEntry->isArchived();
299 }));
300
301 $entry = new Entry($this->user);
302
303 $this->contentProxy
304 ->expects($this->exactly(2))
305 ->method('updateEntry')
306 ->willReturn($entry);
307
bf9ace06 308 $pocketImport->setClient($httpMockClient);
79d0e38e
JB
309 $pocketImport->authorize('wunderbar_code');
310
311 $res = $pocketImport->setMarkAsRead(true)->import();
312
313 $this->assertTrue($res);
f808b016 314 $this->assertSame(['skipped' => 0, 'imported' => 2, 'queued' => 0], $pocketImport->getSummary());
79d0e38e
JB
315 }
316
13470c35
JB
317 /**
318 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
319 */
320 public function testImportWithRabbit()
321 {
bf9ace06 322 $httpMockClient = new HttpMockClient();
13470c35
JB
323
324 $body = <<<'JSON'
325{
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",
330 "favorite": "1",
331 "status": "1",
7f753117
JB
332 "time_added": "1473020899",
333 "time_updated": "1473020899",
334 "time_read": "0",
335 "time_favorited": "0",
336 "sort_id": 0,
13470c35
JB
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.",
340 "is_article": "1",
341 "has_video": "0",
342 "has_image": "0",
343 "word_count": "3197"
344}
345JSON;
346
bf9ace06 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
349 {
350 "status": 1,
351 "list": {
352 "229279690": $body
13470c35 353 }
bf9ace06 354 }
355JSON
356 ));
13470c35
JB
357
358 $pocketImport = $this->getPocketImport();
359
360 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
361 ->disableOriginalConstructor()
362 ->getMock();
363
364 $entryRepo->expects($this->never())
365 ->method('findByUrlAndUserId');
366
367 $this->em
368 ->expects($this->never())
369 ->method('getRepository');
370
371 $entry = new Entry($this->user);
372
373 $this->contentProxy
374 ->expects($this->never())
375 ->method('updateEntry');
376
377 $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
378 ->disableOriginalConstructor()
379 ->getMock();
380
381 $bodyAsArray = json_decode($body, true);
382 // because with just use `new User()` so it doesn't have an id
383 $bodyAsArray['userId'] = null;
384
385 $producer
386 ->expects($this->once())
387 ->method('publish')
388 ->with(json_encode($bodyAsArray));
389
bf9ace06 390 $pocketImport->setClient($httpMockClient);
b3437d58 391 $pocketImport->setProducer($producer);
13470c35
JB
392 $pocketImport->authorize('wunderbar_code');
393
394 $res = $pocketImport->setMarkAsRead(true)->import();
395
396 $this->assertTrue($res);
f808b016 397 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
13470c35
JB
398 }
399
b3437d58
JB
400 /**
401 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
402 */
403 public function testImportWithRedis()
404 {
bf9ace06 405 $httpMockClient = new HttpMockClient();
b3437d58
JB
406
407 $body = <<<'JSON'
408{
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",
413 "favorite": "1",
414 "status": "1",
415 "time_added": "1473020899",
416 "time_updated": "1473020899",
417 "time_read": "0",
418 "time_favorited": "0",
419 "sort_id": 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.",
423 "is_article": "1",
424 "has_video": "0",
425 "has_image": "0",
426 "word_count": "3197"
427}
428JSON;
429
bf9ace06 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
432 {
433 "status": 1,
434 "list": {
435 "229279690": $body
b3437d58 436 }
bf9ace06 437 }
438JSON
439 ));
b3437d58
JB
440
441 $pocketImport = $this->getPocketImport();
442
443 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
444 ->disableOriginalConstructor()
445 ->getMock();
446
447 $entryRepo->expects($this->never())
448 ->method('findByUrlAndUserId');
449
450 $this->em
451 ->expects($this->never())
452 ->method('getRepository');
453
454 $entry = new Entry($this->user);
455
456 $this->contentProxy
457 ->expects($this->never())
458 ->method('updateEntry');
459
460 $factory = new RedisMockFactory();
461 $redisMock = $factory->getAdapter('Predis\Client', true);
462
463 $queue = new RedisQueue($redisMock, 'pocket');
464 $producer = new Producer($queue);
465
bf9ace06 466 $pocketImport->setClient($httpMockClient);
b3437d58
JB
467 $pocketImport->setProducer($producer);
468 $pocketImport->authorize('wunderbar_code');
469
470 $res = $pocketImport->setMarkAsRead(true)->import();
471
472 $this->assertTrue($res);
f808b016 473 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
b3437d58
JB
474
475 $this->assertNotEmpty($redisMock->lpop('pocket'));
476 }
477
252ebd60
JB
478 public function testImportBadResponse()
479 {
bf9ace06 480 $httpMockClient = new HttpMockClient();
252ebd60 481
bf9ace06 482 $httpMockClient->addResponse(new Response(200, ['Content-Type' => 'application/json'], json_encode(['access_token' => 'wunderbar_token'])));
483 $httpMockClient->addResponse(new Response(403));
7ec2897e
JB
484
485 $pocketImport = $this->getPocketImport();
bf9ace06 486 $pocketImport->setClient($httpMockClient);
252ebd60
JB
487 $pocketImport->authorize('wunderbar_code');
488
489 $res = $pocketImport->import();
7ec2897e 490
252ebd60 491 $this->assertFalse($res);
7ec2897e 492
252ebd60
JB
493 $records = $this->logHandler->getRecords();
494 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
f808b016 495 $this->assertSame('ERROR', $records[0]['level_name']);
7ec2897e 496 }
19d9efab
JB
497
498 public function testImportWithExceptionFromGraby()
499 {
bf9ace06 500 $httpMockClient = new HttpMockClient();
501
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'
504 {
505 "status": 1,
506 "list": {
507 "229279689": {
508 "status": "1",
509 "favorite": "1",
510 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
19d9efab
JB
511 }
512 }
bf9ace06 513 }
514
515JSON
516 ));
19d9efab 517
7816eb62 518 $pocketImport = $this->getPocketImport('ConsumerKey', 1);
19d9efab
JB
519
520 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
521 ->disableOriginalConstructor()
522 ->getMock();
523
524 $entryRepo->expects($this->once())
525 ->method('findByUrlAndUserId')
526 ->will($this->onConsecutiveCalls(false, true));
527
528 $this->em
529 ->expects($this->once())
530 ->method('getRepository')
531 ->willReturn($entryRepo);
532
533 $entry = new Entry($this->user);
534
535 $this->contentProxy
536 ->expects($this->once())
537 ->method('updateEntry')
538 ->will($this->throwException(new \Exception()));
539
bf9ace06 540 $pocketImport->setClient($httpMockClient);
19d9efab
JB
541 $pocketImport->authorize('wunderbar_code');
542
543 $res = $pocketImport->import();
544
545 $this->assertTrue($res);
f808b016
JB
546 $this->assertSame(['skipped' => 0, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
547 }
548
549 private function getPocketImport($consumerKey = 'ConsumerKey', $dispatched = 0)
550 {
551 $this->user = new User();
552
553 $config = new Config($this->user);
554 $config->setPocketConsumerKey('xxx');
555
556 $this->user->setConfig($config);
557
558 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
559 ->disableOriginalConstructor()
560 ->getMock();
561
562 $this->tagsAssigner = $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
563 ->disableOriginalConstructor()
564 ->getMock();
565
566 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
567 ->disableOriginalConstructor()
568 ->getMock();
569
570 $this->uow = $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
571 ->disableOriginalConstructor()
572 ->getMock();
573
574 $this->em
575 ->expects($this->any())
576 ->method('getUnitOfWork')
577 ->willReturn($this->uow);
578
579 $this->uow
580 ->expects($this->any())
581 ->method('getScheduledEntityInsertions')
582 ->willReturn([]);
583
584 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
585 ->disableOriginalConstructor()
586 ->getMock();
587
588 $dispatcher
589 ->expects($this->exactly($dispatched))
590 ->method('dispatch');
591
592 $pocket = new PocketImport($this->em, $this->contentProxy, $this->tagsAssigner, $dispatcher);
593 $pocket->setUser($this->user);
594
595 $this->logHandler = new TestHandler();
596 $logger = new Logger('test', [$this->logHandler]);
597 $pocket->setLogger($logger);
598
599 return $pocket;
19d9efab 600 }
7ec2897e 601}