]> git.immae.eu Git - github/wallabag/wallabag.git/blob - tests/Wallabag/ImportBundle/Import/PocketImportTest.php
Retrieve created date from Pocket
[github/wallabag/wallabag.git] / tests / Wallabag / ImportBundle / Import / PocketImportTest.php
1 <?php
2
3 namespace Tests\Wallabag\ImportBundle\Import;
4
5 use Wallabag\UserBundle\Entity\User;
6 use Wallabag\CoreBundle\Entity\Entry;
7 use Wallabag\ImportBundle\Import\PocketImport;
8 use GuzzleHttp\Client;
9 use GuzzleHttp\Subscriber\Mock;
10 use GuzzleHttp\Message\Response;
11 use GuzzleHttp\Stream\Stream;
12 use Monolog\Logger;
13 use Monolog\Handler\TestHandler;
14
15 class PocketImportTest extends \PHPUnit_Framework_TestCase
16 {
17 protected $token;
18 protected $user;
19 protected $em;
20 protected $contentProxy;
21 protected $logHandler;
22
23 private function getPocketImport($consumerKey = 'ConsumerKey')
24 {
25 $this->user = new User();
26
27 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
28 ->disableOriginalConstructor()
29 ->getMock();
30
31 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
32 ->disableOriginalConstructor()
33 ->getMock();
34
35 $config = $this->getMockBuilder('Craue\ConfigBundle\Util\Config')
36 ->disableOriginalConstructor()
37 ->getMock();
38
39 $config->expects($this->any())
40 ->method('get')
41 ->with('pocket_consumer_key')
42 ->willReturn($consumerKey);
43
44 $pocket = new PocketImport(
45 $this->em,
46 $this->contentProxy,
47 $config
48 );
49 $pocket->setUser($this->user);
50
51 $this->logHandler = new TestHandler();
52 $logger = new Logger('test', [$this->logHandler]);
53 $pocket->setLogger($logger);
54
55 return $pocket;
56 }
57
58 public function testInit()
59 {
60 $pocketImport = $this->getPocketImport();
61
62 $this->assertEquals('Pocket', $pocketImport->getName());
63 $this->assertNotEmpty($pocketImport->getUrl());
64 $this->assertEquals('import.pocket.description', $pocketImport->getDescription());
65 }
66
67 public function testOAuthRequest()
68 {
69 $client = new Client();
70
71 $mock = new Mock([
72 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['code' => 'wunderbar_code']))),
73 ]);
74
75 $client->getEmitter()->attach($mock);
76
77 $pocketImport = $this->getPocketImport();
78 $pocketImport->setClient($client);
79
80 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
81
82 $this->assertEquals('wunderbar_code', $code);
83 }
84
85 public function testOAuthRequestBadResponse()
86 {
87 $client = new Client();
88
89 $mock = new Mock([
90 new Response(403),
91 ]);
92
93 $client->getEmitter()->attach($mock);
94
95 $pocketImport = $this->getPocketImport();
96 $pocketImport->setClient($client);
97
98 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
99
100 $this->assertFalse($code);
101
102 $records = $this->logHandler->getRecords();
103 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']);
104 $this->assertEquals('ERROR', $records[0]['level_name']);
105 }
106
107 public function testOAuthAuthorize()
108 {
109 $client = new Client();
110
111 $mock = new Mock([
112 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
113 ]);
114
115 $client->getEmitter()->attach($mock);
116
117 $pocketImport = $this->getPocketImport();
118 $pocketImport->setClient($client);
119
120 $res = $pocketImport->authorize('wunderbar_code');
121
122 $this->assertTrue($res);
123 $this->assertEquals('wunderbar_token', $pocketImport->getAccessToken());
124 }
125
126 public function testOAuthAuthorizeBadResponse()
127 {
128 $client = new Client();
129
130 $mock = new Mock([
131 new Response(403),
132 ]);
133
134 $client->getEmitter()->attach($mock);
135
136 $pocketImport = $this->getPocketImport();
137 $pocketImport->setClient($client);
138
139 $res = $pocketImport->authorize('wunderbar_code');
140
141 $this->assertFalse($res);
142
143 $records = $this->logHandler->getRecords();
144 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']);
145 $this->assertEquals('ERROR', $records[0]['level_name']);
146 }
147
148 /**
149 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
150 */
151 public function testImport()
152 {
153 $client = new Client();
154
155 $mock = new Mock([
156 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
157 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
158 {
159 "status": 1,
160 "list": {
161 "229279689": {
162 "item_id": "229279689",
163 "resolved_id": "229279689",
164 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
165 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
166 "favorite": "1",
167 "status": "1",
168 "time_added": "1473020899",
169 "time_updated": "1473020899",
170 "time_read": "0",
171 "time_favorited": "0",
172 "sort_id": 0,
173 "resolved_title": "The Massive Ryder Cup Preview",
174 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
175 "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.",
176 "is_article": "1",
177 "is_index": "0",
178 "has_video": "1",
179 "has_image": "1",
180 "word_count": "3197",
181 "images": {
182 "1": {
183 "item_id": "229279689",
184 "image_id": "1",
185 "src": "http://a.espncdn.com/combiner/i?img=/photo/2012/0927/grant_g_ryder_cr_640.jpg&w=640&h=360",
186 "width": "0",
187 "height": "0",
188 "credit": "Jamie Squire/Getty Images",
189 "caption": ""
190 }
191 },
192 "videos": {
193 "1": {
194 "item_id": "229279689",
195 "video_id": "1",
196 "src": "http://www.youtube.com/v/Er34PbFkVGk?version=3&hl=en_US&rel=0",
197 "width": "420",
198 "height": "315",
199 "type": "1",
200 "vid": "Er34PbFkVGk"
201 }
202 },
203 "tags": {
204 "grantland": {
205 "item_id": "1147652870",
206 "tag": "grantland"
207 },
208 "Ryder Cup": {
209 "item_id": "1147652870",
210 "tag": "Ryder Cup"
211 }
212 }
213 },
214 "229279690": {
215 "item_id": "229279689",
216 "resolved_id": "229279689",
217 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
218 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
219 "favorite": "1",
220 "status": "1",
221 "time_added": "1473020899",
222 "time_updated": "1473020899",
223 "time_read": "0",
224 "time_favorited": "0",
225 "sort_id": 1,
226 "resolved_title": "The Massive Ryder Cup Preview",
227 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
228 "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.",
229 "is_article": "1",
230 "is_index": "0",
231 "has_video": "0",
232 "has_image": "0",
233 "word_count": "3197"
234 }
235 }
236 }
237 ')),
238 ]);
239
240 $client->getEmitter()->attach($mock);
241
242 $pocketImport = $this->getPocketImport();
243
244 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
245 ->disableOriginalConstructor()
246 ->getMock();
247
248 $entryRepo->expects($this->exactly(2))
249 ->method('findByUrlAndUserId')
250 ->will($this->onConsecutiveCalls(false, true));
251
252 $this->em
253 ->expects($this->exactly(2))
254 ->method('getRepository')
255 ->willReturn($entryRepo);
256
257 $entry = new Entry($this->user);
258
259 $this->contentProxy
260 ->expects($this->once())
261 ->method('updateEntry')
262 ->willReturn($entry);
263
264 $pocketImport->setClient($client);
265 $pocketImport->authorize('wunderbar_code');
266
267 $res = $pocketImport->import();
268
269 $this->assertTrue($res);
270 $this->assertEquals(['skipped' => 1, 'imported' => 1], $pocketImport->getSummary());
271 }
272
273 /**
274 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
275 */
276 public function testImportAndMarkAllAsRead()
277 {
278 $client = new Client();
279
280 $mock = new Mock([
281 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
282 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
283 {
284 "status": 1,
285 "list": {
286 "229279689": {
287 "item_id": "229279689",
288 "resolved_id": "229279689",
289 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
290 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
291 "favorite": "1",
292 "status": "1",
293 "time_added": "1473020899",
294 "time_updated": "1473020899",
295 "time_read": "0",
296 "time_favorited": "0",
297 "sort_id": 0,
298 "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 "is_article": "1",
300 "has_video": "1",
301 "has_image": "1",
302 "word_count": "3197"
303 },
304 "229279690": {
305 "item_id": "229279689",
306 "resolved_id": "229279689",
307 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview/2",
308 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
309 "favorite": "1",
310 "status": "0",
311 "time_added": "1473020899",
312 "time_updated": "1473020899",
313 "time_read": "0",
314 "time_favorited": "0",
315 "sort_id": 1,
316 "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.",
317 "is_article": "1",
318 "has_video": "0",
319 "has_image": "0",
320 "word_count": "3197"
321 }
322 }
323 }
324 ')),
325 ]);
326
327 $client->getEmitter()->attach($mock);
328
329 $pocketImport = $this->getPocketImport();
330
331 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
332 ->disableOriginalConstructor()
333 ->getMock();
334
335 $entryRepo->expects($this->exactly(2))
336 ->method('findByUrlAndUserId')
337 ->will($this->onConsecutiveCalls(false, false));
338
339 $this->em
340 ->expects($this->exactly(2))
341 ->method('getRepository')
342 ->willReturn($entryRepo);
343
344 // check that every entry persisted are archived
345 $this->em
346 ->expects($this->any())
347 ->method('persist')
348 ->with($this->callback(function ($persistedEntry) {
349 return $persistedEntry->isArchived();
350 }));
351
352 $entry = new Entry($this->user);
353
354 $this->contentProxy
355 ->expects($this->exactly(2))
356 ->method('updateEntry')
357 ->willReturn($entry);
358
359 $pocketImport->setClient($client);
360 $pocketImport->authorize('wunderbar_code');
361
362 $res = $pocketImport->setMarkAsRead(true)->import();
363
364 $this->assertTrue($res);
365 $this->assertEquals(['skipped' => 0, 'imported' => 2], $pocketImport->getSummary());
366 }
367
368 /**
369 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
370 */
371 public function testImportWithRabbit()
372 {
373 $client = new Client();
374
375 $body = <<<'JSON'
376 {
377 "item_id": "229279689",
378 "resolved_id": "229279689",
379 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
380 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
381 "favorite": "1",
382 "status": "1",
383 "time_added": "1473020899",
384 "time_updated": "1473020899",
385 "time_read": "0",
386 "time_favorited": "0",
387 "sort_id": 0,
388 "resolved_title": "The Massive Ryder Cup Preview",
389 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
390 "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.",
391 "is_article": "1",
392 "has_video": "0",
393 "has_image": "0",
394 "word_count": "3197"
395 }
396 JSON;
397
398 $mock = new Mock([
399 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
400 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
401 {
402 "status": 1,
403 "list": {
404 "229279690": '.$body.'
405 }
406 }
407 ')),
408 ]);
409
410 $client->getEmitter()->attach($mock);
411
412 $pocketImport = $this->getPocketImport();
413
414 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
415 ->disableOriginalConstructor()
416 ->getMock();
417
418 $entryRepo->expects($this->never())
419 ->method('findByUrlAndUserId');
420
421 $this->em
422 ->expects($this->never())
423 ->method('getRepository');
424
425 $entry = new Entry($this->user);
426
427 $this->contentProxy
428 ->expects($this->never())
429 ->method('updateEntry');
430
431 $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
432 ->disableOriginalConstructor()
433 ->getMock();
434
435 $bodyAsArray = json_decode($body, true);
436 // because with just use `new User()` so it doesn't have an id
437 $bodyAsArray['userId'] = null;
438
439 $producer
440 ->expects($this->once())
441 ->method('publish')
442 ->with(json_encode($bodyAsArray));
443
444 $pocketImport->setClient($client);
445 $pocketImport->setRabbitmqProducer($producer);
446 $pocketImport->authorize('wunderbar_code');
447
448 $res = $pocketImport->setMarkAsRead(true)->import();
449
450 $this->assertTrue($res);
451 $this->assertEquals(['skipped' => 0, 'imported' => 1], $pocketImport->getSummary());
452 }
453
454 public function testImportBadResponse()
455 {
456 $client = new Client();
457
458 $mock = new Mock([
459 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
460 new Response(403),
461 ]);
462
463 $client->getEmitter()->attach($mock);
464
465 $pocketImport = $this->getPocketImport();
466 $pocketImport->setClient($client);
467 $pocketImport->authorize('wunderbar_code');
468
469 $res = $pocketImport->import();
470
471 $this->assertFalse($res);
472
473 $records = $this->logHandler->getRecords();
474 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
475 $this->assertEquals('ERROR', $records[0]['level_name']);
476 }
477
478 public function testImportWithExceptionFromGraby()
479 {
480 $client = new Client();
481
482 $mock = new Mock([
483 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
484 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
485 {
486 "status": 1,
487 "list": {
488 "229279689": {
489 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
490 }
491 }
492 }
493 ')),
494 ]);
495
496 $client->getEmitter()->attach($mock);
497
498 $pocketImport = $this->getPocketImport();
499
500 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
501 ->disableOriginalConstructor()
502 ->getMock();
503
504 $entryRepo->expects($this->once())
505 ->method('findByUrlAndUserId')
506 ->will($this->onConsecutiveCalls(false, true));
507
508 $this->em
509 ->expects($this->once())
510 ->method('getRepository')
511 ->willReturn($entryRepo);
512
513 $entry = new Entry($this->user);
514
515 $this->contentProxy
516 ->expects($this->once())
517 ->method('updateEntry')
518 ->will($this->throwException(new \Exception()));
519
520 $pocketImport->setClient($client);
521 $pocketImport->authorize('wunderbar_code');
522
523 $res = $pocketImport->import();
524
525 $this->assertTrue($res);
526 $this->assertEquals(['skipped' => 1, 'imported' => 0], $pocketImport->getSummary());
527 }
528 }