]> git.immae.eu Git - github/wallabag/wallabag.git/blame - tests/Wallabag/CoreBundle/Helper/ContentProxyTest.php
Merge pull request #3245 from wallabag/fix-bc
[github/wallabag/wallabag.git] / tests / Wallabag / CoreBundle / Helper / ContentProxyTest.php
CommitLineData
558d9aab
JB
1<?php
2
a2c1b94e 3namespace Tests\Wallabag\CoreBundle\Helper;
558d9aab 4
0c5bcd82 5use Psr\Log\NullLogger;
d5c2cc54
JB
6use Monolog\Logger;
7use Monolog\Handler\TestHandler;
558d9aab 8use Wallabag\CoreBundle\Helper\ContentProxy;
c2656f96
JB
9use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\CoreBundle\Entity\Tag;
619cc453 11use Wallabag\UserBundle\Entity\User;
6bc6fb1f 12use Wallabag\CoreBundle\Helper\RuleBasedTagger;
74a75f7d 13use Graby\Graby;
0d349ea6
JB
14use Symfony\Component\Validator\Validator\RecursiveValidator;
15use Symfony\Component\Validator\ConstraintViolationList;
16use Symfony\Component\Validator\ConstraintViolation;
558d9aab 17
a2c1b94e 18class ContentProxyTest extends \PHPUnit_Framework_TestCase
558d9aab 19{
ac1509a6 20 private $fetchingErrorMessage = 'wallabag can\'t retrieve contents for this article. Please <a href="http://doc.wallabag.org/en/user/errors_during_fetching.html#how-can-i-help-to-fix-that">troubleshoot this issue</a>.';
a2c1b94e 21
4d0ec0e7
JB
22 public function testWithBadUrl()
23 {
24 $tagger = $this->getTaggerMock();
25 $tagger->expects($this->once())
26 ->method('tag');
27
28 $graby = $this->getMockBuilder('Graby\Graby')
4094ea47 29 ->setMethods(['fetchContent'])
4d0ec0e7
JB
30 ->disableOriginalConstructor()
31 ->getMock();
32
33 $graby->expects($this->any())
34 ->method('fetchContent')
4094ea47 35 ->willReturn([
4d0ec0e7
JB
36 'html' => false,
37 'title' => '',
38 'url' => '',
39 'content_type' => '',
40 'language' => '',
4094ea47 41 ]);
4d0ec0e7 42
0d349ea6 43 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
7aba665e
JC
44 $entry = new Entry(new User());
45 $proxy->updateEntry($entry, 'http://user@:80');
4d0ec0e7
JB
46
47 $this->assertEquals('http://user@:80', $entry->getUrl());
48 $this->assertEmpty($entry->getTitle());
fc2b7bda 49 $this->assertEquals($this->fetchingErrorMessage, $entry->getContent());
4d0ec0e7
JB
50 $this->assertEmpty($entry->getPreviewPicture());
51 $this->assertEmpty($entry->getMimetype());
52 $this->assertEmpty($entry->getLanguage());
53 $this->assertEquals(0.0, $entry->getReadingTime());
54 $this->assertEquals(false, $entry->getDomainName());
55 }
56
558d9aab
JB
57 public function testWithEmptyContent()
58 {
f530f7f5
KG
59 $tagger = $this->getTaggerMock();
60 $tagger->expects($this->once())
61 ->method('tag');
62
558d9aab 63 $graby = $this->getMockBuilder('Graby\Graby')
4094ea47 64 ->setMethods(['fetchContent'])
558d9aab
JB
65 ->disableOriginalConstructor()
66 ->getMock();
67
68 $graby->expects($this->any())
69 ->method('fetchContent')
4094ea47 70 ->willReturn([
98f0929f
JB
71 'html' => false,
72 'title' => '',
73 'url' => '',
74 'content_type' => '',
75 'language' => '',
4094ea47 76 ]);
558d9aab 77
0d349ea6 78 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
7aba665e
JC
79 $entry = new Entry(new User());
80 $proxy->updateEntry($entry, 'http://0.0.0.0');
558d9aab
JB
81
82 $this->assertEquals('http://0.0.0.0', $entry->getUrl());
83 $this->assertEmpty($entry->getTitle());
fc2b7bda 84 $this->assertEquals($this->fetchingErrorMessage, $entry->getContent());
558d9aab
JB
85 $this->assertEmpty($entry->getPreviewPicture());
86 $this->assertEmpty($entry->getMimetype());
98f0929f 87 $this->assertEmpty($entry->getLanguage());
da3d4998
JB
88 $this->assertEquals(0.0, $entry->getReadingTime());
89 $this->assertEquals('0.0.0.0', $entry->getDomainName());
558d9aab
JB
90 }
91
92 public function testWithEmptyContentButOG()
93 {
f530f7f5
KG
94 $tagger = $this->getTaggerMock();
95 $tagger->expects($this->once())
96 ->method('tag');
97
558d9aab 98 $graby = $this->getMockBuilder('Graby\Graby')
4094ea47 99 ->setMethods(['fetchContent'])
558d9aab
JB
100 ->disableOriginalConstructor()
101 ->getMock();
102
103 $graby->expects($this->any())
104 ->method('fetchContent')
4094ea47 105 ->willReturn([
98f0929f
JB
106 'html' => false,
107 'title' => '',
108 'url' => '',
109 'content_type' => '',
110 'language' => '',
10b35097 111 'status' => '',
4094ea47 112 'open_graph' => [
98f0929f
JB
113 'og_title' => 'my title',
114 'og_description' => 'desc',
4094ea47
JB
115 ],
116 ]);
558d9aab 117
0d349ea6 118 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
7aba665e
JC
119 $entry = new Entry(new User());
120 $proxy->updateEntry($entry, 'http://domain.io');
558d9aab 121
da3d4998 122 $this->assertEquals('http://domain.io', $entry->getUrl());
558d9aab 123 $this->assertEquals('my title', $entry->getTitle());
d09fe4d2 124 $this->assertEquals($this->fetchingErrorMessage.'<p><i>But we found a short description: </i></p>desc', $entry->getContent());
558d9aab 125 $this->assertEmpty($entry->getPreviewPicture());
98f0929f 126 $this->assertEmpty($entry->getLanguage());
10b35097 127 $this->assertEmpty($entry->getHttpStatus());
558d9aab 128 $this->assertEmpty($entry->getMimetype());
da3d4998
JB
129 $this->assertEquals(0.0, $entry->getReadingTime());
130 $this->assertEquals('domain.io', $entry->getDomainName());
558d9aab
JB
131 }
132
133 public function testWithContent()
134 {
f530f7f5
KG
135 $tagger = $this->getTaggerMock();
136 $tagger->expects($this->once())
137 ->method('tag');
138
558d9aab 139 $graby = $this->getMockBuilder('Graby\Graby')
4094ea47 140 ->setMethods(['fetchContent'])
558d9aab
JB
141 ->disableOriginalConstructor()
142 ->getMock();
143
144 $graby->expects($this->any())
145 ->method('fetchContent')
4094ea47 146 ->willReturn([
da3d4998 147 'html' => str_repeat('this is my content', 325),
558d9aab
JB
148 'title' => 'this is my title',
149 'url' => 'http://1.1.1.1',
150 'content_type' => 'text/html',
98f0929f 151 'language' => 'fr',
10b35097 152 'status' => '200',
4094ea47 153 'open_graph' => [
558d9aab
JB
154 'og_title' => 'my OG title',
155 'og_description' => 'OG desc',
f1e29e69 156 'og_image' => 'http://3.3.3.3/cover.jpg',
4094ea47
JB
157 ],
158 ]);
558d9aab 159
0d349ea6 160 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
7aba665e
JC
161 $entry = new Entry(new User());
162 $proxy->updateEntry($entry, 'http://0.0.0.0');
558d9aab
JB
163
164 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
165 $this->assertEquals('this is my title', $entry->getTitle());
da3d4998 166 $this->assertContains('this is my content', $entry->getContent());
558d9aab
JB
167 $this->assertEquals('http://3.3.3.3/cover.jpg', $entry->getPreviewPicture());
168 $this->assertEquals('text/html', $entry->getMimetype());
98f0929f 169 $this->assertEquals('fr', $entry->getLanguage());
10b35097 170 $this->assertEquals('200', $entry->getHttpStatus());
da3d4998
JB
171 $this->assertEquals(4.0, $entry->getReadingTime());
172 $this->assertEquals('1.1.1.1', $entry->getDomainName());
558d9aab 173 }
f530f7f5 174
3d71d403
JB
175 public function testWithContentAndNoOgImage()
176 {
177 $tagger = $this->getTaggerMock();
178 $tagger->expects($this->once())
179 ->method('tag');
180
181 $graby = $this->getMockBuilder('Graby\Graby')
182 ->setMethods(['fetchContent'])
183 ->disableOriginalConstructor()
184 ->getMock();
185
186 $graby->expects($this->any())
187 ->method('fetchContent')
188 ->willReturn([
189 'html' => str_repeat('this is my content', 325),
190 'title' => 'this is my title',
191 'url' => 'http://1.1.1.1',
192 'content_type' => 'text/html',
193 'language' => 'fr',
194 'status' => '200',
195 'open_graph' => [
196 'og_title' => 'my OG title',
197 'og_description' => 'OG desc',
0d349ea6 198 'og_image' => null,
3d71d403
JB
199 ],
200 ]);
201
0d349ea6 202 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
d5c2cc54
JB
203 $entry = new Entry(new User());
204 $proxy->updateEntry($entry, 'http://0.0.0.0');
3d71d403
JB
205
206 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
207 $this->assertEquals('this is my title', $entry->getTitle());
208 $this->assertContains('this is my content', $entry->getContent());
41d45c61 209 $this->assertNull($entry->getPreviewPicture());
0d349ea6
JB
210 $this->assertEquals('text/html', $entry->getMimetype());
211 $this->assertEquals('fr', $entry->getLanguage());
212 $this->assertEquals('200', $entry->getHttpStatus());
213 $this->assertEquals(4.0, $entry->getReadingTime());
214 $this->assertEquals('1.1.1.1', $entry->getDomainName());
215 }
216
217 public function testWithContentAndBadLanguage()
218 {
219 $tagger = $this->getTaggerMock();
220 $tagger->expects($this->once())
221 ->method('tag');
222
223 $validator = $this->getValidator();
224 $validator->expects($this->exactly(2))
225 ->method('validate')
226 ->will($this->onConsecutiveCalls(
227 new ConstraintViolationList([new ConstraintViolation('oops', 'oops', [], 'oops', 'language', 'dontexist')]),
228 new ConstraintViolationList()
229 ));
230
231 $graby = $this->getMockBuilder('Graby\Graby')
232 ->setMethods(['fetchContent'])
233 ->disableOriginalConstructor()
234 ->getMock();
235
236 $graby->expects($this->any())
237 ->method('fetchContent')
238 ->willReturn([
239 'html' => str_repeat('this is my content', 325),
240 'title' => 'this is my title',
241 'url' => 'http://1.1.1.1',
242 'content_type' => 'text/html',
243 'language' => 'dontexist',
244 'status' => '200',
245 ]);
246
247 $proxy = new ContentProxy($graby, $tagger, $validator, $this->getLogger(), $this->fetchingErrorMessage);
248 $entry = new Entry(new User());
249 $proxy->updateEntry($entry, 'http://0.0.0.0');
250
251 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
252 $this->assertEquals('this is my title', $entry->getTitle());
253 $this->assertContains('this is my content', $entry->getContent());
254 $this->assertEquals('text/html', $entry->getMimetype());
41d45c61 255 $this->assertNull($entry->getLanguage());
0d349ea6
JB
256 $this->assertEquals('200', $entry->getHttpStatus());
257 $this->assertEquals(4.0, $entry->getReadingTime());
258 $this->assertEquals('1.1.1.1', $entry->getDomainName());
259 }
260
261 public function testWithContentAndBadOgImage()
262 {
263 $tagger = $this->getTaggerMock();
264 $tagger->expects($this->once())
265 ->method('tag');
266
267 $validator = $this->getValidator();
268 $validator->expects($this->exactly(2))
269 ->method('validate')
270 ->will($this->onConsecutiveCalls(
271 new ConstraintViolationList(),
272 new ConstraintViolationList([new ConstraintViolation('oops', 'oops', [], 'oops', 'url', 'https://')])
273 ));
274
275 $graby = $this->getMockBuilder('Graby\Graby')
276 ->setMethods(['fetchContent'])
277 ->disableOriginalConstructor()
278 ->getMock();
279
280 $graby->expects($this->any())
281 ->method('fetchContent')
282 ->willReturn([
283 'html' => str_repeat('this is my content', 325),
284 'title' => 'this is my title',
285 'url' => 'http://1.1.1.1',
286 'content_type' => 'text/html',
287 'language' => 'fr',
288 'status' => '200',
289 'open_graph' => [
290 'og_title' => 'my OG title',
291 'og_description' => 'OG desc',
292 'og_image' => 'https://',
293 ],
294 ]);
295
296 $proxy = new ContentProxy($graby, $tagger, $validator, $this->getLogger(), $this->fetchingErrorMessage);
297 $entry = new Entry(new User());
298 $proxy->updateEntry($entry, 'http://0.0.0.0');
299
300 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
301 $this->assertEquals('this is my title', $entry->getTitle());
302 $this->assertContains('this is my content', $entry->getContent());
41d45c61 303 $this->assertNull($entry->getPreviewPicture());
3d71d403
JB
304 $this->assertEquals('text/html', $entry->getMimetype());
305 $this->assertEquals('fr', $entry->getLanguage());
306 $this->assertEquals('200', $entry->getHttpStatus());
307 $this->assertEquals(4.0, $entry->getReadingTime());
308 $this->assertEquals('1.1.1.1', $entry->getDomainName());
309 }
310
4d0ec0e7
JB
311 public function testWithForcedContent()
312 {
313 $tagger = $this->getTaggerMock();
314 $tagger->expects($this->once())
315 ->method('tag');
316
0d349ea6 317 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
7aba665e
JC
318 $entry = new Entry(new User());
319 $proxy->updateEntry(
320 $entry,
0d6cfb88
JB
321 'http://0.0.0.0',
322 [
323 'html' => str_repeat('this is my content', 325),
324 'title' => 'this is my title',
325 'url' => 'http://1.1.1.1',
326 'content_type' => 'text/html',
327 'language' => 'fr',
f0378b4d
JB
328 'date' => '1395635872',
329 'authors' => ['Jeremy', 'Nico', 'Thomas'],
330 'all_headers' => [
331 'Cache-Control' => 'no-cache',
38a04dee 332 ],
0d6cfb88
JB
333 ]
334 );
4d0ec0e7
JB
335
336 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
337 $this->assertEquals('this is my title', $entry->getTitle());
338 $this->assertContains('this is my content', $entry->getContent());
339 $this->assertEquals('text/html', $entry->getMimetype());
340 $this->assertEquals('fr', $entry->getLanguage());
341 $this->assertEquals(4.0, $entry->getReadingTime());
342 $this->assertEquals('1.1.1.1', $entry->getDomainName());
f0378b4d
JB
343 $this->assertEquals('24/03/2014', $entry->getPublishedAt()->format('d/m/Y'));
344 $this->assertContains('Jeremy', $entry->getPublishedBy());
345 $this->assertContains('Nico', $entry->getPublishedBy());
346 $this->assertContains('Thomas', $entry->getPublishedBy());
347 $this->assertContains('no-cache', $entry->getHeaders());
348 }
349
350 public function testWithForcedContentAndDatetime()
351 {
352 $tagger = $this->getTaggerMock();
353 $tagger->expects($this->once())
354 ->method('tag');
355
d5c2cc54 356 $logHandler = new TestHandler();
6acadf8e 357 $logger = new Logger('test', [$logHandler]);
d5c2cc54 358
0d349ea6 359 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $logger, $this->fetchingErrorMessage);
7aba665e 360 $entry = new Entry(new User());
6acadf8e 361 $proxy->updateEntry(
7aba665e 362 $entry,
6acadf8e 363 'http://1.1.1.1',
f0378b4d
JB
364 [
365 'html' => str_repeat('this is my content', 325),
366 'title' => 'this is my title',
367 'url' => 'http://1.1.1.1',
368 'content_type' => 'text/html',
369 'language' => 'fr',
370 'date' => '2016-09-08T11:55:58+0200',
371 ]
372 );
373
374 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
375 $this->assertEquals('this is my title', $entry->getTitle());
376 $this->assertContains('this is my content', $entry->getContent());
377 $this->assertEquals('text/html', $entry->getMimetype());
378 $this->assertEquals('fr', $entry->getLanguage());
379 $this->assertEquals(4.0, $entry->getReadingTime());
380 $this->assertEquals('1.1.1.1', $entry->getDomainName());
381 $this->assertEquals('08/09/2016', $entry->getPublishedAt()->format('d/m/Y'));
382 }
383
384 public function testWithForcedContentAndBadDate()
385 {
386 $tagger = $this->getTaggerMock();
387 $tagger->expects($this->once())
388 ->method('tag');
389
390 $logger = new Logger('foo');
391 $handler = new TestHandler();
392 $logger->pushHandler($handler);
393
0d349ea6 394 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $logger, $this->fetchingErrorMessage);
7aba665e
JC
395 $entry = new Entry(new User());
396 $proxy->updateEntry(
397 $entry,
6acadf8e 398 'http://1.1.1.1',
f0378b4d
JB
399 [
400 'html' => str_repeat('this is my content', 325),
401 'title' => 'this is my title',
402 'url' => 'http://1.1.1.1',
403 'content_type' => 'text/html',
404 'language' => 'fr',
405 'date' => '01 02 2012',
406 ]
407 );
408
409 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
410 $this->assertEquals('this is my title', $entry->getTitle());
411 $this->assertContains('this is my content', $entry->getContent());
412 $this->assertEquals('text/html', $entry->getMimetype());
413 $this->assertEquals('fr', $entry->getLanguage());
414 $this->assertEquals(4.0, $entry->getReadingTime());
415 $this->assertEquals('1.1.1.1', $entry->getDomainName());
416 $this->assertNull($entry->getPublishedAt());
417
418 $records = $handler->getRecords();
419
420 $this->assertCount(1, $records);
421 $this->assertContains('Error while defining date', $records[0]['message']);
4d0ec0e7
JB
422 }
423
424 public function testTaggerThrowException()
425 {
4d0ec0e7
JB
426 $tagger = $this->getTaggerMock();
427 $tagger->expects($this->once())
428 ->method('tag')
429 ->will($this->throwException(new \Exception()));
430
0d349ea6 431 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
7aba665e 432 $entry = new Entry(new User());
6acadf8e
JB
433 $proxy->updateEntry(
434 $entry,
435 'http://1.1.1.1',
436 [
437 'html' => str_repeat('this is my content', 325),
438 'title' => 'this is my title',
439 'url' => 'http://1.1.1.1',
440 'content_type' => 'text/html',
441 'language' => 'fr',
442 ]
d0e9b3d6 443 );
4d0ec0e7
JB
444
445 $this->assertCount(0, $entry->getTags());
446 }
447
74a75f7d
JB
448 public function dataForCrazyHtml()
449 {
450 return [
451 'script and comment' => [
452 '<strong>Script inside:</strong> <!--[if gte IE 4]><script>alert(\'lol\');</script><![endif]--><br />',
38a04dee 453 'lol',
74a75f7d
JB
454 ],
455 'script' => [
456 '<strong>Script inside:</strong><script>alert(\'lol\');</script>',
38a04dee 457 'script',
74a75f7d
JB
458 ],
459 ];
460 }
461
462 /**
463 * @dataProvider dataForCrazyHtml
464 */
465 public function testWithCrazyHtmlContent($html, $escapedString)
466 {
467 $tagger = $this->getTaggerMock();
468 $tagger->expects($this->once())
469 ->method('tag');
470
0d349ea6 471 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
6acadf8e
JB
472 $entry = new Entry(new User());
473 $proxy->updateEntry(
474 $entry,
74a75f7d
JB
475 'http://1.1.1.1',
476 [
477 'html' => $html,
478 'title' => 'this is my title',
479 'url' => 'http://1.1.1.1',
480 'content_type' => 'text/html',
481 'language' => 'fr',
482 'status' => '200',
483 'open_graph' => [
484 'og_title' => 'my OG title',
485 'og_description' => 'OG desc',
486 'og_image' => 'http://3.3.3.3/cover.jpg',
487 ],
488 ]
489 );
490
491 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
492 $this->assertEquals('this is my title', $entry->getTitle());
493 $this->assertNotContains($escapedString, $entry->getContent());
494 $this->assertEquals('http://3.3.3.3/cover.jpg', $entry->getPreviewPicture());
495 $this->assertEquals('text/html', $entry->getMimetype());
496 $this->assertEquals('fr', $entry->getLanguage());
497 $this->assertEquals('200', $entry->getHttpStatus());
498 $this->assertEquals('1.1.1.1', $entry->getDomainName());
499 }
500
f530f7f5
KG
501 private function getTaggerMock()
502 {
6bc6fb1f 503 return $this->getMockBuilder(RuleBasedTagger::class)
4094ea47 504 ->setMethods(['tag'])
f530f7f5
KG
505 ->disableOriginalConstructor()
506 ->getMock();
507 }
1c9cd2a7 508
0c5bcd82 509 private function getLogger()
1c9cd2a7 510 {
0c5bcd82 511 return new NullLogger();
1c9cd2a7 512 }
0d349ea6
JB
513
514 private function getValidator()
515 {
516 return $this->getMockBuilder(RecursiveValidator::class)
517 ->setMethods(['validate'])
518 ->disableOriginalConstructor()
519 ->getMock();
520 }
558d9aab 521}