]> git.immae.eu Git - github/wallabag/wallabag.git/blob - tests/Wallabag/ImportBundle/Import/PocketImportTest.php
Add test for RabbitMQ
[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 "resolved_title": "The Massive Ryder Cup Preview",
169 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
170 "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.",
171 "is_article": "1",
172 "has_video": "1",
173 "has_image": "1",
174 "word_count": "3197",
175 "images": {
176 "1": {
177 "item_id": "229279689",
178 "image_id": "1",
179 "src": "http://a.espncdn.com/combiner/i?img=/photo/2012/0927/grant_g_ryder_cr_640.jpg&w=640&h=360",
180 "width": "0",
181 "height": "0",
182 "credit": "Jamie Squire/Getty Images",
183 "caption": ""
184 }
185 },
186 "videos": {
187 "1": {
188 "item_id": "229279689",
189 "video_id": "1",
190 "src": "http://www.youtube.com/v/Er34PbFkVGk?version=3&hl=en_US&rel=0",
191 "width": "420",
192 "height": "315",
193 "type": "1",
194 "vid": "Er34PbFkVGk"
195 }
196 },
197 "tags": {
198 "grantland": {
199 "item_id": "1147652870",
200 "tag": "grantland"
201 },
202 "Ryder Cup": {
203 "item_id": "1147652870",
204 "tag": "Ryder Cup"
205 }
206 }
207 },
208 "229279690": {
209 "item_id": "229279689",
210 "resolved_id": "229279689",
211 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
212 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
213 "favorite": "1",
214 "status": "1",
215 "resolved_title": "The Massive Ryder Cup Preview",
216 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
217 "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.",
218 "is_article": "1",
219 "has_video": "0",
220 "has_image": "0",
221 "word_count": "3197"
222 }
223 }
224 }
225 ')),
226 ]);
227
228 $client->getEmitter()->attach($mock);
229
230 $pocketImport = $this->getPocketImport();
231
232 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
233 ->disableOriginalConstructor()
234 ->getMock();
235
236 $entryRepo->expects($this->exactly(2))
237 ->method('findByUrlAndUserId')
238 ->will($this->onConsecutiveCalls(false, true));
239
240 $this->em
241 ->expects($this->exactly(2))
242 ->method('getRepository')
243 ->willReturn($entryRepo);
244
245 $entry = new Entry($this->user);
246
247 $this->contentProxy
248 ->expects($this->once())
249 ->method('updateEntry')
250 ->willReturn($entry);
251
252 $pocketImport->setClient($client);
253 $pocketImport->authorize('wunderbar_code');
254
255 $res = $pocketImport->import();
256
257 $this->assertTrue($res);
258 $this->assertEquals(['skipped' => 1, 'imported' => 1], $pocketImport->getSummary());
259 }
260
261 /**
262 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
263 */
264 public function testImportAndMarkAllAsRead()
265 {
266 $client = new Client();
267
268 $mock = new Mock([
269 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
270 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
271 {
272 "status": 1,
273 "list": {
274 "229279689": {
275 "item_id": "229279689",
276 "resolved_id": "229279689",
277 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
278 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
279 "favorite": "1",
280 "status": "1",
281 "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.",
282 "is_article": "1",
283 "has_video": "1",
284 "has_image": "1",
285 "word_count": "3197"
286 },
287 "229279690": {
288 "item_id": "229279689",
289 "resolved_id": "229279689",
290 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview/2",
291 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
292 "favorite": "1",
293 "status": "0",
294 "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.",
295 "is_article": "1",
296 "has_video": "0",
297 "has_image": "0",
298 "word_count": "3197"
299 }
300 }
301 }
302 ')),
303 ]);
304
305 $client->getEmitter()->attach($mock);
306
307 $pocketImport = $this->getPocketImport();
308
309 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
310 ->disableOriginalConstructor()
311 ->getMock();
312
313 $entryRepo->expects($this->exactly(2))
314 ->method('findByUrlAndUserId')
315 ->will($this->onConsecutiveCalls(false, false));
316
317 $this->em
318 ->expects($this->exactly(2))
319 ->method('getRepository')
320 ->willReturn($entryRepo);
321
322 // check that every entry persisted are archived
323 $this->em
324 ->expects($this->any())
325 ->method('persist')
326 ->with($this->callback(function ($persistedEntry) {
327 return $persistedEntry->isArchived();
328 }));
329
330 $entry = new Entry($this->user);
331
332 $this->contentProxy
333 ->expects($this->exactly(2))
334 ->method('updateEntry')
335 ->willReturn($entry);
336
337 $pocketImport->setClient($client);
338 $pocketImport->authorize('wunderbar_code');
339
340 $res = $pocketImport->setMarkAsRead(true)->import();
341
342 $this->assertTrue($res);
343 $this->assertEquals(['skipped' => 0, 'imported' => 2], $pocketImport->getSummary());
344 }
345
346 /**
347 * Will sample results from https://getpocket.com/developer/docs/v3/retrieve.
348 */
349 public function testImportWithRabbit()
350 {
351 $client = new Client();
352
353 $body = <<<'JSON'
354 {
355 "item_id": "229279689",
356 "resolved_id": "229279689",
357 "given_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
358 "given_title": "The Massive Ryder Cup Preview - The Triangle Blog - Grantland",
359 "favorite": "1",
360 "status": "1",
361 "resolved_title": "The Massive Ryder Cup Preview",
362 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview",
363 "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.",
364 "is_article": "1",
365 "has_video": "0",
366 "has_image": "0",
367 "word_count": "3197"
368 }
369 JSON;
370
371 $mock = new Mock([
372 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
373 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
374 {
375 "status": 1,
376 "list": {
377 "229279690": '.$body.'
378 }
379 }
380 ')),
381 ]);
382
383 $client->getEmitter()->attach($mock);
384
385 $pocketImport = $this->getPocketImport();
386
387 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
388 ->disableOriginalConstructor()
389 ->getMock();
390
391 $entryRepo->expects($this->never())
392 ->method('findByUrlAndUserId');
393
394 $this->em
395 ->expects($this->never())
396 ->method('getRepository');
397
398 $entry = new Entry($this->user);
399
400 $this->contentProxy
401 ->expects($this->never())
402 ->method('updateEntry');
403
404 $producer = $this->getMockBuilder('OldSound\RabbitMqBundle\RabbitMq\Producer')
405 ->disableOriginalConstructor()
406 ->getMock();
407
408 $bodyAsArray = json_decode($body, true);
409 // because with just use `new User()` so it doesn't have an id
410 $bodyAsArray['userId'] = null;
411
412 $producer
413 ->expects($this->once())
414 ->method('publish')
415 ->with(json_encode($bodyAsArray));
416
417 $pocketImport->setClient($client);
418 $pocketImport->setRabbitmqProducer($producer);
419 $pocketImport->authorize('wunderbar_code');
420
421 $res = $pocketImport->setMarkAsRead(true)->import();
422
423 $this->assertTrue($res);
424 $this->assertEquals(['skipped' => 0, 'imported' => 1], $pocketImport->getSummary());
425 }
426
427 public function testImportBadResponse()
428 {
429 $client = new Client();
430
431 $mock = new Mock([
432 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
433 new Response(403),
434 ]);
435
436 $client->getEmitter()->attach($mock);
437
438 $pocketImport = $this->getPocketImport();
439 $pocketImport->setClient($client);
440 $pocketImport->authorize('wunderbar_code');
441
442 $res = $pocketImport->import();
443
444 $this->assertFalse($res);
445
446 $records = $this->logHandler->getRecords();
447 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
448 $this->assertEquals('ERROR', $records[0]['level_name']);
449 }
450
451 public function testImportWithExceptionFromGraby()
452 {
453 $client = new Client();
454
455 $mock = new Mock([
456 new Response(200, ['Content-Type' => 'application/json'], Stream::factory(json_encode(['access_token' => 'wunderbar_token']))),
457 new Response(200, ['Content-Type' => 'application/json'], Stream::factory('
458 {
459 "status": 1,
460 "list": {
461 "229279689": {
462 "resolved_url": "http://www.grantland.com/blog/the-triangle/post/_/id/38347/ryder-cup-preview"
463 }
464 }
465 }
466 ')),
467 ]);
468
469 $client->getEmitter()->attach($mock);
470
471 $pocketImport = $this->getPocketImport();
472
473 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
474 ->disableOriginalConstructor()
475 ->getMock();
476
477 $entryRepo->expects($this->once())
478 ->method('findByUrlAndUserId')
479 ->will($this->onConsecutiveCalls(false, true));
480
481 $this->em
482 ->expects($this->once())
483 ->method('getRepository')
484 ->willReturn($entryRepo);
485
486 $entry = new Entry($this->user);
487
488 $this->contentProxy
489 ->expects($this->once())
490 ->method('updateEntry')
491 ->will($this->throwException(new \Exception()));
492
493 $pocketImport->setClient($client);
494 $pocketImport->authorize('wunderbar_code');
495
496 $res = $pocketImport->import();
497
498 $this->assertTrue($res);
499 $this->assertEquals(['skipped' => 1, 'imported' => 0], $pocketImport->getSummary());
500 }
501 }