diff options
Diffstat (limited to 'apps/files/tests/Controller')
-rw-r--r-- | apps/files/tests/Controller/ApiControllerTest.php | 249 | ||||
-rw-r--r-- | apps/files/tests/Controller/ConversionApiControllerTest.php | 96 | ||||
-rw-r--r-- | apps/files/tests/Controller/ViewControllerTest.php | 617 |
3 files changed, 410 insertions, 552 deletions
diff --git a/apps/files/tests/Controller/ApiControllerTest.php b/apps/files/tests/Controller/ApiControllerTest.php index 6df3f46c5a9..e74989eb2f5 100644 --- a/apps/files/tests/Controller/ApiControllerTest.php +++ b/apps/files/tests/Controller/ApiControllerTest.php @@ -1,47 +1,38 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Nina Pypchenko <22447785+nina-py@users.noreply.github.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OCA\Files\Controller; use OCA\Files\Service\TagService; use OCA\Files\Service\UserConfig; +use OCA\Files\Service\ViewConfig; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\FileDisplayResponse; +use OCP\AppFramework\Http\Response; use OCP\Files\File; use OCP\Files\Folder; +use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFile; +use OCP\Files\Storage\ISharedStorage; +use OCP\Files\Storage\IStorage; use OCP\Files\StorageNotAvailableException; use OCP\IConfig; +use OCP\IL10N; use OCP\IPreview; use OCP\IRequest; use OCP\IUser; use OCP\IUserSession; use OCP\Share\IManager; +use OCP\Share\IShare; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; /** @@ -50,33 +41,25 @@ use Test\TestCase; * @package OCA\Files\Controller */ class ApiControllerTest extends TestCase { - /** @var string */ - private $appName = 'files'; - /** @var \OCP\IUser */ - private $user; - /** @var IRequest */ - private $request; - /** @var TagService */ - private $tagService; - /** @var IPreview|\PHPUnit\Framework\MockObject\MockObject */ - private $preview; - /** @var ApiController */ - private $apiController; - /** @var \OCP\Share\IManager */ - private $shareManager; - /** @var \OCP\IConfig */ - private $config; - /** @var Folder|\PHPUnit\Framework\MockObject\MockObject */ - private $userFolder; - /** @var UserConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $userConfig; + private string $appName = 'files'; + private IUser $user; + private IRequest $request; + private TagService $tagService; + private IPreview&MockObject $preview; + private ApiController $apiController; + private IManager $shareManager; + private IConfig $config; + private Folder&MockObject $userFolder; + private UserConfig&MockObject $userConfig; + private ViewConfig&MockObject $viewConfig; + private IL10N&MockObject $l10n; + private IRootFolder&MockObject $rootFolder; + private LoggerInterface&MockObject $logger; protected function setUp(): void { parent::setUp(); - $this->request = $this->getMockBuilder(IRequest::class) - ->disableOriginalConstructor() - ->getMock(); + $this->request = $this->createMock(IRequest::class); $this->user = $this->createMock(IUser::class); $this->user->expects($this->any()) ->method('getUID') @@ -85,20 +68,16 @@ class ApiControllerTest extends TestCase { $userSession->expects($this->any()) ->method('getUser') ->willReturn($this->user); - $this->tagService = $this->getMockBuilder(TagService::class) - ->disableOriginalConstructor() - ->getMock(); - $this->shareManager = $this->getMockBuilder(IManager::class) - ->disableOriginalConstructor() - ->getMock(); - $this->preview = $this->getMockBuilder(IPreview::class) - ->disableOriginalConstructor() - ->getMock(); + $this->tagService = $this->createMock(TagService::class); + $this->shareManager = $this->createMock(IManager::class); + $this->preview = $this->createMock(IPreview::class); $this->config = $this->createMock(IConfig::class); - $this->userFolder = $this->getMockBuilder(Folder::class) - ->disableOriginalConstructor() - ->getMock(); + $this->userFolder = $this->createMock(Folder::class); $this->userConfig = $this->createMock(UserConfig::class); + $this->viewConfig = $this->createMock(ViewConfig::class); + $this->l10n = $this->createMock(IL10N::class); + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->apiController = new ApiController( $this->appName, @@ -109,16 +88,20 @@ class ApiControllerTest extends TestCase { $this->shareManager, $this->config, $this->userFolder, - $this->userConfig + $this->userConfig, + $this->viewConfig, + $this->l10n, + $this->rootFolder, + $this->logger, ); } - public function testUpdateFileTagsEmpty() { + public function testUpdateFileTagsEmpty(): void { $expected = new DataResponse([]); $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt')); } - public function testUpdateFileTagsWorking() { + public function testUpdateFileTagsWorking(): void { $this->tagService->expects($this->once()) ->method('updateFileTags') ->with('/path.txt', ['Tag1', 'Tag2']); @@ -132,37 +115,37 @@ class ApiControllerTest extends TestCase { $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2'])); } - public function testUpdateFileTagsNotFoundException() { + public function testUpdateFileTagsNotFoundException(): void { $this->tagService->expects($this->once()) ->method('updateFileTags') ->with('/path.txt', ['Tag1', 'Tag2']) - ->will($this->throwException(new NotFoundException('My error message'))); + ->willThrowException(new NotFoundException('My error message')); $expected = new DataResponse(['message' => 'My error message'], Http::STATUS_NOT_FOUND); $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2'])); } - public function testUpdateFileTagsStorageNotAvailableException() { + public function testUpdateFileTagsStorageNotAvailableException(): void { $this->tagService->expects($this->once()) ->method('updateFileTags') ->with('/path.txt', ['Tag1', 'Tag2']) - ->will($this->throwException(new StorageNotAvailableException('My error message'))); + ->willThrowException(new StorageNotAvailableException('My error message')); $expected = new DataResponse(['message' => 'My error message'], Http::STATUS_SERVICE_UNAVAILABLE); $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2'])); } - public function testUpdateFileTagsStorageGenericException() { + public function testUpdateFileTagsStorageGenericException(): void { $this->tagService->expects($this->once()) ->method('updateFileTags') ->with('/path.txt', ['Tag1', 'Tag2']) - ->will($this->throwException(new \Exception('My error message'))); + ->willThrowException(new \Exception('My error message')); $expected = new DataResponse(['message' => 'My error message'], Http::STATUS_NOT_FOUND); $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2'])); } - public function testGetThumbnailInvalidSize() { + public function testGetThumbnailInvalidSize(): void { $this->userFolder->method('get') ->with($this->equalTo('')) ->willThrowException(new NotFoundException()); @@ -170,8 +153,13 @@ class ApiControllerTest extends TestCase { $this->assertEquals($expected, $this->apiController->getThumbnail(0, 0, '')); } - public function testGetThumbnailInvalidImage() { + public function testGetThumbnailInvalidImage(): void { + $storage = $this->createMock(IStorage::class); + $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(false); + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $file->method('getStorage')->willReturn($storage); $this->userFolder->method('get') ->with($this->equalTo('unknown.jpg')) ->willReturn($file); @@ -183,8 +171,65 @@ class ApiControllerTest extends TestCase { $this->assertEquals($expected, $this->apiController->getThumbnail(10, 10, 'unknown.jpg')); } - public function testGetThumbnail() { + public function testGetThumbnailInvalidPartFile(): void { $file = $this->createMock(File::class); + $file->method('getId')->willReturn(0); + $this->userFolder->method('get') + ->with($this->equalTo('unknown.jpg')) + ->willReturn($file); + $expected = new DataResponse(['message' => 'File not found.'], Http::STATUS_NOT_FOUND); + $this->assertEquals($expected, $this->apiController->getThumbnail(10, 10, 'unknown.jpg')); + } + + public function testGetThumbnailSharedNoDownload(): void { + $share = $this->createMock(IShare::class); + $share->expects(self::once()) + ->method('canSeeContent') + ->willReturn(false); + + $storage = $this->createMock(ISharedStorage::class); + $storage->expects(self::once()) + ->method('instanceOfStorage') + ->with(ISharedStorage::class) + ->willReturn(true); + $storage->expects(self::once()) + ->method('getShare') + ->willReturn($share); + + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $file->method('getStorage')->willReturn($storage); + + $this->userFolder->method('get') + ->with('unknown.jpg') + ->willReturn($file); + + $this->preview->expects($this->never()) + ->method('getPreview'); + + $expected = new DataResponse(['message' => 'File not found.'], Http::STATUS_NOT_FOUND); + $this->assertEquals($expected, $this->apiController->getThumbnail(10, 10, 'unknown.jpg')); + } + + public function testGetThumbnailShared(): void { + $share = $this->createMock(IShare::class); + $share->expects(self::once()) + ->method('canSeeContent') + ->willReturn(true); + + $storage = $this->createMock(ISharedStorage::class); + $storage->expects(self::once()) + ->method('instanceOfStorage') + ->with(ISharedStorage::class) + ->willReturn(true); + $storage->expects(self::once()) + ->method('getShare') + ->willReturn($share); + + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $file->method('getStorage')->willReturn($storage); + $this->userFolder->method('get') ->with($this->equalTo('known.jpg')) ->willReturn($file); @@ -199,69 +244,55 @@ class ApiControllerTest extends TestCase { $ret = $this->apiController->getThumbnail(10, 10, 'known.jpg'); $this->assertEquals(Http::STATUS_OK, $ret->getStatus()); - $this->assertInstanceOf(Http\FileDisplayResponse::class, $ret); - } - - public function testUpdateFileSorting() { - $mode = 'mtime'; - $direction = 'desc'; - - $this->config->expects($this->exactly(2)) - ->method('setUserValue') - ->withConsecutive( - [$this->user->getUID(), 'files', 'file_sorting', $mode], - [$this->user->getUID(), 'files', 'file_sorting_direction', $direction], - ); - - $expected = new HTTP\Response(); - $actual = $this->apiController->updateFileSorting($mode, $direction); - $this->assertEquals($expected, $actual); + $this->assertInstanceOf(FileDisplayResponse::class, $ret); } - public function invalidSortingModeData() { - return [ - ['color', 'asc'], - ['name', 'size'], - ['foo', 'bar'] - ]; - } + public function testGetThumbnail(): void { + $storage = $this->createMock(IStorage::class); + $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(false); - /** - * @dataProvider invalidSortingModeData - */ - public function testUpdateInvalidFileSorting($mode, $direction) { - $this->config->expects($this->never()) - ->method('setUserValue'); + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $file->method('getStorage')->willReturn($storage); - $expected = new Http\Response(null); - $expected->setStatus(Http::STATUS_UNPROCESSABLE_ENTITY); + $this->userFolder->method('get') + ->with($this->equalTo('known.jpg')) + ->willReturn($file); + $preview = $this->createMock(ISimpleFile::class); + $preview->method('getName')->willReturn('my name'); + $preview->method('getMTime')->willReturn(42); + $this->preview->expects($this->once()) + ->method('getPreview') + ->with($this->equalTo($file), 10, 10, true) + ->willReturn($preview); - $result = $this->apiController->updateFileSorting($mode, $direction); + $ret = $this->apiController->getThumbnail(10, 10, 'known.jpg'); - $this->assertEquals($expected, $result); + $this->assertEquals(Http::STATUS_OK, $ret->getStatus()); + $this->assertInstanceOf(FileDisplayResponse::class, $ret); } - public function testShowHiddenFiles() { + public function testShowHiddenFiles(): void { $show = false; $this->config->expects($this->once()) ->method('setUserValue') ->with($this->user->getUID(), 'files', 'show_hidden', '0'); - $expected = new Http\Response(); + $expected = new Response(); $actual = $this->apiController->showHiddenFiles($show); $this->assertEquals($expected, $actual); } - public function testCropImagePreviews() { + public function testCropImagePreviews(): void { $crop = true; $this->config->expects($this->once()) ->method('setUserValue') ->with($this->user->getUID(), 'files', 'crop_image_previews', '1'); - $expected = new Http\Response(); + $expected = new Response(); $actual = $this->apiController->cropImagePreviews($crop); $this->assertEquals($expected, $actual); diff --git a/apps/files/tests/Controller/ConversionApiControllerTest.php b/apps/files/tests/Controller/ConversionApiControllerTest.php new file mode 100644 index 00000000000..659fbe1a956 --- /dev/null +++ b/apps/files/tests/Controller/ConversionApiControllerTest.php @@ -0,0 +1,96 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\Files\Controller; + +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCS\OCSException; +use OCP\AppFramework\OCS\OCSNotFoundException; +use OCP\Files\Conversion\IConversionManager; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\IL10N; +use OCP\IRequest; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +/** + * Class ConversionApiController + * + * @package OCA\Files\Controller + */ +class ConversionApiControllerTest extends TestCase { + private string $appName = 'files'; + private ConversionApiController $conversionApiController; + private IRequest&MockObject $request; + private IConversionManager&MockObject $fileConversionManager; + private IRootFolder&MockObject $rootFolder; + private File&MockObject $file; + private Folder&MockObject $userFolder; + private IL10N&MockObject $l10n; + private string $user; + + protected function setUp(): void { + parent::setUp(); + + $this->request = $this->createMock(IRequest::class); + $this->fileConversionManager = $this->createMock(IConversionManager::class); + $this->file = $this->createMock(File::class); + $this->l10n = $this->createMock(IL10N::class); + $this->user = 'userid'; + + $this->userFolder = $this->createMock(Folder::class); + + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->rootFolder->method('getUserFolder')->with($this->user)->willReturn($this->userFolder); + + $this->conversionApiController = new ConversionApiController( + $this->appName, + $this->request, + $this->fileConversionManager, + $this->rootFolder, + $this->l10n, + $this->user, + ); + } + + public function testThrowsNotFoundException(): void { + $this->expectException(OCSNotFoundException::class); + $this->conversionApiController->convert(42, 'image/png'); + } + + public function testThrowsOcsException(): void { + $this->userFolder->method('getFirstNodeById')->with(42)->willReturn($this->file); + $this->fileConversionManager->method('convert')->willThrowException(new \Exception()); + + $this->expectException(OCSException::class); + $this->conversionApiController->convert(42, 'image/png'); + } + + public function testConvert(): void { + $convertedFileAbsolutePath = $this->user . '/files/test.png'; + + $this->userFolder->method('getFirstNodeById')->with(42)->willReturn($this->file); + $this->userFolder->method('getRelativePath')->with($convertedFileAbsolutePath)->willReturn('/test.png'); + $this->userFolder->method('get')->with('/test.png')->willReturn($this->file); + + $this->file->method('getId')->willReturn(42); + + $this->fileConversionManager->method('convert')->with($this->file, 'image/png', null)->willReturn($convertedFileAbsolutePath); + + $actual = $this->conversionApiController->convert(42, 'image/png', null); + $expected = new DataResponse([ + 'path' => '/test.png', + 'fileId' => 42, + ], Http::STATUS_CREATED); + + $this->assertEquals($expected, $actual); + } +} diff --git a/apps/files/tests/Controller/ViewControllerTest.php b/apps/files/tests/Controller/ViewControllerTest.php index 08ec7d17a1d..01aa955a13e 100644 --- a/apps/files/tests/Controller/ViewControllerTest.php +++ b/apps/files/tests/Controller/ViewControllerTest.php @@ -1,105 +1,88 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Kesselberg <mail@danielkesselberg.de> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Michael Weimann <mail@michael-weimann.eu> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Nina Pypchenko <22447785+nina-py@users.noreply.github.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OCA\Files\Tests\Controller; -use OCA\Files\Activity\Helper; +use OC\Files\FilenameValidator; +use OC\Route\Router; +use OC\URLGenerator; use OCA\Files\Controller\ViewController; use OCA\Files\Service\UserConfig; +use OCA\Files\Service\ViewConfig; use OCP\App\IAppManager; -use OCP\AppFramework\Http; +use OCP\AppFramework\Http\ContentSecurityPolicy; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; +use OCP\Authentication\TwoFactorAuth\IRegistry; +use OCP\Diagnostics\IEventLogger; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\File; use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\Template\ITemplateManager; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserSession; -use OCP\Share\IManager; -use OCP\Template; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; use Test\TestCase; /** * Class ViewControllerTest * + * @group RoutingWeirdness + * * @package OCA\Files\Tests\Controller */ class ViewControllerTest extends TestCase { - /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */ - private $request; - /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */ - private $urlGenerator; - /** @var IL10N */ - private $l10n; - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $config; - /** @var EventDispatcherInterface */ - private $eventDispatcher; - /** @var ViewController|\PHPUnit\Framework\MockObject\MockObject */ - private $viewController; - /** @var IUser */ - private $user; - /** @var IUserSession */ - private $userSession; - /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */ - private $appManager; - /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */ - private $rootFolder; - /** @var Helper|\PHPUnit\Framework\MockObject\MockObject */ - private $activityHelper; - /** @var IInitialState|\PHPUnit\Framework\MockObject\MockObject */ - private $initialState; - /** @var ITemplateManager|\PHPUnit\Framework\MockObject\MockObject */ - private $templateManager; - /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */ - private $shareManager; - /** @var UserConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $userConfig; + private ContainerInterface&MockObject $container; + private IAppManager&MockObject $appManager; + private ICacheFactory&MockObject $cacheFactory; + private IConfig&MockObject $config; + private IEventDispatcher $eventDispatcher; + private IEventLogger&MockObject $eventLogger; + private IInitialState&MockObject $initialState; + private IL10N&MockObject $l10n; + private IRequest&MockObject $request; + private IRootFolder&MockObject $rootFolder; + private ITemplateManager&MockObject $templateManager; + private IURLGenerator $urlGenerator; + private IUser&MockObject $user; + private IUserSession&MockObject $userSession; + private LoggerInterface&MockObject $logger; + private UserConfig&MockObject $userConfig; + private ViewConfig&MockObject $viewConfig; + private Router $router; + private IRegistry&MockObject $twoFactorRegistry; + + private ViewController&MockObject $viewController; protected function setUp(): void { parent::setUp(); - $this->request = $this->getMockBuilder(IRequest::class)->getMock(); - $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)->getMock(); - $this->l10n = $this->getMockBuilder(IL10N::class)->getMock(); - $this->config = $this->getMockBuilder(IConfig::class)->getMock(); + $this->appManager = $this->createMock(IAppManager::class); + $this->config = $this->createMock(IConfig::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); - $this->userSession = $this->getMockBuilder(IUserSession::class)->getMock(); - $this->appManager = $this->getMockBuilder('\OCP\App\IAppManager')->getMock(); + $this->initialState = $this->createMock(IInitialState::class); + $this->l10n = $this->createMock(IL10N::class); + $this->request = $this->createMock(IRequest::class); + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->templateManager = $this->createMock(ITemplateManager::class); + $this->userConfig = $this->createMock(UserConfig::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->viewConfig = $this->createMock(ViewConfig::class); + $this->twoFactorRegistry = $this->createMock(IRegistry::class); + $this->user = $this->getMockBuilder(IUser::class)->getMock(); $this->user->expects($this->any()) ->method('getUID') @@ -107,13 +90,42 @@ class ViewControllerTest extends TestCase { $this->userSession->expects($this->any()) ->method('getUser') ->willReturn($this->user); - $this->rootFolder = $this->getMockBuilder('\OCP\Files\IRootFolder')->getMock(); - $this->activityHelper = $this->createMock(Helper::class); - $this->initialState = $this->createMock(IInitialState::class); - $this->templateManager = $this->createMock(ITemplateManager::class); - $this->shareManager = $this->createMock(IManager::class); - $this->userConfig = $this->createMock(UserConfig::class); - $this->viewController = $this->getMockBuilder('\OCA\Files\Controller\ViewController') + + // Make sure we know the app is enabled + $this->appManager->expects($this->any()) + ->method('cleanAppId') + ->willReturnArgument(0); + $this->appManager->expects($this->any()) + ->method('getAppPath') + ->willReturnCallback(fn (string $appid): string => \OC::$SERVERROOT . '/apps/' . $appid); + $this->appManager->expects($this->any()) + ->method('isAppLoaded') + ->willReturn(true); + + $this->cacheFactory = $this->createMock(ICacheFactory::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->eventLogger = $this->createMock(IEventLogger::class); + $this->container = $this->createMock(ContainerInterface::class); + $this->router = new Router( + $this->logger, + $this->request, + $this->config, + $this->eventLogger, + $this->container, + $this->appManager, + ); + + // Create a real URLGenerator instance to generate URLs + $this->urlGenerator = new URLGenerator( + $this->config, + $this->userSession, + $this->cacheFactory, + $this->request, + $this->router + ); + + $filenameValidator = $this->createMock(FilenameValidator::class); + $this->viewController = $this->getMockBuilder(ViewController::class) ->setConstructorArgs([ 'files', $this->request, @@ -124,20 +136,20 @@ class ViewControllerTest extends TestCase { $this->userSession, $this->appManager, $this->rootFolder, - $this->activityHelper, $this->initialState, $this->templateManager, - $this->shareManager, $this->userConfig, + $this->viewConfig, + $filenameValidator, + $this->twoFactorRegistry, + ]) + ->onlyMethods([ + 'getStorageInfo', ]) - ->setMethods([ - 'getStorageInfo', - 'renderScript' - ]) - ->getMock(); + ->getMock(); } - public function testIndexWithRegularBrowser() { + public function testIndexWithRegularBrowser(): void { $this->viewController ->expects($this->any()) ->method('getStorageInfo') @@ -149,397 +161,105 @@ class ViewControllerTest extends TestCase { 'owner' => 'MyName', 'ownerDisplayName' => 'MyDisplayName', ]); + $this->config ->method('getUserValue') ->willReturnMap([ [$this->user->getUID(), 'files', 'file_sorting', 'name', 'name'], [$this->user->getUID(), 'files', 'file_sorting_direction', 'asc', 'asc'], + [$this->user->getUID(), 'files', 'files_sorting_configs', '{}', '{}'], [$this->user->getUID(), 'files', 'show_hidden', false, false], [$this->user->getUID(), 'files', 'crop_image_previews', true, true], [$this->user->getUID(), 'files', 'show_grid', true], ]); + $baseFolderFiles = $this->getMockBuilder(Folder::class)->getMock(); + + $this->rootFolder->expects($this->any()) + ->method('getUserFolder') + ->with('testuser1') + ->willReturn($baseFolderFiles); + $this->config ->expects($this->any()) ->method('getAppValue') ->willReturnArgument(2); - $this->shareManager->method('shareApiAllowLinks') - ->willReturn(true); - $nav = new Template('files', 'appnavigation'); - $nav->assign('navigationItems', [ - 'files' => [ - 'id' => 'files', - 'appname' => 'files', - 'script' => 'list.php', - 'order' => 0, - 'name' => \OC::$server->getL10N('files')->t('All files'), - 'active' => false, - 'icon' => '', - 'type' => 'link', - 'classes' => '', - 'expanded' => false, - 'unread' => 0, - ], - 'recent' => [ - 'id' => 'recent', - 'appname' => 'files', - 'script' => 'recentlist.php', - 'order' => 2, - 'name' => \OC::$server->getL10N('files')->t('Recent'), - 'active' => false, - 'icon' => '', - 'type' => 'link', - 'classes' => '', - 'expanded' => false, - 'unread' => 0, - ], - 'favorites' => [ - 'id' => 'favorites', - 'appname' => 'files', - 'script' => 'simplelist.php', - 'order' => 5, - 'name' => \OC::$server->getL10N('files')->t('Favorites'), - 'active' => false, - 'icon' => '', - 'type' => 'link', - 'classes' => 'collapsible', - 'sublist' => [ - [ - 'id' => '-test1', - 'dir' => '/test1', - 'order' => 6, - 'name' => 'test1', - 'icon' => 'folder', - 'params' => [ - 'view' => 'files', - 'dir' => '/test1', - ], - ], - [ - 'name' => 'test2', - 'id' => '-test2-', - 'dir' => '/test2/', - 'order' => 7, - 'icon' => 'folder', - 'params' => [ - 'view' => 'files', - 'dir' => '/test2/', - ], - ], - [ - 'name' => 'sub4', - 'id' => '-test3-sub4', - 'dir' => '/test3/sub4', - 'order' => 8, - 'icon' => 'folder', - 'params' => [ - 'view' => 'files', - 'dir' => '/test3/sub4', - ], - ], - [ - 'name' => 'sub6', - 'id' => '-test5-sub6-', - 'dir' => '/test5/sub6/', - 'order' => 9, - 'icon' => 'folder', - 'params' => [ - 'view' => 'files', - 'dir' => '/test5/sub6/', - ], - ], - ], - 'expanded' => false, - 'unread' => 0, - ], - 'systemtagsfilter' => [ - 'id' => 'systemtagsfilter', - 'appname' => 'systemtags', - 'script' => 'list.php', - 'order' => 25, - 'name' => \OC::$server->getL10N('systemtags')->t('Tags'), - 'active' => false, - 'icon' => '', - 'type' => 'link', - 'classes' => '', - 'expanded' => false, - 'unread' => 0, - ], - 'trashbin' => [ - 'id' => 'trashbin', - 'appname' => 'files_trashbin', - 'script' => 'list.php', - 'order' => 50, - 'name' => \OC::$server->getL10N('files_trashbin')->t('Deleted files'), - 'active' => false, - 'icon' => '', - 'type' => 'link', - 'classes' => 'pinned', - 'expanded' => false, - 'unread' => 0, - ], - 'shareoverview' => [ - 'id' => 'shareoverview', - 'appname' => 'files_sharing', - 'script' => 'list.php', - 'order' => 18, - 'name' => \OC::$server->getL10N('files_sharing')->t('Shares'), - 'classes' => 'collapsible', - 'sublist' => [ - [ - 'id' => 'sharingout', - 'appname' => 'files_sharing', - 'script' => 'list.php', - 'order' => 16, - 'name' => \OC::$server->getL10N('files_sharing')->t('Shared with others'), - ], - [ - 'id' => 'sharingin', - 'appname' => 'files_sharing', - 'script' => 'list.php', - 'order' => 15, - 'name' => \OC::$server->getL10N('files_sharing')->t('Shared with you'), - ], - [ - 'id' => 'sharinglinks', - 'appname' => 'files_sharing', - 'script' => 'list.php', - 'order' => 17, - 'name' => \OC::$server->getL10N('files_sharing')->t('Shared by link', []), - ], - [ - 'id' => 'deletedshares', - 'appname' => 'files_sharing', - 'script' => 'list.php', - 'order' => 19, - 'name' => \OC::$server->getL10N('files_sharing')->t('Deleted shares'), - ], - [ - 'id' => 'pendingshares', - 'appname' => 'files_sharing', - 'script' => 'list.php', - 'order' => 19, - 'name' => \OC::$server->getL10N('files_sharing')->t('Pending shares'), - ], - ], - 'active' => false, - 'icon' => '', - 'type' => 'link', - 'expanded' => false, - 'unread' => 0, - ] - ]); - - $expected = new Http\TemplateResponse( + $expected = new TemplateResponse( 'files', 'index', - [ - 'usedSpacePercent' => 123, - 'owner' => 'MyName', - 'ownerDisplayName' => 'MyDisplayName', - 'isPublic' => false, - 'defaultFileSorting' => 'name', - 'defaultFileSortingDirection' => 'asc', - 'showHiddenFiles' => 0, - 'cropImagePreviews' => 1, - 'fileNotFound' => 0, - 'allowShareWithLink' => 'yes', - 'appNavigation' => $nav, - 'appContents' => [ - 'files' => [ - 'id' => 'files', - 'content' => null, - ], - 'recent' => [ - 'id' => 'recent', - 'content' => null, - ], - 'favorites' => [ - 'id' => 'favorites', - 'content' => null, - ], - 'systemtagsfilter' => [ - 'id' => 'systemtagsfilter', - 'content' => null, - ], - 'trashbin' => [ - 'id' => 'trashbin', - 'content' => null, - ], - 'sharingout' => [ - 'id' => 'sharingout', - 'content' => null, - ], - 'sharingin' => [ - 'id' => 'sharingin', - 'content' => null, - ], - 'sharinglinks' => [ - 'id' => 'sharinglinks', - 'content' => null, - ], - 'deletedshares' => [ - 'id' => 'deletedshares', - 'content' => null, - ], - 'pendingshares' => [ - 'id' => 'pendingshares', - 'content' => null - ], - 'shareoverview' => [ - 'id' => 'shareoverview', - 'content' => null, - ], - '-test1' => [ - 'id' => '-test1', - 'content' => '', - ], - '-test2-' => [ - 'id' => '-test2-', - 'content' => '', - ], - '-test3-sub4' => [ - 'id' => '-test3-sub4', - 'content' => '', - ], - '-test5-sub6-' => [ - 'id' => '-test5-sub6-', - 'content' => '', - ], - ], - 'hiddenFields' => [], - 'showgridview' => null - ] ); - $policy = new Http\ContentSecurityPolicy(); + $policy = new ContentSecurityPolicy(); + $policy->addAllowedWorkerSrcDomain('\'self\''); $policy->addAllowedFrameDomain('\'self\''); $expected->setContentSecurityPolicy($policy); - $this->activityHelper->method('getFavoriteFilePaths') - ->with($this->user->getUID()) - ->willReturn([ - 'item' => [], - 'folders' => [ - '/test1', - '/test2/', - '/test3/sub4', - '/test5/sub6/', - ], - ]); - $this->assertEquals($expected, $this->viewController->index('MyDir', 'MyView')); } - public function testShowFileRouteWithFolder() { - $node = $this->getMockBuilder(Folder::class)->getMock(); - $node->expects($this->once()) - ->method('getPath') - ->willReturn('/testuser1/files/test/sub'); + public static function dataTestShortRedirect(): array { + // openfile is true by default + // opendetails is undefined by default + // both will be evaluated as truthy + return [ + [null, null, '/index.php/apps/files/files/123456?openfile=true'], + ['', null, '/index.php/apps/files/files/123456?openfile=true'], + [null, '', '/index.php/apps/files/files/123456?openfile=true&opendetails=true'], + ['', '', '/index.php/apps/files/files/123456?openfile=true&opendetails=true'], + ['false', '', '/index.php/apps/files/files/123456?openfile=false'], + [null, 'false', '/index.php/apps/files/files/123456?openfile=true&opendetails=false'], + ['true', 'false', '/index.php/apps/files/files/123456?openfile=true&opendetails=false'], + ['false', 'true', '/index.php/apps/files/files/123456?openfile=false&opendetails=true'], + ['false', 'false', '/index.php/apps/files/files/123456?openfile=false&opendetails=false'], + ]; + } - $baseFolder = $this->getMockBuilder(Folder::class)->getMock(); + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestShortRedirect')] + public function testShortRedirect(?string $openfile, ?string $opendetails, string $result): void { + $this->appManager->expects($this->any()) + ->method('isEnabledForUser') + ->with('files') + ->willReturn(true); - $this->rootFolder->expects($this->once()) + $baseFolderFiles = $this->getMockBuilder(Folder::class)->getMock(); + $this->rootFolder->expects($this->any()) ->method('getUserFolder') ->with('testuser1') - ->willReturn($baseFolder); - - $baseFolder->expects($this->once()) - ->method('getById') - ->with(123) - ->willReturn([$node]); - $baseFolder->expects($this->once()) - ->method('getRelativePath') - ->with('/testuser1/files/test/sub') - ->willReturn('/test/sub'); - - $this->urlGenerator - ->expects($this->once()) - ->method('linkToRoute') - ->with('files.view.index', ['dir' => '/test/sub']) - ->willReturn('/apps/files/?dir=/test/sub'); - - $expected = new Http\RedirectResponse('/apps/files/?dir=/test/sub'); - $this->assertEquals($expected, $this->viewController->index('', '', '123')); - } + ->willReturn($baseFolderFiles); - public function testShowFileRouteWithFile() { $parentNode = $this->getMockBuilder(Folder::class)->getMock(); $parentNode->expects($this->once()) ->method('getPath') - ->willReturn('testuser1/files/test'); - - $baseFolder = $this->getMockBuilder(Folder::class)->getMock(); - - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('testuser1') - ->willReturn($baseFolder); + ->willReturn('testuser1/files/Folder'); $node = $this->getMockBuilder(File::class)->getMock(); $node->expects($this->once()) ->method('getParent') ->willReturn($parentNode); - $node->expects($this->once()) - ->method('getName') - ->willReturn('somefile.txt'); - - $baseFolder->expects($this->once()) - ->method('getById') - ->with(123) - ->willReturn([$node]); - $baseFolder->expects($this->once()) - ->method('getRelativePath') - ->with('testuser1/files/test') - ->willReturn('/test'); - - $this->urlGenerator - ->expects($this->once()) - ->method('linkToRoute') - ->with('files.view.index', ['dir' => '/test', 'scrollto' => 'somefile.txt']) - ->willReturn('/apps/files/?dir=/test/sub&scrollto=somefile.txt'); - $expected = new Http\RedirectResponse('/apps/files/?dir=/test/sub&scrollto=somefile.txt'); - $this->assertEquals($expected, $this->viewController->index('', '', '123')); - } - - public function testShowFileRouteWithInvalidFileId() { - $baseFolder = $this->getMockBuilder(Folder::class)->getMock(); - $this->rootFolder->expects($this->once()) - ->method('getUserFolder') - ->with('testuser1') - ->willReturn($baseFolder); - - $baseFolder->expects($this->once()) - ->method('getById') - ->with(123) - ->willReturn([]); + $baseFolderFiles->expects($this->any()) + ->method('getFirstNodeById') + ->with(123456) + ->willReturn($node); - $this->urlGenerator->expects($this->once()) - ->method('linkToRoute') - ->with('files.view.index', ['fileNotFound' => true]) - ->willReturn('redirect.url'); - - $response = $this->viewController->index('', 'MyView', '123'); - $this->assertInstanceOf('OCP\AppFramework\Http\RedirectResponse', $response); - $this->assertEquals('redirect.url', $response->getRedirectURL()); + $response = $this->viewController->showFile('123456', $opendetails, $openfile); + $this->assertStringContainsString($result, $response->getHeaders()['Location']); } - public function testShowFileRouteWithTrashedFile() { - $this->appManager->expects($this->once()) + public function testShowFileRouteWithTrashedFile(): void { + $this->appManager->expects($this->exactly(2)) ->method('isEnabledForUser') - ->with('files_trashbin') ->willReturn(true); - $parentNode = $this->getMockBuilder(Folder::class)->getMock(); + $parentNode = $this->createMock(Folder::class); $parentNode->expects($this->once()) ->method('getPath') ->willReturn('testuser1/files_trashbin/files/test.d1462861890/sub'); - $baseFolderFiles = $this->getMockBuilder(Folder::class)->getMock(); - $baseFolderTrash = $this->getMockBuilder(Folder::class)->getMock(); + $baseFolderFiles = $this->createMock(Folder::class); + $baseFolderTrash = $this->createMock(Folder::class); - $this->rootFolder->expects($this->once()) + $this->rootFolder->expects($this->any()) ->method('getUserFolder') ->with('testuser1') ->willReturn($baseFolderFiles); @@ -548,35 +268,46 @@ class ViewControllerTest extends TestCase { ->with('testuser1/files_trashbin/files/') ->willReturn($baseFolderTrash); - $baseFolderFiles->expects($this->once()) - ->method('getById') + $baseFolderFiles->expects($this->any()) + ->method('getFirstNodeById') ->with(123) - ->willReturn([]); + ->willReturn(null); - $node = $this->getMockBuilder(File::class)->getMock(); + $node = $this->createMock(File::class); $node->expects($this->once()) ->method('getParent') ->willReturn($parentNode); - $node->expects($this->once()) - ->method('getName') - ->willReturn('somefile.txt'); $baseFolderTrash->expects($this->once()) - ->method('getById') + ->method('getFirstNodeById') ->with(123) - ->willReturn([$node]); + ->willReturn($node); $baseFolderTrash->expects($this->once()) ->method('getRelativePath') ->with('testuser1/files_trashbin/files/test.d1462861890/sub') ->willReturn('/test.d1462861890/sub'); - $this->urlGenerator - ->expects($this->once()) - ->method('linkToRoute') - ->with('files.view.index', ['view' => 'trashbin', 'dir' => '/test.d1462861890/sub', 'scrollto' => 'somefile.txt']) - ->willReturn('/apps/files/?view=trashbin&dir=/test.d1462861890/sub&scrollto=somefile.txt'); - - $expected = new Http\RedirectResponse('/apps/files/?view=trashbin&dir=/test.d1462861890/sub&scrollto=somefile.txt'); + $expected = new RedirectResponse('/index.php/apps/files/trashbin/123?dir=/test.d1462861890/sub'); $this->assertEquals($expected, $this->viewController->index('', '', '123')); } + + public function testTwoFactorAuthEnabled(): void { + $this->twoFactorRegistry->method('getProviderStates') + ->willReturn([ + 'totp' => true, + 'backup_codes' => true, + ]); + + $invokedCountProvideInitialState = $this->exactly(9); + $this->initialState->expects($invokedCountProvideInitialState) + ->method('provideInitialState') + ->willReturnCallback(function ($key, $data) use ($invokedCountProvideInitialState) { + if ($invokedCountProvideInitialState->numberOfInvocations() === 9) { + $this->assertEquals('isTwoFactorEnabled', $key); + $this->assertTrue($data); + } + }); + + $this->viewController->index('', '', null); + } } |