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