From e26e2060f5470ce8bf4c5973284bae07b8af170a Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 17 Jan 2020 21:34:12 +0100 Subject: Add and update unit test for the new system (Bookmark + Service) See #1307 --- tests/bookmark/BookmarkArrayTest.php | 239 +++++++ tests/bookmark/BookmarkFileServiceTest.php | 1042 ++++++++++++++++++++++++++++ tests/bookmark/BookmarkFilterTest.php | 514 ++++++++++++++ tests/bookmark/BookmarkInitializerTest.php | 120 ++++ tests/bookmark/BookmarkTest.php | 388 +++++++++++ tests/bookmark/LinkDBTest.php | 656 ----------------- tests/bookmark/LinkFilterTest.php | 507 -------------- tests/bookmark/LinkUtilsTest.php | 9 - 8 files changed, 2303 insertions(+), 1172 deletions(-) create mode 100644 tests/bookmark/BookmarkArrayTest.php create mode 100644 tests/bookmark/BookmarkFileServiceTest.php create mode 100644 tests/bookmark/BookmarkFilterTest.php create mode 100644 tests/bookmark/BookmarkInitializerTest.php create mode 100644 tests/bookmark/BookmarkTest.php delete mode 100644 tests/bookmark/LinkDBTest.php delete mode 100644 tests/bookmark/LinkFilterTest.php (limited to 'tests/bookmark') diff --git a/tests/bookmark/BookmarkArrayTest.php b/tests/bookmark/BookmarkArrayTest.php new file mode 100644 index 00000000..0f8f04c5 --- /dev/null +++ b/tests/bookmark/BookmarkArrayTest.php @@ -0,0 +1,239 @@ +assertTrue(is_iterable($array)); + $this->assertEmpty($array); + } + + /** + * Test adding entries to the array, specifying the key offset or not. + */ + public function testArrayAccessAddEntries() + { + $array = new BookmarkArray(); + $bookmark = new Bookmark(); + $bookmark->setId(11)->validate(); + $array[] = $bookmark; + $this->assertCount(1, $array); + $this->assertTrue(isset($array[11])); + $this->assertNull($array[0]); + $this->assertEquals($bookmark, $array[11]); + + $bookmark = new Bookmark(); + $bookmark->setId(14)->validate(); + $array[14] = $bookmark; + $this->assertCount(2, $array); + $this->assertTrue(isset($array[14])); + $this->assertNull($array[0]); + $this->assertEquals($bookmark, $array[14]); + } + + /** + * Test adding a bad entry: wrong type + * + * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException + */ + public function testArrayAccessAddBadEntryInstance() + { + $array = new BookmarkArray(); + $array[] = 'nope'; + } + + /** + * Test adding a bad entry: no id + * + * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException + */ + public function testArrayAccessAddBadEntryNoId() + { + $array = new BookmarkArray(); + $bookmark = new Bookmark(); + $array[] = $bookmark; + } + + /** + * Test adding a bad entry: no url + * + * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException + */ + public function testArrayAccessAddBadEntryNoUrl() + { + $array = new BookmarkArray(); + $bookmark = (new Bookmark())->setId(11); + $array[] = $bookmark; + } + + /** + * Test adding a bad entry: invalid offset + * + * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException + */ + public function testArrayAccessAddBadEntryOffset() + { + $array = new BookmarkArray(); + $bookmark = (new Bookmark())->setId(11); + $bookmark->validate(); + $array['nope'] = $bookmark; + } + + /** + * Test adding a bad entry: invalid ID type + * + * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException + */ + public function testArrayAccessAddBadEntryIdType() + { + $array = new BookmarkArray(); + $bookmark = (new Bookmark())->setId('nope'); + $bookmark->validate(); + $array[] = $bookmark; + } + + /** + * Test adding a bad entry: ID/offset not consistent + * + * @expectedException Shaarli\Bookmark\Exception\InvalidBookmarkException + */ + public function testArrayAccessAddBadEntryIdOffset() + { + $array = new BookmarkArray(); + $bookmark = (new Bookmark())->setId(11); + $bookmark->validate(); + $array[14] = $bookmark; + } + + /** + * Test update entries through array access. + */ + public function testArrayAccessUpdateEntries() + { + $array = new BookmarkArray(); + $bookmark = new Bookmark(); + $bookmark->setId(11)->validate(); + $bookmark->setTitle('old'); + $array[] = $bookmark; + $bookmark = new Bookmark(); + $bookmark->setId(11)->validate(); + $bookmark->setTitle('test'); + $array[] = $bookmark; + $this->assertCount(1, $array); + $this->assertEquals('test', $array[11]->getTitle()); + + $bookmark = new Bookmark(); + $bookmark->setId(11)->validate(); + $bookmark->setTitle('test2'); + $array[11] = $bookmark; + $this->assertCount(1, $array); + $this->assertEquals('test2', $array[11]->getTitle()); + } + + /** + * Test delete entries through array access. + */ + public function testArrayAccessDeleteEntries() + { + $array = new BookmarkArray(); + $bookmark11 = new Bookmark(); + $bookmark11->setId(11)->validate(); + $array[] = $bookmark11; + $bookmark14 = new Bookmark(); + $bookmark14->setId(14)->validate(); + $array[] = $bookmark14; + $bookmark23 = new Bookmark(); + $bookmark23->setId(23)->validate(); + $array[] = $bookmark23; + $bookmark0 = new Bookmark(); + $bookmark0->setId(0)->validate(); + $array[] = $bookmark0; + $this->assertCount(4, $array); + + unset($array[14]); + $this->assertCount(3, $array); + $this->assertEquals($bookmark11, $array[11]); + $this->assertEquals($bookmark23, $array[23]); + $this->assertEquals($bookmark0, $array[0]); + + unset($array[23]); + $this->assertCount(2, $array); + $this->assertEquals($bookmark11, $array[11]); + $this->assertEquals($bookmark0, $array[0]); + + unset($array[11]); + $this->assertCount(1, $array); + $this->assertEquals($bookmark0, $array[0]); + + unset($array[0]); + $this->assertCount(0, $array); + } + + /** + * Test iterating through array access. + */ + public function testArrayAccessIterate() + { + $array = new BookmarkArray(); + $bookmark11 = new Bookmark(); + $bookmark11->setId(11)->validate(); + $array[] = $bookmark11; + $bookmark14 = new Bookmark(); + $bookmark14->setId(14)->validate(); + $array[] = $bookmark14; + $bookmark23 = new Bookmark(); + $bookmark23->setId(23)->validate(); + $array[] = $bookmark23; + $this->assertCount(3, $array); + + foreach ($array as $id => $bookmark) { + $this->assertEquals(${'bookmark'. $id}, $bookmark); + } + } + + /** + * Test reordering the array. + */ + public function testReorder() + { + $refDB = new \ReferenceLinkDB(); + $refDB->write('sandbox/datastore.php'); + + + $bookmarks = $refDB->getLinks(); + $bookmarks->reorder('ASC'); + $this->assertInstanceOf(BookmarkArray::class, $bookmarks); + + $stickyIds = [11, 10]; + $standardIds = [42, 4, 9, 1, 0, 7, 6, 8, 41]; + $linkIds = array_merge($stickyIds, $standardIds); + $cpt = 0; + foreach ($bookmarks as $key => $value) { + $this->assertEquals($linkIds[$cpt++], $key); + } + + $bookmarks = $refDB->getLinks(); + $bookmarks->reorder('DESC'); + $this->assertInstanceOf(BookmarkArray::class, $bookmarks); + + $linkIds = array_merge(array_reverse($stickyIds), array_reverse($standardIds)); + $cpt = 0; + foreach ($bookmarks as $key => $value) { + $this->assertEquals($linkIds[$cpt++], $key); + } + } +} diff --git a/tests/bookmark/BookmarkFileServiceTest.php b/tests/bookmark/BookmarkFileServiceTest.php new file mode 100644 index 00000000..1b438a7f --- /dev/null +++ b/tests/bookmark/BookmarkFileServiceTest.php @@ -0,0 +1,1042 @@ +conf = new ConfigManager(self::$testConf); + $this->conf->set('resource.datastore', self::$testDatastore); + $this->conf->set('resource.updates', self::$testUpdates); + $this->refDB = new \ReferenceLinkDB(); + $this->refDB->write(self::$testDatastore); + $this->history = new History('sandbox/history.php'); + $this->publicLinkDB = new BookmarkFileService($this->conf, $this->history, false); + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + } + + /** + * Test migrate() method with a legacy datastore. + */ + public function testDatabaseMigration() + { + if (!defined('SHAARLI_VERSION')) { + define('SHAARLI_VERSION', 'dev'); + } + + $this->refDB = new \ReferenceLinkDB(true); + $this->refDB->write(self::$testDatastore); + $db = self::getMethod('migrate'); + $db->invokeArgs($this->privateLinkDB, []); + + $db = new \FakeBookmarkService($this->conf, $this->history, true); + $this->assertInstanceOf(BookmarkArray::class, $db->getBookmarks()); + $this->assertEquals($this->refDB->countLinks(), $db->count()); + } + + /** + * Test get() method for a defined and saved bookmark + */ + public function testGetDefinedSaved() + { + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle()); + } + + /** + * Test get() method for a defined and not saved bookmark + */ + public function testGetDefinedNotSaved() + { + $bookmark = new Bookmark(); + $this->privateLinkDB->add($bookmark); + $createdBookmark = $this->privateLinkDB->get(43); + $this->assertEquals(43, $createdBookmark->getId()); + $this->assertEmpty($createdBookmark->getDescription()); + } + + /** + * Test get() method for an undefined bookmark + * + * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException + */ + public function testGetUndefined() + { + $this->privateLinkDB->get(666); + } + + /** + * Test add() method for a bookmark fully built + */ + public function testAddFull() + { + $bookmark = new Bookmark(); + $bookmark->setUrl($url = 'https://domain.tld/index.php'); + $bookmark->setShortUrl('abc'); + $bookmark->setTitle($title = 'This a brand new bookmark'); + $bookmark->setDescription($desc = 'It should be created and written'); + $bookmark->setTags($tags = ['tag1', 'tagssss']); + $bookmark->setThumbnail($thumb = 'http://thumb.tld/dle.png'); + $bookmark->setPrivate(true); + $bookmark->setSticky(true); + $bookmark->setCreated($created = DateTime::createFromFormat('Ymd_His', '20190518_140354')); + $bookmark->setUpdated($updated = DateTime::createFromFormat('Ymd_His', '20190518_150354')); + + $this->privateLinkDB->add($bookmark); + $bookmark = $this->privateLinkDB->get(43); + $this->assertEquals(43, $bookmark->getId()); + $this->assertEquals($url, $bookmark->getUrl()); + $this->assertEquals('abc', $bookmark->getShortUrl()); + $this->assertEquals($title, $bookmark->getTitle()); + $this->assertEquals($desc, $bookmark->getDescription()); + $this->assertEquals($tags, $bookmark->getTags()); + $this->assertEquals($thumb, $bookmark->getThumbnail()); + $this->assertTrue($bookmark->isPrivate()); + $this->assertTrue($bookmark->isSticky()); + $this->assertEquals($created, $bookmark->getCreated()); + $this->assertEquals($updated, $bookmark->getUpdated()); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $bookmark = $this->privateLinkDB->get(43); + $this->assertEquals(43, $bookmark->getId()); + $this->assertEquals($url, $bookmark->getUrl()); + $this->assertEquals('abc', $bookmark->getShortUrl()); + $this->assertEquals($title, $bookmark->getTitle()); + $this->assertEquals($desc, $bookmark->getDescription()); + $this->assertEquals($tags, $bookmark->getTags()); + $this->assertEquals($thumb, $bookmark->getThumbnail()); + $this->assertTrue($bookmark->isPrivate()); + $this->assertTrue($bookmark->isSticky()); + $this->assertEquals($created, $bookmark->getCreated()); + $this->assertEquals($updated, $bookmark->getUpdated()); + } + + /** + * Test add() method for a bookmark without any field set + */ + public function testAddMinimal() + { + $bookmark = new Bookmark(); + $this->privateLinkDB->add($bookmark); + + $bookmark = $this->privateLinkDB->get(43); + $this->assertEquals(43, $bookmark->getId()); + $this->assertRegExp('/\?[\w\-]{6}/', $bookmark->getUrl()); + $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl()); + $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle()); + $this->assertEmpty($bookmark->getDescription()); + $this->assertEmpty($bookmark->getTags()); + $this->assertEmpty($bookmark->getThumbnail()); + $this->assertFalse($bookmark->isPrivate()); + $this->assertFalse($bookmark->isSticky()); + $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getCreated()); + $this->assertNull($bookmark->getUpdated()); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $bookmark = $this->privateLinkDB->get(43); + $this->assertEquals(43, $bookmark->getId()); + $this->assertRegExp('/\?[\w\-]{6}/', $bookmark->getUrl()); + $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl()); + $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle()); + $this->assertEmpty($bookmark->getDescription()); + $this->assertEmpty($bookmark->getTags()); + $this->assertEmpty($bookmark->getThumbnail()); + $this->assertFalse($bookmark->isPrivate()); + $this->assertFalse($bookmark->isSticky()); + $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getCreated()); + $this->assertNull($bookmark->getUpdated()); + } + + /** + * Test add() method for a bookmark without any field set and without writing the data store + * + * @expectedExceptionMessage Shaarli\Bookmark\Exception\BookmarkNotFoundException + */ + public function testAddMinimalNoWrite() + { + $bookmark = new Bookmark(); + $this->privateLinkDB->add($bookmark); + + $bookmark = $this->privateLinkDB->get(43); + $this->assertEquals(43, $bookmark->getId()); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $this->privateLinkDB->get(43); + } + + /** + * Test add() method while logged out + * + * @expectedException \Exception + * @expectedExceptionMessage You're not authorized to alter the datastore + */ + public function testAddLoggedOut() + { + $this->publicLinkDB->add(new Bookmark()); + } + + /** + * Test add() method with an entry which is not a bookmark instance + * + * @expectedException \Exception + * @expectedExceptionMessage Provided data is invalid + */ + public function testAddNotABookmark() + { + $this->privateLinkDB->add(['title' => 'hi!']); + } + + /** + * Test add() method with a Bookmark already containing an ID + * + * @expectedException \Exception + * @expectedExceptionMessage This bookmarks already exists + */ + public function testAddWithId() + { + $bookmark = new Bookmark(); + $bookmark->setId(43); + $this->privateLinkDB->add($bookmark); + } + + /** + * Test set() method for a bookmark fully built + */ + public function testSetFull() + { + $bookmark = $this->privateLinkDB->get(42); + $bookmark->setUrl($url = 'https://domain.tld/index.php'); + $bookmark->setShortUrl('abc'); + $bookmark->setTitle($title = 'This a brand new bookmark'); + $bookmark->setDescription($desc = 'It should be created and written'); + $bookmark->setTags($tags = ['tag1', 'tagssss']); + $bookmark->setThumbnail($thumb = 'http://thumb.tld/dle.png'); + $bookmark->setPrivate(true); + $bookmark->setSticky(true); + $bookmark->setCreated($created = DateTime::createFromFormat('Ymd_His', '20190518_140354')); + $bookmark->setUpdated($updated = DateTime::createFromFormat('Ymd_His', '20190518_150354')); + + $this->privateLinkDB->set($bookmark); + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals($url, $bookmark->getUrl()); + $this->assertEquals('abc', $bookmark->getShortUrl()); + $this->assertEquals($title, $bookmark->getTitle()); + $this->assertEquals($desc, $bookmark->getDescription()); + $this->assertEquals($tags, $bookmark->getTags()); + $this->assertEquals($thumb, $bookmark->getThumbnail()); + $this->assertTrue($bookmark->isPrivate()); + $this->assertTrue($bookmark->isSticky()); + $this->assertEquals($created, $bookmark->getCreated()); + $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated()); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals($url, $bookmark->getUrl()); + $this->assertEquals('abc', $bookmark->getShortUrl()); + $this->assertEquals($title, $bookmark->getTitle()); + $this->assertEquals($desc, $bookmark->getDescription()); + $this->assertEquals($tags, $bookmark->getTags()); + $this->assertEquals($thumb, $bookmark->getThumbnail()); + $this->assertTrue($bookmark->isPrivate()); + $this->assertTrue($bookmark->isSticky()); + $this->assertEquals($created, $bookmark->getCreated()); + $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated()); + } + + /** + * Test set() method for a bookmark without any field set + */ + public function testSetMinimal() + { + $bookmark = $this->privateLinkDB->get(42); + $this->privateLinkDB->set($bookmark); + + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals('?WDWyig', $bookmark->getUrl()); + $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl()); + $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle()); + $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription()); + $this->assertEquals(['ut'], $bookmark->getTags()); + $this->assertFalse($bookmark->getThumbnail()); + $this->assertFalse($bookmark->isPrivate()); + $this->assertFalse($bookmark->isSticky()); + $this->assertEquals( + DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20100310_101010'), + $bookmark->getCreated() + ); + $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated()); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals('?WDWyig', $bookmark->getUrl()); + $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl()); + $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle()); + $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription()); + $this->assertEquals(['ut'], $bookmark->getTags()); + $this->assertFalse($bookmark->getThumbnail()); + $this->assertFalse($bookmark->isPrivate()); + $this->assertFalse($bookmark->isSticky()); + $this->assertEquals( + DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20100310_101010'), + $bookmark->getCreated() + ); + $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getUpdated()); + } + + /** + * Test set() method for a bookmark without any field set and without writing the data store + */ + public function testSetMinimalNoWrite() + { + $bookmark = $this->privateLinkDB->get(42); + $bookmark->setTitle($title = 'hi!'); + $this->privateLinkDB->set($bookmark, false); + + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals($title, $bookmark->getTitle()); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle()); + } + + /** + * Test set() method while logged out + * + * @expectedException \Exception + * @expectedExceptionMessage You're not authorized to alter the datastore + */ + public function testSetLoggedOut() + { + $this->publicLinkDB->set(new Bookmark()); + } + + /** + * Test set() method with an entry which is not a bookmark instance + * + * @expectedException \Exception + * @expectedExceptionMessage Provided data is invalid + */ + public function testSetNotABookmark() + { + $this->privateLinkDB->set(['title' => 'hi!']); + } + + /** + * Test set() method with a Bookmark without an ID defined. + * + * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException + */ + public function testSetWithoutId() + { + $bookmark = new Bookmark(); + $this->privateLinkDB->set($bookmark); + } + + /** + * Test set() method with a Bookmark with an unknow ID + * + * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException + */ + public function testSetWithUnknownId() + { + $bookmark = new Bookmark(); + $bookmark->setId(666); + $this->privateLinkDB->set($bookmark); + } + + /** + * Test addOrSet() method with a new ID + */ + public function testAddOrSetNew() + { + $bookmark = new Bookmark(); + $this->privateLinkDB->addOrSet($bookmark); + + $bookmark = $this->privateLinkDB->get(43); + $this->assertEquals(43, $bookmark->getId()); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $bookmark = $this->privateLinkDB->get(43); + $this->assertEquals(43, $bookmark->getId()); + } + + /** + * Test addOrSet() method with an existing ID + */ + public function testAddOrSetExisting() + { + $bookmark = $this->privateLinkDB->get(42); + $bookmark->setTitle($title = 'hi!'); + $this->privateLinkDB->addOrSet($bookmark); + + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals($title, $bookmark->getTitle()); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals($title, $bookmark->getTitle()); + } + + /** + * Test addOrSet() method while logged out + * + * @expectedException \Exception + * @expectedExceptionMessage You're not authorized to alter the datastore + */ + public function testAddOrSetLoggedOut() + { + $this->publicLinkDB->addOrSet(new Bookmark()); + } + + /** + * Test addOrSet() method with an entry which is not a bookmark instance + * + * @expectedException \Exception + * @expectedExceptionMessage Provided data is invalid + */ + public function testAddOrSetNotABookmark() + { + $this->privateLinkDB->addOrSet(['title' => 'hi!']); + } + + /** + * Test addOrSet() method for a bookmark without any field set and without writing the data store + */ + public function testAddOrSetMinimalNoWrite() + { + $bookmark = $this->privateLinkDB->get(42); + $bookmark->setTitle($title = 'hi!'); + $this->privateLinkDB->addOrSet($bookmark, false); + + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals($title, $bookmark->getTitle()); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $bookmark = $this->privateLinkDB->get(42); + $this->assertEquals(42, $bookmark->getId()); + $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle()); + } + + /** + * Test remove() method with an existing Bookmark + * + * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException + */ + public function testRemoveExisting() + { + $bookmark = $this->privateLinkDB->get(42); + $this->privateLinkDB->remove($bookmark); + + $exception = null; + try { + $this->privateLinkDB->get(42); + } catch (BookmarkNotFoundException $e) { + $exception = $e; + } + $this->assertInstanceOf(BookmarkNotFoundException::class, $exception); + + // reload from file + $this->privateLinkDB = new BookmarkFileService($this->conf, $this->history, true); + + $this->privateLinkDB->get(42); + } + + /** + * Test remove() method while logged out + * + * @expectedException \Exception + * @expectedExceptionMessage You're not authorized to alter the datastore + */ + public function testRemoveLoggedOut() + { + $bookmark = $this->privateLinkDB->get(42); + $this->publicLinkDB->remove($bookmark); + } + + /** + * Test remove() method with an entry which is not a bookmark instance + * + * @expectedException \Exception + * @expectedExceptionMessage Provided data is invalid + */ + public function testRemoveNotABookmark() + { + $this->privateLinkDB->remove(['title' => 'hi!']); + } + + /** + * Test remove() method with a Bookmark with an unknown ID + * + * @expectedException Shaarli\Bookmark\Exception\BookmarkNotFoundException + */ + public function testRemoveWithUnknownId() + { + $bookmark = new Bookmark(); + $bookmark->setId(666); + $this->privateLinkDB->remove($bookmark); + } + + /** + * Test exists() method + */ + public function testExists() + { + $this->assertTrue($this->privateLinkDB->exists(42)); // public + $this->assertTrue($this->privateLinkDB->exists(6)); // private + + $this->assertTrue($this->privateLinkDB->exists(42, BookmarkFilter::$ALL)); + $this->assertTrue($this->privateLinkDB->exists(6, BookmarkFilter::$ALL)); + + $this->assertTrue($this->privateLinkDB->exists(42, BookmarkFilter::$PUBLIC)); + $this->assertFalse($this->privateLinkDB->exists(6, BookmarkFilter::$PUBLIC)); + + $this->assertFalse($this->privateLinkDB->exists(42, BookmarkFilter::$PRIVATE)); + $this->assertTrue($this->privateLinkDB->exists(6, BookmarkFilter::$PRIVATE)); + + $this->assertTrue($this->publicLinkDB->exists(42)); + $this->assertFalse($this->publicLinkDB->exists(6)); + + $this->assertTrue($this->publicLinkDB->exists(42, BookmarkFilter::$PUBLIC)); + $this->assertFalse($this->publicLinkDB->exists(6, BookmarkFilter::$PUBLIC)); + + $this->assertFalse($this->publicLinkDB->exists(42, BookmarkFilter::$PRIVATE)); + $this->assertTrue($this->publicLinkDB->exists(6, BookmarkFilter::$PRIVATE)); + } + + /** + * Test initialize() method + */ + public function testInitialize() + { + $dbSize = $this->privateLinkDB->count(); + $this->privateLinkDB->initialize(); + $this->assertEquals($dbSize + 2, $this->privateLinkDB->count()); + $this->assertEquals( + 'My secret stuff... - Pastebin.com', + $this->privateLinkDB->get(43)->getTitle() + ); + $this->assertEquals( + 'The personal, minimalist, super-fast, database free, bookmarking service', + $this->privateLinkDB->get(44)->getTitle() + ); + } + + /* + * The following tests have been taken from the legacy LinkDB test and adapted + * to make sure that nothing have been broken in the migration process. + * They mostly cover search/filters. Some of them might be redundant with the previous ones. + */ + + /** + * Attempt to instantiate a LinkDB whereas the datastore is not writable + * + * @expectedException Shaarli\Bookmark\Exception\NotWritableDataStoreException + * @expectedExceptionMessageRegExp #Couldn't load data from the data store file "null".*# + */ + public function testConstructDatastoreNotWriteable() + { + $conf = new ConfigManager('tests/utils/config/configJson'); + $conf->set('resource.datastore', 'null/store.db'); + new BookmarkFileService($conf, $this->history, true); + } + + /** + * The DB doesn't exist, ensure it is created with an empty datastore + */ + public function testCheckDBNewLoggedIn() + { + unlink(self::$testDatastore); + $this->assertFileNotExists(self::$testDatastore); + new BookmarkFileService($this->conf, $this->history, true); + $this->assertFileExists(self::$testDatastore); + + // ensure the correct data has been written + $this->assertGreaterThan(0, filesize(self::$testDatastore)); + } + + /** + * The DB doesn't exist, but not logged in, ensure it initialized, but the file is not written + */ + public function testCheckDBNewLoggedOut() + { + unlink(self::$testDatastore); + $this->assertFileNotExists(self::$testDatastore); + $db = new \FakeBookmarkService($this->conf, $this->history, false); + $this->assertFileNotExists(self::$testDatastore); + $this->assertInstanceOf(BookmarkArray::class, $db->getBookmarks()); + $this->assertCount(0, $db->getBookmarks()); + } + + /** + * Load public bookmarks from the DB + */ + public function testReadPublicDB() + { + $this->assertEquals( + $this->refDB->countPublicLinks(), + $this->publicLinkDB->count() + ); + } + + /** + * Load public and private bookmarks from the DB + */ + public function testReadPrivateDB() + { + $this->assertEquals( + $this->refDB->countLinks(), + $this->privateLinkDB->count() + ); + } + + /** + * Save the bookmarks to the DB + */ + public function testSave() + { + $testDB = new BookmarkFileService($this->conf, $this->history, true); + $dbSize = $testDB->count(); + + $bookmark = new Bookmark(); + $testDB->add($bookmark); + + $testDB = new BookmarkFileService($this->conf, $this->history, true); + $this->assertEquals($dbSize + 1, $testDB->count()); + } + + /** + * Count existing bookmarks - public bookmarks hidden + */ + public function testCountHiddenPublic() + { + $this->conf->set('privacy.hide_public_links', true); + $linkDB = new BookmarkFileService($this->conf, $this->history, false); + + $this->assertEquals(0, $linkDB->count()); + } + + /** + * List the days for which bookmarks have been posted + */ + public function testDays() + { + $this->assertEquals( + ['20100309', '20100310', '20121206', '20121207', '20130614', '20150310'], + $this->publicLinkDB->days() + ); + + $this->assertEquals( + ['20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'], + $this->privateLinkDB->days() + ); + } + + /** + * The URL corresponds to an existing entry in the DB + */ + public function testGetKnownLinkFromURL() + { + $link = $this->publicLinkDB->findByUrl('http://mediagoblin.org/'); + + $this->assertNotEquals(false, $link); + $this->assertContains( + 'A free software media publishing platform', + $link->getDescription() + ); + } + + /** + * The URL is not in the DB + */ + public function testGetUnknownLinkFromURL() + { + $this->assertEquals( + false, + $this->publicLinkDB->findByUrl('http://dev.null') + ); + } + + /** + * Lists all tags + */ + public function testAllTags() + { + $this->assertEquals( + [ + 'web' => 3, + 'cartoon' => 2, + 'gnu' => 2, + 'dev' => 1, + 'samba' => 1, + 'media' => 1, + 'software' => 1, + 'stallman' => 1, + 'free' => 1, + '-exclude' => 1, + 'hashtag' => 2, + // The DB contains a link with `sTuff` and another one with `stuff` tag. + // They need to be grouped with the first case found - order by date DESC: `sTuff`. + 'sTuff' => 2, + 'ut' => 1, + ], + $this->publicLinkDB->bookmarksCountPerTag() + ); + + $this->assertEquals( + [ + 'web' => 4, + 'cartoon' => 3, + 'gnu' => 2, + 'dev' => 2, + 'samba' => 1, + 'media' => 1, + 'software' => 1, + 'stallman' => 1, + 'free' => 1, + 'html' => 1, + 'w3c' => 1, + 'css' => 1, + 'Mercurial' => 1, + 'sTuff' => 2, + '-exclude' => 1, + '.hidden' => 1, + 'hashtag' => 2, + 'tag1' => 1, + 'tag2' => 1, + 'tag3' => 1, + 'tag4' => 1, + 'ut' => 1, + ], + $this->privateLinkDB->bookmarksCountPerTag() + ); + $this->assertEquals( + [ + 'web' => 4, + 'cartoon' => 2, + 'gnu' => 1, + 'dev' => 1, + 'samba' => 1, + 'media' => 1, + 'html' => 1, + 'w3c' => 1, + 'css' => 1, + 'Mercurial' => 1, + '.hidden' => 1, + 'hashtag' => 1, + ], + $this->privateLinkDB->bookmarksCountPerTag(['web']) + ); + $this->assertEquals( + [ + 'web' => 1, + 'html' => 1, + 'w3c' => 1, + 'css' => 1, + 'Mercurial' => 1, + ], + $this->privateLinkDB->bookmarksCountPerTag(['web'], 'private') + ); + } + + /** + * Test filter with string. + */ + public function testFilterString() + { + $tags = 'dev cartoon'; + $request = ['searchtags' => $tags]; + $this->assertEquals( + 2, + count($this->privateLinkDB->search($request, null, true)) + ); + } + + /** + * Test filter with array. + */ + public function testFilterArray() + { + $tags = ['dev', 'cartoon']; + $request = ['searchtags' => $tags]; + $this->assertEquals( + 2, + count($this->privateLinkDB->search($request, null, true)) + ); + } + + /** + * Test hidden tags feature: + * tags starting with a dot '.' are only visible when logged in. + */ + public function testHiddenTags() + { + $tags = '.hidden'; + $request = ['searchtags' => $tags]; + $this->assertEquals( + 1, + count($this->privateLinkDB->search($request, 'all', true)) + ); + + $this->assertEquals( + 0, + count($this->publicLinkDB->search($request, 'public', true)) + ); + } + + /** + * Test filterHash() with a valid smallhash. + */ + public function testFilterHashValid() + { + $request = smallHash('20150310_114651'); + $this->assertEquals( + 1, + count($this->publicLinkDB->findByHash($request)) + ); + $request = smallHash('20150310_114633' . 8); + $this->assertEquals( + 1, + count($this->publicLinkDB->findByHash($request)) + ); + } + + /** + * Test filterHash() with an invalid smallhash. + * + * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException + */ + public function testFilterHashInValid1() + { + $request = 'blabla'; + $this->publicLinkDB->findByHash($request); + } + + /** + * Test filterHash() with an empty smallhash. + * + * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException + */ + public function testFilterHashInValid() + { + $this->publicLinkDB->findByHash(''); + } + + /** + * Test linksCountPerTag all tags without filter. + * Equal occurrences should be sorted alphabetically. + */ + public function testCountLinkPerTagAllNoFilter() + { + $expected = [ + 'web' => 4, + 'cartoon' => 3, + 'dev' => 2, + 'gnu' => 2, + 'hashtag' => 2, + 'sTuff' => 2, + '-exclude' => 1, + '.hidden' => 1, + 'Mercurial' => 1, + 'css' => 1, + 'free' => 1, + 'html' => 1, + 'media' => 1, + 'samba' => 1, + 'software' => 1, + 'stallman' => 1, + 'tag1' => 1, + 'tag2' => 1, + 'tag3' => 1, + 'tag4' => 1, + 'ut' => 1, + 'w3c' => 1, + ]; + $tags = $this->privateLinkDB->bookmarksCountPerTag(); + + $this->assertEquals($expected, $tags, var_export($tags, true)); + } + + /** + * Test linksCountPerTag all tags with filter. + * Equal occurrences should be sorted alphabetically. + */ + public function testCountLinkPerTagAllWithFilter() + { + $expected = [ + 'gnu' => 2, + 'hashtag' => 2, + '-exclude' => 1, + '.hidden' => 1, + 'free' => 1, + 'media' => 1, + 'software' => 1, + 'stallman' => 1, + 'stuff' => 1, + 'web' => 1, + ]; + $tags = $this->privateLinkDB->bookmarksCountPerTag(['gnu']); + + $this->assertEquals($expected, $tags, var_export($tags, true)); + } + + /** + * Test linksCountPerTag public tags with filter. + * Equal occurrences should be sorted alphabetically. + */ + public function testCountLinkPerTagPublicWithFilter() + { + $expected = [ + 'gnu' => 2, + 'hashtag' => 2, + '-exclude' => 1, + '.hidden' => 1, + 'free' => 1, + 'media' => 1, + 'software' => 1, + 'stallman' => 1, + 'stuff' => 1, + 'web' => 1, + ]; + $tags = $this->privateLinkDB->bookmarksCountPerTag(['gnu'], 'public'); + + $this->assertEquals($expected, $tags, var_export($tags, true)); + } + + /** + * Test linksCountPerTag public tags with filter. + * Equal occurrences should be sorted alphabetically. + */ + public function testCountLinkPerTagPrivateWithFilter() + { + $expected = [ + 'cartoon' => 1, + 'dev' => 1, + 'tag1' => 1, + 'tag2' => 1, + 'tag3' => 1, + 'tag4' => 1, + ]; + $tags = $this->privateLinkDB->bookmarksCountPerTag(['dev'], 'private'); + + $this->assertEquals($expected, $tags, var_export($tags, true)); + } + + /** + * Allows to test LinkDB's private methods + * + * @see + * https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html + * http://stackoverflow.com/a/2798203 + */ + protected static function getMethod($name) + { + $class = new ReflectionClass('Shaarli\Bookmark\BookmarkFileService'); + $method = $class->getMethod($name); + $method->setAccessible(true); + return $method; + } +} diff --git a/tests/bookmark/BookmarkFilterTest.php b/tests/bookmark/BookmarkFilterTest.php new file mode 100644 index 00000000..d4c71cb9 --- /dev/null +++ b/tests/bookmark/BookmarkFilterTest.php @@ -0,0 +1,514 @@ +set('resource.datastore', self::$testDatastore); + self::$refDB = new \ReferenceLinkDB(); + self::$refDB->write(self::$testDatastore); + $history = new History('sandbox/history.php'); + self::$bookmarkService = new \FakeBookmarkService($conf, $history, true); + self::$linkFilter = new BookmarkFilter(self::$bookmarkService->getBookmarks()); + } + + /** + * Blank filter. + */ + public function testFilter() + { + $this->assertEquals( + self::$refDB->countLinks(), + count(self::$linkFilter->filter('', '')) + ); + + $this->assertEquals( + self::$refDB->countLinks(), + count(self::$linkFilter->filter('', '', 'all')) + ); + + $this->assertEquals( + self::$refDB->countLinks(), + count(self::$linkFilter->filter('', '', 'randomstr')) + ); + + // Private only. + $this->assertEquals( + self::$refDB->countPrivateLinks(), + count(self::$linkFilter->filter('', '', false, 'private')) + ); + + // Public only. + $this->assertEquals( + self::$refDB->countPublicLinks(), + count(self::$linkFilter->filter('', '', false, 'public')) + ); + + $this->assertEquals( + ReferenceLinkDB::$NB_LINKS_TOTAL, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, '')) + ); + + $this->assertEquals( + self::$refDB->countUntaggedLinks(), + count( + self::$linkFilter->filter( + BookmarkFilter::$FILTER_TAG, + /*$request=*/ + '', + /*$casesensitive=*/ + false, + /*$visibility=*/ + 'all', + /*$untaggedonly=*/ + true + ) + ) + ); + + $this->assertEquals( + ReferenceLinkDB::$NB_LINKS_TOTAL, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, '')) + ); + } + + /** + * Filter bookmarks using a tag + */ + public function testFilterOneTag() + { + $this->assertEquals( + 4, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false)) + ); + + $this->assertEquals( + 4, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false, 'all')) + ); + + $this->assertEquals( + 4, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false, 'default-blabla')) + ); + + // Private only. + $this->assertEquals( + 1, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false, 'private')) + ); + + // Public only. + $this->assertEquals( + 3, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'web', false, 'public')) + ); + } + + /** + * Filter bookmarks using a tag - case-sensitive + */ + public function testFilterCaseSensitiveTag() + { + $this->assertEquals( + 0, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'mercurial', true)) + ); + + $this->assertEquals( + 1, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'Mercurial', true)) + ); + } + + /** + * Filter bookmarks using a tag combination + */ + public function testFilterMultipleTags() + { + $this->assertEquals( + 2, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'dev cartoon', false)) + ); + } + + /** + * Filter bookmarks using a non-existent tag + */ + public function testFilterUnknownTag() + { + $this->assertEquals( + 0, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'null', false)) + ); + } + + /** + * Return bookmarks for a given day + */ + public function testFilterDay() + { + $this->assertEquals( + 4, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '20121206')) + ); + } + + /** + * 404 - day not found + */ + public function testFilterUnknownDay() + { + $this->assertEquals( + 0, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '19700101')) + ); + } + + /** + * Use an invalid date format + * @expectedException Exception + * @expectedExceptionMessageRegExp /Invalid date format/ + */ + public function testFilterInvalidDayWithChars() + { + self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, 'Rainy day, dream away'); + } + + /** + * Use an invalid date format + * @expectedException Exception + * @expectedExceptionMessageRegExp /Invalid date format/ + */ + public function testFilterInvalidDayDigits() + { + self::$linkFilter->filter(BookmarkFilter::$FILTER_DAY, '20'); + } + + /** + * Retrieve a link entry with its hash + */ + public function testFilterSmallHash() + { + $links = self::$linkFilter->filter(BookmarkFilter::$FILTER_HASH, 'IuWvgA'); + + $this->assertEquals( + 1, + count($links) + ); + + $this->assertEquals( + 'MediaGoblin', + $links[7]->getTitle() + ); + } + + /** + * No link for this hash + * + * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException + */ + public function testFilterUnknownSmallHash() + { + self::$linkFilter->filter(BookmarkFilter::$FILTER_HASH, 'Iblaah'); + } + + /** + * Full-text search - no result found. + */ + public function testFilterFullTextNoResult() + { + $this->assertEquals( + 0, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'azertyuiop')) + ); + } + + /** + * Full-text search - result from a link's URL + */ + public function testFilterFullTextURL() + { + $this->assertEquals( + 2, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'ars.userfriendly.org')) + ); + + $this->assertEquals( + 2, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'ars org')) + ); + } + + /** + * Full-text search - result from a link's title only + */ + public function testFilterFullTextTitle() + { + // use miscellaneous cases + $this->assertEquals( + 2, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'userfriendly -')) + ); + $this->assertEquals( + 2, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'UserFriendly -')) + ); + $this->assertEquals( + 2, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'uSeRFrIendlY -')) + ); + + // use miscellaneous case and offset + $this->assertEquals( + 2, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'RFrIendL')) + ); + } + + /** + * Full-text search - result from the link's description only + */ + public function testFilterFullTextDescription() + { + $this->assertEquals( + 1, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'publishing media')) + ); + + $this->assertEquals( + 1, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'mercurial w3c')) + ); + + $this->assertEquals( + 3, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, '"free software"')) + ); + } + + /** + * Full-text search - result from the link's tags only + */ + public function testFilterFullTextTags() + { + $this->assertEquals( + 6, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web')) + ); + + $this->assertEquals( + 6, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web', 'all')) + ); + + $this->assertEquals( + 6, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web', 'bla')) + ); + + // Private only. + $this->assertEquals( + 1, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web', false, 'private')) + ); + + // Public only. + $this->assertEquals( + 5, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'web', false, 'public')) + ); + } + + /** + * Full-text search - result set from mixed sources + */ + public function testFilterFullTextMixed() + { + $this->assertEquals( + 3, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'free software')) + ); + } + + /** + * Full-text search - test exclusion with '-'. + */ + public function testExcludeSearch() + { + $this->assertEquals( + 1, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, 'free -gnu')) + ); + + $this->assertEquals( + ReferenceLinkDB::$NB_LINKS_TOTAL - 1, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TEXT, '-revolution')) + ); + } + + /** + * Full-text search - test AND, exact terms and exclusion combined, across fields. + */ + public function testMultiSearch() + { + $this->assertEquals( + 2, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TEXT, + '"Free Software " stallman "read this" @website stuff' + )) + ); + + $this->assertEquals( + 1, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TEXT, + '"free software " stallman "read this" -beard @website stuff' + )) + ); + } + + /** + * Full-text search - make sure that exact search won't work across fields. + */ + public function testSearchExactTermMultiFieldsKo() + { + $this->assertEquals( + 0, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TEXT, + '"designer naming"' + )) + ); + + $this->assertEquals( + 0, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TEXT, + '"designernaming"' + )) + ); + } + + /** + * Tag search with exclusion. + */ + public function testTagFilterWithExclusion() + { + $this->assertEquals( + 1, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, 'gnu -free')) + ); + + $this->assertEquals( + ReferenceLinkDB::$NB_LINKS_TOTAL - 1, + count(self::$linkFilter->filter(BookmarkFilter::$FILTER_TAG, '-free')) + ); + } + + /** + * Test crossed search (terms + tags). + */ + public function testFilterCrossedSearch() + { + $terms = '"Free Software " stallman "read this" @website stuff'; + $tags = 'free'; + $this->assertEquals( + 1, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT, + array($tags, $terms) + )) + ); + $this->assertEquals( + 2, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT, + array('', $terms) + )) + ); + $this->assertEquals( + 1, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT, + array(false, 'PSR-2') + )) + ); + $this->assertEquals( + 1, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT, + array($tags, '') + )) + ); + $this->assertEquals( + ReferenceLinkDB::$NB_LINKS_TOTAL, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT, + '' + )) + ); + } + + /** + * Filter bookmarks by #hashtag. + */ + public function testFilterByHashtag() + { + $hashtag = 'hashtag'; + $this->assertEquals( + 3, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TAG, + $hashtag + )) + ); + + $hashtag = 'private'; + $this->assertEquals( + 1, + count(self::$linkFilter->filter( + BookmarkFilter::$FILTER_TAG, + $hashtag, + false, + 'private' + )) + ); + } +} diff --git a/tests/bookmark/BookmarkInitializerTest.php b/tests/bookmark/BookmarkInitializerTest.php new file mode 100644 index 00000000..d23eb069 --- /dev/null +++ b/tests/bookmark/BookmarkInitializerTest.php @@ -0,0 +1,120 @@ +conf = new ConfigManager(self::$testConf); + $this->conf->set('resource.datastore', self::$testDatastore); + $this->history = new History('sandbox/history.php'); + $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true); + + $this->initializer = new BookmarkInitializer($this->bookmarkService); + } + + /** + * Test initialize() with an empty data store. + */ + public function testInitializeEmptyDataStore() + { + $refDB = new \ReferenceLinkDB(); + $refDB->write(self::$testDatastore); + $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true); + $this->initializer = new BookmarkInitializer($this->bookmarkService); + + $this->initializer->initialize(); + + $this->assertEquals($refDB->countLinks() + 2, $this->bookmarkService->count()); + $bookmark = $this->bookmarkService->get(43); + $this->assertEquals(43, $bookmark->getId()); + $this->assertEquals('My secret stuff... - Pastebin.com', $bookmark->getTitle()); + $this->assertTrue($bookmark->isPrivate()); + + $bookmark = $this->bookmarkService->get(44); + $this->assertEquals(44, $bookmark->getId()); + $this->assertEquals( + 'The personal, minimalist, super-fast, database free, bookmarking service', + $bookmark->getTitle() + ); + $this->assertFalse($bookmark->isPrivate()); + + // Reload from file + $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true); + $this->assertEquals($refDB->countLinks() + 2, $this->bookmarkService->count()); + $bookmark = $this->bookmarkService->get(43); + $this->assertEquals(43, $bookmark->getId()); + $this->assertEquals('My secret stuff... - Pastebin.com', $bookmark->getTitle()); + $this->assertTrue($bookmark->isPrivate()); + + $bookmark = $this->bookmarkService->get(44); + $this->assertEquals(44, $bookmark->getId()); + $this->assertEquals( + 'The personal, minimalist, super-fast, database free, bookmarking service', + $bookmark->getTitle() + ); + $this->assertFalse($bookmark->isPrivate()); + } + + /** + * Test initialize() with a data store containing bookmarks. + */ + public function testInitializeNotEmptyDataStore() + { + $this->initializer->initialize(); + + $this->assertEquals(2, $this->bookmarkService->count()); + $bookmark = $this->bookmarkService->get(0); + $this->assertEquals(0, $bookmark->getId()); + $this->assertEquals('My secret stuff... - Pastebin.com', $bookmark->getTitle()); + $this->assertTrue($bookmark->isPrivate()); + + $bookmark = $this->bookmarkService->get(1); + $this->assertEquals(1, $bookmark->getId()); + $this->assertEquals( + 'The personal, minimalist, super-fast, database free, bookmarking service', + $bookmark->getTitle() + ); + $this->assertFalse($bookmark->isPrivate()); + } +} diff --git a/tests/bookmark/BookmarkTest.php b/tests/bookmark/BookmarkTest.php new file mode 100644 index 00000000..9a3bbbfc --- /dev/null +++ b/tests/bookmark/BookmarkTest.php @@ -0,0 +1,388 @@ + 1, + 'shorturl' => 'abc', + 'url' => 'https://domain.tld/oof.html?param=value#anchor', + 'title' => 'This is an array link', + 'description' => 'HTML desc

