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.

TagsPluginTest.php 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. <?php
  2. /**
  3. * @author Joas Schilling <nickvergessen@owncloud.com>
  4. * @author Thomas Müller <thomas.mueller@tmit.eu>
  5. * @author Vincent Petry <pvince81@owncloud.com>
  6. *
  7. * @copyright Copyright (c) 2016, ownCloud, Inc.
  8. * @license AGPL-3.0
  9. *
  10. * This code is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License, version 3,
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License, version 3,
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>
  21. *
  22. */
  23. namespace OCA\DAV\Tests\unit\Connector\Sabre;
  24. /**
  25. * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
  26. * This file is licensed under the Affero General Public License version 3 or
  27. * later.
  28. * See the COPYING-README file.
  29. */
  30. class TagsPluginTest extends \Test\TestCase {
  31. const TAGS_PROPERTYNAME = \OCA\DAV\Connector\Sabre\TagsPlugin::TAGS_PROPERTYNAME;
  32. const FAVORITE_PROPERTYNAME = \OCA\DAV\Connector\Sabre\TagsPlugin::FAVORITE_PROPERTYNAME;
  33. const TAG_FAVORITE = \OCA\DAV\Connector\Sabre\TagsPlugin::TAG_FAVORITE;
  34. /**
  35. * @var \Sabre\DAV\Server
  36. */
  37. private $server;
  38. /**
  39. * @var \Sabre\DAV\Tree
  40. */
  41. private $tree;
  42. /**
  43. * @var \OCP\ITagManager
  44. */
  45. private $tagManager;
  46. /**
  47. * @var \OCP\ITags
  48. */
  49. private $tagger;
  50. /**
  51. * @var \OCA\DAV\Connector\Sabre\TagsPlugin
  52. */
  53. private $plugin;
  54. public function setUp() {
  55. parent::setUp();
  56. $this->server = new \Sabre\DAV\Server();
  57. $this->tree = $this->getMockBuilder('\Sabre\DAV\Tree')
  58. ->disableOriginalConstructor()
  59. ->getMock();
  60. $this->tagger = $this->getMock('\OCP\ITags');
  61. $this->tagManager = $this->getMock('\OCP\ITagManager');
  62. $this->tagManager->expects($this->any())
  63. ->method('load')
  64. ->with('files')
  65. ->will($this->returnValue($this->tagger));
  66. $this->plugin = new \OCA\DAV\Connector\Sabre\TagsPlugin($this->tree, $this->tagManager);
  67. $this->plugin->initialize($this->server);
  68. }
  69. /**
  70. * @dataProvider tagsGetPropertiesDataProvider
  71. */
  72. public function testGetProperties($tags, $requestedProperties, $expectedProperties) {
  73. $node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Node')
  74. ->disableOriginalConstructor()
  75. ->getMock();
  76. $node->expects($this->any())
  77. ->method('getId')
  78. ->will($this->returnValue(123));
  79. $expectedCallCount = 0;
  80. if (count($requestedProperties) > 0) {
  81. $expectedCallCount = 1;
  82. }
  83. $this->tagger->expects($this->exactly($expectedCallCount))
  84. ->method('getTagsForObjects')
  85. ->with($this->equalTo(array(123)))
  86. ->will($this->returnValue(array(123 => $tags)));
  87. $propFind = new \Sabre\DAV\PropFind(
  88. '/dummyPath',
  89. $requestedProperties,
  90. 0
  91. );
  92. $this->plugin->handleGetProperties(
  93. $propFind,
  94. $node
  95. );
  96. $result = $propFind->getResultForMultiStatus();
  97. $this->assertEmpty($result[404]);
  98. unset($result[404]);
  99. $this->assertEquals($expectedProperties, $result);
  100. }
  101. /**
  102. * @dataProvider tagsGetPropertiesDataProvider
  103. */
  104. public function testPreloadThenGetProperties($tags, $requestedProperties, $expectedProperties) {
  105. $node1 = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\File')
  106. ->disableOriginalConstructor()
  107. ->getMock();
  108. $node1->expects($this->any())
  109. ->method('getId')
  110. ->will($this->returnValue(111));
  111. $node2 = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\File')
  112. ->disableOriginalConstructor()
  113. ->getMock();
  114. $node2->expects($this->any())
  115. ->method('getId')
  116. ->will($this->returnValue(222));
  117. $expectedCallCount = 0;
  118. if (count($requestedProperties) > 0) {
  119. // this guarantees that getTagsForObjects
  120. // is only called once and then the tags
  121. // are cached
  122. $expectedCallCount = 1;
  123. }
  124. $node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Directory')
  125. ->disableOriginalConstructor()
  126. ->getMock();
  127. $node->expects($this->any())
  128. ->method('getId')
  129. ->will($this->returnValue(123));
  130. $node->expects($this->exactly($expectedCallCount))
  131. ->method('getChildren')
  132. ->will($this->returnValue(array($node1, $node2)));
  133. $this->tagger->expects($this->exactly($expectedCallCount))
  134. ->method('getTagsForObjects')
  135. ->with($this->equalTo(array(123, 111, 222)))
  136. ->will($this->returnValue(
  137. array(
  138. 111 => $tags,
  139. 123 => $tags
  140. )
  141. ));
  142. // simulate sabre recursive PROPFIND traversal
  143. $propFindRoot = new \Sabre\DAV\PropFind(
  144. '/subdir',
  145. $requestedProperties,
  146. 1
  147. );
  148. $propFind1 = new \Sabre\DAV\PropFind(
  149. '/subdir/test.txt',
  150. $requestedProperties,
  151. 0
  152. );
  153. $propFind2 = new \Sabre\DAV\PropFind(
  154. '/subdir/test2.txt',
  155. $requestedProperties,
  156. 0
  157. );
  158. $this->plugin->handleGetProperties(
  159. $propFindRoot,
  160. $node
  161. );
  162. $this->plugin->handleGetProperties(
  163. $propFind1,
  164. $node1
  165. );
  166. $this->plugin->handleGetProperties(
  167. $propFind2,
  168. $node2
  169. );
  170. $result = $propFind1->getResultForMultiStatus();
  171. $this->assertEmpty($result[404]);
  172. unset($result[404]);
  173. $this->assertEquals($expectedProperties, $result);
  174. }
  175. function tagsGetPropertiesDataProvider() {
  176. return array(
  177. // request both, receive both
  178. array(
  179. array('tag1', 'tag2', self::TAG_FAVORITE),
  180. array(self::TAGS_PROPERTYNAME, self::FAVORITE_PROPERTYNAME),
  181. array(
  182. 200 => array(
  183. self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList(array('tag1', 'tag2')),
  184. self::FAVORITE_PROPERTYNAME => true,
  185. )
  186. )
  187. ),
  188. // request tags alone
  189. array(
  190. array('tag1', 'tag2', self::TAG_FAVORITE),
  191. array(self::TAGS_PROPERTYNAME),
  192. array(
  193. 200 => array(
  194. self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList(array('tag1', 'tag2')),
  195. )
  196. )
  197. ),
  198. // request fav alone
  199. array(
  200. array('tag1', 'tag2', self::TAG_FAVORITE),
  201. array(self::FAVORITE_PROPERTYNAME),
  202. array(
  203. 200 => array(
  204. self::FAVORITE_PROPERTYNAME => true,
  205. )
  206. )
  207. ),
  208. // request none
  209. array(
  210. array('tag1', 'tag2', self::TAG_FAVORITE),
  211. array(),
  212. array(
  213. 200 => array()
  214. ),
  215. ),
  216. // request both with none set, receive both
  217. array(
  218. array(),
  219. array(self::TAGS_PROPERTYNAME, self::FAVORITE_PROPERTYNAME),
  220. array(
  221. 200 => array(
  222. self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList(array()),
  223. self::FAVORITE_PROPERTYNAME => false,
  224. )
  225. )
  226. ),
  227. );
  228. }
  229. public function testUpdateTags() {
  230. // this test will replace the existing tags "tagremove" with "tag1" and "tag2"
  231. // and keep "tagkeep"
  232. $node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Node')
  233. ->disableOriginalConstructor()
  234. ->getMock();
  235. $node->expects($this->any())
  236. ->method('getId')
  237. ->will($this->returnValue(123));
  238. $this->tree->expects($this->any())
  239. ->method('getNodeForPath')
  240. ->with('/dummypath')
  241. ->will($this->returnValue($node));
  242. $this->tagger->expects($this->at(0))
  243. ->method('getTagsForObjects')
  244. ->with($this->equalTo(array(123)))
  245. ->will($this->returnValue(array(123 => array('tagkeep', 'tagremove', self::TAG_FAVORITE))));
  246. // then tag as tag1 and tag2
  247. $this->tagger->expects($this->at(1))
  248. ->method('tagAs')
  249. ->with(123, 'tag1');
  250. $this->tagger->expects($this->at(2))
  251. ->method('tagAs')
  252. ->with(123, 'tag2');
  253. // it will untag tag3
  254. $this->tagger->expects($this->at(3))
  255. ->method('unTag')
  256. ->with(123, 'tagremove');
  257. // properties to set
  258. $propPatch = new \Sabre\DAV\PropPatch(array(
  259. self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList(array('tag1', 'tag2', 'tagkeep'))
  260. ));
  261. $this->plugin->handleUpdateProperties(
  262. '/dummypath',
  263. $propPatch
  264. );
  265. $propPatch->commit();
  266. // all requested properties removed, as they were processed already
  267. $this->assertEmpty($propPatch->getRemainingMutations());
  268. $result = $propPatch->getResult();
  269. $this->assertEquals(200, $result[self::TAGS_PROPERTYNAME]);
  270. $this->assertFalse(isset($result[self::FAVORITE_PROPERTYNAME]));
  271. }
  272. public function testUpdateTagsFromScratch() {
  273. $node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Node')
  274. ->disableOriginalConstructor()
  275. ->getMock();
  276. $node->expects($this->any())
  277. ->method('getId')
  278. ->will($this->returnValue(123));
  279. $this->tree->expects($this->any())
  280. ->method('getNodeForPath')
  281. ->with('/dummypath')
  282. ->will($this->returnValue($node));
  283. $this->tagger->expects($this->at(0))
  284. ->method('getTagsForObjects')
  285. ->with($this->equalTo(array(123)))
  286. ->will($this->returnValue(array()));
  287. // then tag as tag1 and tag2
  288. $this->tagger->expects($this->at(1))
  289. ->method('tagAs')
  290. ->with(123, 'tag1');
  291. $this->tagger->expects($this->at(2))
  292. ->method('tagAs')
  293. ->with(123, 'tag2');
  294. // properties to set
  295. $propPatch = new \Sabre\DAV\PropPatch(array(
  296. self::TAGS_PROPERTYNAME => new \OCA\DAV\Connector\Sabre\TagList(array('tag1', 'tag2', 'tagkeep'))
  297. ));
  298. $this->plugin->handleUpdateProperties(
  299. '/dummypath',
  300. $propPatch
  301. );
  302. $propPatch->commit();
  303. // all requested properties removed, as they were processed already
  304. $this->assertEmpty($propPatch->getRemainingMutations());
  305. $result = $propPatch->getResult();
  306. $this->assertEquals(200, $result[self::TAGS_PROPERTYNAME]);
  307. $this->assertFalse(false, isset($result[self::FAVORITE_PROPERTYNAME]));
  308. }
  309. public function testUpdateFav() {
  310. // this test will replace the existing tags "tagremove" with "tag1" and "tag2"
  311. // and keep "tagkeep"
  312. $node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\Node')
  313. ->disableOriginalConstructor()
  314. ->getMock();
  315. $node->expects($this->any())
  316. ->method('getId')
  317. ->will($this->returnValue(123));
  318. $this->tree->expects($this->any())
  319. ->method('getNodeForPath')
  320. ->with('/dummypath')
  321. ->will($this->returnValue($node));
  322. // set favorite tag
  323. $this->tagger->expects($this->once())
  324. ->method('tagAs')
  325. ->with(123, self::TAG_FAVORITE);
  326. // properties to set
  327. $propPatch = new \Sabre\DAV\PropPatch(array(
  328. self::FAVORITE_PROPERTYNAME => true
  329. ));
  330. $this->plugin->handleUpdateProperties(
  331. '/dummypath',
  332. $propPatch
  333. );
  334. $propPatch->commit();
  335. // all requested properties removed, as they were processed already
  336. $this->assertEmpty($propPatch->getRemainingMutations());
  337. $result = $propPatch->getResult();
  338. $this->assertFalse(false, isset($result[self::TAGS_PROPERTYNAME]));
  339. $this->assertEquals(200, isset($result[self::FAVORITE_PROPERTYNAME]));
  340. // unfavorite now
  341. // set favorite tag
  342. $this->tagger->expects($this->once())
  343. ->method('unTag')
  344. ->with(123, self::TAG_FAVORITE);
  345. // properties to set
  346. $propPatch = new \Sabre\DAV\PropPatch(array(
  347. self::FAVORITE_PROPERTYNAME => false
  348. ));
  349. $this->plugin->handleUpdateProperties(
  350. '/dummypath',
  351. $propPatch
  352. );
  353. $propPatch->commit();
  354. // all requested properties removed, as they were processed already
  355. $this->assertEmpty($propPatch->getRemainingMutations());
  356. $result = $propPatch->getResult();
  357. $this->assertFalse(false, isset($result[self::TAGS_PROPERTYNAME]));
  358. $this->assertEquals(200, isset($result[self::FAVORITE_PROPERTYNAME]));
  359. }
  360. }