]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - tests/bookmark/BookmarkFilterTest.php
Feature: highlight fulltext search results
[github/shaarli/Shaarli.git] / tests / bookmark / BookmarkFilterTest.php
CommitLineData
822bffce
A
1<?php
2
6696729b 3namespace Shaarli\Bookmark;
f24896b2 4
6696729b 5use Exception;
fd1ddad9 6use malkusch\lock\mutex\NoMutex;
6696729b 7use ReferenceLinkDB;
e26e2060 8use Shaarli\Config\ConfigManager;
e26e2060 9use Shaarli\History;
a5a9cf23 10use Shaarli\TestCase;
822bffce
A
11
12/**
e26e2060 13 * Class BookmarkFilterTest.
822bffce 14 */
e26e2060 15class BookmarkFilterTest extends TestCase
822bffce 16{
9ec0a611
A
17 /**
18 * @var string Test datastore path.
19 */
20 protected static $testDatastore = 'sandbox/datastore.php';
822bffce 21 /**
e26e2060 22 * @var BookmarkFilter instance.
822bffce
A
23 */
24 protected static $linkFilter;
25
7f96d9ec
A
26 /**
27 * @var ReferenceLinkDB instance
28 */
29 protected static $refDB;
30
9ec0a611 31 /**
e26e2060 32 * @var BookmarkFileService instance
9ec0a611 33 */
e26e2060 34 protected static $bookmarkService;
9ec0a611 35
822bffce 36 /**
6696729b 37 * Instantiate linkFilter with ReferenceLinkDB data.
822bffce 38 */
27ddfec3 39 public static function setUpBeforeClass(): void
822bffce 40 {
fd1ddad9 41 $mutex = new NoMutex();
e26e2060
A
42 $conf = new ConfigManager('tests/utils/config/configJson');
43 $conf->set('resource.datastore', self::$testDatastore);
44 self::$refDB = new \ReferenceLinkDB();
9ec0a611 45 self::$refDB->write(self::$testDatastore);
e26e2060 46 $history = new History('sandbox/history.php');
fd1ddad9 47 self::$bookmarkService = new \FakeBookmarkService($conf, $history, $mutex, true);
e26e2060 48 self::$linkFilter = new BookmarkFilter(self::$bookmarkService->getBookmarks());
822bffce
A
49 }
50
51 /**
52 * Blank filter.
53 */
54 public function testFilter()
55 {
56 $this->assertEquals(
7f96d9ec 57 self::$refDB->countLinks(),
822bffce
A
58 count(self::$linkFilter->filter('', ''))
59 );
60
7f96d9ec
A
61 $this->assertEquals(
62 self::$refDB->countLinks(),
63 count(self::$linkFilter->filter('', '', 'all'))
64 );
65
66 $this->assertEquals(
67 self::$refDB->countLinks(),
68 count(self::$linkFilter->filter('', '', 'randomstr'))
69 );
70
822bffce
A
71 // Private only.
72 $this->assertEquals(
7f96d9ec
A
73 self::$refDB->countPrivateLinks(),
74 count(self::$linkFilter->filter('', '', false, 'private'))
75 );
76
77 // Public only.
78 $this->assertEquals(
79 self::$refDB->countPublicLinks(),
80 count(self::$linkFilter->filter('', '', false, 'public'))
822bffce 81 );
c51fae92
A
82
83 $this->assertEquals(
89baf23d 84 ReferenceLinkDB::$NB_LINKS_TOTAL,
e26e2060 85 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, ''))
c51fae92
A
86 );
87
7d86f40b
A
88 $this->assertEquals(
89 self::$refDB->countUntaggedLinks(),
9d9f6d75
V
90 count(
91 self::$linkFilter->filter(
e26e2060 92 BookmarkFilter::$FILTER_TAG,
6696729b
V
93 /*$request=*/
94 '',
95 /*$casesensitive=*/
96 false,
97 /*$visibility=*/
98 'all',
99 /*$untaggedonly=*/
100 true
9d9f6d75
V
101 )
102 )
7d86f40b
A
103 );
104
c51fae92 105 $this->assertEquals(
89baf23d 106 ReferenceLinkDB::$NB_LINKS_TOTAL,
e26e2060 107 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, ''))
c51fae92 108 );
822bffce
A
109 }
110
111 /**
e26e2060 112 * Filter bookmarks using a tag
822bffce
A
113 */
114 public function testFilterOneTag()
115 {
116 $this->assertEquals(
117 4,
e26e2060 118 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false))
822bffce
A
119 );
120
7f96d9ec
A
121 $this->assertEquals(
122 4,
e26e2060 123 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false, 'all'))
7f96d9ec
A
124 );
125
126 $this->assertEquals(
127 4,
e26e2060 128 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false, 'default-blabla'))
7f96d9ec
A
129 );
130
822bffce
A
131 // Private only.
132 $this->assertEquals(
133 1,
e26e2060 134 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false, 'private'))
7f96d9ec
A
135 );
136
137 // Public only.
138 $this->assertEquals(
139 3,
e26e2060 140 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false, 'public'))
822bffce
A
141 );
142 }
143
144 /**
e26e2060 145 * Filter bookmarks using a tag - case-sensitive
822bffce
A
146 */
147 public function testFilterCaseSensitiveTag()
148 {
149 $this->assertEquals(
150 0,
e26e2060 151 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'mercurial', true))
822bffce
A
152 );
153
154 $this->assertEquals(
155 1,
e26e2060 156 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'Mercurial', true))
822bffce
A
157 );
158 }
159
160 /**
e26e2060 161 * Filter bookmarks using a tag combination
822bffce
A
162 */
163 public function testFilterMultipleTags()
164 {
165 $this->assertEquals(
166 2,
e26e2060 167 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'dev cartoon', false))
822bffce
A
168 );
169 }
170
171 /**
e26e2060 172 * Filter bookmarks using a non-existent tag
822bffce
A
173 */
174 public function testFilterUnknownTag()
175 {
176 $this->assertEquals(
177 0,
e26e2060 178 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'null', false))
822bffce
A
179 );
180 }
181
182 /**
e26e2060 183 * Return bookmarks for a given day
822bffce
A
184 */
185 public function testFilterDay()
186 {
187 $this->assertEquals(
7d86f40b 188 4,
e26e2060 189 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '20121206'))
822bffce
A
190 );
191 }
192
27ddfec3
A
193 /**
194 * Return bookmarks for a given day
195 */
196 public function testFilterDayRestrictedVisibility(): void
197 {
198 $this->assertEquals(
199 3,
200 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '20121206', false, BookmarkFilter::$PUBLIC))
201 );
202 }
203
822bffce
A
204 /**
205 * 404 - day not found
206 */
207 public function testFilterUnknownDay()
208 {
209 $this->assertEquals(
210 0,
e26e2060 211 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '19700101'))
822bffce
A
212 );
213 }
214
215 /**
216 * Use an invalid date format
822bffce
A
217 */
218 public function testFilterInvalidDayWithChars()
219 {
f447edb7 220 $this->expectException(\Exception::class);
b1baca99
A
221 $this->expectExceptionMessageRegExp('/Invalid date format/');
222
e26e2060 223 self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, 'Rainy day, dream away');
822bffce
A
224 }
225
226 /**
227 * Use an invalid date format
822bffce
A
228 */
229 public function testFilterInvalidDayDigits()
230 {
f447edb7 231 $this->expectException(\Exception::class);
b1baca99
A
232 $this->expectExceptionMessageRegExp('/Invalid date format/');
233
e26e2060 234 self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '20');
822bffce
A
235 }
236
237 /**
238 * Retrieve a link entry with its hash
239 */
240 public function testFilterSmallHash()
241 {
e26e2060 242 $links = self::$linkFilter->filter(BookmarkFilter::$FILTER_HASH, 'IuWvgA');
822bffce
A
243
244 $this->assertEquals(
245 1,
246 count($links)
247 );
248
249 $this->assertEquals(
250 'MediaGoblin',
e26e2060 251 $links[7]->getTitle()
822bffce
A
252 );
253 }
254
255 /**
256 * No link for this hash
257 */
258 public function testFilterUnknownSmallHash()
259 {
b1baca99
A
260 $this->expectException(\Shaarli\Bookmark\Exception\BookmarkNotFoundException::class);
261
e26e2060 262 self::$linkFilter->filter(BookmarkFilter::$FILTER_HASH, 'Iblaah');
822bffce
A
263 }
264
522b278b
A
265 /**
266 * Full-text search - no result found.
267 */
268 public function testFilterFullTextNoResult()
269 {
270 $this->assertEquals(
271 0,
e26e2060 272 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'azertyuiop'))
522b278b
A
273 );
274 }
275
822bffce
A
276 /**
277 * Full-text search - result from a link's URL
278 */
279 public function testFilterFullTextURL()
280 {
281 $this->assertEquals(
282 2,
e26e2060 283 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'ars.userfriendly.org'))
822bffce 284 );
9d9f6d75 285
ebd8075a
FV
286 $this->assertEquals(
287 2,
e26e2060 288 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'ars org'))
ebd8075a 289 );
822bffce
A
290 }
291
292 /**
293 * Full-text search - result from a link's title only
294 */
295 public function testFilterFullTextTitle()
296 {
297 // use miscellaneous cases
298 $this->assertEquals(
299 2,
e26e2060 300 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'userfriendly -'))
822bffce
A
301 );
302 $this->assertEquals(
303 2,
e26e2060 304 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'UserFriendly -'))
822bffce
A
305 );
306 $this->assertEquals(
307 2,
e26e2060 308 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'uSeRFrIendlY -'))
822bffce
A
309 );
310
311 // use miscellaneous case and offset
312 $this->assertEquals(
313 2,
e26e2060 314 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'RFrIendL'))
822bffce
A
315 );
316 }
317
318 /**
319 * Full-text search - result from the link's description only
320 */
321 public function testFilterFullTextDescription()
322 {
323 $this->assertEquals(
324 1,
e26e2060 325 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'publishing media'))
ebd8075a 326 );
9d9f6d75 327
ebd8075a
FV
328 $this->assertEquals(
329 1,
e26e2060 330 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'mercurial w3c'))
822bffce 331 );
9d9f6d75 332
ebd8075a 333 $this->assertEquals(
bedd176a 334 3,
e26e2060 335 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, '"free software"'))
067c2dd8 336 );
822bffce
A
337 }
338
339 /**
340 * Full-text search - result from the link's tags only
341 */
342 public function testFilterFullTextTags()
343 {
344 $this->assertEquals(
7f96d9ec 345 6,
e26e2060 346 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web'))
7f96d9ec
A
347 );
348
349 $this->assertEquals(
350 6,
e26e2060 351 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web', 'all'))
7f96d9ec
A
352 );
353
354 $this->assertEquals(
355 6,
e26e2060 356 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web', 'bla'))
822bffce
A
357 );
358
359 // Private only.
360 $this->assertEquals(
361 1,
e26e2060 362 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web', false, 'private'))
7f96d9ec
A
363 );
364
365 // Public only.
366 $this->assertEquals(
367 5,
e26e2060 368 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web', false, 'public'))
822bffce
A
369 );
370 }
371
372 /**
373 * Full-text search - result set from mixed sources
374 */
375 public function testFilterFullTextMixed()
376 {
377 $this->assertEquals(
bedd176a 378 3,
e26e2060 379 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'free software'))
822bffce
A
380 );
381 }
21979ff1 382
bedd176a
A
383 /**
384 * Full-text search - test exclusion with '-'.
385 */
386 public function testExcludeSearch()
387 {
388 $this->assertEquals(
389 1,
e26e2060 390 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'free -gnu'))
bedd176a
A
391 );
392
393 $this->assertEquals(
7d86f40b 394 ReferenceLinkDB::$NB_LINKS_TOTAL - 1,
e26e2060 395 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, '-revolution'))
bedd176a
A
396 );
397 }
398
399 /**
522b278b 400 * Full-text search - test AND, exact terms and exclusion combined, across fields.
bedd176a
A
401 */
402 public function testMultiSearch()
403 {
404 $this->assertEquals(
405 2,
522b278b 406 count(self::$linkFilter->filter(
e26e2060 407 BookmarkFilter::$FILTER_TEXT,
522b278b
A
408 '"Free Software " stallman "read this" @website stuff'
409 ))
bedd176a
A
410 );
411
412 $this->assertEquals(
413 1,
522b278b 414 count(self::$linkFilter->filter(
e26e2060 415 BookmarkFilter::$FILTER_TEXT,
522b278b
A
416 '"free software " stallman "read this" -beard @website stuff'
417 ))
418 );
419 }
420
421 /**
422 * Full-text search - make sure that exact search won't work across fields.
423 */
424 public function testSearchExactTermMultiFieldsKo()
425 {
426 $this->assertEquals(
427 0,
428 count(self::$linkFilter->filter(
e26e2060 429 BookmarkFilter::$FILTER_TEXT,
522b278b
A
430 '"designer naming"'
431 ))
432 );
433
434 $this->assertEquals(
435 0,
436 count(self::$linkFilter->filter(
e26e2060 437 BookmarkFilter::$FILTER_TEXT,
522b278b
A
438 '"designernaming"'
439 ))
bedd176a
A
440 );
441 }
442
21979ff1
A
443 /**
444 * Tag search with exclusion.
445 */
446 public function testTagFilterWithExclusion()
447 {
448 $this->assertEquals(
449 1,
e26e2060 450 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'gnu -free'))
21979ff1
A
451 );
452
453 $this->assertEquals(
7d86f40b 454 ReferenceLinkDB::$NB_LINKS_TOTAL - 1,
e26e2060 455 count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, '-free'))
21979ff1
A
456 );
457 }
c51fae92
A
458
459 /**
460 * Test crossed search (terms + tags).
461 */
462 public function testFilterCrossedSearch()
463 {
464 $terms = '"Free Software " stallman "read this" @website stuff';
465 $tags = 'free';
466 $this->assertEquals(
467 1,
468 count(self::$linkFilter->filter(
e26e2060 469 BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT,
c51fae92
A
470 array($tags, $terms)
471 ))
472 );
473 $this->assertEquals(
474 2,
475 count(self::$linkFilter->filter(
e26e2060 476 BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT,
c51fae92
A
477 array('', $terms)
478 ))
479 );
480 $this->assertEquals(
7d86f40b
A
481 1,
482 count(self::$linkFilter->filter(
e26e2060 483 BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT,
7d86f40b
A
484 array(false, 'PSR-2')
485 ))
486 );
487 $this->assertEquals(
c51fae92
A
488 1,
489 count(self::$linkFilter->filter(
e26e2060 490 BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT,
c51fae92
A
491 array($tags, '')
492 ))
493 );
494 $this->assertEquals(
89baf23d 495 ReferenceLinkDB::$NB_LINKS_TOTAL,
c51fae92 496 count(self::$linkFilter->filter(
e26e2060 497 BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT,
c51fae92
A
498 ''
499 ))
500 );
501 }
9ccca401
A
502
503 /**
e26e2060 504 * Filter bookmarks by #hashtag.
9ccca401
A
505 */
506 public function testFilterByHashtag()
507 {
508 $hashtag = 'hashtag';
509 $this->assertEquals(
510 3,
511 count(self::$linkFilter->filter(
e26e2060 512 BookmarkFilter::$FILTER_TAG,
9ccca401
A
513 $hashtag
514 ))
515 );
516
517 $hashtag = 'private';
518 $this->assertEquals(
519 1,
520 count(self::$linkFilter->filter(
e26e2060 521 BookmarkFilter::$FILTER_TAG,
9ccca401
A
522 $hashtag,
523 false,
7f96d9ec 524 'private'
9ccca401
A
525 ))
526 );
527 }
822bffce 528}