hi!

', + 'thumbnail' => 'https://domain.tld/pic.png', + 'sticky' => true, + 'created' => new \DateTime('-1 minute'), + 'tags' => ['tag1', 'tag2', 'chair'], + 'updated' => new \DateTime(), + 'private' => true, + ]; + + $bookmark = (new Bookmark())->fromArray($data); + $this->assertEquals($data['id'], $bookmark->getId()); + $this->assertEquals($data['shorturl'], $bookmark->getShortUrl()); + $this->assertEquals($data['url'], $bookmark->getUrl()); + $this->assertEquals($data['title'], $bookmark->getTitle()); + $this->assertEquals($data['description'], $bookmark->getDescription()); + $this->assertEquals($data['thumbnail'], $bookmark->getThumbnail()); + $this->assertEquals($data['sticky'], $bookmark->isSticky()); + $this->assertEquals($data['created'], $bookmark->getCreated()); + $this->assertEquals($data['tags'], $bookmark->getTags()); + $this->assertEquals('tag1 tag2 chair', $bookmark->getTagsString()); + $this->assertEquals($data['updated'], $bookmark->getUpdated()); + $this->assertEquals($data['private'], $bookmark->isPrivate()); + $this->assertFalse($bookmark->isNote()); + } + + /** + * Test fromArray() with a link with minimal data. + * Note that I use null values everywhere but this should not happen in the real world. + */ + public function testFromArrayMinimal() + { + $data = [ + 'id' => null, + 'shorturl' => null, + 'url' => null, + 'title' => null, + 'description' => null, + 'created' => null, + 'tags' => null, + 'private' => null, + ]; + + $bookmark = (new Bookmark())->fromArray($data); + $this->assertNull($bookmark->getId()); + $this->assertNull($bookmark->getShortUrl()); + $this->assertNull($bookmark->getUrl()); + $this->assertNull($bookmark->getTitle()); + $this->assertEquals('', $bookmark->getDescription()); + $this->assertNull($bookmark->getCreated()); + $this->assertEquals([], $bookmark->getTags()); + $this->assertEquals('', $bookmark->getTagsString()); + $this->assertNull($bookmark->getUpdated()); + $this->assertFalse($bookmark->getThumbnail()); + $this->assertFalse($bookmark->isSticky()); + $this->assertFalse($bookmark->isPrivate()); + $this->assertTrue($bookmark->isNote()); + } + + /** + * Test validate() with a valid minimal bookmark + */ + public function testValidateValidFullBookmark() + { + $bookmark = new Bookmark(); + $bookmark->setId(2); + $bookmark->setShortUrl('abc'); + $bookmark->setCreated($date = \DateTime::createFromFormat('Ymd_His', '20190514_200102')); + $bookmark->setUpdated($dateUp = \DateTime::createFromFormat('Ymd_His', '20190514_210203')); + $bookmark->setUrl($url = 'https://domain.tld/oof.html?param=value#anchor'); + $bookmark->setTitle($title = 'This is an array link'); + $bookmark->setDescription($desc = 'HTML desc

