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.

FilesPluginTest.php 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Joas Schilling <coding@schilljs.com>
  7. * @author Markus Goetz <markus@woboq.com>
  8. * @author Morris Jobke <hey@morrisjobke.de>
  9. * @author Robin Appelman <robin@icewind.nl>
  10. * @author Roeland Jago Douma <roeland@famdouma.nl>
  11. * @author Stefan Weil <sw@weilnetz.de>
  12. * @author Thomas Müller <thomas.mueller@tmit.eu>
  13. * @author Vincent Petry <vincent@nextcloud.com>
  14. *
  15. * @license AGPL-3.0
  16. *
  17. * This code is free software: you can redistribute it and/or modify
  18. * it under the terms of the GNU Affero General Public License, version 3,
  19. * as published by the Free Software Foundation.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU Affero General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU Affero General Public License, version 3,
  27. * along with this program. If not, see <http://www.gnu.org/licenses/>
  28. *
  29. */
  30. namespace OCA\DAV\Tests\unit\Connector\Sabre;
  31. use OC\User\User;
  32. use OCA\DAV\Connector\Sabre\Directory;
  33. use OCA\DAV\Connector\Sabre\File;
  34. use OCA\DAV\Connector\Sabre\FilesPlugin;
  35. use OCA\DAV\Connector\Sabre\Node;
  36. use OCP\Files\FileInfo;
  37. use OCP\Files\StorageNotAvailableException;
  38. use OCP\IConfig;
  39. use OCP\IPreview;
  40. use OCP\IRequest;
  41. use Sabre\DAV\PropFind;
  42. use Sabre\DAV\PropPatch;
  43. use Sabre\DAV\Server;
  44. use Sabre\DAV\Tree;
  45. use Sabre\HTTP\RequestInterface;
  46. use Sabre\HTTP\ResponseInterface;
  47. use Sabre\Xml\Service;
  48. use Test\TestCase;
  49. /**
  50. * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com>
  51. * This file is licensed under the Affero General Public License version 3 or
  52. * later.
  53. * See the COPYING-README file.
  54. */
  55. class FilesPluginTest extends TestCase {
  56. public const GETETAG_PROPERTYNAME = FilesPlugin::GETETAG_PROPERTYNAME;
  57. public const FILEID_PROPERTYNAME = FilesPlugin::FILEID_PROPERTYNAME;
  58. public const INTERNAL_FILEID_PROPERTYNAME = FilesPlugin::INTERNAL_FILEID_PROPERTYNAME;
  59. public const SIZE_PROPERTYNAME = FilesPlugin::SIZE_PROPERTYNAME;
  60. public const PERMISSIONS_PROPERTYNAME = FilesPlugin::PERMISSIONS_PROPERTYNAME;
  61. public const LASTMODIFIED_PROPERTYNAME = FilesPlugin::LASTMODIFIED_PROPERTYNAME;
  62. public const DOWNLOADURL_PROPERTYNAME = FilesPlugin::DOWNLOADURL_PROPERTYNAME;
  63. public const OWNER_ID_PROPERTYNAME = FilesPlugin::OWNER_ID_PROPERTYNAME;
  64. public const OWNER_DISPLAY_NAME_PROPERTYNAME = FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME;
  65. public const DATA_FINGERPRINT_PROPERTYNAME = FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME;
  66. public const HAS_PREVIEW_PROPERTYNAME = FilesPlugin::HAS_PREVIEW_PROPERTYNAME;
  67. /**
  68. * @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject
  69. */
  70. private $server;
  71. /**
  72. * @var \Sabre\DAV\Tree | \PHPUnit\Framework\MockObject\MockObject
  73. */
  74. private $tree;
  75. /**
  76. * @var FilesPlugin
  77. */
  78. private $plugin;
  79. /**
  80. * @var \OCP\IConfig | \PHPUnit\Framework\MockObject\MockObject
  81. */
  82. private $config;
  83. /**
  84. * @var \OCP\IRequest | \PHPUnit\Framework\MockObject\MockObject
  85. */
  86. private $request;
  87. /**
  88. * @var \OCP\IPreview | \PHPUnit\Framework\MockObject\MockObject
  89. */
  90. private $previewManager;
  91. protected function setUp(): void {
  92. parent::setUp();
  93. $this->server = $this->getMockBuilder(Server::class)
  94. ->disableOriginalConstructor()
  95. ->getMock();
  96. $this->tree = $this->getMockBuilder(Tree::class)
  97. ->disableOriginalConstructor()
  98. ->getMock();
  99. $this->config = $this->createMock(IConfig::class);
  100. $this->config->expects($this->any())->method('getSystemValue')
  101. ->with($this->equalTo('data-fingerprint'), $this->equalTo(''))
  102. ->willReturn('my_fingerprint');
  103. $this->request = $this->getMockBuilder(IRequest::class)
  104. ->disableOriginalConstructor()
  105. ->getMock();
  106. $this->previewManager = $this->getMockBuilder(IPreview::class)
  107. ->disableOriginalConstructor()
  108. ->getMock();
  109. $this->plugin = new FilesPlugin(
  110. $this->tree,
  111. $this->config,
  112. $this->request,
  113. $this->previewManager
  114. );
  115. $response = $this->getMockBuilder(ResponseInterface::class)
  116. ->disableOriginalConstructor()
  117. ->getMock();
  118. $this->server->httpResponse = $response;
  119. $this->server->xml = new Service();
  120. $this->plugin->initialize($this->server);
  121. }
  122. /**
  123. * @param string $class
  124. * @return \PHPUnit\Framework\MockObject\MockObject
  125. */
  126. private function createTestNode($class, $path = '/dummypath') {
  127. $node = $this->getMockBuilder($class)
  128. ->disableOriginalConstructor()
  129. ->getMock();
  130. $node->expects($this->any())
  131. ->method('getId')
  132. ->willReturn(123);
  133. $this->tree->expects($this->any())
  134. ->method('getNodeForPath')
  135. ->with($path)
  136. ->willReturn($node);
  137. $node->expects($this->any())
  138. ->method('getFileId')
  139. ->willReturn('00000123instanceid');
  140. $node->expects($this->any())
  141. ->method('getInternalFileId')
  142. ->willReturn('123');
  143. $node->expects($this->any())
  144. ->method('getEtag')
  145. ->willReturn('"abc"');
  146. $node->expects($this->any())
  147. ->method('getDavPermissions')
  148. ->willReturn('DWCKMSR');
  149. $fileInfo = $this->createMock(FileInfo::class);
  150. $fileInfo->expects($this->any())
  151. ->method('isReadable')
  152. ->willReturn(true);
  153. $node->expects($this->any())
  154. ->method('getFileInfo')
  155. ->willReturn($fileInfo);
  156. return $node;
  157. }
  158. public function testGetPropertiesForFile() {
  159. /** @var \OCA\DAV\Connector\Sabre\File | \PHPUnit\Framework\MockObject\MockObject $node */
  160. $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
  161. $propFind = new PropFind(
  162. '/dummyPath',
  163. [
  164. self::GETETAG_PROPERTYNAME,
  165. self::FILEID_PROPERTYNAME,
  166. self::INTERNAL_FILEID_PROPERTYNAME,
  167. self::SIZE_PROPERTYNAME,
  168. self::PERMISSIONS_PROPERTYNAME,
  169. self::DOWNLOADURL_PROPERTYNAME,
  170. self::OWNER_ID_PROPERTYNAME,
  171. self::OWNER_DISPLAY_NAME_PROPERTYNAME,
  172. self::DATA_FINGERPRINT_PROPERTYNAME,
  173. ],
  174. 0
  175. );
  176. $user = $this->getMockBuilder(User::class)
  177. ->disableOriginalConstructor()->getMock();
  178. $user
  179. ->expects($this->once())
  180. ->method('getUID')
  181. ->willReturn('foo');
  182. $user
  183. ->expects($this->once())
  184. ->method('getDisplayName')
  185. ->willReturn('M. Foo');
  186. $node->expects($this->once())
  187. ->method('getDirectDownload')
  188. ->willReturn(['url' => 'http://example.com/']);
  189. $node->expects($this->exactly(2))
  190. ->method('getOwner')
  191. ->willReturn($user);
  192. $this->plugin->handleGetProperties(
  193. $propFind,
  194. $node
  195. );
  196. $this->assertEquals('"abc"', $propFind->get(self::GETETAG_PROPERTYNAME));
  197. $this->assertEquals('00000123instanceid', $propFind->get(self::FILEID_PROPERTYNAME));
  198. $this->assertEquals('123', $propFind->get(self::INTERNAL_FILEID_PROPERTYNAME));
  199. $this->assertEquals(null, $propFind->get(self::SIZE_PROPERTYNAME));
  200. $this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME));
  201. $this->assertEquals('http://example.com/', $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
  202. $this->assertEquals('foo', $propFind->get(self::OWNER_ID_PROPERTYNAME));
  203. $this->assertEquals('M. Foo', $propFind->get(self::OWNER_DISPLAY_NAME_PROPERTYNAME));
  204. $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
  205. $this->assertEquals([self::SIZE_PROPERTYNAME], $propFind->get404Properties());
  206. }
  207. public function testGetPropertiesStorageNotAvailable() {
  208. /** @var \OCA\DAV\Connector\Sabre\File | \PHPUnit\Framework\MockObject\MockObject $node */
  209. $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
  210. $propFind = new PropFind(
  211. '/dummyPath',
  212. [
  213. self::DOWNLOADURL_PROPERTYNAME,
  214. ],
  215. 0
  216. );
  217. $node->expects($this->once())
  218. ->method('getDirectDownload')
  219. ->will($this->throwException(new StorageNotAvailableException()));
  220. $this->plugin->handleGetProperties(
  221. $propFind,
  222. $node
  223. );
  224. $this->assertEquals(null, $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
  225. }
  226. public function testGetPublicPermissions() {
  227. $this->plugin = new FilesPlugin(
  228. $this->tree,
  229. $this->config,
  230. $this->getMockBuilder(IRequest::class)
  231. ->disableOriginalConstructor()
  232. ->getMock(),
  233. $this->previewManager,
  234. true);
  235. $this->plugin->initialize($this->server);
  236. $propFind = new PropFind(
  237. '/dummyPath',
  238. [
  239. self::PERMISSIONS_PROPERTYNAME,
  240. ],
  241. 0
  242. );
  243. /** @var \OCA\DAV\Connector\Sabre\File | \PHPUnit\Framework\MockObject\MockObject $node */
  244. $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
  245. $node->expects($this->any())
  246. ->method('getDavPermissions')
  247. ->willReturn('DWCKMSR');
  248. $this->plugin->handleGetProperties(
  249. $propFind,
  250. $node
  251. );
  252. $this->assertEquals('DWCKR', $propFind->get(self::PERMISSIONS_PROPERTYNAME));
  253. }
  254. public function testGetPropertiesForDirectory() {
  255. /** @var \OCA\DAV\Connector\Sabre\Directory | \PHPUnit\Framework\MockObject\MockObject $node */
  256. $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\Directory');
  257. $propFind = new PropFind(
  258. '/dummyPath',
  259. [
  260. self::GETETAG_PROPERTYNAME,
  261. self::FILEID_PROPERTYNAME,
  262. self::SIZE_PROPERTYNAME,
  263. self::PERMISSIONS_PROPERTYNAME,
  264. self::DOWNLOADURL_PROPERTYNAME,
  265. self::DATA_FINGERPRINT_PROPERTYNAME,
  266. ],
  267. 0
  268. );
  269. $node->expects($this->once())
  270. ->method('getSize')
  271. ->willReturn(1025);
  272. $this->plugin->handleGetProperties(
  273. $propFind,
  274. $node
  275. );
  276. $this->assertEquals('"abc"', $propFind->get(self::GETETAG_PROPERTYNAME));
  277. $this->assertEquals('00000123instanceid', $propFind->get(self::FILEID_PROPERTYNAME));
  278. $this->assertEquals(1025, $propFind->get(self::SIZE_PROPERTYNAME));
  279. $this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME));
  280. $this->assertEquals(null, $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
  281. $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
  282. $this->assertEquals([self::DOWNLOADURL_PROPERTYNAME], $propFind->get404Properties());
  283. }
  284. public function testGetPropertiesForRootDirectory() {
  285. /** @var \OCA\DAV\Connector\Sabre\Directory|\PHPUnit\Framework\MockObject\MockObject $node */
  286. $node = $this->getMockBuilder(Directory::class)
  287. ->disableOriginalConstructor()
  288. ->getMock();
  289. $node->expects($this->any())->method('getPath')->willReturn('/');
  290. $fileInfo = $this->createMock(FileInfo::class);
  291. $fileInfo->expects($this->any())
  292. ->method('isReadable')
  293. ->willReturn(true);
  294. $node->expects($this->any())
  295. ->method('getFileInfo')
  296. ->willReturn($fileInfo);
  297. $propFind = new PropFind(
  298. '/',
  299. [
  300. self::DATA_FINGERPRINT_PROPERTYNAME,
  301. ],
  302. 0
  303. );
  304. $this->plugin->handleGetProperties(
  305. $propFind,
  306. $node
  307. );
  308. $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
  309. }
  310. public function testGetPropertiesWhenNoPermission() {
  311. // No read permissions can be caused by files access control.
  312. // But we still want to load the directory list, so this is okay for us.
  313. // $this->expectException(\Sabre\DAV\Exception\NotFound::class);
  314. /** @var \OCA\DAV\Connector\Sabre\Directory|\PHPUnit\Framework\MockObject\MockObject $node */
  315. $node = $this->getMockBuilder(Directory::class)
  316. ->disableOriginalConstructor()
  317. ->getMock();
  318. $node->expects($this->any())->method('getPath')->willReturn('/');
  319. $fileInfo = $this->createMock(FileInfo::class);
  320. $fileInfo->expects($this->any())
  321. ->method('isReadable')
  322. ->willReturn(false);
  323. $node->expects($this->any())
  324. ->method('getFileInfo')
  325. ->willReturn($fileInfo);
  326. $propFind = new PropFind(
  327. '/test',
  328. [
  329. self::DATA_FINGERPRINT_PROPERTYNAME,
  330. ],
  331. 0
  332. );
  333. $this->plugin->handleGetProperties(
  334. $propFind,
  335. $node
  336. );
  337. $this->addToAssertionCount(1);
  338. }
  339. public function testUpdateProps() {
  340. $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
  341. $testDate = 'Fri, 13 Feb 2015 00:01:02 GMT';
  342. $node->expects($this->once())
  343. ->method('touch')
  344. ->with($testDate);
  345. $node->expects($this->once())
  346. ->method('setEtag')
  347. ->with('newetag')
  348. ->willReturn(true);
  349. // properties to set
  350. $propPatch = new PropPatch([
  351. self::GETETAG_PROPERTYNAME => 'newetag',
  352. self::LASTMODIFIED_PROPERTYNAME => $testDate
  353. ]);
  354. $this->plugin->handleUpdateProperties(
  355. '/dummypath',
  356. $propPatch
  357. );
  358. $propPatch->commit();
  359. $this->assertEmpty($propPatch->getRemainingMutations());
  360. $result = $propPatch->getResult();
  361. $this->assertEquals(200, $result[self::LASTMODIFIED_PROPERTYNAME]);
  362. $this->assertEquals(200, $result[self::GETETAG_PROPERTYNAME]);
  363. }
  364. public function testUpdatePropsForbidden() {
  365. $propPatch = new PropPatch([
  366. self::OWNER_ID_PROPERTYNAME => 'user2',
  367. self::OWNER_DISPLAY_NAME_PROPERTYNAME => 'User Two',
  368. self::FILEID_PROPERTYNAME => 12345,
  369. self::PERMISSIONS_PROPERTYNAME => 'C',
  370. self::SIZE_PROPERTYNAME => 123,
  371. self::DOWNLOADURL_PROPERTYNAME => 'http://example.com/',
  372. ]);
  373. $this->plugin->handleUpdateProperties(
  374. '/dummypath',
  375. $propPatch
  376. );
  377. $propPatch->commit();
  378. $this->assertEmpty($propPatch->getRemainingMutations());
  379. $result = $propPatch->getResult();
  380. $this->assertEquals(403, $result[self::OWNER_ID_PROPERTYNAME]);
  381. $this->assertEquals(403, $result[self::OWNER_DISPLAY_NAME_PROPERTYNAME]);
  382. $this->assertEquals(403, $result[self::FILEID_PROPERTYNAME]);
  383. $this->assertEquals(403, $result[self::PERMISSIONS_PROPERTYNAME]);
  384. $this->assertEquals(403, $result[self::SIZE_PROPERTYNAME]);
  385. $this->assertEquals(403, $result[self::DOWNLOADURL_PROPERTYNAME]);
  386. }
  387. /**
  388. * Testcase from https://github.com/owncloud/core/issues/5251
  389. *
  390. * |-FolderA
  391. * |-text.txt
  392. * |-test.txt
  393. *
  394. * FolderA is an incoming shared folder and there are no delete permissions.
  395. * Thus moving /FolderA/test.txt to /test.txt should fail already on that check
  396. *
  397. */
  398. public function testMoveSrcNotDeletable() {
  399. $this->expectException(\Sabre\DAV\Exception\Forbidden::class);
  400. $this->expectExceptionMessage('FolderA/test.txt cannot be deleted');
  401. $fileInfoFolderATestTXT = $this->getMockBuilder(FileInfo::class)
  402. ->disableOriginalConstructor()
  403. ->getMock();
  404. $fileInfoFolderATestTXT->expects($this->once())
  405. ->method('isDeletable')
  406. ->willReturn(false);
  407. $node = $this->getMockBuilder(Node::class)
  408. ->disableOriginalConstructor()
  409. ->getMock();
  410. $node->expects($this->once())
  411. ->method('getFileInfo')
  412. ->willReturn($fileInfoFolderATestTXT);
  413. $this->tree->expects($this->once())->method('getNodeForPath')
  414. ->willReturn($node);
  415. $this->plugin->checkMove('FolderA/test.txt', 'test.txt');
  416. }
  417. public function testMoveSrcDeletable() {
  418. $fileInfoFolderATestTXT = $this->getMockBuilder(FileInfo::class)
  419. ->disableOriginalConstructor()
  420. ->getMock();
  421. $fileInfoFolderATestTXT->expects($this->once())
  422. ->method('isDeletable')
  423. ->willReturn(true);
  424. $node = $this->getMockBuilder(Node::class)
  425. ->disableOriginalConstructor()
  426. ->getMock();
  427. $node->expects($this->once())
  428. ->method('getFileInfo')
  429. ->willReturn($fileInfoFolderATestTXT);
  430. $this->tree->expects($this->once())->method('getNodeForPath')
  431. ->willReturn($node);
  432. $this->plugin->checkMove('FolderA/test.txt', 'test.txt');
  433. }
  434. public function testMoveSrcNotExist() {
  435. $this->expectException(\Sabre\DAV\Exception\NotFound::class);
  436. $this->expectExceptionMessage('FolderA/test.txt does not exist');
  437. $node = $this->getMockBuilder(Node::class)
  438. ->disableOriginalConstructor()
  439. ->getMock();
  440. $node->expects($this->once())
  441. ->method('getFileInfo')
  442. ->willReturn(null);
  443. $this->tree->expects($this->once())->method('getNodeForPath')
  444. ->willReturn($node);
  445. $this->plugin->checkMove('FolderA/test.txt', 'test.txt');
  446. }
  447. public function downloadHeadersProvider() {
  448. return [
  449. [
  450. false,
  451. 'attachment; filename*=UTF-8\'\'somefile.xml; filename="somefile.xml"'
  452. ],
  453. [
  454. true,
  455. 'attachment; filename="somefile.xml"'
  456. ],
  457. ];
  458. }
  459. /**
  460. * @dataProvider downloadHeadersProvider
  461. */
  462. public function testDownloadHeaders($isClumsyAgent, $contentDispositionHeader) {
  463. $request = $this->getMockBuilder(RequestInterface::class)
  464. ->disableOriginalConstructor()
  465. ->getMock();
  466. $response = $this->getMockBuilder(ResponseInterface::class)
  467. ->disableOriginalConstructor()
  468. ->getMock();
  469. $request
  470. ->expects($this->once())
  471. ->method('getPath')
  472. ->willReturn('test/somefile.xml');
  473. $node = $this->getMockBuilder(File::class)
  474. ->disableOriginalConstructor()
  475. ->getMock();
  476. $node
  477. ->expects($this->once())
  478. ->method('getName')
  479. ->willReturn('somefile.xml');
  480. $this->tree
  481. ->expects($this->once())
  482. ->method('getNodeForPath')
  483. ->with('test/somefile.xml')
  484. ->willReturn($node);
  485. $this->request
  486. ->expects($this->once())
  487. ->method('isUserAgent')
  488. ->willReturn($isClumsyAgent);
  489. $response
  490. ->expects($this->once())
  491. ->method('addHeader')
  492. ->with('Content-Disposition', $contentDispositionHeader);
  493. $this->plugin->httpGet($request, $response);
  494. }
  495. public function testHasPreview() {
  496. /** @var \OCA\DAV\Connector\Sabre\Directory | \PHPUnit\Framework\MockObject\MockObject $node */
  497. $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\Directory');
  498. $propFind = new PropFind(
  499. '/dummyPath',
  500. [
  501. self::HAS_PREVIEW_PROPERTYNAME
  502. ],
  503. 0
  504. );
  505. $this->previewManager->expects($this->once())
  506. ->method('isAvailable')
  507. ->willReturn(false);
  508. $this->plugin->handleGetProperties(
  509. $propFind,
  510. $node
  511. );
  512. $this->assertEquals("false", $propFind->get(self::HAS_PREVIEW_PROPERTYNAME));
  513. }
  514. }