3 namespace Shaarli\Bookmark
;
5 use malkusch\lock\mutex\NoMutex
;
7 use Shaarli\Config\ConfigManager
;
12 * Class BookmarkFilterTest.
14 class BookmarkFilterTest
extends TestCase
17 * @var string Test datastore path.
19 protected static $testDatastore = 'sandbox/datastore.php';
21 * @var BookmarkFilter instance.
23 protected static $linkFilter;
26 * @var ReferenceLinkDB instance
28 protected static $refDB;
31 * @var BookmarkFileService instance
33 protected static $bookmarkService;
36 * Instantiate linkFilter with ReferenceLinkDB data.
38 public static function setUpBeforeClass(): void
40 $mutex = new NoMutex();
41 $conf = new ConfigManager('tests/utils/config/configJson');
42 $conf->set('resource.datastore', self
::$testDatastore);
43 self
::$refDB = new \
ReferenceLinkDB();
44 self
::$refDB->write(self
::$testDatastore);
45 $history = new History('sandbox/history.php');
46 self
::$bookmarkService = new \
FakeBookmarkService($conf, $history, $mutex, true);
47 self
::$linkFilter = new BookmarkFilter(self
::$bookmarkService->getBookmarks(), $conf);
53 public function testFilter()
56 self
::$refDB->countLinks(),
57 count(self
::$linkFilter->filter('', ''))
61 self
::$refDB->countLinks(),
62 count(self
::$linkFilter->filter('', '', 'all'))
66 self
::$refDB->countLinks(),
67 count(self
::$linkFilter->filter('', '', 'randomstr'))
72 self
::$refDB->countPrivateLinks(),
73 count(self
::$linkFilter->filter('', '', false, 'private'))
78 self
::$refDB->countPublicLinks(),
79 count(self
::$linkFilter->filter('', '', false, 'public'))
83 ReferenceLinkDB
::$NB_LINKS_TOTAL,
84 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, ''))
88 self
::$refDB->countUntaggedLinks(),
90 self
::$linkFilter->filter(
91 BookmarkFilter
::$FILTER_TAG,
105 ReferenceLinkDB
::$NB_LINKS_TOTAL,
106 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, ''))
111 * Filter bookmarks using a tag
113 public function testFilterOneTag()
117 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'web', false))
122 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'web', false, 'all'))
127 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'web', false, 'default-blabla'))
133 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'web', false, 'private'))
139 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'web', false, 'public'))
144 * Filter bookmarks using a tag - case-sensitive
146 public function testFilterCaseSensitiveTag()
150 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'mercurial', true))
155 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'Mercurial', true))
160 * Filter bookmarks using a tag combination
162 public function testFilterMultipleTags()
166 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'dev cartoon', false))
171 * Filter bookmarks using a non-existent tag
173 public function testFilterUnknownTag()
177 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'null', false))
182 * Return bookmarks for a given day
184 public function testFilterDay()
188 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_DAY, '20121206'))
193 * Return bookmarks for a given day
195 public function testFilterDayRestrictedVisibility(): void
199 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_DAY, '20121206', false, BookmarkFilter
::$PUBLIC))
204 * 404 - day not found
206 public function testFilterUnknownDay()
210 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_DAY, '19700101'))
215 * Use an invalid date format
217 public function testFilterInvalidDayWithChars()
219 $this->expectException(\Exception
::class);
220 $this->expectExceptionMessageRegExp('/Invalid date format/');
222 self
::$linkFilter->filter(BookmarkFilter
::$FILTER_DAY, 'Rainy day, dream away');
226 * Use an invalid date format
228 public function testFilterInvalidDayDigits()
230 $this->expectException(\Exception
::class);
231 $this->expectExceptionMessageRegExp('/Invalid date format/');
233 self
::$linkFilter->filter(BookmarkFilter
::$FILTER_DAY, '20');
237 * Retrieve a link entry with its hash
239 public function testFilterSmallHash()
241 $links = self
::$linkFilter->filter(BookmarkFilter
::$FILTER_HASH, 'IuWvgA');
250 $links[7]->getTitle()
255 * No link for this hash
257 public function testFilterUnknownSmallHash()
259 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException
::class);
261 self
::$linkFilter->filter(BookmarkFilter
::$FILTER_HASH, 'Iblaah');
265 * Full-text search - no result found.
267 public function testFilterFullTextNoResult()
271 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'azertyuiop'))
276 * Full-text search - result from a link's URL
278 public function testFilterFullTextURL()
282 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'ars.userfriendly.org'))
287 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'ars org'))
292 * Full-text search - result from a link's title only
294 public function testFilterFullTextTitle()
296 // use miscellaneous cases
299 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'userfriendly -'))
303 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'UserFriendly -'))
307 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'uSeRFrIendlY -'))
310 // use miscellaneous case and offset
313 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'RFrIendL'))
318 * Full-text search - result from the link's description only
320 public function testFilterFullTextDescription()
324 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'publishing media'))
329 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'mercurial w3c'))
334 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, '"free software"'))
339 * Full-text search - result from the link's tags only
341 public function testFilterFullTextTags()
345 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'web'))
350 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'web', 'all'))
355 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'web', 'bla'))
361 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'web', false, 'private'))
367 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'web', false, 'public'))
372 * Full-text search - result set from mixed sources
374 public function testFilterFullTextMixed()
378 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'free software'))
383 * Full-text search - test exclusion with '-'.
385 public function testExcludeSearch()
389 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, 'free -gnu'))
393 ReferenceLinkDB
::$NB_LINKS_TOTAL - 1,
394 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TEXT, '-revolution'))
399 * Full-text search - test AND, exact terms and exclusion combined, across fields.
401 public function testMultiSearch()
405 count(self
::$linkFilter->filter(
406 BookmarkFilter
::$FILTER_TEXT,
407 '"Free Software " stallman "read this" @website stuff'
413 count(self
::$linkFilter->filter(
414 BookmarkFilter
::$FILTER_TEXT,
415 '"free software " stallman "read this" -beard @website stuff'
421 * Full-text search - make sure that exact search won't work across fields.
423 public function testSearchExactTermMultiFieldsKo()
427 count(self
::$linkFilter->filter(
428 BookmarkFilter
::$FILTER_TEXT,
435 count(self
::$linkFilter->filter(
436 BookmarkFilter
::$FILTER_TEXT,
443 * Tag search with exclusion.
445 public function testTagFilterWithExclusion()
449 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, 'gnu -free'))
453 ReferenceLinkDB
::$NB_LINKS_TOTAL - 1,
454 count(self
::$linkFilter->filter(BookmarkFilter
::$FILTER_TAG, '-free'))
459 * Test crossed search (terms + tags).
461 public function testFilterCrossedSearch()
463 $terms = '"Free Software " stallman "read this" @website stuff';
467 count(self
::$linkFilter->filter(
468 BookmarkFilter
::$FILTER_TAG | BookmarkFilter
::$FILTER_TEXT,
474 count(self
::$linkFilter->filter(
475 BookmarkFilter
::$FILTER_TAG | BookmarkFilter
::$FILTER_TEXT,
481 count(self
::$linkFilter->filter(
482 BookmarkFilter
::$FILTER_TAG | BookmarkFilter
::$FILTER_TEXT,
483 array(false, 'PSR-2')
488 count(self
::$linkFilter->filter(
489 BookmarkFilter
::$FILTER_TAG | BookmarkFilter
::$FILTER_TEXT,
494 ReferenceLinkDB
::$NB_LINKS_TOTAL,
495 count(self
::$linkFilter->filter(
496 BookmarkFilter
::$FILTER_TAG | BookmarkFilter
::$FILTER_TEXT,
503 * Filter bookmarks by #hashtag.
505 public function testFilterByHashtag()
507 $hashtag = 'hashtag';
510 count(self
::$linkFilter->filter(
511 BookmarkFilter
::$FILTER_TAG,
516 $hashtag = 'private';
519 count(self
::$linkFilter->filter(
520 BookmarkFilter
::$FILTER_TAG,
529 * Test search result highlights in every field of bookmark reference #9.
531 public function testFullTextSearchHighlight(): void
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'
538 static::assertCount(1, $bookmarks);
539 static::assertArrayHasKey(9, $bookmarks);
541 $bookmark = $bookmarks[9];
542 $expectedHighlights = [
544 ['start' => 0, 'end' => 5], // "psr-2"
545 ['start' => 7, 'end' => 13], // coding
546 ['start' => 20, 'end' => 25], // guide
549 ['start' => 0, 'end' => 10], // "This guide"
550 ['start' => 45, 'end' => 50], // basic
551 ['start' => 58, 'end' => 67], // standard.
554 ['start' => 0, 'end' => 4], // http
555 ['start' => 15, 'end' => 18], // fig
556 ['start' => 27, 'end' => 33], // "psr-2/"
559 ['start' => 0, 'end' => 12], // coding-style
560 ['start' => 23, 'end' => 30], // quality
561 ['start' => 31, 'end' => 40], // assurance
564 static::assertSame($expectedHighlights, $bookmark->getAdditionalContentEntry('search_highlight'));