CommentsNodeTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Joas Schilling <coding@schilljs.com>
  7. * @author Morris Jobke <hey@morrisjobke.de>
  8. * @author Roeland Jago Douma <roeland@famdouma.nl>
  9. * @author Vincent Petry <pvince81@owncloud.com>
  10. *
  11. * @license AGPL-3.0
  12. *
  13. * This code is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU Affero General Public License, version 3,
  15. * as published by the Free Software Foundation.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU Affero General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Affero General Public License, version 3,
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>
  24. *
  25. */
  26. namespace OCA\DAV\Tests\unit\Comments;
  27. use OCA\DAV\Comments\CommentNode;
  28. use OCP\Comments\IComment;
  29. use OCP\Comments\ICommentsManager;
  30. use OCP\Comments\MessageTooLongException;
  31. use OCP\ILogger;
  32. use OCP\IUser;
  33. use OCP\IUserManager;
  34. use OCP\IUserSession;
  35. use Sabre\DAV\PropPatch;
  36. class CommentsNodeTest extends \Test\TestCase {
  37. /** @var ICommentsManager|\PHPUnit_Framework_MockObject_MockObject */
  38. protected $commentsManager;
  39. protected $comment;
  40. protected $node;
  41. protected $userManager;
  42. protected $logger;
  43. protected $userSession;
  44. protected function setUp(): void {
  45. parent::setUp();
  46. $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
  47. ->disableOriginalConstructor()
  48. ->getMock();
  49. $this->comment = $this->getMockBuilder(IComment::class)
  50. ->disableOriginalConstructor()
  51. ->getMock();
  52. $this->userManager = $this->getMockBuilder(IUserManager::class)
  53. ->disableOriginalConstructor()
  54. ->getMock();
  55. $this->userSession = $this->getMockBuilder(IUserSession::class)
  56. ->disableOriginalConstructor()
  57. ->getMock();
  58. $this->logger = $this->getMockBuilder(ILogger::class)
  59. ->disableOriginalConstructor()
  60. ->getMock();
  61. $this->node = new CommentNode(
  62. $this->commentsManager,
  63. $this->comment,
  64. $this->userManager,
  65. $this->userSession,
  66. $this->logger
  67. );
  68. }
  69. public function testDelete() {
  70. $user = $this->getMockBuilder(IUser::class)
  71. ->disableOriginalConstructor()
  72. ->getMock();
  73. $user->expects($this->once())
  74. ->method('getUID')
  75. ->will($this->returnValue('alice'));
  76. $this->userSession->expects($this->once())
  77. ->method('getUser')
  78. ->will($this->returnValue($user));
  79. $this->comment->expects($this->once())
  80. ->method('getId')
  81. ->will($this->returnValue('19'));
  82. $this->comment->expects($this->any())
  83. ->method('getActorType')
  84. ->will($this->returnValue('users'));
  85. $this->comment->expects($this->any())
  86. ->method('getActorId')
  87. ->will($this->returnValue('alice'));
  88. $this->commentsManager->expects($this->once())
  89. ->method('delete')
  90. ->with('19');
  91. $this->node->delete();
  92. }
  93. public function testDeleteForbidden() {
  94. $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
  95. $user = $this->getMockBuilder(IUser::class)
  96. ->disableOriginalConstructor()
  97. ->getMock();
  98. $user->expects($this->once())
  99. ->method('getUID')
  100. ->will($this->returnValue('mallory'));
  101. $this->userSession->expects($this->once())
  102. ->method('getUser')
  103. ->will($this->returnValue($user));
  104. $this->comment->expects($this->never())
  105. ->method('getId');
  106. $this->comment->expects($this->any())
  107. ->method('getActorType')
  108. ->will($this->returnValue('users'));
  109. $this->comment->expects($this->any())
  110. ->method('getActorId')
  111. ->will($this->returnValue('alice'));
  112. $this->commentsManager->expects($this->never())
  113. ->method('delete');
  114. $this->node->delete();
  115. }
  116. public function testGetName() {
  117. $id = '19';
  118. $this->comment->expects($this->once())
  119. ->method('getId')
  120. ->will($this->returnValue($id));
  121. $this->assertSame($this->node->getName(), $id);
  122. }
  123. public function testSetName() {
  124. $this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
  125. $this->node->setName('666');
  126. }
  127. public function testGetLastModified() {
  128. $this->assertSame($this->node->getLastModified(), null);
  129. }
  130. public function testUpdateComment() {
  131. $msg = 'Hello Earth';
  132. $user = $this->getMockBuilder(IUser::class)
  133. ->disableOriginalConstructor()
  134. ->getMock();
  135. $user->expects($this->once())
  136. ->method('getUID')
  137. ->will($this->returnValue('alice'));
  138. $this->userSession->expects($this->once())
  139. ->method('getUser')
  140. ->will($this->returnValue($user));
  141. $this->comment->expects($this->once())
  142. ->method('setMessage')
  143. ->with($msg);
  144. $this->comment->expects($this->any())
  145. ->method('getActorType')
  146. ->will($this->returnValue('users'));
  147. $this->comment->expects($this->any())
  148. ->method('getActorId')
  149. ->will($this->returnValue('alice'));
  150. $this->commentsManager->expects($this->once())
  151. ->method('save')
  152. ->with($this->comment);
  153. $this->assertTrue($this->node->updateComment($msg));
  154. }
  155. public function testUpdateCommentLogException() {
  156. $this->expectException(\Exception::class);
  157. $this->expectExceptionMessage('buh!');
  158. $msg = null;
  159. $user = $this->getMockBuilder(IUser::class)
  160. ->disableOriginalConstructor()
  161. ->getMock();
  162. $user->expects($this->once())
  163. ->method('getUID')
  164. ->will($this->returnValue('alice'));
  165. $this->userSession->expects($this->once())
  166. ->method('getUser')
  167. ->will($this->returnValue($user));
  168. $this->comment->expects($this->once())
  169. ->method('setMessage')
  170. ->with($msg)
  171. ->will($this->throwException(new \Exception('buh!')));
  172. $this->comment->expects($this->any())
  173. ->method('getActorType')
  174. ->will($this->returnValue('users'));
  175. $this->comment->expects($this->any())
  176. ->method('getActorId')
  177. ->will($this->returnValue('alice'));
  178. $this->commentsManager->expects($this->never())
  179. ->method('save');
  180. $this->logger->expects($this->once())
  181. ->method('logException');
  182. $this->node->updateComment($msg);
  183. }
  184. public function testUpdateCommentMessageTooLongException() {
  185. $this->expectException(\Sabre\DAV\Exception\BadRequest::class);
  186. $this->expectExceptionMessage('Message exceeds allowed character limit of');
  187. $user = $this->getMockBuilder(IUser::class)
  188. ->disableOriginalConstructor()
  189. ->getMock();
  190. $user->expects($this->once())
  191. ->method('getUID')
  192. ->will($this->returnValue('alice'));
  193. $this->userSession->expects($this->once())
  194. ->method('getUser')
  195. ->will($this->returnValue($user));
  196. $this->comment->expects($this->once())
  197. ->method('setMessage')
  198. ->will($this->throwException(new MessageTooLongException()));
  199. $this->comment->expects($this->any())
  200. ->method('getActorType')
  201. ->will($this->returnValue('users'));
  202. $this->comment->expects($this->any())
  203. ->method('getActorId')
  204. ->will($this->returnValue('alice'));
  205. $this->commentsManager->expects($this->never())
  206. ->method('save');
  207. $this->logger->expects($this->once())
  208. ->method('logException');
  209. // imagine 'foo' has >1k characters. comment is mocked anyway.
  210. $this->node->updateComment('foo');
  211. }
  212. public function testUpdateForbiddenByUser() {
  213. $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
  214. $msg = 'HaXX0r';
  215. $user = $this->getMockBuilder(IUser::class)
  216. ->disableOriginalConstructor()
  217. ->getMock();
  218. $user->expects($this->once())
  219. ->method('getUID')
  220. ->will($this->returnValue('mallory'));
  221. $this->userSession->expects($this->once())
  222. ->method('getUser')
  223. ->will($this->returnValue($user));
  224. $this->comment->expects($this->never())
  225. ->method('setMessage');
  226. $this->comment->expects($this->any())
  227. ->method('getActorType')
  228. ->will($this->returnValue('users'));
  229. $this->comment->expects($this->any())
  230. ->method('getActorId')
  231. ->will($this->returnValue('alice'));
  232. $this->commentsManager->expects($this->never())
  233. ->method('save');
  234. $this->node->updateComment($msg);
  235. }
  236. public function testUpdateForbiddenByType() {
  237. $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
  238. $msg = 'HaXX0r';
  239. $user = $this->getMockBuilder(IUser::class)
  240. ->disableOriginalConstructor()
  241. ->getMock();
  242. $user->expects($this->never())
  243. ->method('getUID');
  244. $this->userSession->expects($this->once())
  245. ->method('getUser')
  246. ->will($this->returnValue($user));
  247. $this->comment->expects($this->never())
  248. ->method('setMessage');
  249. $this->comment->expects($this->any())
  250. ->method('getActorType')
  251. ->will($this->returnValue('bots'));
  252. $this->commentsManager->expects($this->never())
  253. ->method('save');
  254. $this->node->updateComment($msg);
  255. }
  256. public function testUpdateForbiddenByNotLoggedIn() {
  257. $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
  258. $msg = 'HaXX0r';
  259. $this->userSession->expects($this->once())
  260. ->method('getUser')
  261. ->will($this->returnValue(null));
  262. $this->comment->expects($this->never())
  263. ->method('setMessage');
  264. $this->comment->expects($this->any())
  265. ->method('getActorType')
  266. ->will($this->returnValue('users'));
  267. $this->commentsManager->expects($this->never())
  268. ->method('save');
  269. $this->node->updateComment($msg);
  270. }
  271. public function testPropPatch() {
  272. $propPatch = $this->getMockBuilder(PropPatch::class)
  273. ->disableOriginalConstructor()
  274. ->getMock();
  275. $propPatch->expects($this->once())
  276. ->method('handle')
  277. ->with('{http://owncloud.org/ns}message');
  278. $this->node->propPatch($propPatch);
  279. }
  280. public function testGetProperties() {
  281. $ns = '{http://owncloud.org/ns}';
  282. $expected = [
  283. $ns . 'id' => '123',
  284. $ns . 'parentId' => '12',
  285. $ns . 'topmostParentId' => '2',
  286. $ns . 'childrenCount' => 3,
  287. $ns . 'message' => 'such a nice file you have…',
  288. $ns . 'mentions' => [
  289. [ $ns . 'mention' => [
  290. $ns . 'mentionType' => 'user',
  291. $ns . 'mentionId' => 'alice',
  292. $ns . 'mentionDisplayName' => 'Alice Al-Isson',
  293. ] ],
  294. [ $ns . 'mention' => [
  295. $ns . 'mentionType' => 'user',
  296. $ns . 'mentionId' => 'bob',
  297. $ns . 'mentionDisplayName' => 'Unknown user',
  298. ] ],
  299. ],
  300. $ns . 'verb' => 'comment',
  301. $ns . 'actorType' => 'users',
  302. $ns . 'actorId' => 'alice',
  303. $ns . 'actorDisplayName' => 'Alice of Wonderland',
  304. $ns . 'creationDateTime' => new \DateTime('2016-01-10 18:48:00'),
  305. $ns . 'latestChildDateTime' => new \DateTime('2016-01-12 18:48:00'),
  306. $ns . 'objectType' => 'files',
  307. $ns . 'objectId' => '1848',
  308. $ns . 'isUnread' => null,
  309. ];
  310. $this->commentsManager->expects($this->exactly(2))
  311. ->method('resolveDisplayName')
  312. ->withConsecutive(
  313. [$this->equalTo('user'), $this->equalTo('alice')],
  314. [$this->equalTo('user'), $this->equalTo('bob')]
  315. )
  316. ->willReturnOnConsecutiveCalls('Alice Al-Isson', 'Unknown user');
  317. $this->comment->expects($this->once())
  318. ->method('getId')
  319. ->will($this->returnValue($expected[$ns . 'id']));
  320. $this->comment->expects($this->once())
  321. ->method('getParentId')
  322. ->will($this->returnValue($expected[$ns . 'parentId']));
  323. $this->comment->expects($this->once())
  324. ->method('getTopmostParentId')
  325. ->will($this->returnValue($expected[$ns . 'topmostParentId']));
  326. $this->comment->expects($this->once())
  327. ->method('getChildrenCount')
  328. ->will($this->returnValue($expected[$ns . 'childrenCount']));
  329. $this->comment->expects($this->once())
  330. ->method('getMessage')
  331. ->will($this->returnValue($expected[$ns . 'message']));
  332. $this->comment->expects($this->once())
  333. ->method('getMentions')
  334. ->willReturn([
  335. ['type' => 'user', 'id' => 'alice'],
  336. ['type' => 'user', 'id' => 'bob'],
  337. ]);
  338. $this->comment->expects($this->once())
  339. ->method('getVerb')
  340. ->will($this->returnValue($expected[$ns . 'verb']));
  341. $this->comment->expects($this->exactly(2))
  342. ->method('getActorType')
  343. ->will($this->returnValue($expected[$ns . 'actorType']));
  344. $this->comment->expects($this->exactly(2))
  345. ->method('getActorId')
  346. ->will($this->returnValue($expected[$ns . 'actorId']));
  347. $this->comment->expects($this->once())
  348. ->method('getCreationDateTime')
  349. ->will($this->returnValue($expected[$ns . 'creationDateTime']));
  350. $this->comment->expects($this->once())
  351. ->method('getLatestChildDateTime')
  352. ->will($this->returnValue($expected[$ns . 'latestChildDateTime']));
  353. $this->comment->expects($this->once())
  354. ->method('getObjectType')
  355. ->will($this->returnValue($expected[$ns . 'objectType']));
  356. $this->comment->expects($this->once())
  357. ->method('getObjectId')
  358. ->will($this->returnValue($expected[$ns . 'objectId']));
  359. $user = $this->getMockBuilder(IUser::class)
  360. ->disableOriginalConstructor()
  361. ->getMock();
  362. $user->expects($this->once())
  363. ->method('getDisplayName')
  364. ->will($this->returnValue($expected[$ns . 'actorDisplayName']));
  365. $this->userManager->expects($this->once())
  366. ->method('get')
  367. ->with('alice')
  368. ->will($this->returnValue($user));
  369. $properties = $this->node->getProperties(null);
  370. foreach($properties as $name => $value) {
  371. $this->assertTrue(array_key_exists($name, $expected));
  372. $this->assertSame($expected[$name], $value);
  373. unset($expected[$name]);
  374. }
  375. $this->assertTrue(empty($expected));
  376. }
  377. public function readCommentProvider() {
  378. $creationDT = new \DateTime('2016-01-19 18:48:00');
  379. $diff = new \DateInterval('PT2H');
  380. $readDT1 = clone $creationDT; $readDT1->sub($diff);
  381. $readDT2 = clone $creationDT; $readDT2->add($diff);
  382. return [
  383. [$creationDT, $readDT1, 'true'],
  384. [$creationDT, $readDT2, 'false'],
  385. [$creationDT, null, 'true'],
  386. ];
  387. }
  388. /**
  389. * @dataProvider readCommentProvider
  390. * @param $expected
  391. */
  392. public function testGetPropertiesUnreadProperty($creationDT, $readDT, $expected) {
  393. $this->comment->expects($this->any())
  394. ->method('getCreationDateTime')
  395. ->will($this->returnValue($creationDT));
  396. $this->comment->expects($this->any())
  397. ->method('getMentions')
  398. ->willReturn([]);
  399. $this->commentsManager->expects($this->once())
  400. ->method('getReadMark')
  401. ->will($this->returnValue($readDT));
  402. $this->userSession->expects($this->once())
  403. ->method('getUser')
  404. ->will($this->returnValue(
  405. $this->getMockBuilder(IUser::class)
  406. ->disableOriginalConstructor()
  407. ->getMock()
  408. ));
  409. $properties = $this->node->getProperties(null);
  410. $this->assertTrue(array_key_exists(CommentNode::PROPERTY_NAME_UNREAD, $properties));
  411. $this->assertSame($properties[CommentNode::PROPERTY_NAME_UNREAD], $expected);
  412. }
  413. }