aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/bookmark
diff options
context:
space:
mode:
Diffstat (limited to 'tests/bookmark')
-rw-r--r--tests/bookmark/BookmarkArrayTest.php38
-rw-r--r--tests/bookmark/BookmarkFileServiceTest.php373
-rw-r--r--tests/bookmark/BookmarkFilterTest.php74
-rw-r--r--tests/bookmark/BookmarkInitializerTest.php97
-rw-r--r--tests/bookmark/BookmarkTest.php94
-rw-r--r--tests/bookmark/LinkUtilsTest.php351
6 files changed, 645 insertions, 382 deletions
diff --git a/tests/bookmark/BookmarkArrayTest.php b/tests/bookmark/BookmarkArrayTest.php
index 0f8f04c5..1953078c 100644
--- a/tests/bookmark/BookmarkArrayTest.php
+++ b/tests/bookmark/BookmarkArrayTest.php
@@ -2,10 +2,7 @@
2 2
3namespace Shaarli\Bookmark; 3namespace Shaarli\Bookmark;
4 4
5use PHPUnit\Framework\TestCase; 5use Shaarli\TestCase;
6use Shaarli\Bookmark\Exception\InvalidBookmarkException;
7use Shaarli\Config\ConfigManager;
8use Shaarli\History;
9 6
10/** 7/**
11 * Class BookmarkArrayTest 8 * Class BookmarkArrayTest
@@ -47,22 +44,22 @@ class BookmarkArrayTest extends TestCase
47 44
48 /** 45 /**
49 * Test adding a bad entry: wrong type 46 * Test adding a bad entry: wrong type
50 *
51 * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException
52 */ 47 */
53 public function testArrayAccessAddBadEntryInstance() 48 public function testArrayAccessAddBadEntryInstance()
54 { 49 {
50 $this->expectException(\Shaarli\Bookmark\Exception\InvalidBookmarkException::class);
51
55 $array = new BookmarkArray(); 52 $array = new BookmarkArray();
56 $array[] = 'nope'; 53 $array[] = 'nope';
57 } 54 }
58 55
59 /** 56 /**
60 * Test adding a bad entry: no id 57 * Test adding a bad entry: no id
61 *
62 * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException
63 */ 58 */
64 public function testArrayAccessAddBadEntryNoId() 59 public function testArrayAccessAddBadEntryNoId()
65 { 60 {
61 $this->expectException(\Shaarli\Bookmark\Exception\InvalidBookmarkException::class);
62
66 $array = new BookmarkArray(); 63 $array = new BookmarkArray();
67 $bookmark = new Bookmark(); 64 $bookmark = new Bookmark();
68 $array[] = $bookmark; 65 $array[] = $bookmark;
@@ -70,11 +67,11 @@ class BookmarkArrayTest extends TestCase
70 67
71 /** 68 /**
72 * Test adding a bad entry: no url 69 * Test adding a bad entry: no url
73 *
74 * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException
75 */ 70 */
76 public function testArrayAccessAddBadEntryNoUrl() 71 public function testArrayAccessAddBadEntryNoUrl()
77 { 72 {
73 $this->expectException(\Shaarli\Bookmark\Exception\InvalidBookmarkException::class);
74
78 $array = new BookmarkArray(); 75 $array = new BookmarkArray();
79 $bookmark = (new Bookmark())->setId(11); 76 $bookmark = (new Bookmark())->setId(11);
80 $array[] = $bookmark; 77 $array[] = $bookmark;
@@ -82,11 +79,11 @@ class BookmarkArrayTest extends TestCase
82 79
83 /** 80 /**
84 * Test adding a bad entry: invalid offset 81 * Test adding a bad entry: invalid offset
85 *
86 * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException
87 */ 82 */
88 public function testArrayAccessAddBadEntryOffset() 83 public function testArrayAccessAddBadEntryOffset()
89 { 84 {
85 $this->expectException(\Shaarli\Bookmark\Exception\InvalidBookmarkException::class);
86
90 $array = new BookmarkArray(); 87 $array = new BookmarkArray();
91 $bookmark = (new Bookmark())->setId(11); 88 $bookmark = (new Bookmark())->setId(11);
92 $bookmark->validate(); 89 $bookmark->validate();
@@ -94,25 +91,12 @@ class BookmarkArrayTest extends TestCase
94 } 91 }
95 92
96 /** 93 /**
97 * Test adding a bad entry: invalid ID type
98 *
99 * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException
100 */
101 public function testArrayAccessAddBadEntryIdType()
102 {
103 $array = new BookmarkArray();
104 $bookmark = (new Bookmark())->setId('nope');
105 $bookmark->validate();
106 $array[] = $bookmark;
107 }
108
109 /**
110 * Test adding a bad entry: ID/offset not consistent 94 * Test adding a bad entry: ID/offset not consistent
111 *
112 * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException
113 */ 95 */
114 public function testArrayAccessAddBadEntryIdOffset() 96 public function testArrayAccessAddBadEntryIdOffset()
115 { 97 {
98 $this->expectException(\Shaarli\Bookmark\Exception\InvalidBookmarkException::class);
99
116 $array = new BookmarkArray(); 100 $array = new BookmarkArray();
117 $bookmark = (new Bookmark())->setId(11); 101 $bookmark = (new Bookmark())->setId(11);
118 $bookmark->validate(); 102 $bookmark->validate();
diff --git a/tests/bookmark/BookmarkFileServiceTest.php b/tests/bookmark/BookmarkFileServiceTest.php
index 4900d41d..f619aff3 100644
--- a/tests/bookmark/BookmarkFileServiceTest.php
+++ b/tests/bookmark/BookmarkFileServiceTest.php
@@ -6,7 +6,7 @@
6namespace Shaarli\Bookmark; 6namespace Shaarli\Bookmark;
7 7
8use DateTime; 8use DateTime;
9use PHPUnit\Framework\TestCase; 9use malkusch\lock\mutex\NoMutex;
10use ReferenceLinkDB; 10use ReferenceLinkDB;
11use ReflectionClass; 11use ReflectionClass;
12use Shaarli; 12use Shaarli;
@@ -14,6 +14,7 @@ use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
14use Shaarli\Config\ConfigManager; 14use Shaarli\Config\ConfigManager;
15use Shaarli\Formatter\BookmarkMarkdownFormatter; 15use Shaarli\Formatter\BookmarkMarkdownFormatter;
16use Shaarli\History; 16use Shaarli\History;
17use Shaarli\TestCase;
17 18
18/** 19/**
19 * Unitary tests for LegacyLinkDBTest 20 * Unitary tests for LegacyLinkDBTest
@@ -52,6 +53,9 @@ class BookmarkFileServiceTest extends TestCase
52 */ 53 */
53 protected $privateLinkDB = null; 54 protected $privateLinkDB = null;
54 55
56 /** @var NoMutex */
57 protected $mutex;
58
55 /** 59 /**
56 * Instantiates public and private LinkDBs with test data 60 * Instantiates public and private LinkDBs with test data
57 * 61 *
@@ -66,8 +70,10 @@ class BookmarkFileServiceTest extends TestCase
66 * 70 *
67 * Resets test data for each test 71 * Resets test data for each test
68 */ 72 */
69 protected function setUp() 73 protected function setUp(): void
70 { 74 {
75 $this->mutex = new NoMutex();
76
71 if (file_exists(self::$testDatastore)) { 77 if (file_exists(self::$testDatastore)) {
72 unlink(self::$testDatastore); 78 unlink(self::$testDatastore);
73 } 79 }
@@ -87,8 +93,8 @@ class BookmarkFileServiceTest extends TestCase
87 $this->refDB = new \ReferenceLinkDB(); 93 $this->refDB = new \ReferenceLinkDB();
88 $this->refDB->write(self::$testDatastore); 94 $this->refDB->write(self::$testDatastore);
89 $this->history = new History('sandbox/history.php'); 95 $this->history = new History('sandbox/history.php');
90 $this->publicLinkDB = new BookmarkFileService($this->conf, $this->history, false); 96 $this->publicLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, false);
91 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 97 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
92 } 98 }
93 99
94 /** 100 /**
@@ -105,7 +111,7 @@ class BookmarkFileServiceTest extends TestCase
105 $db = self::getMethod('migrate'); 111 $db = self::getMethod('migrate');
106 $db->invokeArgs($this->privateLinkDB, []); 112 $db->invokeArgs($this->privateLinkDB, []);
107 113
108 $db = new \FakeBookmarkService($this->conf, $this->history, true); 114 $db = new \FakeBookmarkService($this->conf, $this->history, $this->mutex, true);
109 $this->assertInstanceOf(BookmarkArray::class, $db->getBookmarks()); 115 $this->assertInstanceOf(BookmarkArray::class, $db->getBookmarks());
110 $this->assertEquals($this->refDB->countLinks(), $db->count()); 116 $this->assertEquals($this->refDB->countLinks(), $db->count());
111 } 117 }
@@ -134,11 +140,11 @@ class BookmarkFileServiceTest extends TestCase
134 140
135 /** 141 /**
136 * Test get() method for an undefined bookmark 142 * Test get() method for an undefined bookmark
137 *
138 * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException
139 */ 143 */
140 public function testGetUndefined() 144 public function testGetUndefined()
141 { 145 {
146 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
147
142 $this->privateLinkDB->get(666); 148 $this->privateLinkDB->get(666);
143 } 149 }
144 150
@@ -174,7 +180,7 @@ class BookmarkFileServiceTest extends TestCase
174 $this->assertEquals($updated, $bookmark->getUpdated()); 180 $this->assertEquals($updated, $bookmark->getUpdated());
175 181
176 // reload from file 182 // reload from file
177 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 183 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
178 184
179 $bookmark = $this->privateLinkDB->get(43); 185 $bookmark = $this->privateLinkDB->get(43);
180 $this->assertEquals(43, $bookmark->getId()); 186 $this->assertEquals(43, $bookmark->getId());
@@ -200,7 +206,7 @@ class BookmarkFileServiceTest extends TestCase
200 206
201 $bookmark = $this->privateLinkDB->get(43); 207 $bookmark = $this->privateLinkDB->get(43);
202 $this->assertEquals(43, $bookmark->getId()); 208 $this->assertEquals(43, $bookmark->getId());
203 $this->assertRegExp('/\?[\w\-]{6}/', $bookmark->getUrl()); 209 $this->assertRegExp('#/shaare/[\w\-]{6}#', $bookmark->getUrl());
204 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl()); 210 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl());
205 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle()); 211 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle());
206 $this->assertEmpty($bookmark->getDescription()); 212 $this->assertEmpty($bookmark->getDescription());
@@ -212,11 +218,11 @@ class BookmarkFileServiceTest extends TestCase
212 $this->assertNull($bookmark->getUpdated()); 218 $this->assertNull($bookmark->getUpdated());
213 219
214 // reload from file 220 // reload from file
215 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 221 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
216 222
217 $bookmark = $this->privateLinkDB->get(43); 223 $bookmark = $this->privateLinkDB->get(43);
218 $this->assertEquals(43, $bookmark->getId()); 224 $this->assertEquals(43, $bookmark->getId());
219 $this->assertRegExp('/\?[\w\-]{6}/', $bookmark->getUrl()); 225 $this->assertRegExp('#/shaare/[\w\-]{6}#', $bookmark->getUrl());
220 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl()); 226 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl());
221 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle()); 227 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle());
222 $this->assertEmpty($bookmark->getDescription()); 228 $this->assertEmpty($bookmark->getDescription());
@@ -230,53 +236,42 @@ class BookmarkFileServiceTest extends TestCase
230 236
231 /** 237 /**
232 * Test add() method for a bookmark without any field set and without writing the data store 238 * Test add() method for a bookmark without any field set and without writing the data store
233 *
234 * @expectedExceptionMessage Shaarli\Bookmark\Exception\BookmarkNotFoundException
235 */ 239 */
236 public function testAddMinimalNoWrite() 240 public function testAddMinimalNoWrite()
237 { 241 {
242 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
243
238 $bookmark = new Bookmark(); 244 $bookmark = new Bookmark();
239 $this->privateLinkDB->add($bookmark); 245 $this->privateLinkDB->add($bookmark, false);
240 246
241 $bookmark = $this->privateLinkDB->get(43); 247 $bookmark = $this->privateLinkDB->get(43);
242 $this->assertEquals(43, $bookmark->getId()); 248 $this->assertEquals(43, $bookmark->getId());
243 249
244 // reload from file 250 // reload from file
245 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 251 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
246 252
247 $this->privateLinkDB->get(43); 253 $this->privateLinkDB->get(43);
248 } 254 }
249 255
250 /** 256 /**
251 * Test add() method while logged out 257 * Test add() method while logged out
252 *
253 * @expectedException \Exception
254 * @expectedExceptionMessage You're not authorized to alter the datastore
255 */ 258 */
256 public function testAddLoggedOut() 259 public function testAddLoggedOut()
257 { 260 {
258 $this->publicLinkDB->add(new Bookmark()); 261 $this->expectException(\Exception::class);
259 } 262 $this->expectExceptionMessage('You\'re not authorized to alter the datastore');
260 263
261 /** 264 $this->publicLinkDB->add(new Bookmark());
262 * Test add() method with an entry which is not a bookmark instance
263 *
264 * @expectedException \Exception
265 * @expectedExceptionMessage Provided data is invalid
266 */
267 public function testAddNotABookmark()
268 {
269 $this->privateLinkDB->add(['title' => 'hi!']);
270 } 265 }
271 266
272 /** 267 /**
273 * Test add() method with a Bookmark already containing an ID 268 * Test add() method with a Bookmark already containing an ID
274 *
275 * @expectedException \Exception
276 * @expectedExceptionMessage This bookmarks already exists
277 */ 269 */
278 public function testAddWithId() 270 public function testAddWithId()
279 { 271 {
272 $this->expectException(\Exception::class);
273 $this->expectExceptionMessage('This bookmarks already exists');
274
280 $bookmark = new Bookmark(); 275 $bookmark = new Bookmark();
281 $bookmark->setId(43); 276 $bookmark->setId(43);
282 $this->privateLinkDB->add($bookmark); 277 $this->privateLinkDB->add($bookmark);
@@ -314,7 +309,7 @@ class BookmarkFileServiceTest extends TestCase
314 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated()); 309 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated());
315 310
316 // reload from file 311 // reload from file
317 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 312 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
318 313
319 $bookmark = $this->privateLinkDB->get(42); 314 $bookmark = $this->privateLinkDB->get(42);
320 $this->assertEquals(42, $bookmark->getId()); 315 $this->assertEquals(42, $bookmark->getId());
@@ -340,7 +335,7 @@ class BookmarkFileServiceTest extends TestCase
340 335
341 $bookmark = $this->privateLinkDB->get(42); 336 $bookmark = $this->privateLinkDB->get(42);
342 $this->assertEquals(42, $bookmark->getId()); 337 $this->assertEquals(42, $bookmark->getId());
343 $this->assertEquals('?WDWyig', $bookmark->getUrl()); 338 $this->assertEquals('/shaare/WDWyig', $bookmark->getUrl());
344 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl()); 339 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl());
345 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle()); 340 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle());
346 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription()); 341 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription());
@@ -355,11 +350,11 @@ class BookmarkFileServiceTest extends TestCase
355 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated()); 350 $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated());
356 351
357 // reload from file 352 // reload from file
358 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 353 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
359 354
360 $bookmark = $this->privateLinkDB->get(42); 355 $bookmark = $this->privateLinkDB->get(42);
361 $this->assertEquals(42, $bookmark->getId()); 356 $this->assertEquals(42, $bookmark->getId());
362 $this->assertEquals('?WDWyig', $bookmark->getUrl()); 357 $this->assertEquals('/shaare/WDWyig', $bookmark->getUrl());
363 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl()); 358 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl());
364 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle()); 359 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle());
365 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription()); 360 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription());
@@ -388,7 +383,7 @@ class BookmarkFileServiceTest extends TestCase
388 $this->assertEquals($title, $bookmark->getTitle()); 383 $this->assertEquals($title, $bookmark->getTitle());
389 384
390 // reload from file 385 // reload from file
391 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 386 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
392 387
393 $bookmark = $this->privateLinkDB->get(42); 388 $bookmark = $this->privateLinkDB->get(42);
394 $this->assertEquals(42, $bookmark->getId()); 389 $this->assertEquals(42, $bookmark->getId());
@@ -397,44 +392,33 @@ class BookmarkFileServiceTest extends TestCase
397 392
398 /** 393 /**
399 * Test set() method while logged out 394 * Test set() method while logged out
400 *
401 * @expectedException \Exception
402 * @expectedExceptionMessage You're not authorized to alter the datastore
403 */ 395 */
404 public function testSetLoggedOut() 396 public function testSetLoggedOut()
405 { 397 {
406 $this->publicLinkDB->set(new Bookmark()); 398 $this->expectException(\Exception::class);
407 } 399 $this->expectExceptionMessage('You\'re not authorized to alter the datastore');
408 400
409 /** 401 $this->publicLinkDB->set(new Bookmark());
410 * Test set() method with an entry which is not a bookmark instance
411 *
412 * @expectedException \Exception
413 * @expectedExceptionMessage Provided data is invalid
414 */
415 public function testSetNotABookmark()
416 {
417 $this->privateLinkDB->set(['title' => 'hi!']);
418 } 402 }
419 403
420 /** 404 /**
421 * Test set() method with a Bookmark without an ID defined. 405 * Test set() method with a Bookmark without an ID defined.
422 *
423 * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException
424 */ 406 */
425 public function testSetWithoutId() 407 public function testSetWithoutId()
426 { 408 {
409 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
410
427 $bookmark = new Bookmark(); 411 $bookmark = new Bookmark();
428 $this->privateLinkDB->set($bookmark); 412 $this->privateLinkDB->set($bookmark);
429 } 413 }
430 414
431 /** 415 /**
432 * Test set() method with a Bookmark with an unknow ID 416 * Test set() method with a Bookmark with an unknow ID
433 *
434 * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException
435 */ 417 */
436 public function testSetWithUnknownId() 418 public function testSetWithUnknownId()
437 { 419 {
420 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
421
438 $bookmark = new Bookmark(); 422 $bookmark = new Bookmark();
439 $bookmark->setId(666); 423 $bookmark->setId(666);
440 $this->privateLinkDB->set($bookmark); 424 $this->privateLinkDB->set($bookmark);
@@ -452,7 +436,7 @@ class BookmarkFileServiceTest extends TestCase
452 $this->assertEquals(43, $bookmark->getId()); 436 $this->assertEquals(43, $bookmark->getId());
453 437
454 // reload from file 438 // reload from file
455 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 439 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
456 440
457 $bookmark = $this->privateLinkDB->get(43); 441 $bookmark = $this->privateLinkDB->get(43);
458 $this->assertEquals(43, $bookmark->getId()); 442 $this->assertEquals(43, $bookmark->getId());
@@ -472,7 +456,7 @@ class BookmarkFileServiceTest extends TestCase
472 $this->assertEquals($title, $bookmark->getTitle()); 456 $this->assertEquals($title, $bookmark->getTitle());
473 457
474 // reload from file 458 // reload from file
475 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 459 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
476 460
477 $bookmark = $this->privateLinkDB->get(42); 461 $bookmark = $this->privateLinkDB->get(42);
478 $this->assertEquals(42, $bookmark->getId()); 462 $this->assertEquals(42, $bookmark->getId());
@@ -481,24 +465,13 @@ class BookmarkFileServiceTest extends TestCase
481 465
482 /** 466 /**
483 * Test addOrSet() method while logged out 467 * Test addOrSet() method while logged out
484 *
485 * @expectedException \Exception
486 * @expectedExceptionMessage You're not authorized to alter the datastore
487 */ 468 */
488 public function testAddOrSetLoggedOut() 469 public function testAddOrSetLoggedOut()
489 { 470 {
490 $this->publicLinkDB->addOrSet(new Bookmark()); 471 $this->expectException(\Exception::class);
491 } 472 $this->expectExceptionMessage('You\'re not authorized to alter the datastore');
492 473
493 /** 474 $this->publicLinkDB->addOrSet(new Bookmark());
494 * Test addOrSet() method with an entry which is not a bookmark instance
495 *
496 * @expectedException \Exception
497 * @expectedExceptionMessage Provided data is invalid
498 */
499 public function testAddOrSetNotABookmark()
500 {
501 $this->privateLinkDB->addOrSet(['title' => 'hi!']);
502 } 475 }
503 476
504 /** 477 /**
@@ -515,7 +488,7 @@ class BookmarkFileServiceTest extends TestCase
515 $this->assertEquals($title, $bookmark->getTitle()); 488 $this->assertEquals($title, $bookmark->getTitle());
516 489
517 // reload from file 490 // reload from file
518 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 491 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
519 492
520 $bookmark = $this->privateLinkDB->get(42); 493 $bookmark = $this->privateLinkDB->get(42);
521 $this->assertEquals(42, $bookmark->getId()); 494 $this->assertEquals(42, $bookmark->getId());
@@ -524,11 +497,11 @@ class BookmarkFileServiceTest extends TestCase
524 497
525 /** 498 /**
526 * Test remove() method with an existing Bookmark 499 * Test remove() method with an existing Bookmark
527 *
528 * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException
529 */ 500 */
530 public function testRemoveExisting() 501 public function testRemoveExisting()
531 { 502 {
503 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
504
532 $bookmark = $this->privateLinkDB->get(42); 505 $bookmark = $this->privateLinkDB->get(42);
533 $this->privateLinkDB->remove($bookmark); 506 $this->privateLinkDB->remove($bookmark);
534 507
@@ -541,41 +514,30 @@ class BookmarkFileServiceTest extends TestCase
541 $this->assertInstanceOf(BookmarkNotFoundException::class, $exception); 514 $this->assertInstanceOf(BookmarkNotFoundException::class, $exception);
542 515
543 // reload from file 516 // reload from file
544 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); 517 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
545 518
546 $this->privateLinkDB->get(42); 519 $this->privateLinkDB->get(42);
547 } 520 }
548 521
549 /** 522 /**
550 * Test remove() method while logged out 523 * Test remove() method while logged out
551 *
552 * @expectedException \Exception
553 * @expectedExceptionMessage You're not authorized to alter the datastore
554 */ 524 */
555 public function testRemoveLoggedOut() 525 public function testRemoveLoggedOut()
556 { 526 {
527 $this->expectException(\Exception::class);
528 $this->expectExceptionMessage('You\'re not authorized to alter the datastore');
529
557 $bookmark = $this->privateLinkDB->get(42); 530 $bookmark = $this->privateLinkDB->get(42);
558 $this->publicLinkDB->remove($bookmark); 531 $this->publicLinkDB->remove($bookmark);
559 } 532 }
560 533
561 /** 534 /**
562 * Test remove() method with an entry which is not a bookmark instance
563 *
564 * @expectedException \Exception
565 * @expectedExceptionMessage Provided data is invalid
566 */
567 public function testRemoveNotABookmark()
568 {
569 $this->privateLinkDB->remove(['title' => 'hi!']);
570 }
571
572 /**
573 * Test remove() method with a Bookmark with an unknown ID 535 * Test remove() method with a Bookmark with an unknown ID
574 *
575 * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException
576 */ 536 */
577 public function testRemoveWithUnknownId() 537 public function testRemoveWithUnknownId()
578 { 538 {
539 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
540
579 $bookmark = new Bookmark(); 541 $bookmark = new Bookmark();
580 $bookmark->setId(666); 542 $bookmark->setId(666);
581 $this->privateLinkDB->remove($bookmark); 543 $this->privateLinkDB->remove($bookmark);
@@ -615,14 +577,18 @@ class BookmarkFileServiceTest extends TestCase
615 { 577 {
616 $dbSize = $this->privateLinkDB->count(); 578 $dbSize = $this->privateLinkDB->count();
617 $this->privateLinkDB->initialize(); 579 $this->privateLinkDB->initialize();
618 $this->assertEquals($dbSize + 2, $this->privateLinkDB->count()); 580 $this->assertEquals($dbSize + 3, $this->privateLinkDB->count());
619 $this->assertEquals( 581 $this->assertStringStartsWith(
620 'My secret stuff... - Pastebin.com', 582 'Shaarli will automatically pick up the thumbnail for links to a variety of websites.',
621 $this->privateLinkDB->get(43)->getTitle() 583 $this->privateLinkDB->get(43)->getDescription()
622 ); 584 );
623 $this->assertEquals( 585 $this->assertStringStartsWith(
624 'The personal, minimalist, super-fast, database free, bookmarking service', 586 'Adding a shaare without entering a URL creates a text-only "note" post such as this one.',
625 $this->privateLinkDB->get(44)->getTitle() 587 $this->privateLinkDB->get(44)->getDescription()
588 );
589 $this->assertStringStartsWith(
590 'Welcome to Shaarli!',
591 $this->privateLinkDB->get(45)->getDescription()
626 ); 592 );
627 } 593 }
628 594
@@ -631,18 +597,17 @@ class BookmarkFileServiceTest extends TestCase
631 * to make sure that nothing have been broken in the migration process. 597 * to make sure that nothing have been broken in the migration process.
632 * They mostly cover search/filters. Some of them might be redundant with the previous ones. 598 * They mostly cover search/filters. Some of them might be redundant with the previous ones.
633 */ 599 */
634
635 /** 600 /**
636 * Attempt to instantiate a LinkDB whereas the datastore is not writable 601 * Attempt to instantiate a LinkDB whereas the datastore is not writable
637 *
638 * @expectedException Shaarli\Bookmark\Exception\NotWritableDataStoreException
639 * @expectedExceptionMessageRegExp #Couldn't load data from the data store file "null".*#
640 */ 602 */
641 public function testConstructDatastoreNotWriteable() 603 public function testConstructDatastoreNotWriteable()
642 { 604 {
605 $this->expectException(\Shaarli\Bookmark\Exception\NotWritableDataStoreException::class);
606 $this->expectExceptionMessageRegExp('#Couldn\'t load data from the data store file "null".*#');
607
643 $conf = new ConfigManager('tests/utils/config/configJson'); 608 $conf = new ConfigManager('tests/utils/config/configJson');
644 $conf->set('resource.datastore', 'null/store.db'); 609 $conf->set('resource.datastore', 'null/store.db');
645 new BookmarkFileService($conf, $this->history, true); 610 new BookmarkFileService($conf, $this->history, $this->mutex, true);
646 } 611 }
647 612
648 /** 613 /**
@@ -652,7 +617,7 @@ class BookmarkFileServiceTest extends TestCase
652 { 617 {
653 unlink(self::$testDatastore); 618 unlink(self::$testDatastore);
654 $this->assertFileNotExists(self::$testDatastore); 619 $this->assertFileNotExists(self::$testDatastore);
655 new BookmarkFileService($this->conf, $this->history, true); 620 new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
656 $this->assertFileExists(self::$testDatastore); 621 $this->assertFileExists(self::$testDatastore);
657 622
658 // ensure the correct data has been written 623 // ensure the correct data has been written
@@ -666,7 +631,7 @@ class BookmarkFileServiceTest extends TestCase
666 { 631 {
667 unlink(self::$testDatastore); 632 unlink(self::$testDatastore);
668 $this->assertFileNotExists(self::$testDatastore); 633 $this->assertFileNotExists(self::$testDatastore);
669 $db = new \FakeBookmarkService($this->conf, $this->history, false); 634 $db = new \FakeBookmarkService($this->conf, $this->history, $this->mutex, false);
670 $this->assertFileNotExists(self::$testDatastore); 635 $this->assertFileNotExists(self::$testDatastore);
671 $this->assertInstanceOf(BookmarkArray::class, $db->getBookmarks()); 636 $this->assertInstanceOf(BookmarkArray::class, $db->getBookmarks());
672 $this->assertCount(0, $db->getBookmarks()); 637 $this->assertCount(0, $db->getBookmarks());
@@ -699,13 +664,13 @@ class BookmarkFileServiceTest extends TestCase
699 */ 664 */
700 public function testSave() 665 public function testSave()
701 { 666 {
702 $testDB = new BookmarkFileService($this->conf, $this->history, true); 667 $testDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
703 $dbSize = $testDB->count(); 668 $dbSize = $testDB->count();
704 669
705 $bookmark = new Bookmark(); 670 $bookmark = new Bookmark();
706 $testDB->add($bookmark); 671 $testDB->add($bookmark);
707 672
708 $testDB = new BookmarkFileService($this->conf, $this->history, true); 673 $testDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
709 $this->assertEquals($dbSize + 1, $testDB->count()); 674 $this->assertEquals($dbSize + 1, $testDB->count());
710 } 675 }
711 676
@@ -715,28 +680,12 @@ class BookmarkFileServiceTest extends TestCase
715 public function testCountHiddenPublic() 680 public function testCountHiddenPublic()
716 { 681 {
717 $this->conf->set('privacy.hide_public_links', true); 682 $this->conf->set('privacy.hide_public_links', true);
718 $linkDB = new BookmarkFileService($this->conf, $this->history, false); 683 $linkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, false);
719 684
720 $this->assertEquals(0, $linkDB->count()); 685 $this->assertEquals(0, $linkDB->count());
721 } 686 }
722 687
723 /** 688 /**
724 * List the days for which bookmarks have been posted
725 */
726 public function testDays()
727 {
728 $this->assertEquals(
729 ['20100309', '20100310', '20121206', '20121207', '20130614', '20150310'],
730 $this->publicLinkDB->days()
731 );
732
733 $this->assertEquals(
734 ['20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'],
735 $this->privateLinkDB->days()
736 );
737 }
738
739 /**
740 * The URL corresponds to an existing entry in the DB 689 * The URL corresponds to an existing entry in the DB
741 */ 690 */
742 public function testGetKnownLinkFromURL() 691 public function testGetKnownLinkFromURL()
@@ -744,7 +693,7 @@ class BookmarkFileServiceTest extends TestCase
744 $link = $this->publicLinkDB->findByUrl('http://mediagoblin.org/'); 693 $link = $this->publicLinkDB->findByUrl('http://mediagoblin.org/');
745 694
746 $this->assertNotEquals(false, $link); 695 $this->assertNotEquals(false, $link);
747 $this->assertContains( 696 $this->assertContainsPolyfill(
748 'A free software media publishing platform', 697 'A free software media publishing platform',
749 $link->getDescription() 698 $link->getDescription()
750 ); 699 );
@@ -783,6 +732,10 @@ class BookmarkFileServiceTest extends TestCase
783 // They need to be grouped with the first case found - order by date DESC: `sTuff`. 732 // They need to be grouped with the first case found - order by date DESC: `sTuff`.
784 'sTuff' => 2, 733 'sTuff' => 2,
785 'ut' => 1, 734 'ut' => 1,
735 'assurance' => 1,
736 'coding-style' => 1,
737 'quality' => 1,
738 'standards' => 1,
786 ], 739 ],
787 $this->publicLinkDB->bookmarksCountPerTag() 740 $this->publicLinkDB->bookmarksCountPerTag()
788 ); 741 );
@@ -811,12 +764,15 @@ class BookmarkFileServiceTest extends TestCase
811 'tag3' => 1, 764 'tag3' => 1,
812 'tag4' => 1, 765 'tag4' => 1,
813 'ut' => 1, 766 'ut' => 1,
767 'assurance' => 1,
768 'coding-style' => 1,
769 'quality' => 1,
770 'standards' => 1,
814 ], 771 ],
815 $this->privateLinkDB->bookmarksCountPerTag() 772 $this->privateLinkDB->bookmarksCountPerTag()
816 ); 773 );
817 $this->assertEquals( 774 $this->assertEquals(
818 [ 775 [
819 'web' => 4,
820 'cartoon' => 2, 776 'cartoon' => 2,
821 'gnu' => 1, 777 'gnu' => 1,
822 'dev' => 1, 778 'dev' => 1,
@@ -833,7 +789,6 @@ class BookmarkFileServiceTest extends TestCase
833 ); 789 );
834 $this->assertEquals( 790 $this->assertEquals(
835 [ 791 [
836 'web' => 1,
837 'html' => 1, 792 'html' => 1,
838 'w3c' => 1, 793 'w3c' => 1,
839 'css' => 1, 794 'css' => 1,
@@ -894,39 +849,70 @@ class BookmarkFileServiceTest extends TestCase
894 public function testFilterHashValid() 849 public function testFilterHashValid()
895 { 850 {
896 $request = smallHash('20150310_114651'); 851 $request = smallHash('20150310_114651');
897 $this->assertEquals( 852 $this->assertSame(
898 1, 853 $request,
899 count($this->publicLinkDB->findByHash($request)) 854 $this->publicLinkDB->findByHash($request)->getShortUrl()
900 ); 855 );
901 $request = smallHash('20150310_114633' . 8); 856 $request = smallHash('20150310_114633' . 8);
902 $this->assertEquals( 857 $this->assertSame(
903 1, 858 $request,
904 count($this->publicLinkDB->findByHash($request)) 859 $this->publicLinkDB->findByHash($request)->getShortUrl()
905 ); 860 );
906 } 861 }
907 862
908 /** 863 /**
909 * Test filterHash() with an invalid smallhash. 864 * Test filterHash() with an invalid smallhash.
910 *
911 * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException
912 */ 865 */
913 public function testFilterHashInValid1() 866 public function testFilterHashInValid1()
914 { 867 {
868 $this->expectException(BookmarkNotFoundException::class);
869
915 $request = 'blabla'; 870 $request = 'blabla';
916 $this->publicLinkDB->findByHash($request); 871 $this->publicLinkDB->findByHash($request);
917 } 872 }
918 873
919 /** 874 /**
920 * Test filterHash() with an empty smallhash. 875 * Test filterHash() with an empty smallhash.
921 *
922 * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException
923 */ 876 */
924 public function testFilterHashInValid() 877 public function testFilterHashInValid()
925 { 878 {
879 $this->expectException(BookmarkNotFoundException::class);
880
926 $this->publicLinkDB->findByHash(''); 881 $this->publicLinkDB->findByHash('');
927 } 882 }
928 883
929 /** 884 /**
885 * Test filterHash() on a private bookmark while logged out.
886 */
887 public function testFilterHashPrivateWhileLoggedOut()
888 {
889 $this->expectException(BookmarkNotFoundException::class);
890 $this->expectExceptionMessage('The link you are trying to reach does not exist or has been deleted');
891
892 $hash = smallHash('20141125_084734' . 6);
893
894 $this->publicLinkDB->findByHash($hash);
895 }
896
897 /**
898 * Test filterHash() with private key.
899 */
900 public function testFilterHashWithPrivateKey()
901 {
902 $hash = smallHash('20141125_084734' . 6);
903 $privateKey = 'this is usually auto generated';
904
905 $bookmark = $this->privateLinkDB->findByHash($hash);
906 $bookmark->addAdditionalContentEntry('private_key', $privateKey);
907 $this->privateLinkDB->save();
908
909 $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, false);
910 $bookmark = $this->privateLinkDB->findByHash($hash, $privateKey);
911
912 static::assertSame(6, $bookmark->getId());
913 }
914
915 /**
930 * Test linksCountPerTag all tags without filter. 916 * Test linksCountPerTag all tags without filter.
931 * Equal occurrences should be sorted alphabetically. 917 * Equal occurrences should be sorted alphabetically.
932 */ 918 */
@@ -955,6 +941,10 @@ class BookmarkFileServiceTest extends TestCase
955 'tag4' => 1, 941 'tag4' => 1,
956 'ut' => 1, 942 'ut' => 1,
957 'w3c' => 1, 943 'w3c' => 1,
944 'assurance' => 1,
945 'coding-style' => 1,
946 'quality' => 1,
947 'standards' => 1,
958 ]; 948 ];
959 $tags = $this->privateLinkDB->bookmarksCountPerTag(); 949 $tags = $this->privateLinkDB->bookmarksCountPerTag();
960 950
@@ -968,7 +958,6 @@ class BookmarkFileServiceTest extends TestCase
968 public function testCountLinkPerTagAllWithFilter() 958 public function testCountLinkPerTagAllWithFilter()
969 { 959 {
970 $expected = [ 960 $expected = [
971 'gnu' => 2,
972 'hashtag' => 2, 961 'hashtag' => 2,
973 '-exclude' => 1, 962 '-exclude' => 1,
974 '.hidden' => 1, 963 '.hidden' => 1,
@@ -991,7 +980,6 @@ class BookmarkFileServiceTest extends TestCase
991 public function testCountLinkPerTagPublicWithFilter() 980 public function testCountLinkPerTagPublicWithFilter()
992 { 981 {
993 $expected = [ 982 $expected = [
994 'gnu' => 2,
995 'hashtag' => 2, 983 'hashtag' => 2,
996 '-exclude' => 1, 984 '-exclude' => 1,
997 '.hidden' => 1, 985 '.hidden' => 1,
@@ -1015,7 +1003,6 @@ class BookmarkFileServiceTest extends TestCase
1015 { 1003 {
1016 $expected = [ 1004 $expected = [
1017 'cartoon' => 1, 1005 'cartoon' => 1,
1018 'dev' => 1,
1019 'tag1' => 1, 1006 'tag1' => 1,
1020 'tag2' => 1, 1007 'tag2' => 1,
1021 'tag3' => 1, 1008 'tag3' => 1,
@@ -1056,6 +1043,10 @@ class BookmarkFileServiceTest extends TestCase
1056 'stallman' => 1, 1043 'stallman' => 1,
1057 'ut' => 1, 1044 'ut' => 1,
1058 'w3c' => 1, 1045 'w3c' => 1,
1046 'assurance' => 1,
1047 'coding-style' => 1,
1048 'quality' => 1,
1049 'standards' => 1,
1059 ]; 1050 ];
1060 $bookmark = new Bookmark(); 1051 $bookmark = new Bookmark();
1061 $bookmark->setTags(['newTagToCount', BookmarkMarkdownFormatter::NO_MD_TAG]); 1052 $bookmark->setTags(['newTagToCount', BookmarkMarkdownFormatter::NO_MD_TAG]);
@@ -1067,6 +1058,108 @@ class BookmarkFileServiceTest extends TestCase
1067 } 1058 }
1068 1059
1069 /** 1060 /**
1061 * Test find by dates in the middle of the datastore (sorted by dates) with a single bookmark as a result.
1062 */
1063 public function testFilterByDateMidTimePeriodSingleBookmark(): void
1064 {
1065 $bookmarks = $this->privateLinkDB->findByDate(
1066 DateTime::createFromFormat('Ymd_His', '20121206_150000'),
1067 DateTime::createFromFormat('Ymd_His', '20121206_160000'),
1068 $before,
1069 $after
1070 );
1071
1072 static::assertCount(1, $bookmarks);
1073
1074 static::assertSame(9, $bookmarks[0]->getId());
1075 static::assertEquals(DateTime::createFromFormat('Ymd_His', '20121206_142300'), $before);
1076 static::assertEquals(DateTime::createFromFormat('Ymd_His', '20121206_172539'), $after);
1077 }
1078
1079 /**
1080 * Test find by dates in the middle of the datastore (sorted by dates) with a multiple bookmarks as a result.
1081 */
1082 public function testFilterByDateMidTimePeriodMultipleBookmarks(): void
1083 {
1084 $bookmarks = $this->privateLinkDB->findByDate(
1085 DateTime::createFromFormat('Ymd_His', '20121206_150000'),
1086 DateTime::createFromFormat('Ymd_His', '20121206_180000'),
1087 $before,
1088 $after
1089 );
1090
1091 static::assertCount(2, $bookmarks);
1092
1093 static::assertSame(1, $bookmarks[0]->getId());
1094 static::assertSame(9, $bookmarks[1]->getId());
1095 static::assertEquals(DateTime::createFromFormat('Ymd_His', '20121206_142300'), $before);
1096 static::assertEquals(DateTime::createFromFormat('Ymd_His', '20121206_182539'), $after);
1097 }
1098
1099 /**
1100 * Test find by dates at the end of the datastore (sorted by dates).
1101 */
1102 public function testFilterByDateLastTimePeriod(): void
1103 {
1104 $after = new DateTime();
1105 $bookmarks = $this->privateLinkDB->findByDate(
1106 DateTime::createFromFormat('Ymd_His', '20150310_114640'),
1107 DateTime::createFromFormat('Ymd_His', '20450101_010101'),
1108 $before,
1109 $after
1110 );
1111
1112 static::assertCount(1, $bookmarks);
1113
1114 static::assertSame(41, $bookmarks[0]->getId());
1115 static::assertEquals(DateTime::createFromFormat('Ymd_His', '20150310_114633'), $before);
1116 static::assertNull($after);
1117 }
1118
1119 /**
1120 * Test find by dates at the beginning of the datastore (sorted by dates).
1121 */
1122 public function testFilterByDateFirstTimePeriod(): void
1123 {
1124 $before = new DateTime();
1125 $bookmarks = $this->privateLinkDB->findByDate(
1126 DateTime::createFromFormat('Ymd_His', '20000101_101010'),
1127 DateTime::createFromFormat('Ymd_His', '20100309_110000'),
1128 $before,
1129 $after
1130 );
1131
1132 static::assertCount(1, $bookmarks);
1133
1134 static::assertSame(11, $bookmarks[0]->getId());
1135 static::assertNull($before);
1136 static::assertEquals(DateTime::createFromFormat('Ymd_His', '20100310_101010'), $after);
1137 }
1138
1139 /**
1140 * Test getLatest with a sticky bookmark: it should be ignored and return the latest by creation date instead.
1141 */
1142 public function testGetLatestWithSticky(): void
1143 {
1144 $bookmark = $this->publicLinkDB->getLatest();
1145
1146 static::assertSame(41, $bookmark->getId());
1147 }
1148
1149 /**
1150 * Test getLatest with a sticky bookmark: it should be ignored and return the latest by creation date instead.
1151 */
1152 public function testGetLatestEmptyDatastore(): void
1153 {
1154 unlink($this->conf->get('resource.datastore'));
1155 $this->publicLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, false);
1156
1157 $bookmark = $this->publicLinkDB->getLatest();
1158
1159 static::assertNull($bookmark);
1160 }
1161
1162 /**
1070 * Allows to test LinkDB's private methods 1163 * Allows to test LinkDB's private methods
1071 * 1164 *
1072 * @see 1165 * @see
diff --git a/tests/bookmark/BookmarkFilterTest.php b/tests/bookmark/BookmarkFilterTest.php
index d4c71cb9..574d8e3f 100644
--- a/tests/bookmark/BookmarkFilterTest.php
+++ b/tests/bookmark/BookmarkFilterTest.php
@@ -2,12 +2,11 @@
2 2
3namespace Shaarli\Bookmark; 3namespace Shaarli\Bookmark;
4 4
5use Exception; 5use malkusch\lock\mutex\NoMutex;
6use PHPUnit\Framework\TestCase;
7use ReferenceLinkDB; 6use ReferenceLinkDB;
8use Shaarli\Config\ConfigManager; 7use Shaarli\Config\ConfigManager;
9use Shaarli\Formatter\FormatterFactory;
10use Shaarli\History; 8use Shaarli\History;
9use Shaarli\TestCase;
11 10
12/** 11/**
13 * Class BookmarkFilterTest. 12 * Class BookmarkFilterTest.
@@ -36,14 +35,15 @@ class BookmarkFilterTest extends TestCase
36 /** 35 /**
37 * Instantiate linkFilter with ReferenceLinkDB data. 36 * Instantiate linkFilter with ReferenceLinkDB data.
38 */ 37 */
39 public static function setUpBeforeClass() 38 public static function setUpBeforeClass(): void
40 { 39 {
40 $mutex = new NoMutex();
41 $conf = new ConfigManager('tests/utils/config/configJson'); 41 $conf = new ConfigManager('tests/utils/config/configJson');
42 $conf->set('resource.datastore', self::$testDatastore); 42 $conf->set('resource.datastore', self::$testDatastore);
43 self::$refDB = new \ReferenceLinkDB(); 43 self::$refDB = new \ReferenceLinkDB();
44 self::$refDB->write(self::$testDatastore); 44 self::$refDB->write(self::$testDatastore);
45 $history = new History('sandbox/history.php'); 45 $history = new History('sandbox/history.php');
46 self::$bookmarkService = new \FakeBookmarkService($conf, $history, true); 46 self::$bookmarkService = new \FakeBookmarkService($conf, $history, $mutex, true);
47 self::$linkFilter = new BookmarkFilter(self::$bookmarkService->getBookmarks()); 47 self::$linkFilter = new BookmarkFilter(self::$bookmarkService->getBookmarks());
48 } 48 }
49 49
@@ -190,6 +190,17 @@ class BookmarkFilterTest extends TestCase
190 } 190 }
191 191
192 /** 192 /**
193 * Return bookmarks for a given day
194 */
195 public function testFilterDayRestrictedVisibility(): void
196 {
197 $this->assertEquals(
198 3,
199 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '20121206', false, BookmarkFilter::$PUBLIC))
200 );
201 }
202
203 /**
193 * 404 - day not found 204 * 404 - day not found
194 */ 205 */
195 public function testFilterUnknownDay() 206 public function testFilterUnknownDay()
@@ -202,21 +213,23 @@ class BookmarkFilterTest extends TestCase
202 213
203 /** 214 /**
204 * Use an invalid date format 215 * Use an invalid date format
205 * @expectedException Exception
206 * @expectedExceptionMessageRegExp /Invalid date format/
207 */ 216 */
208 public function testFilterInvalidDayWithChars() 217 public function testFilterInvalidDayWithChars()
209 { 218 {
219 $this->expectException(\Exception::class);
220 $this->expectExceptionMessageRegExp('/Invalid date format/');
221
210 self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, 'Rainy day, dream away'); 222 self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, 'Rainy day, dream away');
211 } 223 }
212 224
213 /** 225 /**
214 * Use an invalid date format 226 * Use an invalid date format
215 * @expectedException Exception
216 * @expectedExceptionMessageRegExp /Invalid date format/
217 */ 227 */
218 public function testFilterInvalidDayDigits() 228 public function testFilterInvalidDayDigits()
219 { 229 {
230 $this->expectException(\Exception::class);
231 $this->expectExceptionMessageRegExp('/Invalid date format/');
232
220 self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '20'); 233 self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '20');
221 } 234 }
222 235
@@ -240,11 +253,11 @@ class BookmarkFilterTest extends TestCase
240 253
241 /** 254 /**
242 * No link for this hash 255 * No link for this hash
243 *
244 * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException
245 */ 256 */
246 public function testFilterUnknownSmallHash() 257 public function testFilterUnknownSmallHash()
247 { 258 {
259 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
260
248 self::$linkFilter->filter(BookmarkFilter::$FILTER_HASH, 'Iblaah'); 261 self::$linkFilter->filter(BookmarkFilter::$FILTER_HASH, 'Iblaah');
249 } 262 }
250 263
@@ -511,4 +524,43 @@ class BookmarkFilterTest extends TestCase
511 )) 524 ))
512 ); 525 );
513 } 526 }
527
528 /**
529 * Test search result highlights in every field of bookmark reference #9.
530 */
531 public function testFullTextSearchHighlight(): void
532 {
533 $bookmarks = self::$linkFilter->filter(
534 BookmarkFilter::$FILTER_TEXT,
535 '"psr-2" coding guide http fig "psr-2/" "This guide" basic standard. coding-style quality assurance'
536 );
537
538 static::assertCount(1, $bookmarks);
539 static::assertArrayHasKey(9, $bookmarks);
540
541 $bookmark = $bookmarks[9];
542 $expectedHighlights = [
543 'title' => [
544 ['start' => 0, 'end' => 5], // "psr-2"
545 ['start' => 7, 'end' => 13], // coding
546 ['start' => 20, 'end' => 25], // guide
547 ],
548 'description' => [
549 ['start' => 0, 'end' => 10], // "This guide"
550 ['start' => 45, 'end' => 50], // basic
551 ['start' => 58, 'end' => 67], // standard.
552 ],
553 'url' => [
554 ['start' => 0, 'end' => 4], // http
555 ['start' => 15, 'end' => 18], // fig
556 ['start' => 27, 'end' => 33], // "psr-2/"
557 ],
558 'tags' => [
559 ['start' => 0, 'end' => 12], // coding-style
560 ['start' => 23, 'end' => 30], // quality
561 ['start' => 31, 'end' => 40], // assurance
562 ],
563 ];
564 static::assertSame($expectedHighlights, $bookmark->getAdditionalContentEntry('search_highlight'));
565 }
514} 566}
diff --git a/tests/bookmark/BookmarkInitializerTest.php b/tests/bookmark/BookmarkInitializerTest.php
index d23eb069..0c8420ce 100644
--- a/tests/bookmark/BookmarkInitializerTest.php
+++ b/tests/bookmark/BookmarkInitializerTest.php
@@ -2,10 +2,10 @@
2 2
3namespace Shaarli\Bookmark; 3namespace Shaarli\Bookmark;
4 4
5use PHPUnit\Framework\TestCase; 5use malkusch\lock\mutex\NoMutex;
6use ReferenceLinkDB;
7use Shaarli\Config\ConfigManager; 6use Shaarli\Config\ConfigManager;
8use Shaarli\History; 7use Shaarli\History;
8use Shaarli\TestCase;
9 9
10/** 10/**
11 * Class BookmarkInitializerTest 11 * Class BookmarkInitializerTest
@@ -35,11 +35,15 @@ class BookmarkInitializerTest extends TestCase
35 /** @var BookmarkInitializer instance */ 35 /** @var BookmarkInitializer instance */
36 protected $initializer; 36 protected $initializer;
37 37
38 /** @var NoMutex */
39 protected $mutex;
40
38 /** 41 /**
39 * Initialize an empty BookmarkFileService 42 * Initialize an empty BookmarkFileService
40 */ 43 */
41 public function setUp() 44 public function setUp(): void
42 { 45 {
46 $this->mutex = new NoMutex();
43 if (file_exists(self::$testDatastore)) { 47 if (file_exists(self::$testDatastore)) {
44 unlink(self::$testDatastore); 48 unlink(self::$testDatastore);
45 } 49 }
@@ -48,72 +52,103 @@ class BookmarkInitializerTest extends TestCase
48 $this->conf = new ConfigManager(self::$testConf); 52 $this->conf = new ConfigManager(self::$testConf);
49 $this->conf->set('resource.datastore', self::$testDatastore); 53 $this->conf->set('resource.datastore', self::$testDatastore);
50 $this->history = new History('sandbox/history.php'); 54 $this->history = new History('sandbox/history.php');
51 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true); 55 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
52 56
53 $this->initializer = new BookmarkInitializer($this->bookmarkService); 57 $this->initializer = new BookmarkInitializer($this->bookmarkService);
54 } 58 }
55 59
56 /** 60 /**
57 * Test initialize() with an empty data store. 61 * Test initialize() with a data store containing bookmarks.
58 */ 62 */
59 public function testInitializeEmptyDataStore() 63 public function testInitializeNotEmptyDataStore(): void
60 { 64 {
61 $refDB = new \ReferenceLinkDB(); 65 $refDB = new \ReferenceLinkDB();
62 $refDB->write(self::$testDatastore); 66 $refDB->write(self::$testDatastore);
63 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true); 67 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
64 $this->initializer = new BookmarkInitializer($this->bookmarkService); 68 $this->initializer = new BookmarkInitializer($this->bookmarkService);
65 69
66 $this->initializer->initialize(); 70 $this->initializer->initialize();
67 71
68 $this->assertEquals($refDB->countLinks() + 2, $this->bookmarkService->count()); 72 $this->assertEquals($refDB->countLinks() + 3, $this->bookmarkService->count());
73
69 $bookmark = $this->bookmarkService->get(43); 74 $bookmark = $this->bookmarkService->get(43);
70 $this->assertEquals(43, $bookmark->getId()); 75 $this->assertStringStartsWith(
71 $this->assertEquals('My secret stuff... - Pastebin.com', $bookmark->getTitle()); 76 'Shaarli will automatically pick up the thumbnail for links to a variety of websites.',
77 $bookmark->getDescription()
78 );
72 $this->assertTrue($bookmark->isPrivate()); 79 $this->assertTrue($bookmark->isPrivate());
73 80
74 $bookmark = $this->bookmarkService->get(44); 81 $bookmark = $this->bookmarkService->get(44);
75 $this->assertEquals(44, $bookmark->getId()); 82 $this->assertStringStartsWith(
76 $this->assertEquals( 83 'Adding a shaare without entering a URL creates a text-only "note" post such as this one.',
77 'The personal, minimalist, super-fast, database free, bookmarking service', 84 $bookmark->getDescription()
78 $bookmark->getTitle() 85 );
86 $this->assertTrue($bookmark->isPrivate());
87
88 $bookmark = $this->bookmarkService->get(45);
89 $this->assertStringStartsWith(
90 'Welcome to Shaarli!',
91 $bookmark->getDescription()
79 ); 92 );
80 $this->assertFalse($bookmark->isPrivate()); 93 $this->assertFalse($bookmark->isPrivate());
81 94
95 $this->bookmarkService->save();
96
82 // Reload from file 97 // Reload from file
83 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true); 98 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
84 $this->assertEquals($refDB->countLinks() + 2, $this->bookmarkService->count()); 99 $this->assertEquals($refDB->countLinks() + 3, $this->bookmarkService->count());
100
85 $bookmark = $this->bookmarkService->get(43); 101 $bookmark = $this->bookmarkService->get(43);
86 $this->assertEquals(43, $bookmark->getId()); 102 $this->assertStringStartsWith(
87 $this->assertEquals('My secret stuff... - Pastebin.com', $bookmark->getTitle()); 103 'Shaarli will automatically pick up the thumbnail for links to a variety of websites.',
104 $bookmark->getDescription()
105 );
88 $this->assertTrue($bookmark->isPrivate()); 106 $this->assertTrue($bookmark->isPrivate());
89 107
90 $bookmark = $this->bookmarkService->get(44); 108 $bookmark = $this->bookmarkService->get(44);
91 $this->assertEquals(44, $bookmark->getId()); 109 $this->assertStringStartsWith(
92 $this->assertEquals( 110 'Adding a shaare without entering a URL creates a text-only "note" post such as this one.',
93 'The personal, minimalist, super-fast, database free, bookmarking service', 111 $bookmark->getDescription()
94 $bookmark->getTitle() 112 );
113 $this->assertTrue($bookmark->isPrivate());
114
115 $bookmark = $this->bookmarkService->get(45);
116 $this->assertStringStartsWith(
117 'Welcome to Shaarli!',
118 $bookmark->getDescription()
95 ); 119 );
96 $this->assertFalse($bookmark->isPrivate()); 120 $this->assertFalse($bookmark->isPrivate());
97 } 121 }
98 122
99 /** 123 /**
100 * Test initialize() with a data store containing bookmarks. 124 * Test initialize() with an a non existent datastore file .
101 */ 125 */
102 public function testInitializeNotEmptyDataStore() 126 public function testInitializeNonExistentDataStore(): void
103 { 127 {
128 $this->conf->set('resource.datastore', static::$testDatastore . '_empty');
129 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, $this->mutex, true);
130
104 $this->initializer->initialize(); 131 $this->initializer->initialize();
105 132
106 $this->assertEquals(2, $this->bookmarkService->count()); 133 $this->assertEquals(3, $this->bookmarkService->count());
107 $bookmark = $this->bookmarkService->get(0); 134 $bookmark = $this->bookmarkService->get(0);
108 $this->assertEquals(0, $bookmark->getId()); 135 $this->assertStringStartsWith(
109 $this->assertEquals('My secret stuff... - Pastebin.com', $bookmark->getTitle()); 136 'Shaarli will automatically pick up the thumbnail for links to a variety of websites.',
137 $bookmark->getDescription()
138 );
110 $this->assertTrue($bookmark->isPrivate()); 139 $this->assertTrue($bookmark->isPrivate());
111 140
112 $bookmark = $this->bookmarkService->get(1); 141 $bookmark = $this->bookmarkService->get(1);
113 $this->assertEquals(1, $bookmark->getId()); 142 $this->assertStringStartsWith(
114 $this->assertEquals( 143 'Adding a shaare without entering a URL creates a text-only "note" post such as this one.',
115 'The personal, minimalist, super-fast, database free, bookmarking service', 144 $bookmark->getDescription()
116 $bookmark->getTitle() 145 );
146 $this->assertTrue($bookmark->isPrivate());
147
148 $bookmark = $this->bookmarkService->get(2);
149 $this->assertStringStartsWith(
150 'Welcome to Shaarli!',
151 $bookmark->getDescription()
117 ); 152 );
118 $this->assertFalse($bookmark->isPrivate()); 153 $this->assertFalse($bookmark->isPrivate());
119 } 154 }
diff --git a/tests/bookmark/BookmarkTest.php b/tests/bookmark/BookmarkTest.php
index 9a3bbbfc..4c1ae25d 100644
--- a/tests/bookmark/BookmarkTest.php
+++ b/tests/bookmark/BookmarkTest.php
@@ -2,8 +2,8 @@
2 2
3namespace Shaarli\Bookmark; 3namespace Shaarli\Bookmark;
4 4
5use PHPUnit\Framework\TestCase;
6use Shaarli\Bookmark\Exception\InvalidBookmarkException; 5use Shaarli\Bookmark\Exception\InvalidBookmarkException;
6use Shaarli\TestCase;
7 7
8/** 8/**
9 * Class BookmarkTest 9 * Class BookmarkTest
@@ -124,8 +124,8 @@ class BookmarkTest extends TestCase
124 $this->assertEquals(1, $bookmark->getId()); 124 $this->assertEquals(1, $bookmark->getId());
125 $this->assertEquals('abc', $bookmark->getShortUrl()); 125 $this->assertEquals('abc', $bookmark->getShortUrl());
126 $this->assertEquals($date, $bookmark->getCreated()); 126 $this->assertEquals($date, $bookmark->getCreated());
127 $this->assertEquals('?abc', $bookmark->getUrl()); 127 $this->assertEquals('/shaare/abc', $bookmark->getUrl());
128 $this->assertEquals('?abc', $bookmark->getTitle()); 128 $this->assertEquals('/shaare/abc', $bookmark->getTitle());
129 $this->assertEquals('', $bookmark->getDescription()); 129 $this->assertEquals('', $bookmark->getDescription());
130 $this->assertEquals([], $bookmark->getTags()); 130 $this->assertEquals([], $bookmark->getTags());
131 $this->assertEquals('', $bookmark->getTagsString()); 131 $this->assertEquals('', $bookmark->getTagsString());
@@ -150,26 +150,7 @@ class BookmarkTest extends TestCase
150 $exception = $e; 150 $exception = $e;
151 } 151 }
152 $this->assertNotNull($exception); 152 $this->assertNotNull($exception);
153 $this->assertContains('- ID: '. PHP_EOL, $exception->getMessage()); 153 $this->assertContainsPolyfill('- ID: '. PHP_EOL, $exception->getMessage());
154 }
155
156 /**
157 * Test validate() with a a bookmark with a non integer ID.
158 */
159 public function testValidateNotValidStringId()
160 {
161 $bookmark = new Bookmark();
162 $bookmark->setId('str');
163 $bookmark->setShortUrl('abc');
164 $bookmark->setCreated(\DateTime::createFromFormat('Ymd_His', '20190514_200102'));
165 $exception = null;
166 try {
167 $bookmark->validate();
168 } catch (InvalidBookmarkException $e) {
169 $exception = $e;
170 }
171 $this->assertNotNull($exception);
172 $this->assertContains('- ID: str'. PHP_EOL, $exception->getMessage());
173 } 154 }
174 155
175 /** 156 /**
@@ -188,7 +169,7 @@ class BookmarkTest extends TestCase
188 $exception = $e; 169 $exception = $e;
189 } 170 }
190 $this->assertNotNull($exception); 171 $this->assertNotNull($exception);
191 $this->assertContains('- ShortUrl: '. PHP_EOL, $exception->getMessage()); 172 $this->assertContainsPolyfill('- ShortUrl: '. PHP_EOL, $exception->getMessage());
192 } 173 }
193 174
194 /** 175 /**
@@ -207,26 +188,7 @@ class BookmarkTest extends TestCase
207 $exception = $e; 188 $exception = $e;
208 } 189 }
209 $this->assertNotNull($exception); 190 $this->assertNotNull($exception);
210 $this->assertContains('- Created: '. PHP_EOL, $exception->getMessage()); 191 $this->assertContainsPolyfill('- Created: '. PHP_EOL, $exception->getMessage());
211 }
212
213 /**
214 * Test validate() with a a bookmark with a bad created datetime.
215 */
216 public function testValidateNotValidBadCreated()
217 {
218 $bookmark = new Bookmark();
219 $bookmark->setId(1);
220 $bookmark->setShortUrl('abc');
221 $bookmark->setCreated('hi!');
222 $exception = null;
223 try {
224 $bookmark->validate();
225 } catch (InvalidBookmarkException $e) {
226 $exception = $e;
227 }
228 $this->assertNotNull($exception);
229 $this->assertContains('- Created: Not a DateTime object'. PHP_EOL, $exception->getMessage());
230 } 192 }
231 193
232 /** 194 /**
@@ -385,4 +347,48 @@ class BookmarkTest extends TestCase
385 $bookmark->deleteTag('nope'); 347 $bookmark->deleteTag('nope');
386 $this->assertEquals(['tag1', 'tag2', 'chair'], $bookmark->getTags()); 348 $this->assertEquals(['tag1', 'tag2', 'chair'], $bookmark->getTags());
387 } 349 }
350
351 /**
352 * Test shouldUpdateThumbnail() with bookmarks needing an update.
353 */
354 public function testShouldUpdateThumbnail(): void
355 {
356 $bookmark = (new Bookmark())->setUrl('http://domain.tld/with-image');
357
358 static::assertTrue($bookmark->shouldUpdateThumbnail());
359
360 $bookmark = (new Bookmark())
361 ->setUrl('http://domain.tld/with-image')
362 ->setThumbnail('unknown file')
363 ;
364
365 static::assertTrue($bookmark->shouldUpdateThumbnail());
366 }
367
368 /**
369 * Test shouldUpdateThumbnail() with bookmarks that should not update.
370 */
371 public function testShouldNotUpdateThumbnail(): void
372 {
373 $bookmark = (new Bookmark());
374
375 static::assertFalse($bookmark->shouldUpdateThumbnail());
376
377 $bookmark = (new Bookmark())
378 ->setUrl('ftp://domain.tld/other-protocol', ['ftp'])
379 ;
380
381 static::assertFalse($bookmark->shouldUpdateThumbnail());
382
383 $bookmark = (new Bookmark())
384 ->setUrl('http://domain.tld/with-image')
385 ->setThumbnail(__FILE__)
386 ;
387
388 static::assertFalse($bookmark->shouldUpdateThumbnail());
389
390 $bookmark = (new Bookmark())->setUrl('/shaare/abcdef');
391
392 static::assertFalse($bookmark->shouldUpdateThumbnail());
393 }
388} 394}
diff --git a/tests/bookmark/LinkUtilsTest.php b/tests/bookmark/LinkUtilsTest.php
index 591976f2..3321242f 100644
--- a/tests/bookmark/LinkUtilsTest.php
+++ b/tests/bookmark/LinkUtilsTest.php
@@ -2,9 +2,7 @@
2 2
3namespace Shaarli\Bookmark; 3namespace Shaarli\Bookmark;
4 4
5use PHPUnit\Framework\TestCase; 5use Shaarli\TestCase;
6use ReferenceLinkDB;
7use Shaarli\Config\ConfigManager;
8 6
9require_once 'tests/utils/CurlUtils.php'; 7require_once 'tests/utils/CurlUtils.php';
10 8
@@ -45,6 +43,19 @@ class LinkUtilsTest extends TestCase
45 } 43 }
46 44
47 /** 45 /**
46 * Test headers_extract_charset() when the charset is found with odd quotes.
47 */
48 public function testHeadersExtractExistentCharsetWithQuotes()
49 {
50 $charset = 'x-MacCroatian';
51 $headers = 'text/html; charset="' . $charset . '"otherstuff="test"';
52 $this->assertEquals(strtolower($charset), header_extract_charset($headers));
53
54 $headers = 'text/html; charset=\'' . $charset . '\'otherstuff="test"';
55 $this->assertEquals(strtolower($charset), header_extract_charset($headers));
56 }
57
58 /**
48 * Test headers_extract_charset() when the charset is not found. 59 * Test headers_extract_charset() when the charset is not found.
49 */ 60 */
50 public function testHeadersExtractNonExistentCharset() 61 public function testHeadersExtractNonExistentCharset()
@@ -83,8 +94,78 @@ class LinkUtilsTest extends TestCase
83 public function testHtmlExtractExistentNameTag() 94 public function testHtmlExtractExistentNameTag()
84 { 95 {
85 $description = 'Bob and Alice share cookies.'; 96 $description = 'Bob and Alice share cookies.';
97
98 // Simple one line
86 $html = '<html><meta>stuff2</meta><meta name="description" content="' . $description . '"/></html>'; 99 $html = '<html><meta>stuff2</meta><meta name="description" content="' . $description . '"/></html>';
87 $this->assertEquals($description, html_extract_tag('description', $html)); 100 $this->assertEquals($description, html_extract_tag('description', $html));
101
102 // Simple OpenGraph
103 $html = '<meta property="og:description" content="' . $description . '">';
104 $this->assertEquals($description, html_extract_tag('description', $html));
105
106 // Simple reversed OpenGraph
107 $html = '<meta content="' . $description . '" property="og:description">';
108 $this->assertEquals($description, html_extract_tag('description', $html));
109
110 // ItemProp OpenGraph
111 $html = '<meta itemprop="og:description" content="' . $description . '">';
112 $this->assertEquals($description, html_extract_tag('description', $html));
113
114 // OpenGraph without quotes
115 $html = '<meta property=og:description content="' . $description . '">';
116 $this->assertEquals($description, html_extract_tag('description', $html));
117
118 // OpenGraph reversed without quotes
119 $html = '<meta content="' . $description . '" property=og:description>';
120 $this->assertEquals($description, html_extract_tag('description', $html));
121
122 // OpenGraph with noise
123 $html = '<meta tag1="content1" property="og:description" tag2="content2" content="' .
124 $description . '" tag3="content3">';
125 $this->assertEquals($description, html_extract_tag('description', $html));
126
127 // OpenGraph reversed with noise
128 $html = '<meta tag1="content1" content="' . $description . '" ' .
129 'tag3="content3" tag2="content2" property="og:description">';
130 $this->assertEquals($description, html_extract_tag('description', $html));
131
132 // OpenGraph multiple properties start
133 $html = '<meta property="unrelated og:description" content="' . $description . '">';
134 $this->assertEquals($description, html_extract_tag('description', $html));
135
136 // OpenGraph multiple properties end
137 $html = '<meta property="og:description unrelated" content="' . $description . '">';
138 $this->assertEquals($description, html_extract_tag('description', $html));
139
140 // OpenGraph multiple properties both end
141 $html = '<meta property="og:unrelated1 og:description og:unrelated2" content="' . $description . '">';
142 $this->assertEquals($description, html_extract_tag('description', $html));
143
144 // OpenGraph multiple properties both end with noise
145 $html = '<meta tag1="content1" property="og:unrelated1 og:description og:unrelated2" '.
146 'tag2="content2" content="' . $description . '" tag3="content3">';
147 $this->assertEquals($description, html_extract_tag('description', $html));
148
149 // OpenGraph reversed multiple properties start
150 $html = '<meta content="' . $description . '" property="unrelated og:description">';
151 $this->assertEquals($description, html_extract_tag('description', $html));
152
153 // OpenGraph reversed multiple properties end
154 $html = '<meta content="' . $description . '" property="og:description unrelated">';
155 $this->assertEquals($description, html_extract_tag('description', $html));
156
157 // OpenGraph reversed multiple properties both end
158 $html = '<meta content="' . $description . '" property="og:unrelated1 og:description og:unrelated2">';
159 $this->assertEquals($description, html_extract_tag('description', $html));
160
161 // OpenGraph reversed multiple properties both end with noise
162 $html = '<meta tag1="content1" content="' . $description . '" tag2="content2" '.
163 'property="og:unrelated1 og:description og:unrelated2" tag3="content3">';
164 $this->assertEquals($description, html_extract_tag('description', $html));
165
166 // Suggestion from #1375
167 $html = '<meta property="og:description" name="description" content="' . $description . '">';
168 $this->assertEquals($description, html_extract_tag('description', $html));
88 } 169 }
89 170
90 /** 171 /**
@@ -94,6 +175,25 @@ class LinkUtilsTest extends TestCase
94 { 175 {
95 $html = '<html><meta>stuff2</meta><meta name="image" content="img"/></html>'; 176 $html = '<html><meta>stuff2</meta><meta name="image" content="img"/></html>';
96 $this->assertFalse(html_extract_tag('description', $html)); 177 $this->assertFalse(html_extract_tag('description', $html));
178
179 // Partial meta tag
180 $html = '<meta content="Brief description">';
181 $this->assertFalse(html_extract_tag('description', $html));
182
183 $html = '<meta property="og:description">';
184 $this->assertFalse(html_extract_tag('description', $html));
185
186 $html = '<meta tag1="content1" property="og:description">';
187 $this->assertFalse(html_extract_tag('description', $html));
188
189 $html = '<meta property="og:description" tag1="content1">';
190 $this->assertFalse(html_extract_tag('description', $html));
191
192 $html = '<meta tag1="content1" content="Brief description">';
193 $this->assertFalse(html_extract_tag('description', $html));
194
195 $html = '<meta content="Brief description" tag1="content1">';
196 $this->assertFalse(html_extract_tag('description', $html));
97 } 197 }
98 198
99 /** 199 /**
@@ -116,60 +216,91 @@ class LinkUtilsTest extends TestCase
116 } 216 }
117 217
118 /** 218 /**
219 * Test the header callback with valid value
220 */
221 public function testCurlHeaderCallbackOk(): void
222 {
223 $callback = get_curl_header_callback($charset, 'ut_curl_getinfo_ok');
224 $data = [
225 'HTTP/1.1 200 OK',
226 'Server: GitHub.com',
227 'Date: Sat, 28 Oct 2017 12:01:33 GMT',
228 'Content-Type: text/html; charset=utf-8',
229 'Status: 200 OK',
230 ];
231
232 foreach ($data as $chunk) {
233 static::assertIsInt($callback(null, $chunk));
234 }
235
236 static::assertSame('utf-8', $charset);
237 }
238
239 /**
119 * Test the download callback with valid value 240 * Test the download callback with valid value
120 */ 241 */
121 public function testCurlDownloadCallbackOk() 242 public function testCurlDownloadCallbackOk(): void
122 { 243 {
244 $charset = 'utf-8';
123 $callback = get_curl_download_callback( 245 $callback = get_curl_download_callback(
124 $charset, 246 $charset,
125 $title, 247 $title,
126 $desc, 248 $desc,
127 $keywords, 249 $keywords,
128 false, 250 false
129 'ut_curl_getinfo_ok'
130 ); 251 );
252
131 $data = [ 253 $data = [
132 'HTTP/1.1 200 OK', 254 'th=device-width">'
133 'Server: GitHub.com',
134 'Date: Sat, 28 Oct 2017 12:01:33 GMT',
135 'Content-Type: text/html; charset=utf-8',
136 'Status: 200 OK',
137 'end' => 'th=device-width">'
138 . '<title>Refactoring · GitHub</title>' 255 . '<title>Refactoring · GitHub</title>'
139 . '<link rel="search" type="application/opensea', 256 . '<link rel="search" type="application/opensea',
140 '<title>ignored</title>' 257 '<title>ignored</title>'
141 . '<meta name="description" content="desc" />' 258 . '<meta name="description" content="desc" />'
142 . '<meta name="keywords" content="key1,key2" />', 259 . '<meta name="keywords" content="key1,key2" />',
143 ]; 260 ];
144 foreach ($data as $key => $line) { 261
145 $ignore = null; 262 foreach ($data as $chunk) {
146 $expected = $key !== 'end' ? strlen($line) : false; 263 static::assertSame(strlen($chunk), $callback(null, $chunk));
147 $this->assertEquals($expected, $callback($ignore, $line));
148 if ($expected === false) {
149 break;
150 }
151 } 264 }
152 $this->assertEquals('utf-8', $charset); 265
153 $this->assertEquals('Refactoring · GitHub', $title); 266 static::assertSame('utf-8', $charset);
154 $this->assertEmpty($desc); 267 static::assertSame('Refactoring · GitHub', $title);
155 $this->assertEmpty($keywords); 268 static::assertEmpty($desc);
269 static::assertEmpty($keywords);
270 }
271
272 /**
273 * Test the header callback with valid value
274 */
275 public function testCurlHeaderCallbackNoCharset(): void
276 {
277 $callback = get_curl_header_callback($charset, 'ut_curl_getinfo_no_charset');
278 $data = [
279 'HTTP/1.1 200 OK',
280 ];
281
282 foreach ($data as $chunk) {
283 static::assertSame(strlen($chunk), $callback(null, $chunk));
284 }
285
286 static::assertFalse($charset);
156 } 287 }
157 288
158 /** 289 /**
159 * Test the download callback with valid values and no charset 290 * Test the download callback with valid values and no charset
160 */ 291 */
161 public function testCurlDownloadCallbackOkNoCharset() 292 public function testCurlDownloadCallbackOkNoCharset(): void
162 { 293 {
294 $charset = null;
163 $callback = get_curl_download_callback( 295 $callback = get_curl_download_callback(
164 $charset, 296 $charset,
165 $title, 297 $title,
166 $desc, 298 $desc,
167 $keywords, 299 $keywords,
168 false, 300 false
169 'ut_curl_getinfo_no_charset'
170 ); 301 );
302
171 $data = [ 303 $data = [
172 'HTTP/1.1 200 OK',
173 'end' => 'th=device-width">' 304 'end' => 'th=device-width">'
174 . '<title>Refactoring · GitHub</title>' 305 . '<title>Refactoring · GitHub</title>'
175 . '<link rel="search" type="application/opensea', 306 . '<link rel="search" type="application/opensea',
@@ -177,10 +308,11 @@ class LinkUtilsTest extends TestCase
177 . '<meta name="description" content="desc" />' 308 . '<meta name="description" content="desc" />'
178 . '<meta name="keywords" content="key1,key2" />', 309 . '<meta name="keywords" content="key1,key2" />',
179 ]; 310 ];
180 foreach ($data as $key => $line) { 311
181 $ignore = null; 312 foreach ($data as $chunk) {
182 $this->assertEquals(strlen($line), $callback($ignore, $line)); 313 static::assertSame(strlen($chunk), $callback(null, $chunk));
183 } 314 }
315
184 $this->assertEmpty($charset); 316 $this->assertEmpty($charset);
185 $this->assertEquals('Refactoring · GitHub', $title); 317 $this->assertEquals('Refactoring · GitHub', $title);
186 $this->assertEmpty($desc); 318 $this->assertEmpty($desc);
@@ -190,18 +322,18 @@ class LinkUtilsTest extends TestCase
190 /** 322 /**
191 * Test the download callback with valid values and no charset 323 * Test the download callback with valid values and no charset
192 */ 324 */
193 public function testCurlDownloadCallbackOkHtmlCharset() 325 public function testCurlDownloadCallbackOkHtmlCharset(): void
194 { 326 {
327 $charset = null;
195 $callback = get_curl_download_callback( 328 $callback = get_curl_download_callback(
196 $charset, 329 $charset,
197 $title, 330 $title,
198 $desc, 331 $desc,
199 $keywords, 332 $keywords,
200 false, 333 false
201 'ut_curl_getinfo_no_charset'
202 ); 334 );
335
203 $data = [ 336 $data = [
204 'HTTP/1.1 200 OK',
205 '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />', 337 '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',
206 'end' => 'th=device-width">' 338 'end' => 'th=device-width">'
207 . '<title>Refactoring · GitHub</title>' 339 . '<title>Refactoring · GitHub</title>'
@@ -210,14 +342,10 @@ class LinkUtilsTest extends TestCase
210 . '<meta name="description" content="desc" />' 342 . '<meta name="description" content="desc" />'
211 . '<meta name="keywords" content="key1,key2" />', 343 . '<meta name="keywords" content="key1,key2" />',
212 ]; 344 ];
213 foreach ($data as $key => $line) { 345 foreach ($data as $chunk) {
214 $ignore = null; 346 static::assertSame(strlen($chunk), $callback(null, $chunk));
215 $expected = $key !== 'end' ? strlen($line) : false;
216 $this->assertEquals($expected, $callback($ignore, $line));
217 if ($expected === false) {
218 break;
219 }
220 } 347 }
348
221 $this->assertEquals('utf-8', $charset); 349 $this->assertEquals('utf-8', $charset);
222 $this->assertEquals('Refactoring · GitHub', $title); 350 $this->assertEquals('Refactoring · GitHub', $title);
223 $this->assertEmpty($desc); 351 $this->assertEmpty($desc);
@@ -227,25 +355,26 @@ class LinkUtilsTest extends TestCase
227 /** 355 /**
228 * Test the download callback with valid values and no title 356 * Test the download callback with valid values and no title
229 */ 357 */
230 public function testCurlDownloadCallbackOkNoTitle() 358 public function testCurlDownloadCallbackOkNoTitle(): void
231 { 359 {
360 $charset = 'utf-8';
232 $callback = get_curl_download_callback( 361 $callback = get_curl_download_callback(
233 $charset, 362 $charset,
234 $title, 363 $title,
235 $desc, 364 $desc,
236 $keywords, 365 $keywords,
237 false, 366 false
238 'ut_curl_getinfo_ok'
239 ); 367 );
368
240 $data = [ 369 $data = [
241 'HTTP/1.1 200 OK',
242 'end' => 'th=device-width">Refactoring · GitHub<link rel="search" type="application/opensea', 370 'end' => 'th=device-width">Refactoring · GitHub<link rel="search" type="application/opensea',
243 'ignored', 371 'ignored',
244 ]; 372 ];
245 foreach ($data as $key => $line) { 373
246 $ignore = null; 374 foreach ($data as $chunk) {
247 $this->assertEquals(strlen($line), $callback($ignore, $line)); 375 static::assertSame(strlen($chunk), $callback(null, $chunk));
248 } 376 }
377
249 $this->assertEquals('utf-8', $charset); 378 $this->assertEquals('utf-8', $charset);
250 $this->assertEmpty($title); 379 $this->assertEmpty($title);
251 $this->assertEmpty($desc); 380 $this->assertEmpty($desc);
@@ -253,81 +382,55 @@ class LinkUtilsTest extends TestCase
253 } 382 }
254 383
255 /** 384 /**
256 * Test the download callback with an invalid content type. 385 * Test the header callback with an invalid content type.
257 */ 386 */
258 public function testCurlDownloadCallbackInvalidContentType() 387 public function testCurlHeaderCallbackInvalidContentType(): void
259 { 388 {
260 $callback = get_curl_download_callback( 389 $callback = get_curl_header_callback($charset, 'ut_curl_getinfo_ct_ko');
261 $charset, 390 $data = [
262 $title, 391 'HTTP/1.1 200 OK',
263 $desc, 392 ];
264 $keywords, 393
265 false, 394 static::assertFalse($callback(null, $data[0]));
266 'ut_curl_getinfo_ct_ko' 395 static::assertNull($charset);
267 );
268 $ignore = null;
269 $this->assertFalse($callback($ignore, ''));
270 $this->assertEmpty($charset);
271 $this->assertEmpty($title);
272 } 396 }
273 397
274 /** 398 /**
275 * Test the download callback with an invalid response code. 399 * Test the header callback with an invalid response code.
276 */ 400 */
277 public function testCurlDownloadCallbackInvalidResponseCode() 401 public function testCurlHeaderCallbackInvalidResponseCode(): void
278 { 402 {
279 $callback = $callback = get_curl_download_callback( 403 $callback = get_curl_header_callback($charset, 'ut_curl_getinfo_rc_ko');
280 $charset, 404
281 $title, 405 static::assertFalse($callback(null, ''));
282 $desc, 406 static::assertNull($charset);
283 $keywords,
284 false,
285 'ut_curl_getinfo_rc_ko'
286 );
287 $ignore = null;
288 $this->assertFalse($callback($ignore, ''));
289 $this->assertEmpty($charset);
290 $this->assertEmpty($title);
291 } 407 }
292 408
293 /** 409 /**
294 * Test the download callback with an invalid content type and response code. 410 * Test the header callback with an invalid content type and response code.
295 */ 411 */
296 public function testCurlDownloadCallbackInvalidContentTypeAndResponseCode() 412 public function testCurlHeaderCallbackInvalidContentTypeAndResponseCode(): void
297 { 413 {
298 $callback = $callback = get_curl_download_callback( 414 $callback = get_curl_header_callback($charset, 'ut_curl_getinfo_rs_ct_ko');
299 $charset, 415
300 $title, 416 static::assertFalse($callback(null, ''));
301 $desc, 417 static::assertNull($charset);
302 $keywords,
303 false,
304 'ut_curl_getinfo_rs_ct_ko'
305 );
306 $ignore = null;
307 $this->assertFalse($callback($ignore, ''));
308 $this->assertEmpty($charset);
309 $this->assertEmpty($title);
310 } 418 }
311 419
312 /** 420 /**
313 * Test the download callback with valid value, and retrieve_description option enabled. 421 * Test the download callback with valid value, and retrieve_description option enabled.
314 */ 422 */
315 public function testCurlDownloadCallbackOkWithDesc() 423 public function testCurlDownloadCallbackOkWithDesc(): void
316 { 424 {
425 $charset = 'utf-8';
317 $callback = get_curl_download_callback( 426 $callback = get_curl_download_callback(
318 $charset, 427 $charset,
319 $title, 428 $title,
320 $desc, 429 $desc,
321 $keywords, 430 $keywords,
322 true, 431 true
323 'ut_curl_getinfo_ok'
324 ); 432 );
325 $data = [ 433 $data = [
326 'HTTP/1.1 200 OK',
327 'Server: GitHub.com',
328 'Date: Sat, 28 Oct 2017 12:01:33 GMT',
329 'Content-Type: text/html; charset=utf-8',
330 'Status: 200 OK',
331 'th=device-width">' 434 'th=device-width">'
332 . '<title>Refactoring · GitHub</title>' 435 . '<title>Refactoring · GitHub</title>'
333 . '<link rel="search" type="application/opensea', 436 . '<link rel="search" type="application/opensea',
@@ -335,14 +438,11 @@ class LinkUtilsTest extends TestCase
335 . '<meta name="description" content="link desc" />' 438 . '<meta name="description" content="link desc" />'
336 . '<meta name="keywords" content="key1,key2" />', 439 . '<meta name="keywords" content="key1,key2" />',
337 ]; 440 ];
338 foreach ($data as $key => $line) { 441
339 $ignore = null; 442 foreach ($data as $chunk) {
340 $expected = $key !== 'end' ? strlen($line) : false; 443 static::assertSame(strlen($chunk), $callback(null, $chunk));
341 $this->assertEquals($expected, $callback($ignore, $line));
342 if ($expected === false) {
343 break;
344 }
345 } 444 }
445
346 $this->assertEquals('utf-8', $charset); 446 $this->assertEquals('utf-8', $charset);
347 $this->assertEquals('Refactoring · GitHub', $title); 447 $this->assertEquals('Refactoring · GitHub', $title);
348 $this->assertEquals('link desc', $desc); 448 $this->assertEquals('link desc', $desc);
@@ -353,8 +453,9 @@ class LinkUtilsTest extends TestCase
353 * Test the download callback with valid value, and retrieve_description option enabled, 453 * Test the download callback with valid value, and retrieve_description option enabled,
354 * but no desc or keyword defined in the page. 454 * but no desc or keyword defined in the page.
355 */ 455 */
356 public function testCurlDownloadCallbackOkWithDescNotFound() 456 public function testCurlDownloadCallbackOkWithDescNotFound(): void
357 { 457 {
458 $charset = 'utf-8';
358 $callback = get_curl_download_callback( 459 $callback = get_curl_download_callback(
359 $charset, 460 $charset,
360 $title, 461 $title,
@@ -364,24 +465,16 @@ class LinkUtilsTest extends TestCase
364 'ut_curl_getinfo_ok' 465 'ut_curl_getinfo_ok'
365 ); 466 );
366 $data = [ 467 $data = [
367 'HTTP/1.1 200 OK',
368 'Server: GitHub.com',
369 'Date: Sat, 28 Oct 2017 12:01:33 GMT',
370 'Content-Type: text/html; charset=utf-8',
371 'Status: 200 OK',
372 'th=device-width">' 468 'th=device-width">'
373 . '<title>Refactoring · GitHub</title>' 469 . '<title>Refactoring · GitHub</title>'
374 . '<link rel="search" type="application/opensea', 470 . '<link rel="search" type="application/opensea',
375 'end' => '<title>ignored</title>', 471 'end' => '<title>ignored</title>',
376 ]; 472 ];
377 foreach ($data as $key => $line) { 473
378 $ignore = null; 474 foreach ($data as $chunk) {
379 $expected = $key !== 'end' ? strlen($line) : false; 475 static::assertSame(strlen($chunk), $callback(null, $chunk));
380 $this->assertEquals($expected, $callback($ignore, $line));
381 if ($expected === false) {
382 break;
383 }
384 } 476 }
477
385 $this->assertEquals('utf-8', $charset); 478 $this->assertEquals('utf-8', $charset);
386 $this->assertEquals('Refactoring · GitHub', $title); 479 $this->assertEquals('Refactoring · GitHub', $title);
387 $this->assertEmpty($desc); 480 $this->assertEmpty($desc);
@@ -439,13 +532,13 @@ class LinkUtilsTest extends TestCase
439 カタカナ #カタカナ」カタカナ\n'; 532 カタカナ #カタカナ」カタカナ\n';
440 $autolinkedDescription = hashtag_autolink($rawDescription, $index); 533 $autolinkedDescription = hashtag_autolink($rawDescription, $index);
441 534
442 $this->assertContains($this->getHashtagLink('hashtag', $index), $autolinkedDescription); 535 $this->assertContainsPolyfill($this->getHashtagLink('hashtag', $index), $autolinkedDescription);
443 $this->assertNotContains(' #hashtag', $autolinkedDescription); 536 $this->assertNotContainsPolyfill(' #hashtag', $autolinkedDescription);
444 $this->assertNotContains('>#nothashtag', $autolinkedDescription); 537 $this->assertNotContainsPolyfill('>#nothashtag', $autolinkedDescription);
445 $this->assertContains($this->getHashtagLink('ашок', $index), $autolinkedDescription); 538 $this->assertContainsPolyfill($this->getHashtagLink('ашок', $index), $autolinkedDescription);
446 $this->assertContains($this->getHashtagLink('カタカナ', $index), $autolinkedDescription); 539 $this->assertContainsPolyfill($this->getHashtagLink('カタカナ', $index), $autolinkedDescription);
447 $this->assertContains($this->getHashtagLink('hashtag_hashtag', $index), $autolinkedDescription); 540 $this->assertContainsPolyfill($this->getHashtagLink('hashtag_hashtag', $index), $autolinkedDescription);
448 $this->assertNotContains($this->getHashtagLink('hashtag-nothashtag', $index), $autolinkedDescription); 541 $this->assertNotContainsPolyfill($this->getHashtagLink('hashtag-nothashtag', $index), $autolinkedDescription);
449 } 542 }
450 543
451 /** 544 /**
@@ -456,9 +549,9 @@ class LinkUtilsTest extends TestCase
456 $rawDescription = 'blabla #hashtag x#nothashtag'; 549 $rawDescription = 'blabla #hashtag x#nothashtag';
457 $autolinkedDescription = hashtag_autolink($rawDescription); 550 $autolinkedDescription = hashtag_autolink($rawDescription);
458 551
459 $this->assertContains($this->getHashtagLink('hashtag'), $autolinkedDescription); 552 $this->assertContainsPolyfill($this->getHashtagLink('hashtag'), $autolinkedDescription);
460 $this->assertNotContains(' #hashtag', $autolinkedDescription); 553 $this->assertNotContainsPolyfill(' #hashtag', $autolinkedDescription);
461 $this->assertNotContains('>#nothashtag', $autolinkedDescription); 554 $this->assertNotContainsPolyfill('>#nothashtag', $autolinkedDescription);
462 } 555 }
463 556
464 /** 557 /**
@@ -491,7 +584,7 @@ class LinkUtilsTest extends TestCase
491 */ 584 */
492 private function getHashtagLink($hashtag, $index = '') 585 private function getHashtagLink($hashtag, $index = '')
493 { 586 {
494 $hashtagLink = '<a href="' . $index . '?addtag=$1" title="Hashtag $1">#$1</a>'; 587 $hashtagLink = '<a href="' . $index . './add-tag/$1" title="Hashtag $1">#$1</a>';
495 return str_replace('$1', $hashtag, $hashtagLink); 588 return str_replace('$1', $hashtag, $hashtagLink);
496 } 589 }
497} 590}