contactsManager = $this->createMock(IManager::class); $this->statusService = $this->createMock(StatusService::class); $this->userManager = $this->createMock(IUserManager::class); $this->profileManager = $this->createMock(ProfileManager::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->groupManager = $this->createMock(IGroupManager::class); $this->config = $this->createMock(IConfig::class); $this->knownUserService = $this->createMock(KnownUserService::class); $this->l10nFactory = $this->createMock(IL10NFactory::class); $this->contactsStore = new ContactsStore( $this->contactsManager, $this->statusService, $this->config, $this->profileManager, $this->userManager, $this->urlGenerator, $this->groupManager, $this->knownUserService, $this->l10nFactory, ); } public function testGetContactsWithoutFilter(): void { /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 123, ], [ 'UID' => 567, 'FN' => 'Darren Roner', 'EMAIL' => [ 'darren@roner.au' ], ], ]); $user->expects($this->exactly(2)) ->method('getUID') ->willReturn('user123'); $entries = $this->contactsStore->getContacts($user, ''); $this->assertCount(2, $entries); $this->assertEquals([ 'darren@roner.au' ], $entries[1]->getEMailAddresses()); } public function testGetContactsHidesOwnEntry(): void { /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 'user123', ], [ 'UID' => 567, 'FN' => 'Darren Roner', 'EMAIL' => [ 'darren@roner.au' ], ], ]); $user->expects($this->exactly(2)) ->method('getUID') ->willReturn('user123'); $entries = $this->contactsStore->getContacts($user, ''); $this->assertCount(1, $entries); } public function testGetContactsWithoutBinaryImage(): void { /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $this->urlGenerator->expects($this->any()) ->method('linkToRouteAbsolute') ->with('core.GuestAvatar.getAvatar', $this->anything()) ->willReturn('https://urlToNcAvatar.test'); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 123, ], [ 'UID' => 567, 'FN' => 'Darren Roner', 'EMAIL' => [ 'darren@roner.au' ], 'PHOTO' => base64_encode('photophotophoto'), ], ]); $user->expects($this->exactly(2)) ->method('getUID') ->willReturn('user123'); $entries = $this->contactsStore->getContacts($user, ''); $this->assertCount(2, $entries); $this->assertSame('https://urlToNcAvatar.test', $entries[1]->getAvatar()); } public function testGetContactsWithoutAvatarURI(): void { /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 123, ], [ 'UID' => 567, 'FN' => 'Darren Roner', 'EMAIL' => [ 'darren@roner.au' ], 'PHOTO' => 'VALUE=uri:https://photo', ], ]); $user->expects($this->exactly(2)) ->method('getUID') ->willReturn('user123'); $entries = $this->contactsStore->getContacts($user, ''); $this->assertCount(2, $entries); $this->assertEquals('https://photo', $entries[1]->getAvatar()); } public function testGetContactsWhenUserIsInExcludeGroups(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'], ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'], ['core', 'shareapi_exclude_groups', 'no', 'yes'], ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], ['core', 'shareapi_exclude_groups_list', '', '["group1", "group5", "group6"]'], ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); /** @var IUser|MockObject $currentUser */ $currentUser = $this->createMock(IUser::class); $currentUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('user001'); $this->groupManager->expects($this->once()) ->method('getUserGroupIds') ->with($this->equalTo($currentUser)) ->willReturn(['group1', 'group2', 'group3']); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 'user123', 'isLocalSystemBook' => true ], [ 'UID' => 'user12345', 'isLocalSystemBook' => true ], ]); $entries = $this->contactsStore->getContacts($currentUser, ''); $this->assertCount(0, $entries); } public function testGetContactsOnlyShareIfInTheSameGroup(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'], ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'], ['core', 'shareapi_exclude_groups', 'no', 'no'], ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); /** @var IUser|MockObject $currentUser */ $currentUser = $this->createMock(IUser::class); $currentUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('user001'); $user1 = $this->createMock(IUser::class); $user2 = $this->createMock(IUser::class); $user3 = $this->createMock(IUser::class); $this->groupManager->expects($this->exactly(4)) ->method('getUserGroupIds') ->withConsecutive( [$this->equalTo($currentUser)], [$this->equalTo($user1)], [$this->equalTo($user2)], [$this->equalTo($user3)] ) ->willReturnOnConsecutiveCalls( ['group1', 'group2', 'group3'], ['group1'], ['group2', 'group3'], ['group8', 'group9'] ); $this->userManager->expects($this->exactly(3)) ->method('get') ->withConsecutive( ['user1'], ['user2'], ['user3'] ) ->willReturnOnConsecutiveCalls($user1, $user2, $user3); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 'user1', 'isLocalSystemBook' => true ], [ 'UID' => 'user2', 'isLocalSystemBook' => true ], [ 'UID' => 'user3', 'isLocalSystemBook' => true ], [ 'UID' => 'contact', ], ]); $entries = $this->contactsStore->getContacts($currentUser, ''); $this->assertCount(3, $entries); $this->assertEquals('user1', $entries[0]->getProperty('UID')); $this->assertEquals('user2', $entries[1]->getProperty('UID')); $this->assertEquals('contact', $entries[2]->getProperty('UID')); } public function testGetContactsOnlyEnumerateIfInTheSameGroup(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'], ['core', 'shareapi_exclude_groups', 'no', 'no'], ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); /** @var IUser|MockObject $currentUser */ $currentUser = $this->createMock(IUser::class); $currentUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('user001'); $user1 = $this->createMock(IUser::class); $user2 = $this->createMock(IUser::class); $user3 = $this->createMock(IUser::class); $this->groupManager->expects($this->exactly(4)) ->method('getUserGroupIds') ->withConsecutive( [$this->equalTo($currentUser)], [$this->equalTo($user1)], [$this->equalTo($user2)], [$this->equalTo($user3)] ) ->willReturnOnConsecutiveCalls( ['group1', 'group2', 'group3'], ['group1'], ['group2', 'group3'], ['group8', 'group9'] ); $this->userManager->expects($this->exactly(3)) ->method('get') ->withConsecutive( ['user1'], ['user2'], ['user3'] ) ->willReturn($user1, $user2, $user3); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 'user1', 'isLocalSystemBook' => true ], [ 'UID' => 'user2', 'isLocalSystemBook' => true ], [ 'UID' => 'user3', 'isLocalSystemBook' => true ], [ 'UID' => 'contact', ], ]); $entries = $this->contactsStore->getContacts($currentUser, ''); $this->assertCount(3, $entries); $this->assertEquals('user1', $entries[0]->getProperty('UID')); $this->assertEquals('user2', $entries[1]->getProperty('UID')); $this->assertEquals('contact', $entries[2]->getProperty('UID')); } public function testGetContactsOnlyEnumerateIfPhoneBookMatch(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'], ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'yes'], ['core', 'shareapi_exclude_groups', 'no', 'no'], ['core', 'shareapi_only_share_with_group_members', 'no', 'no'], ]); /** @var IUser|MockObject $currentUser */ $currentUser = $this->createMock(IUser::class); $currentUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('user001'); $this->groupManager->expects($this->once()) ->method('getUserGroupIds') ->with($this->equalTo($currentUser)) ->willReturn(['group1', 'group2', 'group3']); $this->knownUserService->method('isKnownToUser') ->willReturnMap([ ['user001', 'user1', true], ['user001', 'user2', true], ['user001', 'user3', false], ]); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 'user1', 'isLocalSystemBook' => true ], [ 'UID' => 'user2', 'isLocalSystemBook' => true ], [ 'UID' => 'user3', 'isLocalSystemBook' => true ], [ 'UID' => 'contact', ], ]); $entries = $this->contactsStore->getContacts($currentUser, ''); $this->assertCount(3, $entries); $this->assertEquals('user1', $entries[0]->getProperty('UID')); $this->assertEquals('user2', $entries[1]->getProperty('UID')); $this->assertEquals('contact', $entries[2]->getProperty('UID')); } public function testGetContactsOnlyEnumerateIfPhoneBookMatchWithOwnGroupsOnly(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'], ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'yes'], ['core', 'shareapi_exclude_groups', 'no', 'no'], ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); /** @var IUser|MockObject $currentUser */ $currentUser = $this->createMock(IUser::class); $currentUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('user001'); $user1 = $this->createMock(IUser::class); $user2 = $this->createMock(IUser::class); $user3 = $this->createMock(IUser::class); $this->groupManager->expects($this->exactly(4)) ->method('getUserGroupIds') ->withConsecutive( [$this->equalTo($currentUser)], [$this->equalTo($user1)], [$this->equalTo($user2)], [$this->equalTo($user3)] ) ->willReturnOnConsecutiveCalls( ['group1', 'group2', 'group3'], ['group1'], ['group2', 'group3'], ['group8', 'group9'] ); $this->userManager->expects($this->exactly(3)) ->method('get') ->withConsecutive( ['user1'], ['user2'], ['user3'] ) ->willReturnOnConsecutiveCalls($user1, $user2, $user3); $this->knownUserService->method('isKnownToUser') ->willReturnMap([ ['user001', 'user1', true], ['user001', 'user2', true], ['user001', 'user3', true], ]); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 'user1', 'isLocalSystemBook' => true ], [ 'UID' => 'user2', 'isLocalSystemBook' => true ], [ 'UID' => 'user3', 'isLocalSystemBook' => true ], [ 'UID' => 'contact', ], ]); $entries = $this->contactsStore->getContacts($currentUser, ''); $this->assertCount(3, $entries); $this->assertEquals('user1', $entries[0]->getProperty('UID')); $this->assertEquals('user2', $entries[1]->getProperty('UID')); $this->assertEquals('contact', $entries[2]->getProperty('UID')); } public function testGetContactsOnlyEnumerateIfPhoneBookOrSameGroup(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'yes'], ['core', 'shareapi_exclude_groups', 'no', 'no'], ['core', 'shareapi_only_share_with_group_members', 'no', 'no'], ]); /** @var IUser|MockObject $currentUser */ $currentUser = $this->createMock(IUser::class); $currentUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('user001'); $user1 = $this->createMock(IUser::class); $this->groupManager->expects($this->exactly(2)) ->method('getUserGroupIds') ->withConsecutive( [$this->equalTo($currentUser)], [$this->equalTo($user1)] ) ->willReturnOnConsecutiveCalls( ['group1', 'group2', 'group3'], ['group1'] ); $this->userManager->expects($this->once()) ->method('get') ->with('user1') ->willReturn($user1); $this->knownUserService->method('isKnownToUser') ->willReturnMap([ ['user001', 'user1', false], ['user001', 'user2', true], ['user001', 'user3', true], ]); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 'user1', 'isLocalSystemBook' => true ], [ 'UID' => 'user2', 'isLocalSystemBook' => true ], [ 'UID' => 'user3', 'isLocalSystemBook' => true ], [ 'UID' => 'contact', ], ]); $entries = $this->contactsStore->getContacts($currentUser, ''); $this->assertCount(4, $entries); $this->assertEquals('user1', $entries[0]->getProperty('UID')); $this->assertEquals('user2', $entries[1]->getProperty('UID')); $this->assertEquals('user3', $entries[2]->getProperty('UID')); $this->assertEquals('contact', $entries[3]->getProperty('UID')); } public function testGetContactsOnlyEnumerateIfPhoneBookOrSameGroupInOwnGroupsOnly(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'yes'], ['core', 'shareapi_exclude_groups', 'no', 'no'], ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'], ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'], ]); /** @var IUser|MockObject $currentUser */ $currentUser = $this->createMock(IUser::class); $currentUser->expects($this->exactly(2)) ->method('getUID') ->willReturn('user001'); $user1 = $this->createMock(IUser::class); $user2 = $this->createMock(IUser::class); $user3 = $this->createMock(IUser::class); $this->groupManager->expects($this->exactly(4)) ->method('getUserGroupIds') ->withConsecutive( [$this->equalTo($currentUser)], [$this->equalTo($user1)], [$this->equalTo($user2)], [$this->equalTo($user3)] ) ->willReturnOnConsecutiveCalls( ['group1', 'group2', 'group3'], ['group1'], ['group2', 'group3'], ['group8', 'group9'] ); $this->userManager->expects($this->exactly(3)) ->method('get') ->withConsecutive( ['user1'], ['user2'], ['user3'] ) ->willReturnOnConsecutiveCalls($user1, $user2, $user3); $this->knownUserService->method('isKnownToUser') ->willReturnMap([ ['user001', 'user1', false], ['user001', 'user2', true], ['user001', 'user3', true], ]); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo(''), $this->equalTo(['FN', 'EMAIL'])) ->willReturn([ [ 'UID' => 'user1', 'isLocalSystemBook' => true ], [ 'UID' => 'user2', 'isLocalSystemBook' => true ], [ 'UID' => 'user3', 'isLocalSystemBook' => true ], [ 'UID' => 'contact', ], ]); $entries = $this->contactsStore->getContacts($currentUser, ''); $this->assertCount(3, $entries); $this->assertEquals('user1', $entries[0]->getProperty('UID')); $this->assertEquals('user2', $entries[1]->getProperty('UID')); $this->assertEquals('contact', $entries[2]->getProperty('UID')); } public function testGetContactsWithFilter(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'no'], ['core', 'shareapi_restrict_user_enumeration_full_match', 'yes', 'yes'], ]); /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $this->contactsManager->expects($this->any()) ->method('search') ->willReturn([ [ 'UID' => 'a567', 'FN' => 'Darren Roner', 'EMAIL' => [ 'darren@roner.au', ], 'isLocalSystemBook' => true, ], [ 'UID' => 'john', 'FN' => 'John Doe', 'EMAIL' => [ 'john@example.com', ], 'isLocalSystemBook' => true, ], [ 'FN' => 'Anne D', 'EMAIL' => [ 'anne@example.com', ], 'isLocalSystemBook' => false, ], ]); $user->expects($this->any()) ->method('getUID') ->willReturn('user123'); // Complete match on UID should match $entry = $this->contactsStore->getContacts($user, 'a567'); $this->assertSame(2, count($entry)); $this->assertEquals([ 'darren@roner.au' ], $entry[0]->getEMailAddresses()); // Partial match on UID should not match $entry = $this->contactsStore->getContacts($user, 'a56'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); // Complete match on email should match $entry = $this->contactsStore->getContacts($user, 'john@example.com'); $this->assertSame(2, count($entry)); $this->assertEquals([ 'john@example.com' ], $entry[0]->getEMailAddresses()); $this->assertEquals([ 'anne@example.com' ], $entry[1]->getEMailAddresses()); // Partial match on email should not match $entry = $this->contactsStore->getContacts($user, 'john@example.co'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); // Match on FN should not match $entry = $this->contactsStore->getContacts($user, 'Darren Roner'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); // Don't filter users in local addressbook $entry = $this->contactsStore->getContacts($user, 'Anne D'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); } public function testGetContactsWithFilterWithoutFullMatch(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'no'], ['core', 'shareapi_restrict_user_enumeration_full_match', 'yes', 'no'], ]); /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $this->contactsManager->expects($this->any()) ->method('search') ->willReturn([ [ 'UID' => 'a567', 'FN' => 'Darren Roner', 'EMAIL' => [ 'darren@roner.au', ], 'isLocalSystemBook' => true, ], [ 'UID' => 'john', 'FN' => 'John Doe', 'EMAIL' => [ 'john@example.com', ], 'isLocalSystemBook' => true, ], [ 'FN' => 'Anne D', 'EMAIL' => [ 'anne@example.com', ], 'isLocalSystemBook' => false, ], ]); $user->expects($this->any()) ->method('getUID') ->willReturn('user123'); // Complete match on UID should not match $entry = $this->contactsStore->getContacts($user, 'a567'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); // Partial match on UID should not match $entry = $this->contactsStore->getContacts($user, 'a56'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); // Complete match on email should not match $entry = $this->contactsStore->getContacts($user, 'john@example.com'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); // Partial match on email should not match $entry = $this->contactsStore->getContacts($user, 'john@example.co'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); // Match on FN should not match $entry = $this->contactsStore->getContacts($user, 'Darren Roner'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); // Don't filter users in local addressbook $entry = $this->contactsStore->getContacts($user, 'Anne D'); $this->assertSame(1, count($entry)); $this->assertEquals([ 'anne@example.com' ], $entry[0]->getEMailAddresses()); } public function testFindOneUser(): void { $this->config ->method('getAppValue') ->willReturnMap([ ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', 'yes'], ['core', 'shareapi_restrict_user_enumeration_to_group', 'no', 'no'], ['core', 'shareapi_restrict_user_enumeration_to_phone', 'no', 'no'], ['core', 'shareapi_restrict_user_enumeration_full_match', 'yes', 'yes'], ['core', 'shareapi_exclude_groups', 'no', 'yes'], ['core', 'shareapi_exclude_groups_list', '', ''], ['core', 'shareapi_only_share_with_group_members', 'no', 'no'], ]); /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo('a567'), $this->equalTo(['UID'])) ->willReturn([ [ 'UID' => 123, 'isLocalSystemBook' => false ], [ 'UID' => 'a567', 'FN' => 'Darren Roner', 'EMAIL' => [ 'darren@roner.au' ], 'isLocalSystemBook' => true ], ]); $user->expects($this->any()) ->method('getUID') ->willReturn('user123'); $entry = $this->contactsStore->findOne($user, 0, 'a567'); $this->assertEquals([ 'darren@roner.au' ], $entry->getEMailAddresses()); } public function testFindOneEMail(): void { /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo('darren@roner.au'), $this->equalTo(['EMAIL'])) ->willReturn([ [ 'UID' => 123, 'isLocalSystemBook' => false ], [ 'UID' => 'a567', 'FN' => 'Darren Roner', 'EMAIL' => [ 'darren@roner.au' ], 'isLocalSystemBook' => false ], ]); $user->expects($this->any()) ->method('getUID') ->willReturn('user123'); $entry = $this->contactsStore->findOne($user, 4, 'darren@roner.au'); $this->assertEquals([ 'darren@roner.au' ], $entry->getEMailAddresses()); } public function testFindOneNotSupportedType(): void { /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $entry = $this->contactsStore->findOne($user, 42, 'darren@roner.au'); $this->assertEquals(null, $entry); } public function testFindOneNoMatches(): void { /** @var IUser|MockObject $user */ $user = $this->createMock(IUser::class); $this->contactsManager->expects($this->once()) ->method('search') ->with($this->equalTo('a567'), $this->equalTo(['UID'])) ->willReturn([ [ 'UID' => 123, 'isLocalSystemBook' => false ], [ 'UID' => 'a567', 'FN' => 'Darren Roner', 'EMAIL' => [ 'darren@roner.au123' ], 'isLocalSystemBook' => false ], ]); $user->expects($this->never()) ->method('getUID'); $entry = $this->contactsStore->findOne($user, 0, 'a567'); $this->assertEquals(null, $entry); } public function testGetRecentStatusFirst(): void { $user = $this->createMock(IUser::class); $status1 = new UserStatus(); $status1->setUserId('user1'); $status2 = new UserStatus(); $status2->setUserId('user2'); $this->statusService->expects(self::once()) ->method('findAllRecentStatusChanges') ->willReturn([ $status1, $status2, ]); $user1 = $this->createMock(IUser::class); $user1->method('getCloudId')->willReturn('user1@localcloud'); $user2 = $this->createMock(IUser::class); $user2->method('getCloudId')->willReturn('user2@localcloud'); $this->userManager->expects(self::exactly(2)) ->method('get') ->willReturnCallback(function ($uid) use ($user1, $user2) { return match ($uid) { 'user1' => $user1, 'user2' => $user2, }; }); $this->contactsManager ->expects(self::exactly(3)) ->method('search') ->willReturnCallback(function ($uid, $searchProps, $options) { return match ([$uid, $options['limit'] ?? null]) { ['user1@localcloud', 1] => [ [ 'UID' => 'user1', 'URI' => 'user1.vcf', ], ], ['user2@localcloud' => [], 1], // Simulate not found ['', 4] => [ [ 'UID' => 'contact1', 'URI' => 'contact1.vcf', ], [ 'UID' => 'contact2', 'URI' => 'contact2.vcf', ], ], default => [], }; }); $contacts = $this->contactsStore->getContacts( $user, null, 5, ); self::assertCount(3, $contacts); self::assertEquals('user1', $contacts[0]->getProperty('UID')); self::assertEquals('contact1', $contacts[1]->getProperty('UID')); self::assertEquals('contact2', $contacts[2]->getProperty('UID')); } public function testPaginateRecentStatus(): void { $user = $this->createMock(IUser::class); $status1 = new UserStatus(); $status1->setUserId('user1'); $status2 = new UserStatus(); $status2->setUserId('user2'); $status3 = new UserStatus(); $status3->setUserId('user3'); $this->statusService->expects(self::never()) ->method('findAllRecentStatusChanges'); $this->contactsManager ->expects(self::exactly(2)) ->method('search') ->willReturnCallback(function ($uid, $searchProps, $options) { return match ([$uid, $options['limit'] ?? null, $options['offset'] ?? null]) { ['', 2, 0] => [ [ 'UID' => 'contact1', 'URI' => 'contact1.vcf', ], [ 'UID' => 'contact2', 'URI' => 'contact2.vcf', ], ], ['', 2, 3] => [ [ 'UID' => 'contact3', 'URI' => 'contact3.vcf', ], ], default => [], }; }); $page1 = $this->contactsStore->getContacts( $user, null, 2, 0, ); $page2 = $this->contactsStore->getContacts( $user, null, 2, 3, ); self::assertCount(2, $page1); self::assertCount(1, $page2); } }