You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

588 lines
17 KiB

  1. <?php
  2. /**
  3. *
  4. * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com)
  5. *
  6. * @license GNU AGPL version 3 or any later version
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License as
  10. * published by the Free Software Foundation, either version 3 of the
  11. * License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. namespace OCA\Talk\Tests\php\Chat;
  23. use OCA\Talk\Chat\Notifier;
  24. use OCA\Talk\Exceptions\ParticipantNotFoundException;
  25. use OCA\Talk\Files\Util;
  26. use OCA\Talk\Manager;
  27. use OCA\Talk\Participant;
  28. use OCA\Talk\Room;
  29. use OCA\Talk\Service\ParticipantService;
  30. use OCP\Comments\IComment;
  31. use OCP\IConfig;
  32. use OCP\Notification\IManager as INotificationManager;
  33. use OCP\Notification\INotification;
  34. use OCP\IUserManager;
  35. use PHPUnit\Framework\MockObject\MockObject;
  36. use Test\TestCase;
  37. class NotifierTest extends TestCase {
  38. /** @var INotificationManager|MockObject */
  39. protected $notificationManager;
  40. /** @var IUserManager|MockObject */
  41. protected $userManager;
  42. /** @var ParticipantService|MockObject */
  43. protected $participantService;
  44. /** @var Manager|MockObject */
  45. protected $manager;
  46. /** @var IConfig|MockObject */
  47. protected $config;
  48. /** @var Util|MockObject */
  49. protected $util;
  50. /** @var Notifier */
  51. protected $notifier;
  52. public function setUp(): void {
  53. parent::setUp();
  54. $this->notificationManager = $this->createMock(INotificationManager::class);
  55. $this->userManager = $this->createMock(IUserManager::class);
  56. $this->userManager
  57. ->method('userExists')
  58. ->willReturnCallback(function ($userId) {
  59. return $userId !== 'unknownUser';
  60. });
  61. $this->participantService = $this->createMock(ParticipantService::class);
  62. $this->manager = $this->createMock(Manager::class);
  63. $this->config = $this->createMock(IConfig::class);
  64. $this->util = $this->createMock(Util::class);
  65. $this->notifier = new Notifier(
  66. $this->notificationManager,
  67. $this->userManager,
  68. $this->participantService,
  69. $this->manager,
  70. $this->config,
  71. $this->util
  72. );
  73. }
  74. private function newComment($id, $actorType, $actorId, $creationDateTime, $message): IComment {
  75. // $mentionMatches[0] contains the whole matches, while
  76. // $mentionMatches[1] contains the matched subpattern.
  77. $mentionMatches = [];
  78. preg_match_all('/@([a-zA-Z0-9]+)/', $message, $mentionMatches);
  79. $mentions = array_map(function ($mentionMatch) {
  80. return [ 'type' => 'user', 'id' => $mentionMatch ];
  81. }, $mentionMatches[1]);
  82. $comment = $this->createMock(IComment::class);
  83. $comment->method('getId')->willReturn($id);
  84. $comment->method('getObjectId')->willReturn(1234);
  85. $comment->method('getActorType')->willReturn($actorType);
  86. $comment->method('getActorId')->willReturn($actorId);
  87. $comment->method('getCreationDateTime')->willReturn($creationDateTime);
  88. $comment->method('getMessage')->willReturn($message);
  89. $comment->method('getMentions')->willReturn($mentions);
  90. $comment->method('getVerb')->willReturn('comment');
  91. return $comment;
  92. }
  93. private function newNotification($room, IComment $comment): INotification {
  94. $notification = $this->createMock(INotification::class);
  95. $notification->expects($this->once())
  96. ->method('setApp')
  97. ->with('spreed')
  98. ->willReturnSelf();
  99. $notification->expects($this->once())
  100. ->method('setObject')
  101. ->with('chat', $room->getToken())
  102. ->willReturnSelf();
  103. $notification->expects($this->once())
  104. ->method('setSubject')
  105. ->with('mention', [
  106. 'userType' => $comment->getActorType(),
  107. 'userId' => $comment->getActorId(),
  108. ])
  109. ->willReturnSelf();
  110. $notification->expects($this->once())
  111. ->method('setMessage')
  112. ->willReturnSelf();
  113. $notification->expects($this->once())
  114. ->method('setDateTime')
  115. ->with($comment->getCreationDateTime())
  116. ->willReturnSelf();
  117. return $notification;
  118. }
  119. public function testNotifyMentionedUsers(): void {
  120. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'Mention @anotherUser');
  121. $room = $this->createMock(Room::class);
  122. $room->expects($this->any())
  123. ->method('getToken')
  124. ->willReturn('Token123');
  125. $notification = $this->newNotification($room, $comment);
  126. $this->notificationManager->expects($this->once())
  127. ->method('createNotification')
  128. ->willReturn($notification);
  129. $notification->expects($this->once())
  130. ->method('setUser')
  131. ->with('anotherUser')
  132. ->willReturnSelf();
  133. $notification->expects($this->once())
  134. ->method('setMessage')
  135. ->with('comment')
  136. ->willReturnSelf();
  137. $this->manager->expects($this->once())
  138. ->method('getRoomById')
  139. ->with(1234)
  140. ->willReturn($room);
  141. $participant = $this->createMock(Participant::class);
  142. $room->expects($this->once())
  143. ->method('getParticipant')
  144. ->with('anotherUser')
  145. ->willReturn($participant);
  146. $this->notificationManager->expects($this->once())
  147. ->method('notify')
  148. ->with($notification);
  149. $this->notifier->notifyMentionedUsers($room, $comment, []);
  150. }
  151. public function testNotNotifyMentionedUserIfReplyToAuthor(): void {
  152. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'Mention @anotherUser');
  153. $room = $this->createMock(Room::class);
  154. $room->expects($this->any())
  155. ->method('getToken')
  156. ->willReturn('Token123');
  157. $notification = $this->newNotification($room, $comment);
  158. $this->notificationManager->expects($this->once())
  159. ->method('createNotification')
  160. ->willReturn($notification);
  161. $notification->expects($this->never())
  162. ->method('setUser');
  163. $notification->expects($this->once())
  164. ->method('setMessage')
  165. ->with('comment')
  166. ->willReturnSelf();
  167. $this->notificationManager->expects($this->never())
  168. ->method('notify');
  169. $this->notifier->notifyMentionedUsers($room, $comment, ['anotherUser']);
  170. }
  171. public function testNotifyMentionedUsersByGuest(): void {
  172. $comment = $this->newComment(108, 'guests', 'testSpreedSession', new \DateTime('@' . 1000000016), 'Mention @anotherUser');
  173. $room = $this->createMock(Room::class);
  174. $room->expects($this->any())
  175. ->method('getToken')
  176. ->willReturn('Token123');
  177. $notification = $this->newNotification($room, $comment);
  178. $this->notificationManager->expects($this->once())
  179. ->method('createNotification')
  180. ->willReturn($notification);
  181. $notification->expects($this->once())
  182. ->method('setUser')
  183. ->with('anotherUser')
  184. ->willReturnSelf();
  185. $notification->expects($this->once())
  186. ->method('setMessage')
  187. ->with('comment')
  188. ->willReturnSelf();
  189. $this->manager->expects($this->once())
  190. ->method('getRoomById')
  191. ->with(1234)
  192. ->willReturn($room);
  193. $participant = $this->createMock(Participant::class);
  194. $room->expects($this->once())
  195. ->method('getParticipant')
  196. ->with('anotherUser')
  197. ->willReturn($participant);
  198. $this->notificationManager->expects($this->once())
  199. ->method('notify')
  200. ->with($notification);
  201. $this->notifier->notifyMentionedUsers($room, $comment, []);
  202. }
  203. public function testNotifyMentionedUsersWithLongMessageStartMention(): void {
  204. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016),
  205. '123456789 @anotherUserWithOddLengthName 123456789-123456789-123456789-123456789-123456789-123456789');
  206. $room = $this->createMock(Room::class);
  207. $room->expects($this->any())
  208. ->method('getToken')
  209. ->willReturn('Token123');
  210. $notification = $this->newNotification($room, $comment);
  211. $this->notificationManager->expects($this->once())
  212. ->method('createNotification')
  213. ->willReturn($notification);
  214. $notification->expects($this->once())
  215. ->method('setUser')
  216. ->with('anotherUserWithOddLengthName')
  217. ->willReturnSelf();
  218. $notification->expects($this->once())
  219. ->method('setMessage')
  220. ->with('comment')
  221. ->willReturnSelf();
  222. $this->manager->expects($this->once())
  223. ->method('getRoomById')
  224. ->with(1234)
  225. ->willReturn($room);
  226. $participant = $this->createMock(Participant::class);
  227. $room->expects($this->once())
  228. ->method('getParticipant')
  229. ->with('anotherUserWithOddLengthName')
  230. ->willReturn($participant);
  231. $this->notificationManager->expects($this->once())
  232. ->method('notify')
  233. ->with($notification);
  234. $this->notifier->notifyMentionedUsers($room, $comment, []);
  235. }
  236. public function testNotifyMentionedUsersWithLongMessageMiddleMention(): void {
  237. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016),
  238. '123456789-123456789-123456789-1234 @anotherUserWithOddLengthName 6789-123456789-123456789-123456789');
  239. $room = $this->createMock(Room::class);
  240. $room->expects($this->any())
  241. ->method('getToken')
  242. ->willReturn('Token123');
  243. $notification = $this->newNotification($room, $comment);
  244. $this->notificationManager->expects($this->once())
  245. ->method('createNotification')
  246. ->willReturn($notification);
  247. $notification->expects($this->once())
  248. ->method('setUser')
  249. ->with('anotherUserWithOddLengthName')
  250. ->willReturnSelf();
  251. $notification->expects($this->once())
  252. ->method('setMessage')
  253. ->with('comment')
  254. ->willReturnSelf();
  255. $this->manager->expects($this->once())
  256. ->method('getRoomById')
  257. ->with(1234)
  258. ->willReturn($room);
  259. $participant = $this->createMock(Participant::class);
  260. $room->expects($this->once())
  261. ->method('getParticipant')
  262. ->with('anotherUserWithOddLengthName')
  263. ->willReturn($participant);
  264. $this->notificationManager->expects($this->once())
  265. ->method('notify')
  266. ->with($notification);
  267. $this->notifier->notifyMentionedUsers($room, $comment, []);
  268. }
  269. public function testNotifyMentionedUsersWithLongMessageEndMention(): void {
  270. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016),
  271. '123456789-123456789-123456789-123456789-123456789-123456789 @anotherUserWithOddLengthName 123456789');
  272. $room = $this->createMock(Room::class);
  273. $room->expects($this->any())
  274. ->method('getToken')
  275. ->willReturn('Token123');
  276. $notification = $this->newNotification($room, $comment);
  277. $this->notificationManager->expects($this->once())
  278. ->method('createNotification')
  279. ->willReturn($notification);
  280. $notification->expects($this->once())
  281. ->method('setUser')
  282. ->with('anotherUserWithOddLengthName')
  283. ->willReturnSelf();
  284. $notification->expects($this->once())
  285. ->method('setMessage')
  286. ->with('comment')
  287. ->willReturnSelf();
  288. $this->manager->expects($this->once())
  289. ->method('getRoomById')
  290. ->with(1234)
  291. ->willReturn($room);
  292. $participant = $this->createMock(Participant::class);
  293. $room->expects($this->once())
  294. ->method('getParticipant')
  295. ->with('anotherUserWithOddLengthName')
  296. ->willReturn($participant);
  297. $this->notificationManager->expects($this->once())
  298. ->method('notify')
  299. ->with($notification);
  300. $this->notifier->notifyMentionedUsers($room, $comment, []);
  301. }
  302. public function testNotifyMentionedUsersToSelf(): void {
  303. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'Mention @testUser');
  304. $room = $this->createMock(Room::class);
  305. $room->expects($this->any())
  306. ->method('getToken')
  307. ->willReturn('Token123');
  308. $notification = $this->newNotification($room, $comment);
  309. $this->notificationManager->expects($this->once())
  310. ->method('createNotification')
  311. ->willReturn($notification);
  312. $this->notificationManager->expects($this->never())
  313. ->method('notify');
  314. $this->notifier->notifyMentionedUsers($room, $comment, []);
  315. }
  316. public function testNotifyMentionedUsersToUnknownUser(): void {
  317. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'Mention @unknownUser');
  318. $room = $this->createMock(Room::class);
  319. $room->expects($this->any())
  320. ->method('getToken')
  321. ->willReturn('Token123');
  322. $notification = $this->newNotification($room, $comment);
  323. $this->notificationManager->expects($this->once())
  324. ->method('createNotification')
  325. ->willReturn($notification);
  326. $this->notificationManager->expects($this->never())
  327. ->method('notify');
  328. $this->notifier->notifyMentionedUsers($room, $comment, []);
  329. }
  330. public function testNotifyMentionedUsersToUserNotInvitedToChat(): void {
  331. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'Mention @userNotInOneToOneChat');
  332. $room = $this->createMock(Room::class);
  333. $room->expects($this->any())
  334. ->method('getToken')
  335. ->willReturn('Token123');
  336. $room = $this->createMock(Room::class);
  337. $this->manager->expects($this->once())
  338. ->method('getRoomById')
  339. ->with(1234)
  340. ->willReturn($room);
  341. $room->expects($this->once())
  342. ->method('getParticipant')
  343. ->with('userNotInOneToOneChat')
  344. ->will($this->throwException(new ParticipantNotFoundException()));
  345. $notification = $this->newNotification($room, $comment);
  346. $this->notificationManager->expects($this->once())
  347. ->method('createNotification')
  348. ->willReturn($notification);
  349. $this->notificationManager->expects($this->never())
  350. ->method('notify');
  351. $this->notifier->notifyMentionedUsers($room, $comment, []);
  352. }
  353. public function testNotifyMentionedUsersNoMentions(): void {
  354. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'No mentions');
  355. $room = $this->createMock(Room::class);
  356. $room->expects($this->any())
  357. ->method('getToken')
  358. ->willReturn('Token123');
  359. $this->notificationManager->expects($this->never())
  360. ->method('createNotification');
  361. $this->notificationManager->expects($this->never())
  362. ->method('notify');
  363. $this->notifier->notifyMentionedUsers($room, $comment, []);
  364. }
  365. public function testNotifyMentionedUsersSeveralMentions(): void {
  366. $comment = $this->newComment(108, 'users', 'testUser', new \DateTime('@' . 1000000016), 'Mention @anotherUser, and @unknownUser, and @testUser, and @userAbleToJoin');
  367. $room = $this->createMock(Room::class);
  368. $room->expects($this->any())
  369. ->method('getToken')
  370. ->willReturn('Token123');
  371. $notification = $this->newNotification($room, $comment);
  372. $this->notificationManager->expects($this->once())
  373. ->method('createNotification')
  374. ->willReturn($notification);
  375. $notification->expects($this->once())
  376. ->method('setMessage')
  377. ->with('comment')
  378. ->willReturnSelf();
  379. $notification->expects($this->exactly(2))
  380. ->method('setUser')
  381. ->withConsecutive(
  382. [ 'anotherUser' ],
  383. [ 'userAbleToJoin' ]
  384. )
  385. ->willReturnSelf();
  386. $this->manager->expects($this->exactly(2))
  387. ->method('getRoomById')
  388. ->with(1234)
  389. ->willReturn($room);
  390. $participant = $this->createMock(Participant::class);
  391. $room->expects($this->exactly(2))
  392. ->method('getParticipant')
  393. ->withConsecutive(['anotherUser'], ['userAbleToJoin'])
  394. ->willReturn($participant);
  395. $this->notificationManager->expects($this->exactly(2))
  396. ->method('notify')
  397. ->withConsecutive(
  398. [ $notification ],
  399. [ $notification ]
  400. );
  401. $this->notifier->notifyMentionedUsers($room, $comment, []);
  402. }
  403. public function testRemovePendingNotificationsForRoom(): void {
  404. $notification = $this->createMock(INotification::class);
  405. $room = $this->createMock(Room::class);
  406. $room->expects($this->any())
  407. ->method('getToken')
  408. ->willReturn('Token123');
  409. $this->notificationManager->expects($this->once())
  410. ->method('createNotification')
  411. ->willReturn($notification);
  412. $notification->expects($this->once())
  413. ->method('setApp')
  414. ->with('spreed')
  415. ->willReturnSelf();
  416. $notification->expects($this->exactly(3))
  417. ->method('setObject')
  418. ->withConsecutive(
  419. ['chat', 'Token123'],
  420. ['room', 'Token123'],
  421. ['call', 'Token123']
  422. )
  423. ->willReturnSelf();
  424. $this->notificationManager->expects($this->exactly(3))
  425. ->method('markProcessed')
  426. ->with($notification);
  427. $this->notifier->removePendingNotificationsForRoom($room);
  428. }
  429. public function testRemovePendingNotificationsForChatOnly(): void {
  430. $notification = $this->createMock(INotification::class);
  431. $room = $this->createMock(Room::class);
  432. $room->expects($this->any())
  433. ->method('getToken')
  434. ->willReturn('Token123');
  435. $this->notificationManager->expects($this->once())
  436. ->method('createNotification')
  437. ->willReturn($notification);
  438. $notification->expects($this->once())
  439. ->method('setApp')
  440. ->with('spreed')
  441. ->willReturnSelf();
  442. $notification->expects($this->exactly(1))
  443. ->method('setObject')
  444. ->with('chat', 'Token123')
  445. ->willReturnSelf();
  446. $this->notificationManager->expects($this->exactly(1))
  447. ->method('markProcessed')
  448. ->with($notification);
  449. $this->notifier->removePendingNotificationsForRoom($room, true);
  450. }
  451. }