hi!

'); + $bookmark->setTags($tags = ['tag1', 'tag2', 'chair']); + $bookmark->setThumbnail($thumb = 'https://domain.tld/pic.png'); + $bookmark->setPrivate(true); + $bookmark->validate(); + + $this->assertEquals(2, $bookmark->getId()); + $this->assertEquals('abc', $bookmark->getShortUrl()); + $this->assertEquals($date, $bookmark->getCreated()); + $this->assertEquals($dateUp, $bookmark->getUpdated()); + $this->assertEquals($url, $bookmark->getUrl()); + $this->assertEquals($title, $bookmark->getTitle()); + $this->assertEquals($desc, $bookmark->getDescription()); + $this->assertEquals($tags, $bookmark->getTags()); + $this->assertEquals(implode(' ', $tags), $bookmark->getTagsString()); + $this->assertEquals($thumb, $bookmark->getThumbnail()); + $this->assertTrue($bookmark->isPrivate()); + $this->assertFalse($bookmark->isNote()); + } + + /** + * Test validate() with a valid minimal bookmark + */ + public function testValidateValidMinimalBookmark() + { + $bookmark = new Bookmark(); + $bookmark->setId(1); + $bookmark->setShortUrl('abc'); + $bookmark->setCreated($date = \DateTime::createFromFormat('Ymd_His', '20190514_200102')); + $bookmark->validate(); + + $this->assertEquals(1, $bookmark->getId()); + $this->assertEquals('abc', $bookmark->getShortUrl()); + $this->assertEquals($date, $bookmark->getCreated()); + $this->assertEquals('?abc', $bookmark->getUrl()); + $this->assertEquals('?abc', $bookmark->getTitle()); + $this->assertEquals('', $bookmark->getDescription()); + $this->assertEquals([], $bookmark->getTags()); + $this->assertEquals('', $bookmark->getTagsString()); + $this->assertFalse($bookmark->getThumbnail()); + $this->assertFalse($bookmark->isPrivate()); + $this->assertTrue($bookmark->isNote()); + $this->assertNull($bookmark->getUpdated()); + } + + /** + * Test validate() with a a bookmark without ID. + */ + public function testValidateNotValidNoId() + { + $bookmark = new Bookmark(); + $bookmark->setShortUrl('abc'); + $bookmark->setCreated(\DateTime::createFromFormat('Ymd_His', '20190514_200102')); + $exception = null; + try { + $bookmark->validate(); + } catch (InvalidBookmarkException $e) { + $exception = $e; + } + $this->assertNotNull($exception); + $this->assertContains('- ID: '. PHP_EOL, $exception->getMessage()); + } + + /** + * Test validate() with a a bookmark with a non integer ID. + */ + public function testValidateNotValidStringId() + { + $bookmark = new Bookmark(); + $bookmark->setId('str'); + $bookmark->setShortUrl('abc'); + $bookmark->setCreated(\DateTime::createFromFormat('Ymd_His', '20190514_200102')); + $exception = null; + try { + $bookmark->validate(); + } catch (InvalidBookmarkException $e) { + $exception = $e; + } + $this->assertNotNull($exception); + $this->assertContains('- ID: str'. PHP_EOL, $exception->getMessage()); + } + + /** + * Test validate() with a a bookmark without short url. + */ + public function testValidateNotValidNoShortUrl() + { + $bookmark = new Bookmark(); + $bookmark->setId(1); + $bookmark->setCreated(\DateTime::createFromFormat('Ymd_His', '20190514_200102')); + $bookmark->setShortUrl(null); + $exception = null; + try { + $bookmark->validate(); + } catch (InvalidBookmarkException $e) { + $exception = $e; + } + $this->assertNotNull($exception); + $this->assertContains('- ShortUrl: '. PHP_EOL, $exception->getMessage()); + } + + /** + * Test validate() with a a bookmark without created datetime. + */ + public function testValidateNotValidNoCreated() + { + $bookmark = new Bookmark(); + $bookmark->setId(1); + $bookmark->setShortUrl('abc'); + $bookmark->setCreated(null); + $exception = null; + try { + $bookmark->validate(); + } catch (InvalidBookmarkException $e) { + $exception = $e; + } + $this->assertNotNull($exception); + $this->assertContains('- Created: '. PHP_EOL, $exception->getMessage()); + } + + /** + * Test validate() with a a bookmark with a bad created datetime. + */ + public function testValidateNotValidBadCreated() + { + $bookmark = new Bookmark(); + $bookmark->setId(1); + $bookmark->setShortUrl('abc'); + $bookmark->setCreated('hi!'); + $exception = null; + try { + $bookmark->validate(); + } catch (InvalidBookmarkException $e) { + $exception = $e; + } + $this->assertNotNull($exception); + $this->assertContains('- Created: Not a DateTime object'. PHP_EOL, $exception->getMessage()); + } + + /** + * Test setId() and make sure that default fields are generated. + */ + public function testSetIdEmptyGeneratedFields() + { + $bookmark = new Bookmark(); + $bookmark->setId(2); + + $this->assertEquals(2, $bookmark->getId()); + $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl()); + $this->assertTrue(new \DateTime('5 seconds ago') < $bookmark->getCreated()); + } + + /** + * Test setId() and with generated fields already set. + */ + public function testSetIdSetGeneratedFields() + { + $bookmark = new Bookmark(); + $bookmark->setShortUrl('abc'); + $bookmark->setCreated($date = \DateTime::createFromFormat('Ymd_His', '20190514_200102')); + $bookmark->setId(2); + + $this->assertEquals(2, $bookmark->getId()); + $this->assertEquals('abc', $bookmark->getShortUrl()); + $this->assertEquals($date, $bookmark->getCreated()); + } + + /** + * Test setUrl() and make sure it accepts custom protocols + */ + public function testGetUrlWithValidProtocols() + { + $bookmark = new Bookmark(); + $bookmark->setUrl($url = 'myprotocol://helloworld', ['myprotocol']); + $this->assertEquals($url, $bookmark->getUrl()); + + $bookmark->setUrl($url = 'https://helloworld.tld', ['myprotocol']); + $this->assertEquals($url, $bookmark->getUrl()); + } + + /** + * Test setUrl() and make sure it accepts custom protocols + */ + public function testGetUrlWithNotValidProtocols() + { + $bookmark = new Bookmark(); + $bookmark->setUrl('myprotocol://helloworld', []); + $this->assertEquals('http://helloworld', $bookmark->getUrl()); + + $bookmark->setUrl($url = 'https://helloworld.tld', []); + $this->assertEquals($url, $bookmark->getUrl()); + } + + /** + * Test setTagsString() with exotic data + */ + public function testSetTagsString() + { + $bookmark = new Bookmark(); + + $str = 'tag1 tag2 tag3.tag3-2, tag4 , -tag5 '; + $bookmark->setTagsString($str); + $this->assertEquals( + [ + 'tag1', + 'tag2', + 'tag3.tag3-2', + 'tag4', + 'tag5', + ], + $bookmark->getTags() + ); + } + + /** + * Test setTags() with exotic data + */ + public function testSetTags() + { + $bookmark = new Bookmark(); + + $array = [ + 'tag1 ', + ' tag2', + 'tag3.tag3-2,', + ', tag4', + ', ', + '-tag5 ', + ]; + $bookmark->setTags($array); + $this->assertEquals( + [ + 'tag1', + 'tag2', + 'tag3.tag3-2', + 'tag4', + 'tag5', + ], + $bookmark->getTags() + ); + } + + /** + * Test renameTag() + */ + public function testRenameTag() + { + $bookmark = new Bookmark(); + $bookmark->setTags(['tag1', 'tag2', 'chair']); + $bookmark->renameTag('chair', 'table'); + $this->assertEquals(['tag1', 'tag2', 'table'], $bookmark->getTags()); + $bookmark->renameTag('tag1', 'tag42'); + $this->assertEquals(['tag42', 'tag2', 'table'], $bookmark->getTags()); + $bookmark->renameTag('tag42', 'tag43'); + $this->assertEquals(['tag43', 'tag2', 'table'], $bookmark->getTags()); + $bookmark->renameTag('table', 'desk'); + $this->assertEquals(['tag43', 'tag2', 'desk'], $bookmark->getTags()); + } + + /** + * Test renameTag() with a tag that is not present in the bookmark + */ + public function testRenameTagNotExists() + { + $bookmark = new Bookmark(); + $bookmark->setTags(['tag1', 'tag2', 'chair']); + $bookmark->renameTag('nope', 'table'); + $this->assertEquals(['tag1', 'tag2', 'chair'], $bookmark->getTags()); + } + + /** + * Test deleteTag() + */ + public function testDeleteTag() + { + $bookmark = new Bookmark(); + $bookmark->setTags(['tag1', 'tag2', 'chair']); + $bookmark->deleteTag('chair'); + $this->assertEquals(['tag1', 'tag2'], $bookmark->getTags()); + $bookmark->deleteTag('tag1'); + $this->assertEquals(['tag2'], $bookmark->getTags()); + $bookmark->deleteTag('tag2'); + $this->assertEquals([], $bookmark->getTags()); + } + + /** + * Test deleteTag() with a tag that is not present in the bookmark + */ + public function testDeleteTagNotExists() + { + $bookmark = new Bookmark(); + $bookmark->setTags(['tag1', 'tag2', 'chair']); + $bookmark->deleteTag('nope'); + $this->assertEquals(['tag1', 'tag2', 'chair'], $bookmark->getTags()); + } +} diff --git a/tests/bookmark/LinkDBTest.php b/tests/bookmark/LinkDBTest.php deleted file mode 100644 index ffe03cc5..00000000 --- a/tests/bookmark/LinkDBTest.php +++ /dev/null @@ -1,656 +0,0 @@ -write(self::$testDatastore); - - self::$publicLinkDB = new LinkDB(self::$testDatastore, false, false); - self::$privateLinkDB = new LinkDB(self::$testDatastore, true, false); - } - - /** - * Allows to test LinkDB's private methods - * - * @see - * https://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html - * http://stackoverflow.com/a/2798203 - */ - protected static function getMethod($name) - { - $class = new ReflectionClass('Shaarli\Bookmark\LinkDB'); - $method = $class->getMethod($name); - $method->setAccessible(true); - return $method; - } - - /** - * Instantiate LinkDB objects - logged in user - */ - public function testConstructLoggedIn() - { - new LinkDB(self::$testDatastore, true, false); - $this->assertFileExists(self::$testDatastore); - } - - /** - * Instantiate LinkDB objects - logged out or public instance - */ - public function testConstructLoggedOut() - { - new LinkDB(self::$testDatastore, false, false); - $this->assertFileExists(self::$testDatastore); - } - - /** - * Attempt to instantiate a LinkDB whereas the datastore is not writable - * - * @expectedException Shaarli\Exceptions\IOException - * @expectedExceptionMessageRegExp /Error accessing "null"/ - */ - public function testConstructDatastoreNotWriteable() - { - new LinkDB('null/store.db', false, false); - } - - /** - * The DB doesn't exist, ensure it is created with dummy content - */ - public function testCheckDBNew() - { - $linkDB = new LinkDB(self::$testDatastore, false, false); - unlink(self::$testDatastore); - $this->assertFileNotExists(self::$testDatastore); - - $checkDB = self::getMethod('check'); - $checkDB->invokeArgs($linkDB, array()); - $this->assertFileExists(self::$testDatastore); - - // ensure the correct data has been written - $this->assertGreaterThan(0, filesize(self::$testDatastore)); - } - - /** - * The DB exists, don't do anything - */ - public function testCheckDBLoad() - { - $linkDB = new LinkDB(self::$testDatastore, false, false); - $datastoreSize = filesize(self::$testDatastore); - $this->assertGreaterThan(0, $datastoreSize); - - $checkDB = self::getMethod('check'); - $checkDB->invokeArgs($linkDB, array()); - - // ensure the datastore is left unmodified - $this->assertEquals( - $datastoreSize, - filesize(self::$testDatastore) - ); - } - - /** - * Load an empty DB - */ - public function testReadEmptyDB() - { - file_put_contents(self::$testDatastore, ''); - $emptyDB = new LinkDB(self::$testDatastore, false, false); - $this->assertEquals(0, sizeof($emptyDB)); - $this->assertEquals(0, count($emptyDB)); - } - - /** - * Load public links from the DB - */ - public function testReadPublicDB() - { - $this->assertEquals( - self::$refDB->countPublicLinks(), - sizeof(self::$publicLinkDB) - ); - } - - /** - * Load public and private links from the DB - */ - public function testReadPrivateDB() - { - $this->assertEquals( - self::$refDB->countLinks(), - sizeof(self::$privateLinkDB) - ); - } - - /** - * Save the links to the DB - */ - public function testSave() - { - $testDB = new LinkDB(self::$testDatastore, true, false); - $dbSize = sizeof($testDB); - - $link = array( - 'id' => 43, - 'title' => 'an additional link', - 'url' => 'http://dum.my', - 'description' => 'One more', - 'private' => 0, - 'created' => DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20150518_190000'), - 'tags' => 'unit test' - ); - $testDB[$link['id']] = $link; - $testDB->save('tests'); - - $testDB = new LinkDB(self::$testDatastore, true, false); - $this->assertEquals($dbSize + 1, sizeof($testDB)); - } - - /** - * Count existing links - */ - public function testCount() - { - $this->assertEquals( - self::$refDB->countPublicLinks(), - self::$publicLinkDB->count() - ); - $this->assertEquals( - self::$refDB->countLinks(), - self::$privateLinkDB->count() - ); - } - - /** - * Count existing links - public links hidden - */ - public function testCountHiddenPublic() - { - $linkDB = new LinkDB(self::$testDatastore, false, true); - - $this->assertEquals( - 0, - $linkDB->count() - ); - $this->assertEquals( - 0, - $linkDB->count() - ); - } - - /** - * List the days for which links have been posted - */ - public function testDays() - { - $this->assertEquals( - array('20100309', '20100310', '20121206', '20121207', '20130614', '20150310'), - self::$publicLinkDB->days() - ); - - $this->assertEquals( - array('20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'), - self::$privateLinkDB->days() - ); - } - - /** - * The URL corresponds to an existing entry in the DB - */ - public function testGetKnownLinkFromURL() - { - $link = self::$publicLinkDB->getLinkFromUrl('http://mediagoblin.org/'); - - $this->assertNotEquals(false, $link); - $this->assertContains( - 'A free software media publishing platform', - $link['description'] - ); - } - - /** - * The URL is not in the DB - */ - public function testGetUnknownLinkFromURL() - { - $this->assertEquals( - false, - self::$publicLinkDB->getLinkFromUrl('http://dev.null') - ); - } - - /** - * Lists all tags - */ - public function testAllTags() - { - $this->assertEquals( - array( - 'web' => 3, - 'cartoon' => 2, - 'gnu' => 2, - 'dev' => 1, - 'samba' => 1, - 'media' => 1, - 'software' => 1, - 'stallman' => 1, - 'free' => 1, - '-exclude' => 1, - 'hashtag' => 2, - // The DB contains a link with `sTuff` and another one with `stuff` tag. - // They need to be grouped with the first case found - order by date DESC: `sTuff`. - 'sTuff' => 2, - 'ut' => 1, - ), - self::$publicLinkDB->linksCountPerTag() - ); - - $this->assertEquals( - array( - 'web' => 4, - 'cartoon' => 3, - 'gnu' => 2, - 'dev' => 2, - 'samba' => 1, - 'media' => 1, - 'software' => 1, - 'stallman' => 1, - 'free' => 1, - 'html' => 1, - 'w3c' => 1, - 'css' => 1, - 'Mercurial' => 1, - 'sTuff' => 2, - '-exclude' => 1, - '.hidden' => 1, - 'hashtag' => 2, - 'tag1' => 1, - 'tag2' => 1, - 'tag3' => 1, - 'tag4' => 1, - 'ut' => 1, - ), - self::$privateLinkDB->linksCountPerTag() - ); - $this->assertEquals( - array( - 'web' => 4, - 'cartoon' => 2, - 'gnu' => 1, - 'dev' => 1, - 'samba' => 1, - 'media' => 1, - 'html' => 1, - 'w3c' => 1, - 'css' => 1, - 'Mercurial' => 1, - '.hidden' => 1, - 'hashtag' => 1, - ), - self::$privateLinkDB->linksCountPerTag(['web']) - ); - $this->assertEquals( - array( - 'web' => 1, - 'html' => 1, - 'w3c' => 1, - 'css' => 1, - 'Mercurial' => 1, - ), - self::$privateLinkDB->linksCountPerTag(['web'], 'private') - ); - } - - /** - * Test filter with string. - */ - public function testFilterString() - { - $tags = 'dev cartoon'; - $request = array('searchtags' => $tags); - $this->assertEquals( - 2, - count(self::$privateLinkDB->filterSearch($request, true, false)) - ); - } - - /** - * Test filter with string. - */ - public function testFilterArray() - { - $tags = array('dev', 'cartoon'); - $request = array('searchtags' => $tags); - $this->assertEquals( - 2, - count(self::$privateLinkDB->filterSearch($request, true, false)) - ); - } - - /** - * Test hidden tags feature: - * tags starting with a dot '.' are only visible when logged in. - */ - public function testHiddenTags() - { - $tags = '.hidden'; - $request = array('searchtags' => $tags); - $this->assertEquals( - 1, - count(self::$privateLinkDB->filterSearch($request, true, false)) - ); - - $this->assertEquals( - 0, - count(self::$publicLinkDB->filterSearch($request, true, false)) - ); - } - - /** - * Test filterHash() with a valid smallhash. - */ - public function testFilterHashValid() - { - $request = smallHash('20150310_114651'); - $this->assertEquals( - 1, - count(self::$publicLinkDB->filterHash($request)) - ); - $request = smallHash('20150310_114633' . 8); - $this->assertEquals( - 1, - count(self::$publicLinkDB->filterHash($request)) - ); - } - - /** - * Test filterHash() with an invalid smallhash. - * - * @expectedException \Shaarli\Bookmark\Exception\LinkNotFoundException - */ - public function testFilterHashInValid1() - { - $request = 'blabla'; - self::$publicLinkDB->filterHash($request); - } - - /** - * Test filterHash() with an empty smallhash. - * - * @expectedException \Shaarli\Bookmark\Exception\LinkNotFoundException - */ - public function testFilterHashInValid() - { - self::$publicLinkDB->filterHash(''); - } - - /** - * Test reorder with asc/desc parameter. - */ - public function testReorderLinksDesc() - { - self::$privateLinkDB->reorder('ASC'); - $stickyIds = [11, 10]; - $standardIds = [42, 4, 9, 1, 0, 7, 6, 8, 41]; - $linkIds = array_merge($stickyIds, $standardIds); - $cpt = 0; - foreach (self::$privateLinkDB as $key => $value) { - $this->assertEquals($linkIds[$cpt++], $key); - } - self::$privateLinkDB->reorder('DESC'); - $linkIds = array_merge(array_reverse($stickyIds), array_reverse($standardIds)); - $cpt = 0; - foreach (self::$privateLinkDB as $key => $value) { - $this->assertEquals($linkIds[$cpt++], $key); - } - } - - /** - * Test rename tag with a valid value present in multiple links - */ - public function testRenameTagMultiple() - { - self::$refDB->write(self::$testDatastore); - $linkDB = new LinkDB(self::$testDatastore, true, false); - - $res = $linkDB->renameTag('cartoon', 'Taz'); - $this->assertEquals(3, count($res)); - $this->assertContains(' Taz ', $linkDB[4]['tags']); - $this->assertContains(' Taz ', $linkDB[1]['tags']); - $this->assertContains(' Taz ', $linkDB[0]['tags']); - } - - /** - * Test rename tag with a valid value - */ - public function testRenameTagCaseSensitive() - { - self::$refDB->write(self::$testDatastore); - $linkDB = new LinkDB(self::$testDatastore, true, false); - - $res = $linkDB->renameTag('sTuff', 'Taz'); - $this->assertEquals(1, count($res)); - $this->assertEquals('Taz', $linkDB[41]['tags']); - } - - /** - * Test rename tag with invalid values - */ - public function testRenameTagInvalid() - { - $linkDB = new LinkDB(self::$testDatastore, false, false); - - $this->assertFalse($linkDB->renameTag('', 'test')); - $this->assertFalse($linkDB->renameTag('', '')); - // tag non existent - $this->assertEquals([], $linkDB->renameTag('test', '')); - $this->assertEquals([], $linkDB->renameTag('test', 'retest')); - } - - /** - * Test delete tag with a valid value - */ - public function testDeleteTag() - { - self::$refDB->write(self::$testDatastore); - $linkDB = new LinkDB(self::$testDatastore, true, false); - - $res = $linkDB->renameTag('cartoon', null); - $this->assertEquals(3, count($res)); - $this->assertNotContains('cartoon', $linkDB[4]['tags']); - } - - /** - * Test linksCountPerTag all tags without filter. - * Equal occurrences should be sorted alphabetically. - */ - public function testCountLinkPerTagAllNoFilter() - { - $expected = [ - 'web' => 4, - 'cartoon' => 3, - 'dev' => 2, - 'gnu' => 2, - 'hashtag' => 2, - 'sTuff' => 2, - '-exclude' => 1, - '.hidden' => 1, - 'Mercurial' => 1, - 'css' => 1, - 'free' => 1, - 'html' => 1, - 'media' => 1, - 'samba' => 1, - 'software' => 1, - 'stallman' => 1, - 'tag1' => 1, - 'tag2' => 1, - 'tag3' => 1, - 'tag4' => 1, - 'ut' => 1, - 'w3c' => 1, - ]; - $tags = self::$privateLinkDB->linksCountPerTag(); - - $this->assertEquals($expected, $tags, var_export($tags, true)); - } - - /** - * Test linksCountPerTag all tags with filter. - * Equal occurrences should be sorted alphabetically. - */ - public function testCountLinkPerTagAllWithFilter() - { - $expected = [ - 'gnu' => 2, - 'hashtag' => 2, - '-exclude' => 1, - '.hidden' => 1, - 'free' => 1, - 'media' => 1, - 'software' => 1, - 'stallman' => 1, - 'stuff' => 1, - 'web' => 1, - ]; - $tags = self::$privateLinkDB->linksCountPerTag(['gnu']); - - $this->assertEquals($expected, $tags, var_export($tags, true)); - } - - /** - * Test linksCountPerTag public tags with filter. - * Equal occurrences should be sorted alphabetically. - */ - public function testCountLinkPerTagPublicWithFilter() - { - $expected = [ - 'gnu' => 2, - 'hashtag' => 2, - '-exclude' => 1, - '.hidden' => 1, - 'free' => 1, - 'media' => 1, - 'software' => 1, - 'stallman' => 1, - 'stuff' => 1, - 'web' => 1, - ]; - $tags = self::$privateLinkDB->linksCountPerTag(['gnu'], 'public'); - - $this->assertEquals($expected, $tags, var_export($tags, true)); - } - - /** - * Test linksCountPerTag public tags with filter. - * Equal occurrences should be sorted alphabetically. - */ - public function testCountLinkPerTagPrivateWithFilter() - { - $expected = [ - 'cartoon' => 1, - 'dev' => 1, - 'tag1' => 1, - 'tag2' => 1, - 'tag3' => 1, - 'tag4' => 1, - ]; - $tags = self::$privateLinkDB->linksCountPerTag(['dev'], 'private'); - - $this->assertEquals($expected, $tags, var_export($tags, true)); - } - - /** - * Make sure that bookmarks with the same timestamp have a consistent order: - * if their creation date is equal, bookmarks are sorted by ID DESC. - */ - public function testConsistentOrder() - { - $nextId = 43; - $creation = DateTime::createFromFormat('Ymd_His', '20190807_130444'); - $linkDB = new LinkDB(self::$testDatastore, true, false); - for ($i = 0; $i < 4; ++$i) { - $linkDB[$nextId + $i] = [ - 'id' => $nextId + $i, - 'url' => 'http://'. $i, - 'created' => $creation, - 'title' => true, - 'description' => true, - 'tags' => true, - ]; - } - - // Check 4 new links 4 times - for ($i = 0; $i < 4; ++$i) { - $linkDB->save('tests'); - $linkDB = new LinkDB(self::$testDatastore, true, false); - $count = 3; - foreach ($linkDB as $link) { - if ($link['sticky'] === true) { - continue; - } - $this->assertEquals($nextId + $count, $link['id']); - $this->assertEquals('http://'. $count, $link['url']); - if (--$count < 0) { - break; - } - } - } - } -} diff --git a/tests/bookmark/LinkFilterTest.php b/tests/bookmark/LinkFilterTest.php deleted file mode 100644 index 808f8122..00000000 --- a/tests/bookmark/LinkFilterTest.php +++ /dev/null @@ -1,507 +0,0 @@ -write(self::$testDatastore); - self::$linkDB = new LinkDB(self::$testDatastore, true, false); - self::$linkFilter = new LinkFilter(self::$linkDB); - } - - /** - * Blank filter. - */ - public function testFilter() - { - $this->assertEquals( - self::$refDB->countLinks(), - count(self::$linkFilter->filter('', '')) - ); - - $this->assertEquals( - self::$refDB->countLinks(), - count(self::$linkFilter->filter('', '', 'all')) - ); - - $this->assertEquals( - self::$refDB->countLinks(), - count(self::$linkFilter->filter('', '', 'randomstr')) - ); - - // Private only. - $this->assertEquals( - self::$refDB->countPrivateLinks(), - count(self::$linkFilter->filter('', '', false, 'private')) - ); - - // Public only. - $this->assertEquals( - self::$refDB->countPublicLinks(), - count(self::$linkFilter->filter('', '', false, 'public')) - ); - - $this->assertEquals( - ReferenceLinkDB::$NB_LINKS_TOTAL, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, '')) - ); - - $this->assertEquals( - self::$refDB->countUntaggedLinks(), - count( - self::$linkFilter->filter( - LinkFilter::$FILTER_TAG, - /*$request=*/ - '', - /*$casesensitive=*/ - false, - /*$visibility=*/ - 'all', - /*$untaggedonly=*/ - true - ) - ) - ); - - $this->assertEquals( - ReferenceLinkDB::$NB_LINKS_TOTAL, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '')) - ); - } - - /** - * Filter links using a tag - */ - public function testFilterOneTag() - { - $this->assertEquals( - 4, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false)) - ); - - $this->assertEquals( - 4, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'all')) - ); - - $this->assertEquals( - 4, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'default-blabla')) - ); - - // Private only. - $this->assertEquals( - 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'private')) - ); - - // Public only. - $this->assertEquals( - 3, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'web', false, 'public')) - ); - } - - /** - * Filter links using a tag - case-sensitive - */ - public function testFilterCaseSensitiveTag() - { - $this->assertEquals( - 0, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'mercurial', true)) - ); - - $this->assertEquals( - 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'Mercurial', true)) - ); - } - - /** - * Filter links using a tag combination - */ - public function testFilterMultipleTags() - { - $this->assertEquals( - 2, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'dev cartoon', false)) - ); - } - - /** - * Filter links using a non-existent tag - */ - public function testFilterUnknownTag() - { - $this->assertEquals( - 0, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'null', false)) - ); - } - - /** - * Return links for a given day - */ - public function testFilterDay() - { - $this->assertEquals( - 4, - count(self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '20121206')) - ); - } - - /** - * 404 - day not found - */ - public function testFilterUnknownDay() - { - $this->assertEquals( - 0, - count(self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '19700101')) - ); - } - - /** - * Use an invalid date format - * @expectedException Exception - * @expectedExceptionMessageRegExp /Invalid date format/ - */ - public function testFilterInvalidDayWithChars() - { - self::$linkFilter->filter(LinkFilter::$FILTER_DAY, 'Rainy day, dream away'); - } - - /** - * Use an invalid date format - * @expectedException Exception - * @expectedExceptionMessageRegExp /Invalid date format/ - */ - public function testFilterInvalidDayDigits() - { - self::$linkFilter->filter(LinkFilter::$FILTER_DAY, '20'); - } - - /** - * Retrieve a link entry with its hash - */ - public function testFilterSmallHash() - { - $links = self::$linkFilter->filter(LinkFilter::$FILTER_HASH, 'IuWvgA'); - - $this->assertEquals( - 1, - count($links) - ); - - $this->assertEquals( - 'MediaGoblin', - $links[7]['title'] - ); - } - - /** - * No link for this hash - * - * @expectedException \Shaarli\Bookmark\Exception\LinkNotFoundException - */ - public function testFilterUnknownSmallHash() - { - self::$linkFilter->filter(LinkFilter::$FILTER_HASH, 'Iblaah'); - } - - /** - * Full-text search - no result found. - */ - public function testFilterFullTextNoResult() - { - $this->assertEquals( - 0, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'azertyuiop')) - ); - } - - /** - * Full-text search - result from a link's URL - */ - public function testFilterFullTextURL() - { - $this->assertEquals( - 2, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars.userfriendly.org')) - ); - - $this->assertEquals( - 2, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'ars org')) - ); - } - - /** - * Full-text search - result from a link's title only - */ - public function testFilterFullTextTitle() - { - // use miscellaneous cases - $this->assertEquals( - 2, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'userfriendly -')) - ); - $this->assertEquals( - 2, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'UserFriendly -')) - ); - $this->assertEquals( - 2, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'uSeRFrIendlY -')) - ); - - // use miscellaneous case and offset - $this->assertEquals( - 2, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'RFrIendL')) - ); - } - - /** - * Full-text search - result from the link's description only - */ - public function testFilterFullTextDescription() - { - $this->assertEquals( - 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'publishing media')) - ); - - $this->assertEquals( - 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'mercurial w3c')) - ); - - $this->assertEquals( - 3, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '"free software"')) - ); - } - - /** - * Full-text search - result from the link's tags only - */ - public function testFilterFullTextTags() - { - $this->assertEquals( - 6, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web')) - ); - - $this->assertEquals( - 6, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'all')) - ); - - $this->assertEquals( - 6, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', 'bla')) - ); - - // Private only. - $this->assertEquals( - 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'private')) - ); - - // Public only. - $this->assertEquals( - 5, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'web', false, 'public')) - ); - } - - /** - * Full-text search - result set from mixed sources - */ - public function testFilterFullTextMixed() - { - $this->assertEquals( - 3, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'free software')) - ); - } - - /** - * Full-text search - test exclusion with '-'. - */ - public function testExcludeSearch() - { - $this->assertEquals( - 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, 'free -gnu')) - ); - - $this->assertEquals( - ReferenceLinkDB::$NB_LINKS_TOTAL - 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TEXT, '-revolution')) - ); - } - - /** - * Full-text search - test AND, exact terms and exclusion combined, across fields. - */ - public function testMultiSearch() - { - $this->assertEquals( - 2, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TEXT, - '"Free Software " stallman "read this" @website stuff' - )) - ); - - $this->assertEquals( - 1, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TEXT, - '"free software " stallman "read this" -beard @website stuff' - )) - ); - } - - /** - * Full-text search - make sure that exact search won't work across fields. - */ - public function testSearchExactTermMultiFieldsKo() - { - $this->assertEquals( - 0, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TEXT, - '"designer naming"' - )) - ); - - $this->assertEquals( - 0, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TEXT, - '"designernaming"' - )) - ); - } - - /** - * Tag search with exclusion. - */ - public function testTagFilterWithExclusion() - { - $this->assertEquals( - 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, 'gnu -free')) - ); - - $this->assertEquals( - ReferenceLinkDB::$NB_LINKS_TOTAL - 1, - count(self::$linkFilter->filter(LinkFilter::$FILTER_TAG, '-free')) - ); - } - - /** - * Test crossed search (terms + tags). - */ - public function testFilterCrossedSearch() - { - $terms = '"Free Software " stallman "read this" @website stuff'; - $tags = 'free'; - $this->assertEquals( - 1, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT, - array($tags, $terms) - )) - ); - $this->assertEquals( - 2, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT, - array('', $terms) - )) - ); - $this->assertEquals( - 1, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT, - array(false, 'PSR-2') - )) - ); - $this->assertEquals( - 1, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT, - array($tags, '') - )) - ); - $this->assertEquals( - ReferenceLinkDB::$NB_LINKS_TOTAL, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TAG | LinkFilter::$FILTER_TEXT, - '' - )) - ); - } - - /** - * Filter links by #hashtag. - */ - public function testFilterByHashtag() - { - $hashtag = 'hashtag'; - $this->assertEquals( - 3, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TAG, - $hashtag - )) - ); - - $hashtag = 'private'; - $this->assertEquals( - 1, - count(self::$linkFilter->filter( - LinkFilter::$FILTER_TAG, - $hashtag, - false, - 'private' - )) - ); - } -} diff --git a/tests/bookmark/LinkUtilsTest.php b/tests/bookmark/LinkUtilsTest.php index 78cb8f2a..591976f2 100644 --- a/tests/bookmark/LinkUtilsTest.php +++ b/tests/bookmark/LinkUtilsTest.php @@ -388,15 +388,6 @@ class LinkUtilsTest extends TestCase $this->assertEmpty($keywords); } - /** - * Test count_private. - */ - public function testCountPrivateLinks() - { - $refDB = new ReferenceLinkDB(); - $this->assertEquals($refDB->countPrivateLinks(), count_private($refDB->getLinks())); - } - /** * Test text2clickable. */ -- cgit v1.2.3