ManagerTest.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. namespace Test\DirectEditing;
  7. use OC\DirectEditing\Manager;
  8. use OC\Files\Node\File;
  9. use OCP\AppFramework\Http\DataResponse;
  10. use OCP\AppFramework\Http\NotFoundResponse;
  11. use OCP\AppFramework\Http\Response;
  12. use OCP\DirectEditing\ACreateEmpty;
  13. use OCP\DirectEditing\IEditor;
  14. use OCP\DirectEditing\IToken;
  15. use OCP\Encryption\IManager;
  16. use OCP\Files\Folder;
  17. use OCP\Files\IRootFolder;
  18. use OCP\IDBConnection;
  19. use OCP\IL10N;
  20. use OCP\IUser;
  21. use OCP\IUserSession;
  22. use OCP\L10N\IFactory;
  23. use OCP\Security\ISecureRandom;
  24. use PHPUnit\Framework\MockObject\MockObject;
  25. use Test\TestCase;
  26. class CreateEmpty extends ACreateEmpty {
  27. public function getId(): string {
  28. return 'createEmpty';
  29. }
  30. public function getName(): string {
  31. return 'create empty file';
  32. }
  33. public function getExtension(): string {
  34. return '.txt';
  35. }
  36. public function getMimetype(): string {
  37. return 'text/plain';
  38. }
  39. }
  40. class Editor implements IEditor {
  41. public function getId(): string {
  42. return 'testeditor';
  43. }
  44. public function getName(): string {
  45. return 'Test editor';
  46. }
  47. public function getMimetypes(): array {
  48. return [ 'text/plain' ];
  49. }
  50. public function getMimetypesOptional(): array {
  51. return [];
  52. }
  53. public function getCreators(): array {
  54. return [
  55. new CreateEmpty()
  56. ];
  57. }
  58. public function isSecure(): bool {
  59. return false;
  60. }
  61. public function open(IToken $token): Response {
  62. return new DataResponse('edit page');
  63. }
  64. }
  65. /**
  66. * Class ManagerTest
  67. *
  68. * @package Test\DirectEditing
  69. * @group DB
  70. */
  71. class ManagerTest extends TestCase {
  72. private $manager;
  73. /**
  74. * @var Editor
  75. */
  76. private $editor;
  77. /**
  78. * @var MockObject|ISecureRandom
  79. */
  80. private $random;
  81. /**
  82. * @var IDBConnection
  83. */
  84. private $connection;
  85. /**
  86. * @var MockObject|IUserSession
  87. */
  88. private $userSession;
  89. /**
  90. * @var MockObject|IRootFolder
  91. */
  92. private $rootFolder;
  93. /**
  94. * @var MockObject|Folder
  95. */
  96. private $userFolder;
  97. /**
  98. * @var MockObject|IL10N
  99. */
  100. private $l10n;
  101. /**
  102. * @var MockObject|IManager
  103. */
  104. private $encryptionManager;
  105. protected function setUp(): void {
  106. parent::setUp();
  107. $this->editor = new Editor();
  108. $this->random = $this->createMock(ISecureRandom::class);
  109. $this->connection = \OC::$server->getDatabaseConnection();
  110. $this->userSession = $this->createMock(IUserSession::class);
  111. $this->rootFolder = $this->createMock(IRootFolder::class);
  112. $this->userFolder = $this->createMock(Folder::class);
  113. $this->l10n = $this->createMock(IL10N::class);
  114. $this->encryptionManager = $this->createMock(IManager::class);
  115. $l10nFactory = $this->createMock(IFactory::class);
  116. $l10nFactory->expects($this->once())
  117. ->method('get')
  118. ->willReturn($this->l10n);
  119. $this->rootFolder->expects($this->any())
  120. ->method('getUserFolder')
  121. ->willReturn($this->userFolder);
  122. $user = $this->createMock(IUser::class);
  123. $user->expects(self::any())
  124. ->method('getUID')
  125. ->willReturn('admin');
  126. $this->userSession->expects(self::any())
  127. ->method('getUser')
  128. ->willReturn($user);
  129. $this->manager = new Manager(
  130. $this->random, $this->connection, $this->userSession, $this->rootFolder, $l10nFactory, $this->encryptionManager
  131. );
  132. $this->manager->registerDirectEditor($this->editor);
  133. }
  134. public function testEditorRegistration(): void {
  135. $this->assertEquals($this->manager->getEditors(), ['testeditor' => $this->editor]);
  136. }
  137. public function testCreateToken(): void {
  138. $expectedToken = 'TOKEN' . time();
  139. $file = $this->createMock(File::class);
  140. $file->expects($this->any())
  141. ->method('getId')
  142. ->willReturn(123);
  143. $this->random->expects($this->once())
  144. ->method('generate')
  145. ->willReturn($expectedToken);
  146. $folder = $this->createMock(Folder::class);
  147. $this->userFolder
  148. ->method('nodeExists')
  149. ->withConsecutive(['/File.txt'], ['/'])
  150. ->willReturnOnConsecutiveCalls(false, true);
  151. $this->userFolder
  152. ->method('get')
  153. ->with('/')
  154. ->willReturn($folder);
  155. $folder->expects($this->once())
  156. ->method('newFile')
  157. ->willReturn($file);
  158. $token = $this->manager->create('/File.txt', 'testeditor', 'createEmpty');
  159. $this->assertEquals($token, $expectedToken);
  160. }
  161. public function testCreateTokenAccess(): void {
  162. $expectedToken = 'TOKEN' . time();
  163. $file = $this->createMock(File::class);
  164. $file->expects($this->any())
  165. ->method('getId')
  166. ->willReturn(123);
  167. $this->random->expects($this->once())
  168. ->method('generate')
  169. ->willReturn($expectedToken);
  170. $folder = $this->createMock(Folder::class);
  171. $this->userFolder
  172. ->method('nodeExists')
  173. ->withConsecutive(['/File.txt'], ['/'])
  174. ->willReturnOnConsecutiveCalls(false, true);
  175. $this->userFolder
  176. ->method('get')
  177. ->with('/')
  178. ->willReturn($folder);
  179. $folder->expects($this->once())
  180. ->method('newFile')
  181. ->willReturn($file);
  182. $this->manager->create('/File.txt', 'testeditor', 'createEmpty');
  183. $firstResult = $this->manager->edit($expectedToken);
  184. $secondResult = $this->manager->edit($expectedToken);
  185. $this->assertInstanceOf(DataResponse::class, $firstResult);
  186. $this->assertInstanceOf(NotFoundResponse::class, $secondResult);
  187. }
  188. public function testOpenByPath(): void {
  189. $expectedToken = 'TOKEN' . time();
  190. $file = $this->createMock(File::class);
  191. $file->expects($this->any())
  192. ->method('getId')
  193. ->willReturn(123);
  194. $file->expects($this->any())
  195. ->method('getPath')
  196. ->willReturn('/admin/files/File.txt');
  197. $this->random->expects($this->once())
  198. ->method('generate')
  199. ->willReturn($expectedToken);
  200. $folder = $this->createMock(Folder::class);
  201. $this->userFolder
  202. ->method('nodeExists')
  203. ->withConsecutive(['/File.txt'], ['/'])
  204. ->willReturnOnConsecutiveCalls(false, true);
  205. $this->userFolder
  206. ->method('get')
  207. ->with('/File.txt')
  208. ->willReturn($file);
  209. $this->userFolder
  210. ->method('getRelativePath')
  211. ->willReturn('/File.txt');
  212. $this->manager->open('/File.txt', 'testeditor');
  213. $firstResult = $this->manager->edit($expectedToken);
  214. $secondResult = $this->manager->edit($expectedToken);
  215. $this->assertInstanceOf(DataResponse::class, $firstResult);
  216. $this->assertInstanceOf(NotFoundResponse::class, $secondResult);
  217. }
  218. public function testOpenById(): void {
  219. $expectedToken = 'TOKEN' . time();
  220. $fileRead = $this->createMock(File::class);
  221. $fileRead->method('getPermissions')
  222. ->willReturn(1);
  223. $fileRead->expects($this->any())
  224. ->method('getId')
  225. ->willReturn(123);
  226. $fileRead->expects($this->any())
  227. ->method('getPath')
  228. ->willReturn('/admin/files/shared_file.txt');
  229. $file = $this->createMock(File::class);
  230. $file->method('getPermissions')
  231. ->willReturn(1);
  232. $file->expects($this->any())
  233. ->method('getId')
  234. ->willReturn(123);
  235. $file->expects($this->any())
  236. ->method('getPath')
  237. ->willReturn('/admin/files/File.txt');
  238. $this->random->expects($this->once())
  239. ->method('generate')
  240. ->willReturn($expectedToken);
  241. $folder = $this->createMock(Folder::class);
  242. $folder->expects($this->any())
  243. ->method('getById')
  244. ->willReturn([
  245. $fileRead,
  246. $file
  247. ]);
  248. $this->userFolder
  249. ->method('nodeExists')
  250. ->withConsecutive(['/File.txt'], ['/'])
  251. ->willReturnOnConsecutiveCalls(false, true);
  252. $this->userFolder
  253. ->method('get')
  254. ->with('/')
  255. ->willReturn($folder);
  256. $this->userFolder
  257. ->method('getRelativePath')
  258. ->willReturn('/File.txt');
  259. $this->manager->open('/', 'testeditor', 123);
  260. $firstResult = $this->manager->edit($expectedToken);
  261. $secondResult = $this->manager->edit($expectedToken);
  262. $this->assertInstanceOf(DataResponse::class, $firstResult);
  263. $this->assertInstanceOf(NotFoundResponse::class, $secondResult);
  264. }
  265. public function testCreateFileAlreadyExists(): void {
  266. $this->expectException(\RuntimeException::class);
  267. $this->userFolder
  268. ->method('nodeExists')
  269. ->with('/File.txt')
  270. ->willReturn(true);
  271. $this->manager->create('/File.txt', 'testeditor', 'createEmpty');
  272. }
  273. }