UPSTREAM BASELINE: nextcloud/spreed v22.0.12 (без изменений)
Type checking / changes (push) Has been cancelled
Type checking / test (push) Has been cancelled
Type checking / typescript-summary (push) Has been cancelled
Node tests / changes (push) Has been cancelled
Node tests / test (push) Has been cancelled
Node tests / test-summary (push) Has been cancelled
Type checking / changes (push) Has been cancelled
Type checking / test (push) Has been cancelled
Type checking / typescript-summary (push) Has been cancelled
Node tests / changes (push) Has been cancelled
Node tests / test (push) Has been cancelled
Node tests / test-summary (push) Has been cancelled
Источник: https://github.com/nextcloud/spreed/archive/refs/tags/v22.0.12.tar.gz С этого коммита ветка официального Nextcloud Talk отрезана (решение владельца 2026-07-06). Все дальнейшие изменения — только наши; версии релизов: 22.0.12-f7.N.
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Talk\Tests\php\Chat\AutoComplete;
|
||||
|
||||
use OC\Collaboration\Collaborators\SearchResult;
|
||||
use OCA\Talk\Chat\AutoComplete\SearchPlugin;
|
||||
use OCA\Talk\Federation\Authenticator;
|
||||
use OCA\Talk\Files\Util;
|
||||
use OCA\Talk\GuestManager;
|
||||
use OCA\Talk\Model\Attendee;
|
||||
use OCA\Talk\Model\Session;
|
||||
use OCA\Talk\Participant;
|
||||
use OCA\Talk\Room;
|
||||
use OCA\Talk\Service\ParticipantService;
|
||||
use OCA\Talk\TalkSession;
|
||||
use OCP\Collaboration\Collaborators\ISearchResult;
|
||||
use OCP\IL10N;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Test\TestCase;
|
||||
|
||||
class SearchPluginTest extends TestCase {
|
||||
protected IUserManager&MockObject $userManager;
|
||||
protected GuestManager&MockObject $guestManager;
|
||||
protected TalkSession&MockObject $talkSession;
|
||||
protected ParticipantService&MockObject $participantService;
|
||||
protected Util&MockObject $util;
|
||||
protected Authenticator&MockObject $federationAuthenticator;
|
||||
protected IL10N&MockObject $l;
|
||||
protected ?string $userId = null;
|
||||
protected SearchPlugin $plugin;
|
||||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
$this->guestManager = $this->createMock(GuestManager::class);
|
||||
$this->talkSession = $this->createMock(TalkSession::class);
|
||||
$this->participantService = $this->createMock(ParticipantService::class);
|
||||
$this->util = $this->createMock(Util::class);
|
||||
$this->federationAuthenticator = $this->createMock(Authenticator::class);
|
||||
$this->userId = 'current';
|
||||
$this->l = $this->createMock(IL10N::class);
|
||||
$this->l->expects($this->any())
|
||||
->method('t')
|
||||
->willReturnCallback(function ($text, $parameters = []) {
|
||||
return vsprintf($text, $parameters);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $methods
|
||||
* @return SearchPlugin|MockObject
|
||||
*/
|
||||
protected function getPlugin(array $methods = []) {
|
||||
if (empty($methods)) {
|
||||
return new SearchPlugin(
|
||||
$this->userManager,
|
||||
$this->guestManager,
|
||||
$this->talkSession,
|
||||
$this->participantService,
|
||||
$this->util,
|
||||
$this->userId,
|
||||
$this->l,
|
||||
$this->federationAuthenticator,
|
||||
);
|
||||
}
|
||||
|
||||
return $this->getMockBuilder(SearchPlugin::class)
|
||||
->setConstructorArgs([
|
||||
$this->userManager,
|
||||
$this->guestManager,
|
||||
$this->talkSession,
|
||||
$this->participantService,
|
||||
$this->util,
|
||||
$this->userId,
|
||||
$this->l,
|
||||
$this->federationAuthenticator,
|
||||
])
|
||||
->onlyMethods($methods)
|
||||
->getMock();
|
||||
}
|
||||
|
||||
protected function createParticipantMock(string $uid, string $displayName, string $session = ''): Participant {
|
||||
/** @var Participant&MockObject $p */
|
||||
$p = $this->createMock(Participant::class);
|
||||
$a = Attendee::fromRow([
|
||||
'actor_type' => $uid ? 'users' : 'guests',
|
||||
'actor_id' => $uid ?: sha1($session),
|
||||
'display_name' => $displayName,
|
||||
]);
|
||||
$s = Session::fromRow([
|
||||
'session_id' => $session,
|
||||
]);
|
||||
$p->expects($this->any())
|
||||
->method('getAttendee')
|
||||
->willReturn($a);
|
||||
$p->expects($this->any())
|
||||
->method('getSession')
|
||||
->willReturn($s);
|
||||
|
||||
$p->expects($this->any())
|
||||
->method('isGuest')
|
||||
->willReturn($uid === '');
|
||||
|
||||
return $p;
|
||||
}
|
||||
|
||||
public function testSearch(): void {
|
||||
$result = $this->createMock(ISearchResult::class);
|
||||
$room = $this->createMock(Room::class);
|
||||
|
||||
$this->participantService->expects($this->once())
|
||||
->method('getParticipantsForRoom')
|
||||
->with($room)
|
||||
->willReturn([
|
||||
$this->createParticipantMock('123', 'OneTwoThree'),
|
||||
$this->createParticipantMock('foo', 'Foo Bar'),
|
||||
$this->createParticipantMock('', 'Guest 1-6', '123456'),
|
||||
$this->createParticipantMock('bar', 'Bar Tender'),
|
||||
$this->createParticipantMock('', 'Guest a-f', 'abcdef'),
|
||||
]);
|
||||
|
||||
$plugin = $this->getPlugin(['searchUsers', 'searchGuests']);
|
||||
$plugin->setContext(['room' => $room]);
|
||||
$plugin->expects($this->once())
|
||||
->method('searchUsers')
|
||||
->with('fo', ['123' => 'OneTwoThree', 'foo' => 'Foo Bar', 'bar' => 'Bar Tender'], $result)
|
||||
->willReturnCallback(function ($search, $users, $result): void {
|
||||
array_map(function ($user): void {
|
||||
$this->assertIsString($user);
|
||||
}, $users);
|
||||
});
|
||||
$plugin->expects($this->once())
|
||||
->method('searchGuests')
|
||||
->with('fo', $this->anything(), $result)
|
||||
->willReturnCallback(function ($search, $guests, $result): void {
|
||||
array_map(function ($guest): void {
|
||||
$this->assertInstanceOf(Attendee::class, $guest);
|
||||
}, $guests);
|
||||
});
|
||||
|
||||
$plugin->search('fo', 10, 0, $result);
|
||||
}
|
||||
|
||||
public static function dataSearchUsers(): array {
|
||||
return [
|
||||
['test', [], [], [], []],
|
||||
['test', [
|
||||
'current' => 'test',
|
||||
'foo' => '',
|
||||
'test' => 'Te st',
|
||||
'test1' => 'Te st 1',
|
||||
], [['test1' => 'Te st 1']], [['current' => 'test'], ['test' => 'Te st']]],
|
||||
['test', [
|
||||
'foo' => 'Test',
|
||||
'bar' => 'test One',
|
||||
], [['bar' => 'test One']], [['foo' => 'Test']]],
|
||||
['', ['foo' => '', 'bar' => ''], [['foo' => ''], ['bar' => '']], []],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $users
|
||||
*/
|
||||
#[DataProvider('dataSearchUsers')]
|
||||
public function testSearchUsers(string $search, array $users, array $expected, array $expectedExact): void {
|
||||
$result = $this->createMock(ISearchResult::class);
|
||||
|
||||
|
||||
$result->expects($this->once())
|
||||
->method('addResultSet')
|
||||
->with($this->anything(), $expected, $expectedExact);
|
||||
|
||||
$plugin = $this->getPlugin(['createResult']);
|
||||
$plugin->method('createResult')
|
||||
->willReturnCallback(function ($type, $uid, $name) {
|
||||
return [$uid => $name];
|
||||
});
|
||||
|
||||
self::invokePrivate($plugin, 'searchUsers', [$search, $users, $result]);
|
||||
}
|
||||
|
||||
public static function dataSearchGuests(): array {
|
||||
return [
|
||||
['test', [], [], []],
|
||||
['', ['abcdef' => ''], [['abcdef' => 'Guest']], []],
|
||||
['Guest', ['abcdef' => ''], [], [['abcdef' => 'Guest']]],
|
||||
['est', ['abcdef' => '', 'foobar' => 'est'], [['abcdef' => 'Guest']], [['foobar' => 'est']]],
|
||||
['Ast', ['abcdef' => '', 'foobar' => 'ast'], [], [['foobar' => 'ast']]],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataSearchGuests')]
|
||||
public function testSearchGuests(string $search, array $guests, array $expected, array $expectedExact): void {
|
||||
$result = $this->createMock(ISearchResult::class);
|
||||
$result->expects($this->once())
|
||||
->method('addResultSet')
|
||||
->with($this->anything(), $expected, $expectedExact);
|
||||
|
||||
$attendees = [];
|
||||
foreach ($guests as $actorId => $displayName) {
|
||||
$attendees[] = Attendee::fromRow([
|
||||
'actorId' => $actorId,
|
||||
'displayName' => $displayName,
|
||||
]);
|
||||
}
|
||||
|
||||
$plugin = $this->getPlugin(['createGuestResult']);
|
||||
$plugin->expects($this->any())
|
||||
->method('createGuestResult')
|
||||
->willReturnCallback(function ($hash, $name) {
|
||||
return [$hash => $name];
|
||||
});
|
||||
|
||||
self::invokePrivate($plugin, 'searchGuests', [$search, $attendees, $result]);
|
||||
}
|
||||
|
||||
protected function createUserMock(array $userData) {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->willReturn($userData['uid']);
|
||||
$user->expects($this->any())
|
||||
->method('getDisplayName')
|
||||
->willReturn($userData['name']);
|
||||
return $user;
|
||||
}
|
||||
|
||||
public static function dataCreateResult(): array {
|
||||
return [
|
||||
['user', 'foo', 'bar', '', ['label' => 'bar', 'value' => ['shareType' => 'user', 'shareWith' => 'foo']]],
|
||||
['user', 'test', 'Test', '', ['label' => 'Test', 'value' => ['shareType' => 'user', 'shareWith' => 'test']]],
|
||||
['user', 'test', '', 'Test', ['label' => 'Test', 'value' => ['shareType' => 'user', 'shareWith' => 'test']]],
|
||||
['user', 'test', '', null, ['label' => 'test', 'value' => ['shareType' => 'user', 'shareWith' => 'test']]],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataCreateResult')]
|
||||
public function testCreateResult(string $type, string $uid, string $name, ?string $managerName, array $expected): void {
|
||||
if ($managerName !== null) {
|
||||
$this->userManager->expects($this->any())
|
||||
->method('getDisplayName')
|
||||
->with($uid)
|
||||
->willReturn($managerName);
|
||||
} else {
|
||||
$this->userManager->expects($this->any())
|
||||
->method('getDisplayName')
|
||||
->with($uid)
|
||||
->willReturn(null);
|
||||
}
|
||||
|
||||
$plugin = $this->getPlugin();
|
||||
$this->assertEquals($expected, self::invokePrivate($plugin, 'createResult', [$type, $uid, $name]));
|
||||
}
|
||||
|
||||
|
||||
public static function dataCreateGuestResult(): array {
|
||||
return [
|
||||
['1234', 'foo', ['label' => 'foo', 'value' => ['shareType' => 'guest', 'shareWith' => 'guest/1234']]],
|
||||
['abcd', 'bar', ['label' => 'bar', 'value' => ['shareType' => 'guest', 'shareWith' => 'guest/abcd']]],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataCreateGuestResult')]
|
||||
public function testCreateGuestResult(string $actorId, string $name, array $expected): void {
|
||||
$plugin = $this->getPlugin();
|
||||
$this->assertEquals($expected, self::invokePrivate($plugin, 'createGuestResult', [$actorId, $name]));
|
||||
}
|
||||
|
||||
public static function dataSearchGroups(): array {
|
||||
return [
|
||||
// $search, $groups, $isGroup, $totalMatches, $totalExactMatches
|
||||
['', ['groupid' => 'group'], true, 1, 0],
|
||||
['groupid', ['groupid' => 'group'], true, 0, 1],
|
||||
['gro', ['groupid' => 'group'], true, 1, 0],
|
||||
['not', ['groupid' => 'group'], false, 0, 0],
|
||||
['name', ['groupid' => 'name'], true, 0, 1],
|
||||
['na', ['groupid' => 'name'], true, 1, 0],
|
||||
['not', ['groupid' => 'group'], true, 0, 0],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataSearchGroups')]
|
||||
public function testSearchGroups(string $search, array $groups, bool $isGroup, int $totalMatches, int $totalExactMatches): void {
|
||||
$plugin = $this->getPlugin(['createGroupResult']);
|
||||
$plugin->expects($this->any())
|
||||
->method('createGroupResult')
|
||||
->willReturnCallback(function ($groupId) {
|
||||
return [
|
||||
'label' => $groupId,
|
||||
'value' => [
|
||||
'shareType' => 'group',
|
||||
'shareWith' => 'group/' . $groupId,
|
||||
],
|
||||
];
|
||||
});
|
||||
$searchResult = new SearchResult();
|
||||
self::invokePrivate($plugin, 'searchGroups', [$search, $groups, $searchResult]);
|
||||
$actual = $searchResult->asArray();
|
||||
$this->assertCount($totalMatches, $actual['groups']);
|
||||
$this->assertCount($totalExactMatches, $actual['exact']['groups']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Talk\Tests\php\Chat\AutoComplete;
|
||||
|
||||
use OCA\Talk\Chat\AutoComplete\Sorter;
|
||||
use OCA\Talk\Chat\CommentsManager;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Test\TestCase;
|
||||
|
||||
class SorterTest extends TestCase {
|
||||
protected CommentsManager&MockObject $commentsManager;
|
||||
|
||||
protected string $userId;
|
||||
|
||||
protected ?Sorter $sorter = null;
|
||||
|
||||
protected static array $user1 = [
|
||||
'label' => 'Seattle',
|
||||
'value' => [
|
||||
'shareType' => 'user',
|
||||
'shareWith' => 'seattle',
|
||||
],
|
||||
];
|
||||
|
||||
protected static array $user2 = [
|
||||
'label' => 'New York',
|
||||
'value' => [
|
||||
'shareType' => 'user',
|
||||
'shareWith' => 'new_york',
|
||||
],
|
||||
];
|
||||
|
||||
protected static array $user3 = [
|
||||
'label' => 'ttle Sea',
|
||||
'value' => [
|
||||
'shareType' => 'user',
|
||||
'shareWith' => 'ttle_sea',
|
||||
],
|
||||
];
|
||||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->commentsManager = $this->createMock(CommentsManager::class);
|
||||
$this->sorter = new Sorter($this->commentsManager);
|
||||
}
|
||||
|
||||
public function testGetId(): void {
|
||||
$this->assertSame('talk_chat_participants', $this->sorter->getId());
|
||||
}
|
||||
|
||||
public static function dataSort(): array {
|
||||
return [
|
||||
'no user posted' => ['', ['users' => [self::$user1, self::$user2]], [], ['users' => [self::$user1, self::$user2]]],
|
||||
'second user posted' => ['', ['users' => [self::$user1, self::$user2]], ['new_york' => new \DateTime('2000-01-01')], ['users' => [self::$user2, self::$user1]]],
|
||||
'second user posted later' => ['', ['users' => [self::$user1, self::$user2]], ['seattle' => new \DateTime('2017-01-01'), 'new_york' => new \DateTime('2018-01-01')], ['users' => [self::$user2, self::$user1]]],
|
||||
'second user posted earlier' => ['', ['users' => [self::$user1, self::$user2]], ['seattle' => new \DateTime('2018-01-01'), 'new_york' => new \DateTime('2017-01-01')], ['users' => [self::$user1, self::$user2]]],
|
||||
'starting match first1' => ['Sea', ['users' => [self::$user1, self::$user3]], [], ['users' => [self::$user1, self::$user3]]],
|
||||
'starting match first2' => ['Sea', ['users' => [self::$user3, self::$user1]], [], ['users' => [self::$user1, self::$user3]]],
|
||||
'no users' => ['', ['groups' => [self::$user1, self::$user2]], [], ['groups' => [self::$user1, self::$user2]]],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataSort')]
|
||||
public function testSort(string $search, array $toSort, array $comments, array $expected): void {
|
||||
$this->commentsManager->expects(isset($toSort['users']) ? $this->once() : $this->never())
|
||||
->method('getLastCommentDateByActor')
|
||||
->with('chat', '23', 'comment', 'users', $this->anything())
|
||||
->willReturn($comments);
|
||||
|
||||
$this->sorter->sort($toSort, [
|
||||
'itemType' => 'chat',
|
||||
'itemId' => '23',
|
||||
'search' => $search,
|
||||
]);
|
||||
$this->assertSame($expected, $toSort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,854 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Talk\Tests\php\Chat;
|
||||
|
||||
use OCA\Talk\Chat\ChatManager;
|
||||
use OCA\Talk\Chat\CommentsManager;
|
||||
use OCA\Talk\Chat\Notifier;
|
||||
use OCA\Talk\Model\Attendee;
|
||||
use OCA\Talk\Model\AttendeeMapper;
|
||||
use OCA\Talk\Model\Invitation;
|
||||
use OCA\Talk\Participant;
|
||||
use OCA\Talk\Room;
|
||||
use OCA\Talk\Service\AttachmentService;
|
||||
use OCA\Talk\Service\ParticipantService;
|
||||
use OCA\Talk\Service\PollService;
|
||||
use OCA\Talk\Service\RoomService;
|
||||
use OCA\Talk\Service\ThreadService;
|
||||
use OCA\Talk\Share\RoomShareProvider;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\Collaboration\Reference\IReferenceManager;
|
||||
use OCP\Comments\IComment;
|
||||
use OCP\Comments\ICommentsManager;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUser;
|
||||
use OCP\Notification\IManager as INotificationManager;
|
||||
use OCP\Security\RateLimiting\ILimiter;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\Share\IManager;
|
||||
use OCP\Share\IShare;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Test\TestCase;
|
||||
|
||||
#[Group('DB')]
|
||||
class ChatManagerTest extends TestCase {
|
||||
protected CommentsManager|ICommentsManager|MockObject $commentsManager;
|
||||
protected IEventDispatcher&MockObject $dispatcher;
|
||||
protected INotificationManager&MockObject $notificationManager;
|
||||
protected IManager&MockObject $shareManager;
|
||||
protected RoomShareProvider&MockObject $shareProvider;
|
||||
protected ParticipantService&MockObject $participantService;
|
||||
protected RoomService&MockObject $roomService;
|
||||
protected PollService&MockObject $pollService;
|
||||
protected ThreadService&MockObject $threadService;
|
||||
protected Notifier&MockObject $notifier;
|
||||
protected ITimeFactory&MockObject $timeFactory;
|
||||
protected AttachmentService&MockObject $attachmentService;
|
||||
protected IReferenceManager&MockObject $referenceManager;
|
||||
protected ILimiter&MockObject $rateLimiter;
|
||||
protected IRequest&MockObject $request;
|
||||
protected LoggerInterface&MockObject $logger;
|
||||
protected IL10N&MockObject $l;
|
||||
protected ?ChatManager $chatManager = null;
|
||||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->commentsManager = $this->createMock(CommentsManager::class);
|
||||
$this->dispatcher = $this->createMock(IEventDispatcher::class);
|
||||
$this->notificationManager = $this->createMock(INotificationManager::class);
|
||||
$this->shareManager = $this->createMock(IManager::class);
|
||||
$this->shareProvider = $this->createMock(RoomShareProvider::class);
|
||||
$this->participantService = $this->createMock(ParticipantService::class);
|
||||
$this->roomService = $this->createMock(RoomService::class);
|
||||
$this->pollService = $this->createMock(PollService::class);
|
||||
$this->threadService = $this->createMock(ThreadService::class);
|
||||
$this->notifier = $this->createMock(Notifier::class);
|
||||
$this->timeFactory = $this->createMock(ITimeFactory::class);
|
||||
$this->attachmentService = $this->createMock(AttachmentService::class);
|
||||
$this->referenceManager = $this->createMock(IReferenceManager::class);
|
||||
$this->rateLimiter = $this->createMock(ILimiter::class);
|
||||
$this->request = $this->createMock(IRequest::class);
|
||||
$this->l = $this->createMock(IL10N::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
|
||||
$this->l->method('n')
|
||||
->willReturnCallback(function (string $singular, string $plural, int $count, array $parameters = []) {
|
||||
$text = $count === 1 ? $singular : $plural;
|
||||
return vsprintf(str_replace('%n', (string)$count, $text), $parameters);
|
||||
});
|
||||
|
||||
$this->chatManager = $this->getManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $methods
|
||||
* @return ChatManager|MockObject
|
||||
*/
|
||||
protected function getManager(array $methods = []): ChatManager {
|
||||
$cacheFactory = $this->createMock(ICacheFactory::class);
|
||||
|
||||
if (!empty($methods)) {
|
||||
return $this->getMockBuilder(ChatManager::class)
|
||||
->setConstructorArgs([
|
||||
$this->commentsManager,
|
||||
$this->dispatcher,
|
||||
\OCP\Server::get(IDBConnection::class),
|
||||
$this->notificationManager,
|
||||
$this->shareManager,
|
||||
$this->shareProvider,
|
||||
$this->participantService,
|
||||
$this->roomService,
|
||||
$this->pollService,
|
||||
$this->threadService,
|
||||
$this->notifier,
|
||||
$cacheFactory,
|
||||
$this->timeFactory,
|
||||
$this->attachmentService,
|
||||
$this->referenceManager,
|
||||
$this->rateLimiter,
|
||||
$this->request,
|
||||
$this->l,
|
||||
$this->logger,
|
||||
])
|
||||
->onlyMethods($methods)
|
||||
->getMock();
|
||||
}
|
||||
|
||||
return new ChatManager(
|
||||
$this->commentsManager,
|
||||
$this->dispatcher,
|
||||
\OCP\Server::get(IDBConnection::class),
|
||||
$this->notificationManager,
|
||||
$this->shareManager,
|
||||
$this->shareProvider,
|
||||
$this->participantService,
|
||||
$this->roomService,
|
||||
$this->pollService,
|
||||
$this->threadService,
|
||||
$this->notifier,
|
||||
$cacheFactory,
|
||||
$this->timeFactory,
|
||||
$this->attachmentService,
|
||||
$this->referenceManager,
|
||||
$this->rateLimiter,
|
||||
$this->request,
|
||||
$this->l,
|
||||
$this->logger,
|
||||
);
|
||||
}
|
||||
|
||||
private function newComment($id, string $actorType, string $actorId, \DateTime $creationDateTime, string $message): IComment {
|
||||
$comment = $this->createMock(IComment::class);
|
||||
|
||||
$id = (string)$id;
|
||||
|
||||
$comment->method('getId')->willReturn($id);
|
||||
$comment->method('getActorType')->willReturn($actorType);
|
||||
$comment->method('getActorId')->willReturn($actorId);
|
||||
$comment->method('getCreationDateTime')->willReturn($creationDateTime);
|
||||
$comment->method('getMessage')->willReturn($message);
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return IComment|MockObject
|
||||
*/
|
||||
private function newCommentFromArray(array $data): IComment {
|
||||
$comment = $this->createMock(IComment::class);
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if ($key === 'id') {
|
||||
$value = (string)$value;
|
||||
}
|
||||
$comment->method('get' . ucfirst($key))->willReturn($value);
|
||||
}
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
protected function assertCommentEquals(array $data, IComment $comment): void {
|
||||
if (isset($data['id'])) {
|
||||
$id = $data['id'];
|
||||
unset($data['id']);
|
||||
$this->assertEquals($id, $comment->getId());
|
||||
}
|
||||
|
||||
$this->assertEquals($data, [
|
||||
'actorType' => $comment->getActorType(),
|
||||
'actorId' => $comment->getActorId(),
|
||||
'creationDateTime' => $comment->getCreationDateTime(),
|
||||
'message' => $comment->getMessage(),
|
||||
'referenceId' => $comment->getReferenceId(),
|
||||
'parentId' => $comment->getParentId(),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function dataSendMessage(): array {
|
||||
return [
|
||||
'simple message' => ['testUser1', 'testMessage1', '', '0'],
|
||||
'reference id' => ['testUser2', 'testMessage2', 'referenceId2', '0'],
|
||||
'as a reply' => ['testUser3', 'testMessage3', '', '23'],
|
||||
'reply w/ ref' => ['testUser4', 'testMessage4', 'referenceId4', '23'],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataSendMessage')]
|
||||
public function testSendMessage(string $userId, string $message, string $referenceId, string $parentId): void {
|
||||
$creationDateTime = new \DateTime();
|
||||
|
||||
$commentExpected = [
|
||||
'actorType' => 'users',
|
||||
'actorId' => $userId,
|
||||
'creationDateTime' => $creationDateTime,
|
||||
'message' => $message,
|
||||
'referenceId' => $referenceId,
|
||||
'parentId' => $parentId,
|
||||
];
|
||||
|
||||
$comment = $this->newCommentFromArray($commentExpected);
|
||||
|
||||
if ($parentId !== '0') {
|
||||
$replyTo = $this->newCommentFromArray([
|
||||
'id' => $parentId,
|
||||
]);
|
||||
|
||||
$comment->expects($this->once())
|
||||
->method('setParentId')
|
||||
->with($parentId);
|
||||
} else {
|
||||
$replyTo = null;
|
||||
}
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('create')
|
||||
->with('users', $userId, 'chat', 1234)
|
||||
->willReturn($comment);
|
||||
|
||||
$comment->expects($this->once())
|
||||
->method('setMessage')
|
||||
->with($message);
|
||||
|
||||
$comment->expects($this->once())
|
||||
->method('setCreationDateTime')
|
||||
->with($creationDateTime);
|
||||
|
||||
$comment->expects($referenceId === '' ? $this->never() : $this->once())
|
||||
->method('setReferenceId')
|
||||
->with($referenceId);
|
||||
|
||||
$comment->expects($this->once())
|
||||
->method('setVerb')
|
||||
->with('comment');
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('save')
|
||||
->with($comment);
|
||||
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn(1234);
|
||||
|
||||
$this->notifier->expects($this->once())
|
||||
->method('notifyMentionedUsers')
|
||||
->with($chat, $comment);
|
||||
|
||||
$participant = $this->createMock(Participant::class);
|
||||
|
||||
$return = $this->chatManager->sendMessage($chat, $participant, 'users', $userId, $message, $creationDateTime, $replyTo, $referenceId, false);
|
||||
|
||||
$this->assertCommentEquals($commentExpected, $return);
|
||||
}
|
||||
|
||||
public function testGetHistory(): void {
|
||||
$offset = 1;
|
||||
$limit = 42;
|
||||
$expected = [
|
||||
$this->newComment(110, 'users', 'testUnknownUser', new \DateTime('@' . 1000000042), 'testMessage3'),
|
||||
$this->newComment(109, 'guests', 'testSpreedSession', new \DateTime('@' . 1000000023), 'testMessage2'),
|
||||
$this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'testMessage1')
|
||||
];
|
||||
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn(1234);
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('getCommentsWithVerbForObjectSinceComment')
|
||||
->with('chat', 1234, [], $offset, 'desc', $limit)
|
||||
->willReturn($expected);
|
||||
|
||||
$comments = $this->chatManager->getHistory($chat, $offset, $limit, false);
|
||||
|
||||
$this->assertEquals($expected, $comments);
|
||||
}
|
||||
|
||||
public function testWaitForNewMessages(): void {
|
||||
$offset = 1;
|
||||
$limit = 42;
|
||||
$timeout = 23;
|
||||
$expected = [
|
||||
$this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'testMessage1'),
|
||||
$this->newComment(109, 'guests', 'testSpreedSession', new \DateTime('@' . 1000000023), 'testMessage2'),
|
||||
$this->newComment(110, 'users', 'testUnknownUser', new \DateTime('@' . 1000000042), 'testMessage3'),
|
||||
];
|
||||
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn(1234);
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('getCommentsWithVerbForObjectSinceComment')
|
||||
->with('chat', 1234, [], $offset, 'asc', $limit)
|
||||
->willReturn($expected);
|
||||
|
||||
$this->notifier->expects($this->once())
|
||||
->method('markMentionNotificationsRead')
|
||||
->with($chat, 'userId');
|
||||
|
||||
/** @var IUser&MockObject $user */
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->willReturn('userId');
|
||||
|
||||
$comments = $this->chatManager->waitForNewMessages($chat, $offset, $limit, $timeout, $user, false, true);
|
||||
|
||||
$this->assertEquals($expected, $comments);
|
||||
}
|
||||
|
||||
public function testWaitForNewMessagesWithWaiting(): void {
|
||||
$offset = 1;
|
||||
$limit = 42;
|
||||
$timeout = 23;
|
||||
$expected = [
|
||||
$this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'testMessage1'),
|
||||
$this->newComment(109, 'guests', 'testSpreedSession', new \DateTime('@' . 1000000023), 'testMessage2'),
|
||||
$this->newComment(110, 'users', 'testUnknownUser', new \DateTime('@' . 1000000042), 'testMessage3'),
|
||||
];
|
||||
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn(1234);
|
||||
|
||||
$this->commentsManager->expects($this->exactly(2))
|
||||
->method('getCommentsWithVerbForObjectSinceComment')
|
||||
->with('chat', 1234, [], $offset, 'asc', $limit)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
[],
|
||||
$expected
|
||||
);
|
||||
|
||||
$this->notifier->expects($this->once())
|
||||
->method('markMentionNotificationsRead')
|
||||
->with($chat, 'userId');
|
||||
|
||||
/** @var IUser&MockObject $user */
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->expects($this->any())
|
||||
->method('getUID')
|
||||
->willReturn('userId');
|
||||
|
||||
$comments = $this->chatManager->waitForNewMessages($chat, $offset, $limit, $timeout, $user, false, true);
|
||||
|
||||
$this->assertEquals($expected, $comments);
|
||||
}
|
||||
|
||||
public function testGetUnreadCount(): void {
|
||||
/** @var Room&MockObject $chat */
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->atLeastOnce())
|
||||
->method('getId')
|
||||
->willReturn(23);
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('getNumberOfCommentsWithVerbsForObjectSinceComment')
|
||||
->with('chat', 23, 42, ['comment', 'object_shared']);
|
||||
|
||||
$this->chatManager->getUnreadCount($chat, 42);
|
||||
}
|
||||
|
||||
public function testDeleteMessages(): void {
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn(1234);
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('deleteCommentsAtObject')
|
||||
->with('chat', 1234);
|
||||
|
||||
$this->notifier->expects($this->once())
|
||||
->method('removePendingNotificationsForRoom')
|
||||
->with($chat);
|
||||
|
||||
$this->chatManager->deleteMessages($chat);
|
||||
}
|
||||
|
||||
public function testDeleteMessage(): void {
|
||||
$mapper = new AttendeeMapper(\OCP\Server::get(IDBConnection::class));
|
||||
$attendee = $mapper->createAttendeeFromRow([
|
||||
'a_id' => 1,
|
||||
'room_id' => 123,
|
||||
'actor_type' => Attendee::ACTOR_USERS,
|
||||
'actor_id' => 'user',
|
||||
'display_name' => 'user-display',
|
||||
'pin' => '',
|
||||
'participant_type' => Participant::USER,
|
||||
'favorite' => true,
|
||||
'notification_level' => Participant::NOTIFY_MENTION,
|
||||
'notification_calls' => Participant::NOTIFY_CALLS_ON,
|
||||
'last_joined_call' => 0,
|
||||
'last_read_message' => 0,
|
||||
'last_mention_message' => 0,
|
||||
'last_mention_direct' => 0,
|
||||
'read_privacy' => Participant::PRIVACY_PUBLIC,
|
||||
'permissions' => Attendee::PERMISSIONS_DEFAULT,
|
||||
'access_token' => '',
|
||||
'remote_id' => '',
|
||||
'phone_number' => '',
|
||||
'call_id' => '',
|
||||
'invited_cloud_id' => '',
|
||||
'state' => Invitation::STATE_ACCEPTED,
|
||||
'unread_messages' => 0,
|
||||
'last_attendee_activity' => 0,
|
||||
'archived' => 0,
|
||||
'important' => 0,
|
||||
'sensitive' => 0,
|
||||
'has_unread_threads' => false,
|
||||
'has_unread_thread_mentions' => false,
|
||||
'has_unread_thread_directs' => false,
|
||||
]);
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn(1234);
|
||||
$participant = new Participant($chat, $attendee, null);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$comment = $this->createMock(IComment::class);
|
||||
$comment->method('getId')
|
||||
->willReturn('123456');
|
||||
$comment->method('getVerb')
|
||||
->willReturn('comment');
|
||||
$comment->expects($this->once())
|
||||
->method('setMessage');
|
||||
$comment->expects($this->once())
|
||||
->method('setVerb')
|
||||
->with('comment_deleted');
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('save')
|
||||
->with($comment);
|
||||
|
||||
$systemMessage = $this->createMock(IComment::class);
|
||||
|
||||
$chatManager = $this->getManager(['addSystemMessage']);
|
||||
$chatManager->expects($this->once())
|
||||
->method('addSystemMessage')
|
||||
->with($chat, $participant, Attendee::ACTOR_USERS, 'user', $this->anything(), $this->anything(), false, null, $comment)
|
||||
->willReturn($systemMessage);
|
||||
|
||||
$this->assertSame($systemMessage, $chatManager->deleteMessage($chat, $comment, $participant, $date));
|
||||
}
|
||||
|
||||
public function testDeleteMessageFileShare(): void {
|
||||
$mapper = new AttendeeMapper(\OCP\Server::get(IDBConnection::class));
|
||||
$attendee = $mapper->createAttendeeFromRow([
|
||||
'a_id' => 1,
|
||||
'room_id' => 123,
|
||||
'actor_type' => Attendee::ACTOR_USERS,
|
||||
'actor_id' => 'user',
|
||||
'display_name' => 'user-display',
|
||||
'pin' => '',
|
||||
'participant_type' => Participant::USER,
|
||||
'favorite' => true,
|
||||
'notification_level' => Participant::NOTIFY_MENTION,
|
||||
'notification_calls' => Participant::NOTIFY_CALLS_ON,
|
||||
'last_joined_call' => 0,
|
||||
'last_read_message' => 0,
|
||||
'last_mention_message' => 0,
|
||||
'last_mention_direct' => 0,
|
||||
'read_privacy' => Participant::PRIVACY_PUBLIC,
|
||||
'permissions' => Attendee::PERMISSIONS_DEFAULT,
|
||||
'access_token' => '',
|
||||
'remote_id' => '',
|
||||
'phone_number' => '',
|
||||
'call_id' => '',
|
||||
'invited_cloud_id' => '',
|
||||
'state' => Invitation::STATE_ACCEPTED,
|
||||
'unread_messages' => 0,
|
||||
'last_attendee_activity' => 0,
|
||||
'archived' => 0,
|
||||
'important' => 0,
|
||||
'sensitive' => 0,
|
||||
'has_unread_threads' => false,
|
||||
'has_unread_thread_mentions' => false,
|
||||
'has_unread_thread_directs' => false,
|
||||
]);
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn(1234);
|
||||
$chat->expects($this->any())
|
||||
->method('getToken')
|
||||
->willReturn('T0k3N');
|
||||
$participant = new Participant($chat, $attendee, null);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$comment = $this->createMock(IComment::class);
|
||||
$comment->method('getId')
|
||||
->willReturn('123456');
|
||||
$comment->method('getVerb')
|
||||
->willReturn('object_shared');
|
||||
$comment->expects($this->once())
|
||||
->method('getMessage')
|
||||
->willReturn(json_encode(['message' => 'file_shared', 'parameters' => ['share' => '42']]));
|
||||
$comment->expects($this->once())
|
||||
->method('setMessage');
|
||||
$comment->expects($this->once())
|
||||
->method('setVerb')
|
||||
->with('comment_deleted');
|
||||
|
||||
$share = $this->createMock(IShare::class);
|
||||
$share->method('getShareType')
|
||||
->willReturn(IShare::TYPE_ROOM);
|
||||
$share->method('getSharedWith')
|
||||
->willReturn('T0k3N');
|
||||
$share->method('getShareOwner')
|
||||
->willReturn('user');
|
||||
|
||||
$this->shareManager->method('getShareById')
|
||||
->with('ocRoomShare:42')
|
||||
->willReturn($share);
|
||||
|
||||
$this->shareManager->expects($this->once())
|
||||
->method('deleteShare')
|
||||
->willReturn($share);
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('save')
|
||||
->with($comment);
|
||||
|
||||
$systemMessage = $this->createMock(IComment::class);
|
||||
|
||||
$chatManager = $this->getManager(['addSystemMessage']);
|
||||
$chatManager->expects($this->once())
|
||||
->method('addSystemMessage')
|
||||
->with($chat, $participant, Attendee::ACTOR_USERS, 'user', $this->anything(), $this->anything(), false, null, $comment)
|
||||
->willReturn($systemMessage);
|
||||
|
||||
$this->assertSame($systemMessage, $chatManager->deleteMessage($chat, $comment, $participant, $date));
|
||||
}
|
||||
|
||||
public function testDeleteMessageFileShareNotFound(): void {
|
||||
$mapper = new AttendeeMapper(\OCP\Server::get(IDBConnection::class));
|
||||
$attendee = $mapper->createAttendeeFromRow([
|
||||
'a_id' => 1,
|
||||
'room_id' => 123,
|
||||
'actor_type' => Attendee::ACTOR_USERS,
|
||||
'actor_id' => 'user',
|
||||
'display_name' => 'user-display',
|
||||
'pin' => '',
|
||||
'participant_type' => Participant::USER,
|
||||
'favorite' => true,
|
||||
'notification_level' => Participant::NOTIFY_MENTION,
|
||||
'notification_calls' => Participant::NOTIFY_CALLS_ON,
|
||||
'last_joined_call' => 0,
|
||||
'last_read_message' => 0,
|
||||
'last_mention_message' => 0,
|
||||
'last_mention_direct' => 0,
|
||||
'read_privacy' => Participant::PRIVACY_PUBLIC,
|
||||
'permissions' => Attendee::PERMISSIONS_DEFAULT,
|
||||
'access_token' => '',
|
||||
'remote_id' => '',
|
||||
'phone_number' => '',
|
||||
'call_id' => '',
|
||||
'invited_cloud_id' => '',
|
||||
'state' => Invitation::STATE_ACCEPTED,
|
||||
'unread_messages' => 0,
|
||||
'last_attendee_activity' => 0,
|
||||
'archived' => 0,
|
||||
'important' => 0,
|
||||
'sensitive' => 0,
|
||||
'has_unread_threads' => false,
|
||||
'has_unread_thread_mentions' => false,
|
||||
'has_unread_thread_directs' => false,
|
||||
]);
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn(1234);
|
||||
$participant = new Participant($chat, $attendee, null);
|
||||
|
||||
$date = new \DateTime();
|
||||
|
||||
$comment = $this->createMock(IComment::class);
|
||||
$comment->method('getId')
|
||||
->willReturn('123456');
|
||||
$comment->method('getVerb')
|
||||
->willReturn('object_shared');
|
||||
$comment->expects($this->once())
|
||||
->method('getMessage')
|
||||
->willReturn(json_encode(['message' => 'file_shared', 'parameters' => ['share' => '42']]));
|
||||
|
||||
$this->shareManager->method('getShareById')
|
||||
->with('ocRoomShare:42')
|
||||
->willThrowException(new ShareNotFound());
|
||||
|
||||
$this->commentsManager->expects($this->never())
|
||||
->method('save');
|
||||
|
||||
$systemMessage = $this->createMock(IComment::class);
|
||||
|
||||
$chatManager = $this->getManager(['addSystemMessage']);
|
||||
$chatManager->expects($this->never())
|
||||
->method('addSystemMessage');
|
||||
|
||||
$this->expectException(ShareNotFound::class);
|
||||
$this->assertSame($systemMessage, $chatManager->deleteMessage($chat, $comment, $participant, $date));
|
||||
}
|
||||
|
||||
public function testClearHistory(): void {
|
||||
$chat = $this->createMock(Room::class);
|
||||
$chat->expects($this->any())
|
||||
->method('getId')
|
||||
->willReturn(1234);
|
||||
$chat->expects($this->any())
|
||||
->method('getToken')
|
||||
->willReturn('t0k3n');
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('deleteCommentsAtObject')
|
||||
->with('chat', 1234);
|
||||
|
||||
$this->shareProvider->expects($this->once())
|
||||
->method('deleteInRoom')
|
||||
->with('t0k3n');
|
||||
|
||||
$this->notifier->expects($this->once())
|
||||
->method('removePendingNotificationsForRoom')
|
||||
->with($chat, true);
|
||||
|
||||
$this->participantService->expects($this->once())
|
||||
->method('resetChatDetails')
|
||||
->with($chat);
|
||||
|
||||
$date = new \DateTime();
|
||||
$this->timeFactory->method('getDateTime')
|
||||
->willReturn($date);
|
||||
|
||||
$manager = $this->getManager(['addSystemMessage']);
|
||||
$manager->expects($this->once())
|
||||
->method('addSystemMessage')
|
||||
->with(
|
||||
$chat,
|
||||
null,
|
||||
'users',
|
||||
'admin',
|
||||
json_encode(['message' => 'history_cleared', 'parameters' => []]),
|
||||
$date,
|
||||
false
|
||||
);
|
||||
$manager->clearHistory($chat, 'users', 'admin');
|
||||
}
|
||||
|
||||
public static function dataSearchIsPartOfConversationNameOrAtAll(): array {
|
||||
return [
|
||||
'found a in all' => [
|
||||
'a', 'room', true
|
||||
],
|
||||
'found h in here' => [
|
||||
'h', 'room', true
|
||||
],
|
||||
'case sensitive, not found A in all' => [
|
||||
'A', 'room', false
|
||||
],
|
||||
'case sensitive, not found H in here' => [
|
||||
'H', 'room', false
|
||||
],
|
||||
'non case sensitive, found r in room' => [
|
||||
'R', 'room', true
|
||||
],
|
||||
'found r in begin of room' => [
|
||||
'r', 'room', true
|
||||
],
|
||||
'found o in middle of room' => [
|
||||
'o', 'room', true
|
||||
],
|
||||
'not found all in middle of text' => [
|
||||
'notbeginingall', 'room', false
|
||||
],
|
||||
'not found here in middle of text' => [
|
||||
'notbegininghere', 'room', false
|
||||
],
|
||||
'not found room in middle of text' => [
|
||||
'notbeginingroom', 'room', false
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataSearchIsPartOfConversationNameOrAtAll')]
|
||||
public function testSearchIsPartOfConversationNameOrAtAll(string $search, string $roomDisplayName, bool $expected): void {
|
||||
$actual = self::invokePrivate($this->chatManager, 'searchIsPartOfConversationNameOrAtAll', [$search, $roomDisplayName]);
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public static function dataAddConversationNotify(): array {
|
||||
return [
|
||||
[
|
||||
'',
|
||||
['getType' => Room::TYPE_ONE_TO_ONE],
|
||||
[],
|
||||
null,
|
||||
[],
|
||||
],
|
||||
[
|
||||
'',
|
||||
['getDisplayName' => 'test', 'getMentionPermissions' => 0],
|
||||
['getAttendee' => Attendee::fromRow([
|
||||
'actor_type' => Attendee::ACTOR_USERS,
|
||||
'actor_id' => 'user',
|
||||
])],
|
||||
324,
|
||||
[['id' => 'all', 'label' => 'test', 'source' => 'calls', 'mentionId' => 'all', 'details' => 'All 324 participants']]
|
||||
],
|
||||
[
|
||||
'',
|
||||
['getMentionPermissions' => 1],
|
||||
['hasModeratorPermissions' => false],
|
||||
null,
|
||||
[],
|
||||
],
|
||||
[
|
||||
'all',
|
||||
['getDisplayName' => 'test', 'getMentionPermissions' => 0],
|
||||
['getAttendee' => Attendee::fromRow([
|
||||
'actor_type' => Attendee::ACTOR_USERS,
|
||||
'actor_id' => 'user',
|
||||
])],
|
||||
1,
|
||||
[['id' => 'all', 'label' => 'test', 'source' => 'calls', 'mentionId' => 'all']],
|
||||
],
|
||||
[
|
||||
'all',
|
||||
['getDisplayName' => 'test', 'getMentionPermissions' => 1],
|
||||
[
|
||||
'getAttendee' => Attendee::fromRow([
|
||||
'actor_type' => Attendee::ACTOR_USERS,
|
||||
'actor_id' => 'user',
|
||||
]),
|
||||
'hasModeratorPermissions' => true,
|
||||
],
|
||||
8,
|
||||
[['id' => 'all', 'label' => 'test', 'source' => 'calls', 'mentionId' => 'all', 'details' => 'All 8 participants']],
|
||||
],
|
||||
[
|
||||
'here',
|
||||
['getDisplayName' => 'test', 'getMentionPermissions' => 0],
|
||||
['getAttendee' => Attendee::fromRow([
|
||||
'actor_type' => Attendee::ACTOR_GUESTS,
|
||||
'actor_id' => 'guest',
|
||||
])],
|
||||
12,
|
||||
[['id' => 'all', 'label' => 'test', 'source' => 'calls', 'mentionId' => 'all', 'details' => 'All 12 participants']],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataAddConversationNotify')]
|
||||
public function testAddConversationNotify(string $search, array $roomMocks, array $participantMocks, ?int $totalCount, array $expected): void {
|
||||
$room = $this->createMock(Room::class);
|
||||
foreach ($roomMocks as $method => $return) {
|
||||
$room->expects($this->once())
|
||||
->method($method)
|
||||
->willReturn($return);
|
||||
}
|
||||
|
||||
$participant = $this->createMock(Participant::class);
|
||||
foreach ($participantMocks as $method => $return) {
|
||||
$participant->expects($this->once())
|
||||
->method($method)
|
||||
->willReturn($return);
|
||||
}
|
||||
|
||||
if ($totalCount !== null) {
|
||||
$this->participantService->method('getNumberOfUsers')
|
||||
->willReturn($totalCount);
|
||||
}
|
||||
|
||||
$actual = $this->chatManager->addConversationNotify([], $search, $room, $participant);
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
#[DataProvider('dataIsSharedFile')]
|
||||
public function testIsSharedFile(string $message, bool $expected): void {
|
||||
$actual = $this->chatManager->isSharedFile($message);
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public static function dataIsSharedFile(): array {
|
||||
return [
|
||||
['', false],
|
||||
[json_encode([]), false],
|
||||
[json_encode(['parameters' => '']), false],
|
||||
[json_encode(['parameters' => []]), false],
|
||||
[json_encode(['parameters' => ['share' => null]]), false],
|
||||
[json_encode(['parameters' => ['share' => '']]), false],
|
||||
[json_encode(['parameters' => ['share' => []]]), false],
|
||||
[json_encode(['parameters' => ['share' => 0]]), false],
|
||||
[json_encode(['parameters' => ['share' => 1]]), true],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataFilterCommentsWithNonExistingFiles')]
|
||||
public function testFilterCommentsWithNonExistingFiles(array $list, int $expectedCount): void {
|
||||
// Transform text messages in instance of comment and mock with the message
|
||||
foreach ($list as $key => $message) {
|
||||
$list[$key] = $this->createMock(IComment::class);
|
||||
$list[$key]->method('getMessage')
|
||||
->willReturn($message);
|
||||
$messageDecoded = json_decode($message, true);
|
||||
if (isset($messageDecoded['parameters']['share']) && $messageDecoded['parameters']['share'] === 'notExists') {
|
||||
$this->shareProvider->expects($this->once())
|
||||
->method('getShareById')
|
||||
->with('notExists')
|
||||
->willThrowException(new ShareNotFound());
|
||||
}
|
||||
}
|
||||
if (count($list) !== $expectedCount) {
|
||||
}
|
||||
$result = $this->chatManager->filterCommentsWithNonExistingFiles($list);
|
||||
$this->assertCount($expectedCount, $result);
|
||||
}
|
||||
|
||||
public static function dataFilterCommentsWithNonExistingFiles(): array {
|
||||
return [
|
||||
[[], 0],
|
||||
[[json_encode(['parameters' => ['not a shared file']])], 1],
|
||||
[[json_encode(['parameters' => ['share' => 'notExists']])], 0],
|
||||
[[json_encode(['parameters' => ['share' => 1]])], 1],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,465 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Talk\Tests\php\Chat;
|
||||
|
||||
use OC\Comments\Comment;
|
||||
use OCA\Talk\Chat\Notifier;
|
||||
use OCA\Talk\Exceptions\ParticipantNotFoundException;
|
||||
use OCA\Talk\Files\Util;
|
||||
use OCA\Talk\Model\Attendee;
|
||||
use OCA\Talk\Model\Session;
|
||||
use OCA\Talk\Participant;
|
||||
use OCA\Talk\Room;
|
||||
use OCA\Talk\Service\ParticipantService;
|
||||
use OCA\Talk\Service\ThreadService;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\Comments\IComment;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Notification\IManager as INotificationManager;
|
||||
use OCP\Notification\INotification;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Test\TestCase;
|
||||
|
||||
class NotifierTest extends TestCase {
|
||||
protected INotificationManager&MockObject $notificationManager;
|
||||
protected IUserManager&MockObject $userManager;
|
||||
protected IGroupManager&MockObject $groupManager;
|
||||
protected ParticipantService&MockObject $participantService;
|
||||
protected ThreadService&MockObject $threadService;
|
||||
protected IConfig&MockObject $config;
|
||||
protected ITimeFactory&MockObject $timeFactory;
|
||||
protected Util&MockObject $util;
|
||||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->notificationManager = $this->createMock(INotificationManager::class);
|
||||
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
$this->userManager
|
||||
->method('userExists')
|
||||
->willReturnCallback(function ($userId) {
|
||||
return $userId !== 'unknownUser';
|
||||
});
|
||||
$this->groupManager = $this->createMock(IGroupManager::class);
|
||||
|
||||
$this->participantService = $this->createMock(ParticipantService::class);
|
||||
$this->threadService = $this->createMock(ThreadService::class);
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->timeFactory = $this->createMock(ITimeFactory::class);
|
||||
$this->util = $this->createMock(Util::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $methods
|
||||
* @return Notifier|MockObject
|
||||
*/
|
||||
protected function getNotifier(array $methods = []) {
|
||||
if (!empty($methods)) {
|
||||
return $this->getMockBuilder(Notifier::class)
|
||||
->setConstructorArgs([
|
||||
$this->notificationManager,
|
||||
$this->userManager,
|
||||
$this->groupManager,
|
||||
$this->participantService,
|
||||
$this->threadService,
|
||||
$this->config,
|
||||
$this->timeFactory,
|
||||
$this->util,
|
||||
])
|
||||
->onlyMethods($methods)
|
||||
->getMock();
|
||||
}
|
||||
return new Notifier(
|
||||
$this->notificationManager,
|
||||
$this->userManager,
|
||||
$this->groupManager,
|
||||
$this->participantService,
|
||||
$this->threadService,
|
||||
$this->config,
|
||||
$this->timeFactory,
|
||||
$this->util
|
||||
);
|
||||
}
|
||||
|
||||
private function newComment($id, $actorType, $actorId, $creationDateTime, $message): IComment {
|
||||
$comment = new Comment([
|
||||
'id' => $id,
|
||||
'object_id' => '1234',
|
||||
'object_type' => 'chat',
|
||||
'actor_type' => $actorType,
|
||||
'actor_id' => $actorId,
|
||||
'creation_date_time' => $creationDateTime,
|
||||
'message' => $message,
|
||||
'verb' => 'comment',
|
||||
]);
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Room|MockObject
|
||||
*/
|
||||
private function getRoom($settings = []) {
|
||||
/** @var Room|MockObject */
|
||||
$room = $this->createMock(Room::class);
|
||||
|
||||
$this->participantService->expects($this->any())
|
||||
->method('getParticipant')
|
||||
->willReturnCallback(function (Room $room, string $actorId) use ($settings): Participant {
|
||||
if ($actorId === 'userNotInOneToOneChat') {
|
||||
throw new ParticipantNotFoundException();
|
||||
}
|
||||
$attendeeRow = [
|
||||
'actor_type' => 'user',
|
||||
'actor_id' => $actorId,
|
||||
];
|
||||
if (isset($settings['attendee'][$actorId])) {
|
||||
$attendeeRow = array_merge($attendeeRow, $settings['attendee'][$actorId]);
|
||||
}
|
||||
$attendee = Attendee::fromRow($attendeeRow);
|
||||
return new Participant($room, $attendee, null);
|
||||
});
|
||||
|
||||
return $room;
|
||||
}
|
||||
|
||||
public static function dataNotifyMentionedUsers(): array {
|
||||
return [
|
||||
'no notifications' => [
|
||||
'No mentions', [], [], [],
|
||||
],
|
||||
'notify a mentioned user' => [
|
||||
'Mention @anotherUser', [], [['id' => 'anotherUser', 'type' => 'users', 'reason' => 'direct']], [['id' => 'anotherUser', 'type' => 'users', 'reason' => 'direct']],
|
||||
],
|
||||
'not notify mentioned user if already notified' => [
|
||||
'Mention @anotherUser', [['id' => 'anotherUser', 'type' => 'users', 'reason' => 'reply']], [], [['id' => 'anotherUser', 'type' => 'users', 'reason' => 'reply']],
|
||||
],
|
||||
'notify mentioned Users With Long Message Start Mention' => [
|
||||
'123456789 @anotherUserWithOddLengthName 123456789-123456789-123456789-123456789-123456789-123456789', [], [['id' => 'anotherUserWithOddLengthName', 'type' => 'users', 'reason' => 'direct']], [['id' => 'anotherUserWithOddLengthName', 'type' => 'users', 'reason' => 'direct']],
|
||||
],
|
||||
'notify mentioned users with long message middle mention' => [
|
||||
'123456789-123456789-123456789-1234 @anotherUserWithOddLengthName 6789-123456789-123456789-123456789', [], [['id' => 'anotherUserWithOddLengthName', 'type' => 'users', 'reason' => 'direct']], [['id' => 'anotherUserWithOddLengthName', 'type' => 'users', 'reason' => 'direct']],
|
||||
],
|
||||
'notify mentioned users with long message end mention' => [
|
||||
'123456789-123456789-123456789-123456789-123456789-123456789 @anotherUserWithOddLengthName 123456789', [], [['id' => 'anotherUserWithOddLengthName', 'type' => 'users', 'reason' => 'direct']], [['id' => 'anotherUserWithOddLengthName', 'type' => 'users', 'reason' => 'direct']],
|
||||
],
|
||||
'mention herself' => [
|
||||
'Mention @testUser', [], [], [],
|
||||
],
|
||||
'not notify unknownuser' => [
|
||||
'Mention @unknownUser', [], [], [],
|
||||
],
|
||||
'notify mentioned users several mentions' => [
|
||||
'Mention @anotherUser, and @unknownUser, and @testUser, and @userAbleToJoin', [],
|
||||
[['id' => 'anotherUser', 'type' => 'users', 'reason' => 'direct'], ['id' => 'userAbleToJoin', 'type' => 'users', 'reason' => 'direct']],
|
||||
[['id' => 'anotherUser', 'type' => 'users', 'reason' => 'direct'], ['id' => 'userAbleToJoin', 'type' => 'users', 'reason' => 'direct']],
|
||||
],
|
||||
'notify mentioned users to user not invited to chat' => [
|
||||
'Mention @userNotInOneToOneChat', [], [], [],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataNotifyMentionedUsers')]
|
||||
public function testNotifyMentionedUsers(string $message, array $alreadyNotifiedUsers, array $notify, array $expectedReturn): void {
|
||||
if (count($notify)) {
|
||||
$this->notificationManager->expects($this->exactly(count($notify)))
|
||||
->method('notify');
|
||||
}
|
||||
|
||||
$room = $this->getRoom();
|
||||
$comment = $this->newComment('108', 'users', 'testUser', new \DateTime('@' . 1000000016), $message);
|
||||
$notifier = $this->getNotifier([]);
|
||||
$participant = $this->createMock(Participant::class);
|
||||
$actual = $notifier->notifyMentionedUsers($room, $comment, $alreadyNotifiedUsers, false, $participant);
|
||||
|
||||
$this->assertEqualsCanonicalizing($expectedReturn, $actual);
|
||||
}
|
||||
|
||||
public static function dataShouldParticipantBeNotified(): array {
|
||||
return [
|
||||
[Attendee::ACTOR_GROUPS, 'test1', null, Attendee::ACTOR_USERS, 'test1', [], false, Notifier::PRIORITY_NONE],
|
||||
[Attendee::ACTOR_USERS, 'test1', null, Attendee::ACTOR_USERS, 'test1', [], false, Notifier::PRIORITY_NONE],
|
||||
[Attendee::ACTOR_USERS, 'test1', null, Attendee::ACTOR_USERS, 'test2', [], false, Notifier::PRIORITY_NORMAL],
|
||||
[Attendee::ACTOR_USERS, 'test1', null, Attendee::ACTOR_USERS, 'test2', [['id' => 'test1', 'type' => Attendee::ACTOR_USERS]], false, Notifier::PRIORITY_NONE],
|
||||
[Attendee::ACTOR_USERS, 'test1', null, Attendee::ACTOR_USERS, 'test2', [['id' => 'test1', 'type' => Attendee::ACTOR_FEDERATED_USERS]], false, Notifier::PRIORITY_NORMAL],
|
||||
[Attendee::ACTOR_USERS, 'test1', Session::SESSION_TIMEOUT - 5, Attendee::ACTOR_USERS, 'test2', [], false, Notifier::PRIORITY_NONE],
|
||||
[Attendee::ACTOR_USERS, 'test1', Session::SESSION_TIMEOUT + 5, Attendee::ACTOR_USERS, 'test2', [], false, Notifier::PRIORITY_NORMAL],
|
||||
|
||||
// Marked as important, still blocked by session and being the author, but otherwise with PRIORITY_IMPORTANT
|
||||
[Attendee::ACTOR_USERS, 'test1', null, Attendee::ACTOR_USERS, 'test1', [], true, Notifier::PRIORITY_NONE],
|
||||
[Attendee::ACTOR_USERS, 'test1', null, Attendee::ACTOR_USERS, 'test2', [], true, Notifier::PRIORITY_IMPORTANT],
|
||||
[Attendee::ACTOR_USERS, 'test1', Session::SESSION_TIMEOUT - 5, Attendee::ACTOR_USERS, 'test2', [], true, Notifier::PRIORITY_NONE],
|
||||
[Attendee::ACTOR_USERS, 'test1', Session::SESSION_TIMEOUT + 5, Attendee::ACTOR_USERS, 'test2', [], true, Notifier::PRIORITY_IMPORTANT],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataShouldParticipantBeNotified')]
|
||||
public function testShouldParticipantBeNotified(string $actorType, string $actorId, ?int $sessionAge, string $commentActorType, string $commentActorId, array $alreadyNotifiedUsers, bool $isImportant, int $expected): void {
|
||||
$comment = $this->createMock(IComment::class);
|
||||
$comment->method('getActorType')
|
||||
->willReturn($commentActorType);
|
||||
$comment->method('getActorId')
|
||||
->willReturn($commentActorId);
|
||||
|
||||
$room = $this->createMock(Room::class);
|
||||
$attendee = Attendee::fromRow([
|
||||
'actor_type' => $actorType,
|
||||
'actor_id' => $actorId,
|
||||
'important' => $isImportant,
|
||||
]);
|
||||
$session = null;
|
||||
if ($sessionAge !== null) {
|
||||
$current = 1234567;
|
||||
$this->timeFactory->method('getTime')
|
||||
->willReturn($current);
|
||||
|
||||
$session = Session::fromRow([
|
||||
'last_ping' => $current - $sessionAge,
|
||||
]);
|
||||
}
|
||||
$participant = new Participant($room, $attendee, $session);
|
||||
|
||||
self::assertSame($expected, self::invokePrivate($this->getNotifier(), 'shouldParticipantBeNotified', [$participant, $comment, $alreadyNotifiedUsers]));
|
||||
}
|
||||
|
||||
public function testRemovePendingNotificationsForRoom(): void {
|
||||
$notification = $this->createMock(INotification::class);
|
||||
|
||||
$room = $this->createMock(Room::class);
|
||||
$room->expects($this->any())
|
||||
->method('getToken')
|
||||
->willReturn('Token123');
|
||||
|
||||
$this->notificationManager->expects($this->once())
|
||||
->method('createNotification')
|
||||
->willReturn($notification);
|
||||
|
||||
$notification->expects($this->once())
|
||||
->method('setApp')
|
||||
->with('spreed')
|
||||
->willReturnSelf();
|
||||
|
||||
$notification->expects($this->atLeastOnce())
|
||||
->method('setObject')
|
||||
->with($this->anything(), 'Token123')
|
||||
->willReturnSelf();
|
||||
|
||||
$this->notificationManager->expects($this->atLeastOnce())
|
||||
->method('markProcessed')
|
||||
->with($notification);
|
||||
|
||||
$this->getNotifier()->removePendingNotificationsForRoom($room);
|
||||
}
|
||||
|
||||
public function testRemovePendingNotificationsForChatOnly(): void {
|
||||
$notification = $this->createMock(INotification::class);
|
||||
|
||||
$room = $this->createMock(Room::class);
|
||||
$room->expects($this->any())
|
||||
->method('getToken')
|
||||
->willReturn('Token123');
|
||||
|
||||
$this->notificationManager->expects($this->once())
|
||||
->method('createNotification')
|
||||
->willReturn($notification);
|
||||
|
||||
$notification->expects($this->once())
|
||||
->method('setApp')
|
||||
->with('spreed')
|
||||
->willReturnSelf();
|
||||
|
||||
$notification->expects($this->atLeastOnce())
|
||||
->method('setObject')
|
||||
->with($this->anything(), 'Token123')
|
||||
->willReturnSelf();
|
||||
|
||||
$this->notificationManager->expects($this->atLeastOnce())
|
||||
->method('markProcessed')
|
||||
->with($notification);
|
||||
|
||||
$this->getNotifier()->removePendingNotificationsForRoom($room, true);
|
||||
}
|
||||
|
||||
public static function dataAddMentionAllToList(): array {
|
||||
return [
|
||||
'not notify' => [
|
||||
[],
|
||||
[],
|
||||
0,
|
||||
true,
|
||||
[],
|
||||
],
|
||||
'preserve notify list and do not notify all' => [
|
||||
[
|
||||
['id' => 'user1', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
],
|
||||
[],
|
||||
0,
|
||||
true,
|
||||
[
|
||||
['id' => 'user1', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
],
|
||||
],
|
||||
'mention all' => [
|
||||
[
|
||||
['id' => 'user1', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
['id' => 'all', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
],
|
||||
[
|
||||
Attendee::fromRow(['actor_id' => 'user1', 'actor_type' => Attendee::ACTOR_USERS]),
|
||||
Attendee::fromRow(['actor_id' => 'user2', 'actor_type' => Attendee::ACTOR_USERS]),
|
||||
],
|
||||
0,
|
||||
false,
|
||||
[
|
||||
['id' => 'user1', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
['id' => 'user2', 'type' => Attendee::ACTOR_USERS, 'reason' => 'all'],
|
||||
],
|
||||
],
|
||||
'prevent non-moderator to notify all' => [
|
||||
[
|
||||
['id' => 'user1', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
['id' => 'all', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
],
|
||||
[
|
||||
Attendee::fromRow(['actor_id' => 'user1', 'actor_type' => Attendee::ACTOR_USERS]),
|
||||
Attendee::fromRow(['actor_id' => 'user2', 'actor_type' => Attendee::ACTOR_USERS]),
|
||||
],
|
||||
1,
|
||||
false,
|
||||
[
|
||||
['id' => 'user1', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataAddMentionAllToList')]
|
||||
public function testAddMentionAllToList(array $usersToNotify, array $participants, int $mentionPermissions, bool $moderatorPermissions, array $return): void {
|
||||
$room = $this->createMock(Room::class);
|
||||
$room->method('getMentionPermissions')
|
||||
->willReturn($mentionPermissions);
|
||||
|
||||
$this->participantService
|
||||
->method('getActorsByType')
|
||||
->willReturn($participants);
|
||||
|
||||
$participant = $this->createMock(Participant::class);
|
||||
$participant->method('hasModeratorPermissions')
|
||||
->willReturn($moderatorPermissions);
|
||||
|
||||
$actual = self::invokePrivate($this->getNotifier(), 'addMentionAllToList', [$room, $usersToNotify, $participant]);
|
||||
$this->assertCount(count($return), $actual);
|
||||
foreach ($actual as $key => $value) {
|
||||
$this->assertIsArray($value);
|
||||
if (array_key_exists('attendee', $value)) {
|
||||
$this->assertInstanceOf(Attendee::class, $value['attendee']);
|
||||
unset($value['attendee']);
|
||||
}
|
||||
$this->assertEqualsCanonicalizing($return[$key], $value);
|
||||
}
|
||||
}
|
||||
|
||||
public static function dataNotifyReacted(): array {
|
||||
return [
|
||||
'author react to own message'
|
||||
=> [0, Participant::NOTIFY_MENTION, Room::TYPE_GROUP, 'testUser'],
|
||||
'notify never'
|
||||
=> [0, Participant::NOTIFY_NEVER, Room::TYPE_GROUP, 'testUser2'],
|
||||
'notify default, not one to one'
|
||||
=> [0, Participant::NOTIFY_DEFAULT, Room::TYPE_GROUP, 'testUser2'],
|
||||
'notify default, one to one'
|
||||
=> [1, Participant::NOTIFY_DEFAULT, Room::TYPE_ONE_TO_ONE, 'testUser2'],
|
||||
'notify always'
|
||||
=> [1, Participant::NOTIFY_ALWAYS, Room::TYPE_GROUP, 'testUser2'],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataNotifyReacted')]
|
||||
public function testNotifyReacted(int $notify, int $notifyType, int $roomType, string $authorId): void {
|
||||
$this->notificationManager->expects($this->exactly($notify))
|
||||
->method('notify');
|
||||
|
||||
$room = $this->getRoom([
|
||||
'attendee' => [
|
||||
'testUser' => [
|
||||
'notificationLevel' => $notifyType,
|
||||
]
|
||||
]
|
||||
]);
|
||||
$room->method('getType')
|
||||
->willReturn($roomType);
|
||||
$comment = $this->newComment('108', 'users', 'testUser', new \DateTime('@' . 1000000016), 'message');
|
||||
$reaction = $this->newComment('108', 'users', $authorId, new \DateTime('@' . 1000000016), 'message');
|
||||
|
||||
$notifier = $this->getNotifier([]);
|
||||
$notifier->notifyReacted($room, $comment, $reaction);
|
||||
}
|
||||
|
||||
public static function dataGetMentionedUsers(): array {
|
||||
return [
|
||||
'mention one user' => [
|
||||
'Mention @anotherUser',
|
||||
[
|
||||
['id' => 'anotherUser', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
],
|
||||
],
|
||||
'mention two user' => [
|
||||
'Mention @anotherUser, and @unknownUser',
|
||||
[
|
||||
['id' => 'anotherUser', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
['id' => 'unknownUser', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
],
|
||||
],
|
||||
'mention all' => [
|
||||
'Mention @all',
|
||||
[
|
||||
['id' => 'all', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
],
|
||||
],
|
||||
'mention user, all, guest and group' => [
|
||||
'mention @test, @all, @"guest/1" @"group/1"',
|
||||
[
|
||||
['id' => 'test', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
['id' => 'all', 'type' => Attendee::ACTOR_USERS, 'reason' => 'direct'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataGetMentionedUsers')]
|
||||
public function testGetMentionedUsers(string $message, array $expectedReturn): void {
|
||||
$comment = $this->newComment('108', 'users', 'testUser', new \DateTime('@' . 1000000016), $message);
|
||||
$actual = self::invokePrivate($this->getNotifier(), 'getMentionedUsers', [$comment]);
|
||||
$this->assertEqualsCanonicalizing($expectedReturn, $actual);
|
||||
}
|
||||
|
||||
public static function dataGetMentionedUserIds(): array {
|
||||
$return = self::dataGetMentionedUsers();
|
||||
array_walk($return, function (array &$scenario) {
|
||||
array_walk($scenario[1], function (array &$params): void {
|
||||
$params = $params['id'];
|
||||
});
|
||||
return $scenario;
|
||||
});
|
||||
return $return;
|
||||
}
|
||||
|
||||
#[DataProvider('dataGetMentionedUserIds')]
|
||||
public function testGetMentionedUserIds(string $message, array $expectedReturn): void {
|
||||
$comment = $this->newComment('108', 'users', 'testUser', new \DateTime('@' . 1000000016), $message);
|
||||
$actual = self::invokePrivate($this->getNotifier(), 'getMentionedUserIds', [$comment]);
|
||||
$this->assertEqualsCanonicalizing($expectedReturn, $actual);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,618 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Talk\Tests\php\Chat\Parser;
|
||||
|
||||
use OCA\Talk\Chat\Parser\UserMention;
|
||||
use OCA\Talk\Exceptions\ParticipantNotFoundException;
|
||||
use OCA\Talk\GuestManager;
|
||||
use OCA\Talk\Model\Attendee;
|
||||
use OCA\Talk\Model\Message;
|
||||
use OCA\Talk\Participant;
|
||||
use OCA\Talk\Room;
|
||||
use OCA\Talk\Service\AvatarService;
|
||||
use OCA\Talk\Service\ParticipantService;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Comments\IComment;
|
||||
use OCP\Comments\ICommentsManager;
|
||||
use OCP\Federation\ICloudId;
|
||||
use OCP\Federation\ICloudIdManager;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\IUserManager;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Test\TestCase;
|
||||
|
||||
class UserMentionTest extends TestCase {
|
||||
protected IAppManager&MockObject $appManager;
|
||||
protected ICommentsManager&MockObject $commentsManager;
|
||||
protected IUserManager&MockObject $userManager;
|
||||
protected IGroupManager&MockObject $groupManager;
|
||||
protected GuestManager&MockObject $guestManager;
|
||||
protected AvatarService&MockObject $avatarService;
|
||||
protected ICloudIdManager&MockObject $cloudIdManager;
|
||||
protected ParticipantService&MockObject $participantService;
|
||||
protected IL10N&MockObject $l;
|
||||
|
||||
protected ?UserMention $parser = null;
|
||||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->appManager = $this->createMock(IAppManager::class);
|
||||
$this->commentsManager = $this->createMock(ICommentsManager::class);
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
$this->groupManager = $this->createMock(IGroupManager::class);
|
||||
$this->guestManager = $this->createMock(GuestManager::class);
|
||||
$this->avatarService = $this->createMock(AvatarService::class);
|
||||
$this->cloudIdManager = $this->createMock(ICloudIdManager::class);
|
||||
$this->participantService = $this->createMock(ParticipantService::class);
|
||||
$this->l = $this->createMock(IL10N::class);
|
||||
|
||||
$this->parser = new UserMention(
|
||||
$this->appManager,
|
||||
$this->commentsManager,
|
||||
$this->userManager,
|
||||
$this->groupManager,
|
||||
$this->guestManager,
|
||||
$this->avatarService,
|
||||
$this->cloudIdManager,
|
||||
$this->participantService,
|
||||
$this->l,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $mentions
|
||||
* @param array|null $metadata
|
||||
* @return MockObject|IComment
|
||||
*/
|
||||
private function newComment(array $mentions, ?array $metadata = null): IComment {
|
||||
$comment = $this->createMock(IComment::class);
|
||||
|
||||
$comment->method('getMentions')->willReturn($mentions);
|
||||
|
||||
if ($metadata !== null) {
|
||||
$comment->method('getMetaData')->willReturn($metadata);
|
||||
}
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
public function testGetRichMessageWithoutEnrichableReferences(): void {
|
||||
$comment = $this->newComment([]);
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Message without enrichable references', []);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$this->assertEquals('Message without enrichable references', $chatMessage->getMessage());
|
||||
$this->assertEquals([], $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWithSingleMention(): void {
|
||||
$mentions = [
|
||||
['type' => 'user', 'id' => 'testUser'],
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('resolveDisplayName')
|
||||
->with('user', 'testUser')
|
||||
->willReturn('testUser display name');
|
||||
|
||||
$this->userManager->expects($this->once())
|
||||
->method('getDisplayName')
|
||||
->with('testUser')
|
||||
->willReturn('testUser display name');
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention to @testUser', []);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-user1' => [
|
||||
'type' => 'user',
|
||||
'id' => 'testUser',
|
||||
'name' => 'testUser display name',
|
||||
'mention-id' => 'testUser',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-user1}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWithDuplicatedMention(): void {
|
||||
$mentions = [
|
||||
['type' => 'user', 'id' => 'testUser'],
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('resolveDisplayName')
|
||||
->with('user', 'testUser')
|
||||
->willReturn('testUser display name');
|
||||
|
||||
$this->userManager->expects($this->once())
|
||||
->method('getDisplayName')
|
||||
->with('testUser')
|
||||
->willReturn('testUser display name');
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention to @testUser and @testUser again', []);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-user1' => [
|
||||
'type' => 'user',
|
||||
'id' => 'testUser',
|
||||
'name' => 'testUser display name',
|
||||
'mention-id' => 'testUser',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-user1} and {mention-user1} again', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public static function dataGetRichMessageWithMentionsFullyIncludedInOtherMentions(): array {
|
||||
// Based on valid characters from server/lib/private/User/Manager.php
|
||||
return [
|
||||
['testUser', 'testUser1', false],
|
||||
['testUser', 'testUser1', true],
|
||||
['testUser', 'testUser_1', false],
|
||||
['testUser', 'testUser_1', true],
|
||||
['testUser', 'testUser.1', false],
|
||||
['testUser', 'testUser.1', true],
|
||||
['testUser', 'testUser@1', false],
|
||||
['testUser', 'testUser@1', true],
|
||||
['testUser', 'testUser-1', false],
|
||||
['testUser', 'testUser-1', true],
|
||||
['testUser', 'testUser\'1', false],
|
||||
['testUser', 'testUser\'1', true],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataGetRichMessageWithMentionsFullyIncludedInOtherMentions')]
|
||||
public function testGetRichMessageWithMentionsFullyIncludedInOtherMentions(string $baseId, string $longerId, bool $quoted): void {
|
||||
$mentions = [
|
||||
['type' => 'user', 'id' => $baseId],
|
||||
['type' => 'user', 'id' => $longerId],
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
$this->commentsManager->expects($this->exactly(2))
|
||||
->method('resolveDisplayName')
|
||||
->willReturnCallback(function ($type, $id) {
|
||||
return $id . ' display name';
|
||||
});
|
||||
|
||||
$this->userManager->expects($this->exactly(2))
|
||||
->method('getDisplayName')
|
||||
->willReturnMap([
|
||||
[$longerId, $longerId . ' display name'],
|
||||
[$baseId, $baseId . ' display name']
|
||||
]);
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
if ($quoted) {
|
||||
$chatMessage->setMessage('Mention to @"' . $baseId . '" and @"' . $longerId . '"', []);
|
||||
} else {
|
||||
$chatMessage->setMessage('Mention to @' . $baseId . ' and @' . $longerId, []);
|
||||
}
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-user1' => [
|
||||
'type' => 'user',
|
||||
'id' => $longerId,
|
||||
'name' => $longerId . ' display name',
|
||||
'mention-id' => $longerId,
|
||||
],
|
||||
'mention-user2' => [
|
||||
'type' => 'user',
|
||||
'id' => $baseId,
|
||||
'name' => $baseId . ' display name',
|
||||
'mention-id' => $baseId,
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-user2} and {mention-user1}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWithSeveralMentions(): void {
|
||||
$mentions = [
|
||||
['type' => 'user', 'id' => 'testUser1'],
|
||||
['type' => 'user', 'id' => 'testUser2'],
|
||||
['type' => 'user', 'id' => 'testUser3']
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
$this->commentsManager->expects($this->exactly(3))
|
||||
->method('resolveDisplayName')
|
||||
->willReturnMap([
|
||||
['user', 'testUser1', 'testUser1 display name'],
|
||||
['user', 'testUser2', 'testUser2 display name'],
|
||||
['user', 'testUser3', 'testUser3 display name'],
|
||||
]);
|
||||
|
||||
$this->userManager->expects($this->exactly(3))
|
||||
->method('getDisplayName')
|
||||
->willReturnMap([
|
||||
['testUser1', 'testUser1 display name'],
|
||||
['testUser2', 'testUser2 display name'],
|
||||
['testUser3', 'testUser3 display name'],
|
||||
]);
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention to @testUser1, @testUser2, @testUser1 again and @testUser3', []);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-user1' => [
|
||||
'type' => 'user',
|
||||
'id' => 'testUser1',
|
||||
'name' => 'testUser1 display name',
|
||||
'mention-id' => 'testUser1',
|
||||
],
|
||||
'mention-user2' => [
|
||||
'type' => 'user',
|
||||
'id' => 'testUser2',
|
||||
'name' => 'testUser2 display name',
|
||||
'mention-id' => 'testUser2',
|
||||
],
|
||||
'mention-user3' => [
|
||||
'type' => 'user',
|
||||
'id' => 'testUser3',
|
||||
'name' => 'testUser3 display name',
|
||||
'mention-id' => 'testUser3',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-user1}, {mention-user2}, {mention-user1} again and {mention-user3}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWithNonExistingUserMention(): void {
|
||||
$mentions = [
|
||||
['type' => 'user', 'id' => 'me'],
|
||||
['type' => 'user', 'id' => 'testUser'],
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('resolveDisplayName')
|
||||
->with('user', 'testUser')
|
||||
->willReturn('testUser display name');
|
||||
|
||||
$this->userManager->expects($this->exactly(2))
|
||||
->method('getDisplayName')
|
||||
->willReturnMap([
|
||||
['me', null],
|
||||
['testUser', 'testUser display name'],
|
||||
]);
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention @me to @testUser', []);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-user1' => [
|
||||
'type' => 'user',
|
||||
'id' => 'testUser',
|
||||
'name' => 'testUser display name',
|
||||
'mention-id' => 'testUser',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention @me to {mention-user1}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWhenDisplayNameCanNotBeResolved(): void {
|
||||
$mentions = [
|
||||
['type' => 'user', 'id' => 'testUser'],
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
$this->commentsManager->expects($this->once())
|
||||
->method('resolveDisplayName')
|
||||
->willThrowException(new \OutOfBoundsException());
|
||||
|
||||
$this->userManager->expects($this->once())
|
||||
->method('getDisplayName')
|
||||
->with('testUser')
|
||||
->willReturn('existing user but does not resolve later');
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention to @testUser', []);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-user1' => [
|
||||
'type' => 'user',
|
||||
'id' => 'testUser',
|
||||
'name' => '',
|
||||
'mention-id' => 'testUser',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-user1}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWithAtAll(): void {
|
||||
$mentions = [
|
||||
['type' => 'user', 'id' => 'all'],
|
||||
];
|
||||
$metadata = [
|
||||
Message::METADATA_CAN_MENTION_ALL => true,
|
||||
];
|
||||
$comment = $this->newComment($mentions, $metadata);
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
$room->expects($this->once())
|
||||
->method('getType')
|
||||
->willReturn(Room::TYPE_GROUP);
|
||||
$room->expects($this->once())
|
||||
->method('getToken')
|
||||
->willReturn('token');
|
||||
$room->expects($this->once())
|
||||
->method('getDisplayName')
|
||||
->willReturn('name');
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention to @all', []);
|
||||
|
||||
$this->avatarService->method('getAvatarUrl')
|
||||
->with($room)
|
||||
->willReturn('getAvatarUrl');
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-call1' => [
|
||||
'type' => 'call',
|
||||
'id' => 'token',
|
||||
'name' => 'name',
|
||||
'call-type' => 'group',
|
||||
'icon-url' => 'getAvatarUrl',
|
||||
'mention-id' => 'all',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-call1}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWithFederatedUserMention(): void {
|
||||
$mentions = [
|
||||
['type' => 'federated_user', 'id' => 'testUser@example.tld'],
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention to @"federated_user/testUser@example.tld"', []);
|
||||
|
||||
$cloudId = $this->createMock(ICloudId::class);
|
||||
$cloudId->method('getUser')
|
||||
->willReturn('testUser');
|
||||
$cloudId->method('getRemote')
|
||||
->willReturn('example.tld');
|
||||
$cloudId->method('getDisplayId')
|
||||
->willReturn('Display Id');
|
||||
$this->cloudIdManager->method('resolveCloudId')
|
||||
->with('testUser@example.tld')
|
||||
->willReturn($cloudId);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-federated-user1' => [
|
||||
'type' => 'user',
|
||||
'id' => 'testUser',
|
||||
'name' => 'Display Id',
|
||||
'server' => 'example.tld',
|
||||
'mention-id' => 'federated_user/testUser@example.tld',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-federated-user1}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWhenAGuestWithoutNameIsMentioned(): void {
|
||||
$mentions = [
|
||||
['type' => 'guest', 'id' => 'guest/123456'],
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
|
||||
$this->participantService->method('getParticipantByActor')
|
||||
->with($room, Attendee::ACTOR_GUESTS, '123456')
|
||||
->willThrowException(new ParticipantNotFoundException());
|
||||
$this->l->expects($this->any())
|
||||
->method('t')
|
||||
->willReturnCallback(function ($text, $parameters = []) {
|
||||
return vsprintf($text, $parameters);
|
||||
});
|
||||
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention to @"guest/123456"', []);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-guest1' => [
|
||||
'type' => 'guest',
|
||||
'id' => 'guest/123456',
|
||||
'name' => 'Guest',
|
||||
'mention-id' => 'guest/123456',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-guest1}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWhenAGuestWithoutNameIsMentionedMultipleTimes(): void {
|
||||
$mentions = [
|
||||
['type' => 'guest', 'id' => 'guest/123456'],
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
|
||||
$this->participantService->method('getParticipantByActor')
|
||||
->with($room, Attendee::ACTOR_GUESTS, '123456')
|
||||
->willThrowException(new ParticipantNotFoundException());
|
||||
$this->l->expects($this->any())
|
||||
->method('t')
|
||||
->willReturnCallback(function ($text, $parameters = []) {
|
||||
return vsprintf($text, $parameters);
|
||||
});
|
||||
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention to @"guest/123456", and again @"guest/123456"', []);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-guest1' => [
|
||||
'type' => 'guest',
|
||||
'id' => 'guest/123456',
|
||||
'name' => 'Guest',
|
||||
'mention-id' => 'guest/123456',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-guest1}, and again {mention-guest1}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
|
||||
public function testGetRichMessageWhenAGuestWithANameIsMentionedMultipleTimes(): void {
|
||||
$mentions = [
|
||||
['type' => 'guest', 'id' => 'guest/abcdef'],
|
||||
];
|
||||
$comment = $this->newComment($mentions);
|
||||
|
||||
/** @var Room&MockObject $room */
|
||||
$room = $this->createMock(Room::class);
|
||||
/** @var Participant&MockObject $participant */
|
||||
$participant = $this->createMock(Participant::class);
|
||||
/** @var IL10N&MockObject $l */
|
||||
$l = $this->createMock(IL10N::class);
|
||||
|
||||
$attendee = Attendee::fromRow([
|
||||
'actor_type' => 'guests',
|
||||
'actor_id' => 'abcdef',
|
||||
'display_name' => 'Name',
|
||||
]);
|
||||
$participant->method('getAttendee')
|
||||
->willReturn($attendee);
|
||||
|
||||
$this->participantService->method('getParticipantByActor')
|
||||
->with($room, Attendee::ACTOR_GUESTS, 'abcdef')
|
||||
->willReturn($participant);
|
||||
$this->l->expects($this->any())
|
||||
->method('t')
|
||||
->willReturnCallback(function ($text, $parameters = []) {
|
||||
return vsprintf($text, $parameters);
|
||||
});
|
||||
|
||||
$chatMessage = new Message($room, $participant, $comment, $l);
|
||||
$chatMessage->setMessage('Mention to @"guest/abcdef", and again @"guest/abcdef"', []);
|
||||
|
||||
self::invokePrivate($this->parser, 'parseMessage', [$chatMessage]);
|
||||
|
||||
$expectedMessageParameters = [
|
||||
'mention-guest1' => [
|
||||
'type' => 'guest',
|
||||
'id' => 'guest/abcdef',
|
||||
'name' => 'Name',
|
||||
'mention-id' => 'guest/abcdef',
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals('Mention to {mention-guest1}, and again {mention-guest1}', $chatMessage->getMessage());
|
||||
$this->assertEquals($expectedMessageParameters, $chatMessage->getMessageParameters());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,644 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Talk\Tests\php\Chat\SystemMessage;
|
||||
|
||||
use OCA\Talk\Chat\ChatManager;
|
||||
use OCA\Talk\Chat\MessageParser;
|
||||
use OCA\Talk\Chat\SystemMessage\Listener;
|
||||
use OCA\Talk\Events\AParticipantModifiedEvent;
|
||||
use OCA\Talk\Events\ARoomModifiedEvent;
|
||||
use OCA\Talk\Events\AttendeesAddedEvent;
|
||||
use OCA\Talk\Events\ParticipantModifiedEvent;
|
||||
use OCA\Talk\Events\RoomModifiedEvent;
|
||||
use OCA\Talk\Manager;
|
||||
use OCA\Talk\Model\Attendee;
|
||||
use OCA\Talk\Participant;
|
||||
use OCA\Talk\Room;
|
||||
use OCA\Talk\Service\ParticipantService;
|
||||
use OCA\Talk\Service\ThreadService;
|
||||
use OCA\Talk\TalkSession;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\Comments\IComment;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
use OCP\ISession;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Test\TestCase;
|
||||
|
||||
#[Group('DB')]
|
||||
class ListenerTest extends TestCase {
|
||||
public const DUMMY_REFERENCE_ID = 'DUMMY_REFERENCE_ID';
|
||||
|
||||
protected IRequest&MockObject $request;
|
||||
protected ChatManager&MockObject $chatManager;
|
||||
protected IUserSession&MockObject $userSession;
|
||||
protected ISession&MockObject $session;
|
||||
protected TalkSession&MockObject $talkSession;
|
||||
protected ITimeFactory&MockObject $timeFactory;
|
||||
protected IEventDispatcher&MockObject $eventDispatcher;
|
||||
protected Manager&MockObject $manager;
|
||||
protected ParticipantService&MockObject $participantService;
|
||||
protected MessageParser&MockObject $messageParser;
|
||||
protected ThreadService&MockObject $threadService;
|
||||
protected LoggerInterface&MockObject $logger;
|
||||
protected ?array $handlers = null;
|
||||
protected ?\DateTime $dummyTime = null;
|
||||
protected ?Listener $listener = null;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->request = $this->createMock(IRequest::class);
|
||||
$this->request->expects($this->any())
|
||||
->method('getParam')
|
||||
->with('referenceId')
|
||||
->willReturn(self::DUMMY_REFERENCE_ID);
|
||||
|
||||
$this->dummyTime = new \DateTime();
|
||||
|
||||
$this->chatManager = $this->createMock(ChatManager::class);
|
||||
$this->session = $this->createMock(ISession::class);
|
||||
$this->userSession = $this->createMock(IUserSession::class);
|
||||
$this->talkSession = $this->createMock(TalkSession::class);
|
||||
$this->timeFactory = $this->createMock(ITimeFactory::class);
|
||||
$this->timeFactory->method('getDateTime')->willReturn($this->dummyTime);
|
||||
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
|
||||
$this->manager = $this->createMock(Manager::class);
|
||||
$this->participantService = $this->createMock(ParticipantService::class);
|
||||
$this->messageParser = $this->createMock(MessageParser::class);
|
||||
$this->threadService = $this->createMock(ThreadService::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
$l = $this->createMock(IL10N::class);
|
||||
$l->expects($this->any())
|
||||
->method('t')
|
||||
->willReturnCallback(function ($string, $args) {
|
||||
return vsprintf($string, $args);
|
||||
});
|
||||
|
||||
$this->handlers = [];
|
||||
|
||||
$this->eventDispatcher->method('addListener')
|
||||
->willReturnCallback(function ($eventName, $handler): void {
|
||||
$this->handlers[$eventName] ??= [];
|
||||
$this->handlers[$eventName][] = $handler;
|
||||
});
|
||||
|
||||
$this->listener = new Listener(
|
||||
$this->request,
|
||||
$this->chatManager,
|
||||
$this->talkSession,
|
||||
$this->session,
|
||||
$this->userSession,
|
||||
$this->timeFactory,
|
||||
$this->manager,
|
||||
$this->participantService,
|
||||
$this->messageParser,
|
||||
$this->threadService,
|
||||
$l,
|
||||
$this->logger,
|
||||
);
|
||||
}
|
||||
|
||||
private function dispatch(string $eventName, $event): void {
|
||||
$handlers = $this->handlers[$eventName];
|
||||
$this->assertCount(1, $handlers);
|
||||
|
||||
$handlers[0]($event);
|
||||
}
|
||||
|
||||
private function mockLoggedInUser($userId): IUser {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$user->method('getUID')->willReturn($userId);
|
||||
$this->userSession
|
||||
->method('getUser')
|
||||
->willReturn($user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function testAfterUsersAddOneToOne(): void {
|
||||
$room = $this->createMock(Room::class);
|
||||
$room->expects($this->any())
|
||||
->method('getType')
|
||||
->willReturn(Room::TYPE_ONE_TO_ONE);
|
||||
|
||||
$participants = [[
|
||||
'actorType' => 'users',
|
||||
'actorId' => 'alice_actor',
|
||||
'participantType' => Participant::USER,
|
||||
]];
|
||||
$attendees = array_map(static fn (array $participant) => Attendee::fromParams($participant), $participants);
|
||||
$event = new AttendeesAddedEvent($room, $attendees);
|
||||
|
||||
$this->chatManager->expects($this->never())
|
||||
->method('addSystemMessage');
|
||||
|
||||
self::invokePrivate($this->listener, 'handle', [$event]);
|
||||
}
|
||||
|
||||
public static function dataRoomTypes(): array {
|
||||
$expectedMessages = [
|
||||
[
|
||||
'actorType' => 'users',
|
||||
'actorId' => 'alice_actor',
|
||||
'message' => ['message' => 'user_added', 'parameters' => ['user' => 'alice_actor']],
|
||||
],
|
||||
[
|
||||
'actorType' => 'users',
|
||||
'actorId' => 'alice_actor',
|
||||
'message' => ['message' => 'user_added', 'parameters' => ['user' => 'bob']],
|
||||
],
|
||||
[
|
||||
'actorType' => 'users',
|
||||
'actorId' => 'alice_actor',
|
||||
'message' => ['message' => 'user_added', 'parameters' => ['user' => 'carmen']],
|
||||
],
|
||||
[
|
||||
'actorType' => 'users',
|
||||
'actorId' => 'alice_actor',
|
||||
'message' => ['message' => 'user_added', 'parameters' => ['user' => 'delta']],
|
||||
],
|
||||
];
|
||||
|
||||
$allParticipants = [
|
||||
// guest will be ignored
|
||||
[
|
||||
'actorType' => 'guests'
|
||||
],
|
||||
// alice_actor adding self to listed channel
|
||||
[
|
||||
'actorType' => 'users',
|
||||
'actorId' => 'alice_actor',
|
||||
'participantType' => Participant::USER,
|
||||
],
|
||||
// alice_actor added bob
|
||||
[
|
||||
'actorType' => 'users',
|
||||
'actorId' => 'bob',
|
||||
'participantType' => Participant::USER,
|
||||
],
|
||||
// empty participant type
|
||||
[
|
||||
'actorType' => 'users',
|
||||
'actorId' => 'carmen',
|
||||
],
|
||||
// alice_actor adding self-joined mode
|
||||
[
|
||||
'actorType' => 'users',
|
||||
'actorId' => 'delta',
|
||||
'participantType' => Participant::USER_SELF_JOINED,
|
||||
],
|
||||
];
|
||||
|
||||
return [
|
||||
[Room::TYPE_GROUP, '', $allParticipants, $expectedMessages],
|
||||
[Room::TYPE_PUBLIC, '', $allParticipants, $expectedMessages],
|
||||
[Room::TYPE_ONE_TO_ONE, '', $allParticipants, []],
|
||||
[Room::TYPE_GROUP, 'file', $allParticipants, $expectedMessages],
|
||||
[Room::TYPE_PUBLIC, 'file', $allParticipants, $expectedMessages],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataRoomTypes')]
|
||||
public function testAfterUsersAdd(int $roomType, string $objectType, array $participants, array $expectedMessages): void {
|
||||
$this->mockLoggedInUser('alice_actor');
|
||||
|
||||
$room = $this->createMock(Room::class);
|
||||
$room->method('getType')->willReturn($roomType);
|
||||
$room->method('getObjectType')->willReturn($objectType);
|
||||
|
||||
$attendees = array_map(static fn (array $participant) => Attendee::fromParams($participant), $participants);
|
||||
|
||||
// TODO: add all cases
|
||||
$event = new AttendeesAddedEvent($room, $attendees);
|
||||
|
||||
$consecutive = [];
|
||||
foreach ($expectedMessages as $expectedMessage) {
|
||||
$consecutive[] = [
|
||||
$room,
|
||||
null,
|
||||
$expectedMessage['actorType'],
|
||||
$expectedMessage['actorId'],
|
||||
json_encode($expectedMessage['message']),
|
||||
$this->dummyTime,
|
||||
false,
|
||||
self::DUMMY_REFERENCE_ID,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
];
|
||||
}
|
||||
if (!empty($consecutive)) {
|
||||
$i = 0;
|
||||
$this->chatManager->expects($this->exactly(count($consecutive)))
|
||||
->method('addSystemMessage')
|
||||
->willReturnCallback(function () use ($consecutive, &$i) {
|
||||
$this->assertArrayHasKey($i, $consecutive);
|
||||
$this->assertSame($consecutive[$i], func_get_args());
|
||||
$i++;
|
||||
return $this->createMock(IComment::class);
|
||||
});
|
||||
} else {
|
||||
$this->chatManager->expects($this->never())
|
||||
->method('addSystemMessage');
|
||||
}
|
||||
|
||||
self::invokePrivate($this->listener, 'handle', [$event]);
|
||||
}
|
||||
|
||||
public static function dataParticipantTypeChange(): array {
|
||||
return [
|
||||
[
|
||||
Attendee::ACTOR_GROUPS,
|
||||
Participant::USER,
|
||||
Participant::MODERATOR,
|
||||
[],
|
||||
],
|
||||
[
|
||||
Attendee::ACTOR_USERS,
|
||||
Participant::USER,
|
||||
Participant::MODERATOR,
|
||||
[['message' => 'moderator_promoted', 'parameters' => ['user' => 'bob_participant']]],
|
||||
],
|
||||
[
|
||||
Attendee::ACTOR_USERS,
|
||||
Participant::MODERATOR,
|
||||
Participant::USER,
|
||||
[['message' => 'moderator_demoted', 'parameters' => ['user' => 'bob_participant']]],
|
||||
],
|
||||
[
|
||||
Attendee::ACTOR_GUESTS,
|
||||
Participant::GUEST,
|
||||
Participant::GUEST_MODERATOR,
|
||||
[['message' => 'guest_moderator_promoted', 'parameters' => ['type' => 'guests', 'id' => 'bob_participant']]],
|
||||
],
|
||||
[
|
||||
Attendee::ACTOR_GUESTS,
|
||||
Participant::GUEST_MODERATOR,
|
||||
Participant::GUEST,
|
||||
[['message' => 'guest_moderator_demoted', 'parameters' => ['type' => 'guests', 'id' => 'bob_participant']]],
|
||||
],
|
||||
[
|
||||
Attendee::ACTOR_EMAILS,
|
||||
Participant::GUEST,
|
||||
Participant::GUEST_MODERATOR,
|
||||
[['message' => 'guest_moderator_promoted', 'parameters' => ['type' => 'emails', 'id' => 'bob_participant']]],
|
||||
],
|
||||
[
|
||||
Attendee::ACTOR_EMAILS,
|
||||
Participant::GUEST_MODERATOR,
|
||||
Participant::GUEST,
|
||||
[['message' => 'guest_moderator_demoted', 'parameters' => ['type' => 'emails', 'id' => 'bob_participant']]],
|
||||
],
|
||||
[
|
||||
Attendee::ACTOR_USERS,
|
||||
Participant::USER_SELF_JOINED,
|
||||
Participant::USER,
|
||||
[['message' => 'user_added', 'parameters' => ['user' => 'bob_participant']]],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataParticipantTypeChange')]
|
||||
public function testAfterParticipantTypeSet(string $actorType, int $oldParticipantType, int $newParticipantType, array $expectedMessages): void {
|
||||
$this->mockLoggedInUser('alice_actor');
|
||||
|
||||
$room = $this->createMock(Room::class);
|
||||
$room->method('getType')->willReturn(Room::TYPE_GROUP);
|
||||
|
||||
$attendee = new Attendee();
|
||||
$attendee->setActorId('bob_participant');
|
||||
$attendee->setActorType($actorType);
|
||||
|
||||
$participant = $this->createMock(Participant::class);
|
||||
$participant->method('getAttendee')->willReturn($attendee);
|
||||
|
||||
$event = new ParticipantModifiedEvent($room, $participant, AParticipantModifiedEvent::PROPERTY_TYPE, $newParticipantType, $oldParticipantType);
|
||||
|
||||
foreach ($expectedMessages as $expectedMessage) {
|
||||
$consecutive[] = [
|
||||
$room,
|
||||
null,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice_actor',
|
||||
json_encode($expectedMessage),
|
||||
$this->dummyTime,
|
||||
false,
|
||||
self::DUMMY_REFERENCE_ID,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
];
|
||||
}
|
||||
if (isset($consecutive)) {
|
||||
$i = 0;
|
||||
$this->chatManager->expects($this->exactly(count($consecutive)))
|
||||
->method('addSystemMessage')
|
||||
->willReturnCallback(function () use ($consecutive, &$i) {
|
||||
$this->assertArrayHasKey($i, $consecutive);
|
||||
$this->assertSame($consecutive[$i], func_get_args());
|
||||
$i++;
|
||||
return $this->createMock(IComment::class);
|
||||
});
|
||||
} else {
|
||||
$this->chatManager->expects($this->never())
|
||||
->method('addSystemMessage');
|
||||
}
|
||||
|
||||
self::invokePrivate($this->listener, 'handle', [$event]);
|
||||
}
|
||||
|
||||
public static function dataCallRecordingChange(): array {
|
||||
return [
|
||||
[
|
||||
Room::RECORDING_VIDEO_STARTING,
|
||||
Room::RECORDING_NONE,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_VIDEO_STARTING,
|
||||
Room::RECORDING_NONE,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_VIDEO,
|
||||
Room::RECORDING_VIDEO_STARTING,
|
||||
null,
|
||||
null,
|
||||
['message' => 'recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_VIDEO,
|
||||
Room::RECORDING_VIDEO_STARTING,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
['message' => 'recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_VIDEO,
|
||||
Room::RECORDING_NONE,
|
||||
null,
|
||||
null,
|
||||
['message' => 'recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_VIDEO,
|
||||
Room::RECORDING_NONE,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
['message' => 'recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO_STARTING,
|
||||
Room::RECORDING_NONE,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO_STARTING,
|
||||
Room::RECORDING_NONE,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO,
|
||||
Room::RECORDING_AUDIO_STARTING,
|
||||
null,
|
||||
null,
|
||||
['message' => 'audio_recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO,
|
||||
Room::RECORDING_AUDIO_STARTING,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
['message' => 'audio_recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO,
|
||||
Room::RECORDING_NONE,
|
||||
null,
|
||||
null,
|
||||
['message' => 'audio_recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO,
|
||||
Room::RECORDING_NONE,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
['message' => 'audio_recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_NONE,
|
||||
Room::RECORDING_VIDEO_STARTING,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_NONE,
|
||||
Room::RECORDING_VIDEO_STARTING,
|
||||
Attendee::ACTOR_USERS,
|
||||
'bob',
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_NONE,
|
||||
Room::RECORDING_VIDEO,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_NONE,
|
||||
Room::RECORDING_VIDEO,
|
||||
Attendee::ACTOR_USERS,
|
||||
'bob',
|
||||
['message' => 'recording_stopped', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_NONE,
|
||||
Room::RECORDING_AUDIO_STARTING,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_NONE,
|
||||
Room::RECORDING_AUDIO_STARTING,
|
||||
Attendee::ACTOR_USERS,
|
||||
'bob',
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_NONE,
|
||||
Room::RECORDING_AUDIO,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_NONE,
|
||||
Room::RECORDING_AUDIO,
|
||||
Attendee::ACTOR_USERS,
|
||||
'bob',
|
||||
['message' => 'audio_recording_stopped', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_FAILED,
|
||||
Room::RECORDING_VIDEO_STARTING,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_FAILED,
|
||||
Room::RECORDING_AUDIO_STARTING,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_FAILED,
|
||||
Room::RECORDING_VIDEO,
|
||||
null,
|
||||
null,
|
||||
['message' => 'recording_failed', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_FAILED,
|
||||
Room::RECORDING_AUDIO,
|
||||
null,
|
||||
null,
|
||||
['message' => 'recording_failed', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_VIDEO_STARTING,
|
||||
Room::RECORDING_FAILED,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_VIDEO_STARTING,
|
||||
Room::RECORDING_FAILED,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_VIDEO,
|
||||
Room::RECORDING_FAILED,
|
||||
null,
|
||||
null,
|
||||
['message' => 'recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_VIDEO,
|
||||
Room::RECORDING_FAILED,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
['message' => 'recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO_STARTING,
|
||||
Room::RECORDING_FAILED,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO_STARTING,
|
||||
Room::RECORDING_FAILED,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
null,
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO,
|
||||
Room::RECORDING_FAILED,
|
||||
null,
|
||||
null,
|
||||
['message' => 'audio_recording_started', 'parameters' => []],
|
||||
],
|
||||
[
|
||||
Room::RECORDING_AUDIO,
|
||||
Room::RECORDING_FAILED,
|
||||
Attendee::ACTOR_USERS,
|
||||
'alice',
|
||||
['message' => 'audio_recording_started', 'parameters' => []],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('dataCallRecordingChange')]
|
||||
public function testAfterCallRecordingSet(int $newStatus, int $oldStatus, ?string $actorType, ?string $actorId, ?array $expectedMessage): void {
|
||||
$this->mockLoggedInUser('logged_in_user');
|
||||
|
||||
$room = $this->createMock(Room::class);
|
||||
$room->expects($this->any())
|
||||
->method('getType')
|
||||
->willReturn(Room::TYPE_PUBLIC);
|
||||
|
||||
if ($actorType !== null && $actorId !== null) {
|
||||
$attendee = new Attendee();
|
||||
$attendee->setActorType($actorType);
|
||||
$attendee->setActorId($actorId);
|
||||
|
||||
$participant = $this->createMock(Participant::class);
|
||||
$participant->method('getAttendee')->willReturn($attendee);
|
||||
|
||||
$expectedActorType = $actorType;
|
||||
$expectedActorId = $actorId;
|
||||
} else {
|
||||
$participant = null;
|
||||
|
||||
$expectedActorType = Attendee::ACTOR_USERS;
|
||||
$expectedActorId = 'logged_in_user';
|
||||
}
|
||||
|
||||
$event = new RoomModifiedEvent($room, ARoomModifiedEvent::PROPERTY_CALL_RECORDING, $newStatus, $oldStatus, $participant);
|
||||
|
||||
if ($expectedMessage !== null) {
|
||||
$this->chatManager->expects($this->once())
|
||||
->method('addSystemMessage')
|
||||
->with(
|
||||
$room,
|
||||
$participant,
|
||||
$expectedActorType,
|
||||
$expectedActorId,
|
||||
json_encode($expectedMessage),
|
||||
$this->dummyTime,
|
||||
false,
|
||||
self::DUMMY_REFERENCE_ID,
|
||||
null,
|
||||
false
|
||||
);
|
||||
} else {
|
||||
$this->chatManager->expects($this->never())
|
||||
->method('addSystemMessage');
|
||||
}
|
||||
|
||||
self::invokePrivate($this->listener, 'handle', [$event]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user