aboutsummaryrefslogtreecommitdiffstats
path: root/tests/lib/SystemTag
diff options
context:
space:
mode:
Diffstat (limited to 'tests/lib/SystemTag')
-rw-r--r--tests/lib/SystemTag/SystemTagManagerTest.php591
-rw-r--r--tests/lib/SystemTag/SystemTagObjectMapperTest.php406
2 files changed, 997 insertions, 0 deletions
diff --git a/tests/lib/SystemTag/SystemTagManagerTest.php b/tests/lib/SystemTag/SystemTagManagerTest.php
new file mode 100644
index 00000000000..b443d7222b2
--- /dev/null
+++ b/tests/lib/SystemTag/SystemTagManagerTest.php
@@ -0,0 +1,591 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\SystemTag;
+
+use OC\SystemTag\SystemTagManager;
+use OC\SystemTag\SystemTagObjectMapper;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\IAppConfig;
+use OCP\IDBConnection;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\IUserSession;
+use OCP\Server;
+use OCP\SystemTag\ISystemTag;
+use OCP\SystemTag\ISystemTagManager;
+use OCP\SystemTag\TagAlreadyExistsException;
+use OCP\SystemTag\TagNotFoundException;
+use Test\TestCase;
+
+/**
+ * Class TestSystemTagManager
+ *
+ * @group DB
+ * @package Test\SystemTag
+ */
+class SystemTagManagerTest extends TestCase {
+ private ISystemTagManager $tagManager;
+ private IDBConnection $connection;
+ private IGroupManager $groupManager;
+ private IUserSession $userSession;
+ private IAppConfig $appConfig;
+ private IEventDispatcher $dispatcher;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->connection = Server::get(IDBConnection::class);
+
+ $this->dispatcher = $this->createMock(IEventDispatcher::class);
+ $this->groupManager = $this->createMock(IGroupManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->appConfig = $this->createMock(IAppConfig::class);
+
+ $this->tagManager = new SystemTagManager(
+ $this->connection,
+ $this->groupManager,
+ $this->dispatcher,
+ $this->userSession,
+ $this->appConfig,
+ );
+ $this->pruneTagsTables();
+ }
+
+ protected function tearDown(): void {
+ $this->pruneTagsTables();
+ \OC::$CLI = true;
+ parent::tearDown();
+ }
+
+ protected function pruneTagsTables() {
+ $query = $this->connection->getQueryBuilder();
+ $query->delete(SystemTagObjectMapper::RELATION_TABLE)->execute();
+ $query->delete(SystemTagManager::TAG_TABLE)->execute();
+ }
+
+ public static function getAllTagsDataProvider(): array {
+ return [
+ [
+ // no tags at all
+ []
+ ],
+ [
+ // simple
+ [
+ ['one', false, false],
+ ['two', false, false],
+ ]
+ ],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('getAllTagsDataProvider')]
+ public function testGetAllTags($testTags): void {
+ $testTagsById = [];
+ foreach ($testTags as $testTag) {
+ $tag = $this->tagManager->createTag($testTag[0], $testTag[1], $testTag[2]);
+ $testTagsById[$tag->getId()] = $tag;
+ }
+
+ $tagList = $this->tagManager->getAllTags();
+
+ $this->assertCount(count($testTags), $tagList);
+
+ foreach ($testTagsById as $testTagId => $testTag) {
+ $this->assertTrue(isset($tagList[$testTagId]));
+ $this->assertSameTag($tagList[$testTagId], $testTag);
+ }
+ }
+
+ public static function getAllTagsFilteredDataProvider(): array {
+ return [
+ [
+ [
+ // no tags at all
+ ],
+ null,
+ null,
+ []
+ ],
+ // filter by visible only
+ [
+ // none visible
+ [
+ ['one', false, false],
+ ['two', false, false],
+ ],
+ true,
+ null,
+ []
+ ],
+ [
+ // one visible
+ [
+ ['one', true, false],
+ ['two', false, false],
+ ],
+ true,
+ null,
+ [
+ ['one', true, false],
+ ]
+ ],
+ [
+ // one invisible
+ [
+ ['one', true, false],
+ ['two', false, false],
+ ],
+ false,
+ null,
+ [
+ ['two', false, false],
+ ]
+ ],
+ // filter by name pattern
+ [
+ [
+ ['one', true, false],
+ ['one_different', false, false],
+ ['two', true, false],
+ ],
+ null,
+ 'on',
+ [
+ ['one', true, false],
+ ['one_different', false, false],
+ ]
+ ],
+ // filter by name pattern and visibility
+ [
+ // one visible
+ [
+ ['one', true, false],
+ ['two', true, false],
+ ['one_different', false, false],
+ ],
+ true,
+ 'on',
+ [
+ ['one', true, false],
+ ]
+ ],
+ // filter by name pattern in the middle
+ [
+ // one visible
+ [
+ ['abcdefghi', true, false],
+ ['two', true, false],
+ ],
+ null,
+ 'def',
+ [
+ ['abcdefghi', true, false],
+ ]
+ ]
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('getAllTagsFilteredDataProvider')]
+ public function testGetAllTagsFiltered($testTags, $visibilityFilter, $nameSearch, $expectedResults): void {
+ foreach ($testTags as $testTag) {
+ $this->tagManager->createTag($testTag[0], $testTag[1], $testTag[2]);
+ }
+
+ $testTagsById = [];
+ foreach ($expectedResults as $expectedTag) {
+ $tag = $this->tagManager->getTag($expectedTag[0], $expectedTag[1], $expectedTag[2]);
+ $testTagsById[$tag->getId()] = $tag;
+ }
+
+ $tagList = $this->tagManager->getAllTags($visibilityFilter, $nameSearch);
+
+ $this->assertCount(count($testTagsById), $tagList);
+
+ foreach ($testTagsById as $testTagId => $testTag) {
+ $this->assertTrue(isset($tagList[$testTagId]));
+ $this->assertSameTag($tagList[$testTagId], $testTag);
+ }
+ }
+
+ public static function oneTagMultipleFlagsProvider(): array {
+ return [
+ ['one', false, false],
+ ['one', true, false],
+ ['one', false, true],
+ ['one', true, true],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('oneTagMultipleFlagsProvider')]
+ public function testCreateDuplicate($name, $userVisible, $userAssignable): void {
+ $this->expectException(TagAlreadyExistsException::class);
+
+ try {
+ $this->tagManager->createTag($name, $userVisible, $userAssignable);
+ } catch (\Exception $e) {
+ $this->assertTrue(false, 'No exception thrown for the first create call');
+ }
+ $this->tagManager->createTag($name, $userVisible, $userAssignable);
+ }
+
+ public function testCreateDuplicateWithDifferentFlags(): void {
+ $this->expectException(TagAlreadyExistsException::class);
+
+ // Create a tag with specific flags
+ $this->tagManager->createTag('duplicate', true, false);
+ // Try to create a tag with the same name but different flags - should fail
+ $this->tagManager->createTag('duplicate', false, true);
+ }
+
+ public function testCreateOverlongName(): void {
+ $tag = $this->tagManager->createTag('Zona circundante do Palácio Nacional da Ajuda (Jardim das Damas, Salão de Física, Torre Sineira, Paço Velho e Jardim Botânico)', true, true);
+ $this->assertSame('Zona circundante do Palácio Nacional da Ajuda (Jardim das Damas', $tag->getName()); // 63 characters but 64 bytes due to "á"
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('oneTagMultipleFlagsProvider')]
+ public function testGetExistingTag($name, $userVisible, $userAssignable): void {
+ $tag1 = $this->tagManager->createTag($name, $userVisible, $userAssignable);
+ $tag2 = $this->tagManager->getTag($name, $userVisible, $userAssignable);
+
+ $this->assertSameTag($tag1, $tag2);
+ }
+
+ public function testGetExistingTagById(): void {
+ $tag1 = $this->tagManager->createTag('one', true, false);
+ $tag2 = $this->tagManager->createTag('two', false, true);
+
+ $tagList = $this->tagManager->getTagsByIds([$tag1->getId(), $tag2->getId()]);
+
+ $this->assertCount(2, $tagList);
+
+ $this->assertSameTag($tag1, $tagList[$tag1->getId()]);
+ $this->assertSameTag($tag2, $tagList[$tag2->getId()]);
+ }
+
+
+ public function testGetNonExistingTag(): void {
+ $this->expectException(TagNotFoundException::class);
+
+ $this->tagManager->getTag('nonexist', false, false);
+ }
+
+
+ public function testGetNonExistingTagsById(): void {
+ $this->expectException(TagNotFoundException::class);
+
+ $tag1 = $this->tagManager->createTag('one', true, false);
+ $this->tagManager->getTagsByIds([$tag1->getId(), 100, 101]);
+ }
+
+
+ public function testGetInvalidTagIdFormat(): void {
+ $this->expectException(\InvalidArgumentException::class);
+
+ $tag1 = $this->tagManager->createTag('one', true, false);
+ $this->tagManager->getTagsByIds([$tag1->getId() . 'suffix']);
+ }
+
+ public static function updateTagProvider(): array {
+ return [
+ [
+ // update name
+ ['one', true, true, '0082c9'],
+ ['two', true, true, '0082c9']
+ ],
+ [
+ // update one flag
+ ['one', false, true, null],
+ ['one', true, true, '0082c9']
+ ],
+ [
+ // update all flags
+ ['one', false, false, '0082c9'],
+ ['one', true, true, null]
+ ],
+ [
+ // update all
+ ['one', false, false, '0082c9'],
+ ['two', true, true, '0082c9']
+ ],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('updateTagProvider')]
+ public function testUpdateTag($tagCreate, $tagUpdated): void {
+ $tag1 = $this->tagManager->createTag(
+ $tagCreate[0],
+ $tagCreate[1],
+ $tagCreate[2],
+ $tagCreate[3],
+ );
+ $this->tagManager->updateTag(
+ $tag1->getId(),
+ $tagUpdated[0],
+ $tagUpdated[1],
+ $tagUpdated[2],
+ $tagUpdated[3],
+ );
+ $tag2 = $this->tagManager->getTag(
+ $tagUpdated[0],
+ $tagUpdated[1],
+ $tagUpdated[2],
+ $tagUpdated[3],
+ );
+
+ $this->assertEquals($tag2->getId(), $tag1->getId());
+ $this->assertEquals($tag2->getName(), $tagUpdated[0]);
+ $this->assertEquals($tag2->isUserVisible(), $tagUpdated[1]);
+ $this->assertEquals($tag2->isUserAssignable(), $tagUpdated[2]);
+ $this->assertEquals($tag2->getColor(), $tagUpdated[3]);
+
+ }
+
+ public function testUpdateTagToExistingName(): void {
+ $this->expectException(TagAlreadyExistsException::class);
+
+ // Create two different tags
+ $tag1 = $this->tagManager->createTag('first', true, true);
+ $tag2 = $this->tagManager->createTag('second', false, false);
+
+ // Try to update tag2 to have the same name as tag1 - should fail
+ $this->tagManager->updateTag(
+ $tag2->getId(),
+ 'first',
+ false,
+ false,
+ null
+ );
+ }
+
+ public function testDeleteTags(): void {
+ $tag1 = $this->tagManager->createTag('one', true, false);
+ $tag2 = $this->tagManager->createTag('two', false, true);
+
+ $this->tagManager->deleteTags([$tag1->getId(), $tag2->getId()]);
+
+ $this->assertEmpty($this->tagManager->getAllTags());
+ }
+
+
+ public function testDeleteNonExistingTag(): void {
+ $this->expectException(TagNotFoundException::class);
+
+ $this->tagManager->deleteTags([100]);
+ }
+
+ public function testDeleteTagRemovesRelations(): void {
+ $tag1 = $this->tagManager->createTag('one', true, false);
+ $tag2 = $this->tagManager->createTag('two', true, true);
+
+ $tagMapper = new SystemTagObjectMapper($this->connection, $this->tagManager, $this->dispatcher);
+
+ $tagMapper->assignTags(1, 'testtype', $tag1->getId());
+ $tagMapper->assignTags(1, 'testtype', $tag2->getId());
+ $tagMapper->assignTags(2, 'testtype', $tag1->getId());
+
+ $this->tagManager->deleteTags($tag1->getId());
+
+ $tagIdMapping = $tagMapper->getTagIdsForObjects(
+ [1, 2],
+ 'testtype'
+ );
+
+ $this->assertEquals([
+ 1 => [$tag2->getId()],
+ 2 => [],
+ ], $tagIdMapping);
+ }
+
+ public static function visibilityCheckProvider(): array {
+ return [
+ [false, false, false, false],
+ [true, false, false, true],
+ [false, false, true, true],
+ [true, false, true, true],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('visibilityCheckProvider')]
+ public function testVisibilityCheck($userVisible, $userAssignable, $isAdmin, $expectedResult): void {
+ $user = $this->getMockBuilder(IUser::class)->getMock();
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn('test');
+ $tag1 = $this->tagManager->createTag('one', $userVisible, $userAssignable);
+
+ $this->groupManager->expects($this->any())
+ ->method('isAdmin')
+ ->with('test')
+ ->willReturn($isAdmin);
+
+ $this->assertEquals($expectedResult, $this->tagManager->canUserSeeTag($tag1, $user));
+ }
+
+ public static function assignabilityCheckProvider(): array {
+ return [
+ // no groups
+ [false, false, false, false],
+ [true, false, false, false],
+ [true, true, false, true],
+ [false, true, false, false],
+ // admin rulez
+ [false, false, true, true],
+ [false, true, true, true],
+ [true, false, true, true],
+ [true, true, true, true],
+ // ignored groups
+ [false, false, false, false, ['group1'], ['group1']],
+ [true, true, false, true, ['group1'], ['group1']],
+ [true, true, false, true, ['group1'], ['anothergroup']],
+ [false, true, false, false, ['group1'], ['group1']],
+ // admin has precedence over groups
+ [false, false, true, true, ['group1'], ['anothergroup']],
+ [false, true, true, true, ['group1'], ['anothergroup']],
+ [true, false, true, true, ['group1'], ['anothergroup']],
+ [true, true, true, true, ['group1'], ['anothergroup']],
+ // groups only checked when visible and user non-assignable and non-admin
+ [true, false, false, false, ['group1'], ['anothergroup1']],
+ [true, false, false, true, ['group1'], ['group1']],
+ [true, false, false, true, ['group1', 'group2'], ['group2', 'group3']],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('assignabilityCheckProvider')]
+ public function testAssignabilityCheck($userVisible, $userAssignable, $isAdmin, $expectedResult, $userGroupIds = [], $tagGroupIds = []): void {
+ $user = $this->getMockBuilder(IUser::class)->getMock();
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn('test');
+ $tag1 = $this->tagManager->createTag('one', $userVisible, $userAssignable);
+ $this->tagManager->setTagGroups($tag1, $tagGroupIds);
+
+ $this->groupManager->expects($this->any())
+ ->method('isAdmin')
+ ->with('test')
+ ->willReturn($isAdmin);
+ $this->groupManager->expects($this->any())
+ ->method('getUserGroupIds')
+ ->with($user)
+ ->willReturn($userGroupIds);
+
+ $this->assertEquals($expectedResult, $this->tagManager->canUserAssignTag($tag1, $user));
+ }
+
+ public function testTagGroups(): void {
+ $tag1 = $this->tagManager->createTag('tag1', true, false);
+ $tag2 = $this->tagManager->createTag('tag2', true, false);
+ $this->tagManager->setTagGroups($tag1, ['group1', 'group2']);
+ $this->tagManager->setTagGroups($tag2, ['group2', 'group3']);
+
+ $this->assertEquals(['group1', 'group2'], $this->tagManager->getTagGroups($tag1));
+ $this->assertEquals(['group2', 'group3'], $this->tagManager->getTagGroups($tag2));
+
+ // change groups
+ $this->tagManager->setTagGroups($tag1, ['group3', 'group4']);
+ $this->tagManager->setTagGroups($tag2, []);
+
+ $this->assertEquals(['group3', 'group4'], $this->tagManager->getTagGroups($tag1));
+ $this->assertEquals([], $this->tagManager->getTagGroups($tag2));
+ }
+
+ /**
+ * empty groupIds should be ignored
+ */
+ public function testEmptyTagGroup(): void {
+ $tag1 = $this->tagManager->createTag('tag1', true, false);
+ $this->tagManager->setTagGroups($tag1, ['']);
+ $this->assertEquals([], $this->tagManager->getTagGroups($tag1));
+ }
+
+ public static function allowedToCreateProvider(): array {
+ return [
+ [true, null, true],
+ [true, null, false],
+ [false, true, true],
+ [false, true, false],
+ [false, false, false],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('allowedToCreateProvider')]
+ public function testAllowedToCreateTag(bool $isCli, ?bool $isAdmin, bool $isRestricted): void {
+ $oldCli = \OC::$CLI;
+ \OC::$CLI = $isCli;
+
+ $user = $this->getMockBuilder(IUser::class)->getMock();
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn('test');
+ $this->userSession->expects($this->any())
+ ->method('getUser')
+ ->willReturn($isAdmin === null ? null : $user);
+ $this->groupManager->expects($this->any())
+ ->method('isAdmin')
+ ->with('test')
+ ->willReturn($isAdmin);
+ $this->appConfig->expects($this->any())
+ ->method('getValueBool')
+ ->with('systemtags', 'restrict_creation_to_admin')
+ ->willReturn($isRestricted);
+
+ $name = uniqid('tag_', true);
+ $tag = $this->tagManager->createTag($name, true, true);
+ $this->assertEquals($tag->getName(), $name);
+ $this->tagManager->deleteTags($tag->getId());
+
+ \OC::$CLI = $oldCli;
+ }
+
+ public static function disallowedToCreateProvider(): array {
+ return [
+ [false],
+ [null],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('disallowedToCreateProvider')]
+ public function testDisallowedToCreateTag(?bool $isAdmin): void {
+ $oldCli = \OC::$CLI;
+ \OC::$CLI = false;
+
+ $user = $this->getMockBuilder(IUser::class)->getMock();
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn('test');
+ $this->userSession->expects($this->any())
+ ->method('getUser')
+ ->willReturn($isAdmin === null ? null : $user);
+ $this->groupManager->expects($this->any())
+ ->method('isAdmin')
+ ->with('test')
+ ->willReturn($isAdmin);
+ $this->appConfig->expects($this->any())
+ ->method('getValueBool')
+ ->with('systemtags', 'restrict_creation_to_admin')
+ ->willReturn(true);
+
+ $this->expectException(\Exception::class);
+ $tag = $this->tagManager->createTag(uniqid('tag_', true), true, true);
+
+ \OC::$CLI = $oldCli;
+ }
+
+
+ /**
+ * @param ISystemTag $tag1
+ * @param ISystemTag $tag2
+ */
+ private function assertSameTag($tag1, $tag2) {
+ $this->assertEquals($tag1->getId(), $tag2->getId());
+ $this->assertEquals($tag1->getName(), $tag2->getName());
+ $this->assertEquals($tag1->isUserVisible(), $tag2->isUserVisible());
+ $this->assertEquals($tag1->isUserAssignable(), $tag2->isUserAssignable());
+ }
+}
diff --git a/tests/lib/SystemTag/SystemTagObjectMapperTest.php b/tests/lib/SystemTag/SystemTagObjectMapperTest.php
new file mode 100644
index 00000000000..a43bda3b659
--- /dev/null
+++ b/tests/lib/SystemTag/SystemTagObjectMapperTest.php
@@ -0,0 +1,406 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\SystemTag;
+
+use OC\SystemTag\SystemTag;
+use OC\SystemTag\SystemTagManager;
+use OC\SystemTag\SystemTagObjectMapper;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\IDBConnection;
+use OCP\Server;
+use OCP\SystemTag\ISystemTag;
+use OCP\SystemTag\ISystemTagManager;
+use OCP\SystemTag\ISystemTagObjectMapper;
+use OCP\SystemTag\TagNotFoundException;
+use Test\TestCase;
+
+/**
+ * Class TestSystemTagObjectMapper
+ *
+ * @group DB
+ * @package Test\SystemTag
+ */
+class SystemTagObjectMapperTest extends TestCase {
+ /**
+ * @var ISystemTagManager
+ **/
+ private $tagManager;
+
+ /**
+ * @var ISystemTagObjectMapper
+ **/
+ private $tagMapper;
+
+ /**
+ * @var IDBConnection
+ */
+ private $connection;
+
+ /**
+ * @var IEventDispatcher
+ */
+ private $dispatcher;
+
+ /**
+ * @var ISystemTag
+ */
+ private $tag1;
+
+ /**
+ * @var ISystemTag
+ */
+ private $tag2;
+
+ /**
+ * @var ISystemTag
+ */
+ private $tag3;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->connection = Server::get(IDBConnection::class);
+ $this->pruneTagsTables();
+
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->dispatcher = $this->createMock(IEventDispatcher::class);
+
+ $this->tagMapper = new SystemTagObjectMapper(
+ $this->connection,
+ $this->tagManager,
+ $this->dispatcher
+ );
+
+ $this->tag1 = new SystemTag(1, 'testtag1', false, false);
+ $this->tag2 = new SystemTag(2, 'testtag2', true, false);
+ $this->tag3 = new SystemTag(3, 'testtag3', false, false);
+
+ $this->tagManager->expects($this->any())
+ ->method('getTagsByIds')
+ ->willReturnCallback(function ($tagIds) {
+ $result = [];
+ if (in_array(1, $tagIds)) {
+ $result[1] = $this->tag1;
+ }
+ if (in_array(2, $tagIds)) {
+ $result[2] = $this->tag2;
+ }
+ if (in_array(3, $tagIds)) {
+ $result[3] = $this->tag3;
+ }
+ return $result;
+ });
+
+ $this->tagMapper->assignTags('1', 'testtype', $this->tag1->getId());
+ $this->tagMapper->assignTags('1', 'testtype', $this->tag2->getId());
+ $this->tagMapper->assignTags('2', 'testtype', $this->tag1->getId());
+ $this->tagMapper->assignTags('3', 'anothertype', $this->tag1->getId());
+ }
+
+ protected function tearDown(): void {
+ $this->pruneTagsTables();
+ parent::tearDown();
+ }
+
+ protected function pruneTagsTables() {
+ $query = $this->connection->getQueryBuilder();
+ $query->delete(SystemTagObjectMapper::RELATION_TABLE)->execute();
+ $query->delete(SystemTagManager::TAG_TABLE)->execute();
+ }
+
+ public function testGetTagIdsForObjects(): void {
+ $tagIdMapping = $this->tagMapper->getTagIdsForObjects(
+ ['1', '2', '3', '4'],
+ 'testtype'
+ );
+
+ $this->assertEquals([
+ '1' => [$this->tag1->getId(), $this->tag2->getId()],
+ '2' => [$this->tag1->getId()],
+ '3' => [],
+ '4' => [],
+ ], $tagIdMapping);
+ }
+
+ public function testGetTagIdsForNoObjects(): void {
+ $tagIdMapping = $this->tagMapper->getTagIdsForObjects(
+ [],
+ 'testtype'
+ );
+
+ $this->assertEquals([], $tagIdMapping);
+ }
+
+ public function testGetTagIdsForALotOfObjects(): void {
+ $ids = range(1, 10500);
+ $tagIdMapping = $this->tagMapper->getTagIdsForObjects(
+ $ids,
+ 'testtype'
+ );
+
+ $this->assertEquals(10500, count($tagIdMapping));
+ $this->assertEquals([$this->tag1->getId(), $this->tag2->getId()], $tagIdMapping[1]);
+ }
+
+ public function testGetObjectsForTags(): void {
+ $objectIds = $this->tagMapper->getObjectIdsForTags(
+ [$this->tag1->getId(), $this->tag2->getId(), $this->tag3->getId()],
+ 'testtype'
+ );
+ sort($objectIds);
+
+ $this->assertEquals([
+ '1',
+ '2',
+ ], $objectIds);
+ }
+
+ public function testGetObjectsForTagsLimit(): void {
+ $objectIds = $this->tagMapper->getObjectIdsForTags(
+ [$this->tag1->getId()],
+ 'testtype',
+ 1
+ );
+
+ $this->assertEquals([
+ 1,
+ ], $objectIds);
+ }
+
+
+ public function testGetObjectsForTagsLimitWithMultipleTags(): void {
+ $this->expectException(\InvalidArgumentException::class);
+
+ $this->tagMapper->getObjectIdsForTags(
+ [$this->tag1->getId(), $this->tag2->getId(), $this->tag3->getId()],
+ 'testtype',
+ 1
+ );
+ }
+
+ public function testGetObjectsForTagsLimitOffset(): void {
+ $objectIds = $this->tagMapper->getObjectIdsForTags(
+ [$this->tag1->getId()],
+ 'testtype',
+ 1,
+ '1'
+ );
+
+ $this->assertEquals([
+ 2,
+ ], $objectIds);
+ }
+
+
+ public function testGetObjectsForNonExistingTag(): void {
+ $this->expectException(TagNotFoundException::class);
+
+ $this->tagMapper->getObjectIdsForTags(
+ [100],
+ 'testtype'
+ );
+ }
+
+ public function testAssignUnassignTags(): void {
+ $this->tagMapper->unassignTags('1', 'testtype', [$this->tag1->getId()]);
+
+ $tagIdMapping = $this->tagMapper->getTagIdsForObjects('1', 'testtype');
+ $this->assertEquals([
+ 1 => [$this->tag2->getId()],
+ ], $tagIdMapping);
+
+ $this->tagMapper->assignTags('1', 'testtype', [$this->tag1->getId()]);
+ $this->tagMapper->assignTags('1', 'testtype', $this->tag3->getId());
+
+ $tagIdMapping = $this->tagMapper->getTagIdsForObjects('1', 'testtype');
+
+ $this->assertEquals([
+ '1' => [$this->tag1->getId(), $this->tag2->getId(), $this->tag3->getId()],
+ ], $tagIdMapping);
+ }
+
+ public function testReAssignUnassignTags(): void {
+ // reassign tag1
+ $this->tagMapper->assignTags('1', 'testtype', [$this->tag1->getId()]);
+
+ // tag 3 was never assigned
+ $this->tagMapper->unassignTags('1', 'testtype', [$this->tag3->getId()]);
+
+ $this->assertTrue(true, 'No error when reassigning/unassigning');
+ }
+
+
+ public function testAssignNonExistingTags(): void {
+ $this->expectException(TagNotFoundException::class);
+
+ $this->tagMapper->assignTags('1', 'testtype', [100]);
+ }
+
+ public function testAssignNonExistingTagInArray(): void {
+ $caught = false;
+ try {
+ $this->tagMapper->assignTags('1', 'testtype', [100, $this->tag3->getId()]);
+ } catch (TagNotFoundException $e) {
+ $caught = true;
+ }
+
+ $this->assertTrue($caught, 'Exception thrown');
+
+ $tagIdMapping = $this->tagMapper->getTagIdsForObjects(
+ ['1'],
+ 'testtype'
+ );
+
+ $this->assertEquals([
+ '1' => [$this->tag1->getId(), $this->tag2->getId()],
+ ], $tagIdMapping, 'None of the tags got assigned');
+ }
+
+
+ public function testUnassignNonExistingTags(): void {
+ $this->expectException(TagNotFoundException::class);
+
+ $this->tagMapper->unassignTags('1', 'testtype', [100]);
+ }
+
+ public function testUnassignNonExistingTagsInArray(): void {
+ $caught = false;
+ try {
+ $this->tagMapper->unassignTags('1', 'testtype', [100, $this->tag1->getId()]);
+ } catch (TagNotFoundException $e) {
+ $caught = true;
+ }
+
+ $this->assertTrue($caught, 'Exception thrown');
+
+ $tagIdMapping = $this->tagMapper->getTagIdsForObjects(
+ [1],
+ 'testtype'
+ );
+
+ $this->assertEquals([
+ '1' => [$this->tag1->getId(), $this->tag2->getId()],
+ ], $tagIdMapping, 'None of the tags got unassigned');
+ }
+
+ public function testHaveTagAllMatches(): void {
+ $this->assertTrue(
+ $this->tagMapper->haveTag(
+ ['1'],
+ 'testtype',
+ $this->tag1->getId(),
+ true
+ ),
+ 'object 1 has the tag tag1'
+ );
+
+ $this->assertTrue(
+ $this->tagMapper->haveTag(
+ ['1', '2'],
+ 'testtype',
+ $this->tag1->getId(),
+ true
+ ),
+ 'object 1 and object 2 ALL have the tag tag1'
+ );
+
+ $this->assertFalse(
+ $this->tagMapper->haveTag(
+ ['1', '2'],
+ 'testtype',
+ $this->tag2->getId(),
+ true
+ ),
+ 'object 1 has tag2 but not object 2, so not ALL of them'
+ );
+
+ $this->assertFalse(
+ $this->tagMapper->haveTag(
+ ['2'],
+ 'testtype',
+ $this->tag2->getId(),
+ true
+ ),
+ 'object 2 does not have tag2'
+ );
+
+ $this->assertFalse(
+ $this->tagMapper->haveTag(
+ ['3'],
+ 'testtype',
+ $this->tag2->getId(),
+ true
+ ),
+ 'object 3 does not have tag1 due to different type'
+ );
+ }
+
+ public function testHaveTagAtLeastOneMatch(): void {
+ $this->assertTrue(
+ $this->tagMapper->haveTag(
+ ['1'],
+ 'testtype',
+ $this->tag1->getId(),
+ false
+ ),
+ 'object1 has the tag tag1'
+ );
+
+ $this->assertTrue(
+ $this->tagMapper->haveTag(
+ ['1', '2'],
+ 'testtype',
+ $this->tag1->getId(),
+ false
+ ),
+ 'object 1 and object 2 both the tag tag1'
+ );
+
+ $this->assertTrue(
+ $this->tagMapper->haveTag(
+ ['1', '2'],
+ 'testtype',
+ $this->tag2->getId(),
+ false
+ ),
+ 'at least object 1 has the tag tag2'
+ );
+
+ $this->assertFalse(
+ $this->tagMapper->haveTag(
+ ['2'],
+ 'testtype',
+ $this->tag2->getId(),
+ false
+ ),
+ 'object 2 does not have tag2'
+ );
+
+ $this->assertFalse(
+ $this->tagMapper->haveTag(
+ ['3'],
+ 'testtype',
+ $this->tag2->getId(),
+ false
+ ),
+ 'object 3 does not have tag1 due to different type'
+ );
+ }
+
+
+ public function testHaveTagNonExisting(): void {
+ $this->expectException(TagNotFoundException::class);
+
+ $this->tagMapper->haveTag(
+ ['1'],
+ 'testtype',
+ 100
+ );
+ }
+}