diff options
Diffstat (limited to 'apps/theming/tests')
20 files changed, 1082 insertions, 1318 deletions
diff --git a/apps/theming/tests/CapabilitiesTest.php b/apps/theming/tests/CapabilitiesTest.php index 566380b3237..aa08a45a28b 100644 --- a/apps/theming/tests/CapabilitiesTest.php +++ b/apps/theming/tests/CapabilitiesTest.php @@ -1,30 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Guillaume COMPAGNON <gcompagnon@outlook.com> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Joas Schilling <coding@schilljs.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests; @@ -37,6 +16,8 @@ use OCP\Files\IAppData; use OCP\IConfig; use OCP\IURLGenerator; use OCP\IUserSession; +use OCP\ServerVersion; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; /** @@ -45,38 +26,35 @@ use Test\TestCase; * @package OCA\Theming\Tests */ class CapabilitiesTest extends TestCase { - /** @var ThemingDefaults|\PHPUnit\Framework\MockObject\MockObject */ - protected $theming; - - /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */ - protected $url; - - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ - protected $config; - - /** @var Util|\PHPUnit\Framework\MockObject\MockObject */ - protected $util; - + protected ThemingDefaults&MockObject $theming; + protected IURLGenerator&MockObject $url; + protected IConfig&MockObject $config; + protected Util&MockObject $util; protected IUserSession $userSession; - - /** @var Capabilities */ - protected $capabilities; + protected Capabilities $capabilities; protected function setUp(): void { parent::setUp(); $this->theming = $this->createMock(ThemingDefaults::class); - $this->url = $this->getMockBuilder(IURLGenerator::class)->getMock(); + $this->url = $this->createMock(IURLGenerator::class); $this->config = $this->createMock(IConfig::class); $this->util = $this->createMock(Util::class); $this->userSession = $this->createMock(IUserSession::class); - $this->capabilities = new Capabilities($this->theming, $this->util, $this->url, $this->config, $this->userSession); + $this->capabilities = new Capabilities( + $this->theming, + $this->util, + $this->url, + $this->config, + $this->userSession, + ); } - public function dataGetCapabilities() { + public static function dataGetCapabilities(): array { return [ - ['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', 'http://absolute/', true, [ + ['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', '#fff', '#000', 'http://absolute/', true, [ 'name' => 'name', + 'productName' => 'name', 'url' => 'url', 'slogan' => 'slogan', 'color' => '#FFFFFF', @@ -86,13 +64,15 @@ class CapabilitiesTest extends TestCase { 'color-element-dark' => '#FFFFFF', 'logo' => 'http://absolute/logo', 'background' => 'http://absolute/background', + 'background-text' => '#000', 'background-plain' => false, 'background-default' => false, 'logoheader' => 'http://absolute/logo', 'favicon' => 'http://absolute/logo', ]], - ['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', 'http://localhost/', false, [ + ['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', '#fff', '#000', 'http://localhost/', false, [ 'name' => 'name1', + 'productName' => 'name1', 'url' => 'url2', 'slogan' => 'slogan3', 'color' => '#01e4a0', @@ -102,13 +82,15 @@ class CapabilitiesTest extends TestCase { 'color-element-dark' => '#01e4a0', 'logo' => 'http://localhost/logo5', 'background' => 'http://localhost/background6', + 'background-text' => '#000', 'background-plain' => false, 'background-default' => true, 'logoheader' => 'http://localhost/logo5', 'favicon' => 'http://localhost/logo5', ]], - ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', 'http://localhost/', true, [ + ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', true, [ 'name' => 'name1', + 'productName' => 'name1', 'url' => 'url2', 'slogan' => 'slogan3', 'color' => '#000000', @@ -118,13 +100,15 @@ class CapabilitiesTest extends TestCase { 'color-element-dark' => '#4d4d4d', 'logo' => 'http://localhost/logo5', 'background' => '#000000', + 'background-text' => '#ffffff', 'background-plain' => true, 'background-default' => false, 'logoheader' => 'http://localhost/logo5', 'favicon' => 'http://localhost/logo5', ]], - ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', 'http://localhost/', false, [ + ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', false, [ 'name' => 'name1', + 'productName' => 'name1', 'url' => 'url2', 'slogan' => 'slogan3', 'color' => '#000000', @@ -134,6 +118,7 @@ class CapabilitiesTest extends TestCase { 'color-element-dark' => '#4d4d4d', 'logo' => 'http://localhost/logo5', 'background' => '#000000', + 'background-text' => '#ffffff', 'background-plain' => true, 'background-default' => true, 'logoheader' => 'http://localhost/logo5', @@ -143,19 +128,10 @@ class CapabilitiesTest extends TestCase { } /** - * @dataProvider dataGetCapabilities - * @param string $name - * @param string $url - * @param string $slogan - * @param string $color - * @param string $textColor - * @param string $logo - * @param string $background - * @param string $baseUrl - * @param bool $backgroundThemed - * @param string[] $expected + * @param non-empty-array<string, string> $expected */ - public function testGetCapabilities($name, $url, $slogan, $color, $textColor, $logo, $background, $baseUrl, $backgroundThemed, array $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetCapabilities')] + public function testGetCapabilities(string $name, string $url, string $slogan, string $color, string $textColor, string $logo, string $background, string $backgroundColor, string $backgroundTextColor, string $baseUrl, bool $backgroundThemed, array $expected): void { $this->config->expects($this->once()) ->method('getAppValue') ->willReturn($background); @@ -163,11 +139,20 @@ class CapabilitiesTest extends TestCase { ->method('getName') ->willReturn($name); $this->theming->expects($this->once()) + ->method('getProductName') + ->willReturn($name); + $this->theming->expects($this->once()) ->method('getBaseUrl') ->willReturn($url); $this->theming->expects($this->once()) ->method('getSlogan') ->willReturn($slogan); + $this->theming->expects($this->once()) + ->method('getColorBackground') + ->willReturn($backgroundColor); + $this->theming->expects($this->once()) + ->method('getTextColorBackground') + ->willReturn($backgroundTextColor); $this->theming->expects($this->atLeast(1)) ->method('getDefaultColorPrimary') ->willReturn($color); @@ -175,7 +160,7 @@ class CapabilitiesTest extends TestCase { ->method('getLogo') ->willReturn($logo); - $util = new Util($this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class), $this->createMock(ImageManager::class)); + $util = new Util($this->createMock(ServerVersion::class), $this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class), $this->createMock(ImageManager::class)); $this->util->expects($this->exactly(3)) ->method('elementColor') ->with($color) diff --git a/apps/theming/tests/Controller/IconControllerTest.php b/apps/theming/tests/Controller/IconControllerTest.php index d2b52cf738a..c5034600e03 100644 --- a/apps/theming/tests/Controller/IconControllerTest.php +++ b/apps/theming/tests/Controller/IconControllerTest.php @@ -1,29 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net> - * - * @author Joas Schilling <coding@schilljs.com> - * @author Julius Haertl <jus@bitgrid.net> - * @author Julius Härtl <jus@bitgrid.net> - * @author Michael Weimann <mail@michael-weimann.eu> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Controller; @@ -39,29 +19,19 @@ use OCP\AppFramework\Http\DataDisplayResponse; use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Files\NotFoundException; -use OCP\IConfig; use OCP\IRequest; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class IconControllerTest extends TestCase { - /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */ - private $request; - /** @var ThemingDefaults|\PHPUnit\Framework\MockObject\MockObject */ - private $themingDefaults; - /** @var \OCP\AppFramework\Utility\ITimeFactory */ - private $timeFactory; - /** @var IconController|\PHPUnit\Framework\MockObject\MockObject */ - private $iconController; - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $config; - /** @var IconBuilder|\PHPUnit\Framework\MockObject\MockObject */ - private $iconBuilder; - /** @var FileAccessHelper|\PHPUnit\Framework\MockObject\MockObject */ - private $fileAccessHelper; - /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */ - private $appManager; - /** @var ImageManager */ - private $imageManager; + private IRequest&MockObject $request; + private ThemingDefaults&MockObject $themingDefaults; + private ITimeFactory&MockObject $timeFactory; + private IconBuilder&MockObject $iconBuilder; + private FileAccessHelper&MockObject $fileAccessHelper; + private IAppManager&MockObject $appManager; + private ImageManager&MockObject $imageManager; + private IconController $iconController; protected function setUp(): void { $this->request = $this->createMock(IRequest::class); @@ -102,7 +72,7 @@ class IconControllerTest extends TestCase { return new SimpleFile($icon); } - public function testGetThemedIcon() { + public function testGetThemedIcon(): void { $file = $this->iconFileMock('icon-core-filetypes_folder.svg', 'filecontent'); $this->imageManager->expects($this->once()) ->method('getCachedImage') @@ -113,7 +83,7 @@ class IconControllerTest extends TestCase { $this->assertEquals($expected, $this->iconController->getThemedIcon('core', 'filetypes/folder.svg')); } - public function testGetFaviconDefault() { + public function testGetFaviconDefault(): void { if (!extension_loaded('imagick')) { $this->markTestSkipped('Imagemagick is required for dynamic icon generation.'); } @@ -125,13 +95,13 @@ class IconControllerTest extends TestCase { $this->imageManager->expects($this->once()) ->method('getImage', false) ->with('favicon') - ->will($this->throwException(new NotFoundException())); + ->willThrowException(new NotFoundException()); $this->imageManager->expects($this->any()) ->method('shouldReplaceIcons') ->willReturn(true); $this->imageManager->expects($this->once()) ->method('getCachedImage') - ->will($this->throwException(new NotFoundException())); + ->willThrowException(new NotFoundException()); $this->iconBuilder->expects($this->once()) ->method('getFavicon') ->with('core') @@ -145,11 +115,11 @@ class IconControllerTest extends TestCase { $this->assertEquals($expected, $this->iconController->getFavicon()); } - public function testGetFaviconFail() { + public function testGetFaviconFail(): void { $this->imageManager->expects($this->once()) ->method('getImage') ->with('favicon', false) - ->will($this->throwException(new NotFoundException())); + ->willThrowException(new NotFoundException()); $this->imageManager->expects($this->any()) ->method('shouldReplaceIcons') ->willReturn(false); @@ -163,7 +133,7 @@ class IconControllerTest extends TestCase { $this->assertEquals($expected, $this->iconController->getFavicon()); } - public function testGetTouchIconDefault() { + public function testGetTouchIconDefault(): void { if (!extension_loaded('imagick')) { $this->markTestSkipped('Imagemagick is required for dynamic icon generation.'); } @@ -174,7 +144,7 @@ class IconControllerTest extends TestCase { $this->imageManager->expects($this->once()) ->method('getImage') - ->will($this->throwException(new NotFoundException())); + ->willThrowException(new NotFoundException()); $this->imageManager->expects($this->any()) ->method('shouldReplaceIcons') ->willReturn(true); @@ -185,7 +155,7 @@ class IconControllerTest extends TestCase { $file = $this->iconFileMock('filename', 'filecontent'); $this->imageManager->expects($this->once()) ->method('getCachedImage') - ->will($this->throwException(new NotFoundException())); + ->willThrowException(new NotFoundException()); $this->imageManager->expects($this->once()) ->method('setCachedImage') ->willReturn($file); @@ -195,11 +165,11 @@ class IconControllerTest extends TestCase { $this->assertEquals($expected, $this->iconController->getTouchIcon()); } - public function testGetTouchIconFail() { + public function testGetTouchIconFail(): void { $this->imageManager->expects($this->once()) ->method('getImage') ->with('favicon') - ->will($this->throwException(new NotFoundException())); + ->willThrowException(new NotFoundException()); $this->imageManager->expects($this->any()) ->method('shouldReplaceIcons') ->willReturn(false); diff --git a/apps/theming/tests/Controller/ThemingControllerTest.php b/apps/theming/tests/Controller/ThemingControllerTest.php index 5bc27069c6e..fb461f03a28 100644 --- a/apps/theming/tests/Controller/ThemingControllerTest.php +++ b/apps/theming/tests/Controller/ThemingControllerTest.php @@ -1,35 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> - * - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Julius Haertl <jus@bitgrid.net> - * @author Julius Härtl <jus@bitgrid.net> - * @author Kyle Fazzari <kyrofa@ubuntu.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Michael Weimann <mail@michael-weimann.eu> - * @author rakekniven <mark.ziegler@rakekniven.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Controller; @@ -40,54 +14,51 @@ use OCA\Theming\Service\ThemesService; use OCA\Theming\ThemingDefaults; use OCP\App\IAppManager; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\FileDisplayResponse; +use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Utility\ITimeFactory; -use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFile; use OCP\IConfig; use OCP\IL10N; +use OCP\INavigationManager; use OCP\IRequest; use OCP\ITempManager; use OCP\IURLGenerator; +use OCP\Server; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class ThemingControllerTest extends TestCase { - /** @var IRequest|MockObject */ - private $request; - /** @var IConfig|MockObject */ - private $config; - /** @var ThemingDefaults|MockObject */ - private $themingDefaults; - /** @var IL10N|MockObject */ - private $l10n; - /** @var ThemingController */ - private $themingController; - /** @var ITempManager */ - private $tempManager; - /** @var IAppManager|MockObject */ - private $appManager; - /** @var IAppData|MockObject */ - private $appData; - /** @var ImageManager|MockObject */ - private $imageManager; - /** @var IURLGenerator|MockObject */ - private $urlGenerator; - /** @var ThemeService|MockObject */ - private $themesService; + + private IRequest&MockObject $request; + private IConfig&MockObject $config; + private IAppConfig&MockObject $appConfig; + private ThemingDefaults&MockObject $themingDefaults; + private IL10N&MockObject $l10n; + private IAppManager&MockObject $appManager; + private ImageManager&MockObject $imageManager; + private IURLGenerator&MockObject $urlGenerator; + private ThemesService&MockObject $themesService; + private INavigationManager&MockObject $navigationManager; + + private ThemingController $themingController; protected function setUp(): void { $this->request = $this->createMock(IRequest::class); $this->config = $this->createMock(IConfig::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->themingDefaults = $this->createMock(ThemingDefaults::class); $this->l10n = $this->createMock(L10N::class); - $this->appData = $this->createMock(IAppData::class); $this->appManager = $this->createMock(IAppManager::class); - $this->tempManager = \OC::$server->getTempManager(); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->imageManager = $this->createMock(ImageManager::class); $this->themesService = $this->createMock(ThemesService::class); + $this->navigationManager = $this->createMock(INavigationManager::class); $timeFactory = $this->createMock(ITimeFactory::class); $timeFactory->expects($this->any()) @@ -100,20 +71,20 @@ class ThemingControllerTest extends TestCase { 'theming', $this->request, $this->config, + $this->appConfig, $this->themingDefaults, $this->l10n, - $this->tempManager, - $this->appData, $this->urlGenerator, $this->appManager, $this->imageManager, $this->themesService, + $this->navigationManager, ); parent::setUp(); } - public function dataUpdateStylesheetSuccess() { + public static function dataUpdateStylesheetSuccess(): array { return [ ['name', str_repeat('a', 250), 'Saved'], ['url', 'https://nextcloud.com/' . str_repeat('a', 478), 'Saved'], @@ -126,14 +97,8 @@ class ThemingControllerTest extends TestCase { ]; } - /** - * @dataProvider dataUpdateStylesheetSuccess - * - * @param string $setting - * @param string $value - * @param string $message - */ - public function testUpdateStylesheetSuccess($setting, $value, $message) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataUpdateStylesheetSuccess')] + public function testUpdateStylesheetSuccess(string $setting, string $value, string $message): void { $this->themingDefaults ->expects($this->once()) ->method('set') @@ -147,8 +112,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'message' => $message, ], 'status' => 'success', @@ -157,31 +122,39 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->updateStylesheet($setting, $value)); } - public function dataUpdateStylesheetError() { + public static function dataUpdateStylesheetError(): array { + $urls = [ + 'url' => 'web address', + 'imprintUrl' => 'legal notice address', + 'privacyUrl' => 'privacy policy address', + ]; + + $urlTests = []; + foreach ($urls as $urlKey => $urlName) { + // Check length limit + $urlTests[] = [$urlKey, 'http://example.com/' . str_repeat('a', 501), "The given {$urlName} is too long"]; + // Check potential evil javascript + $urlTests[] = [$urlKey, 'javascript:alert(1)', "The given {$urlName} is not a valid URL"]; + // Check XSS + $urlTests[] = [$urlKey, 'https://example.com/"><script/src="alert(\'1\')"><a/href/="', "The given {$urlName} is not a valid URL"]; + } + return [ ['name', str_repeat('a', 251), 'The given name is too long'], - ['url', 'http://example.com/' . str_repeat('a', 501), 'The given web address is too long'], - ['url', str_repeat('a', 501), 'The given web address is not a valid URL'], - ['url', 'javascript:alert(1)', 'The given web address is not a valid URL'], ['slogan', str_repeat('a', 501), 'The given slogan is too long'], - ['color', '0082C9', 'The given color is invalid'], - ['color', '#0082Z9', 'The given color is invalid'], - ['color', 'Nextcloud', 'The given color is invalid'], - ['imprintUrl', '0082C9', 'The given legal notice address is not a valid URL'], - ['imprintUrl', '0082C9', 'The given legal notice address is not a valid URL'], - ['imprintUrl', 'javascript:foo', 'The given legal notice address is not a valid URL'], - ['privacyUrl', '#0082Z9', 'The given privacy policy address is not a valid URL'], + ['primary_color', '0082C9', 'The given color is invalid'], + ['primary_color', '#0082Z9', 'The given color is invalid'], + ['primary_color', 'Nextcloud', 'The given color is invalid'], + ['background_color', '0082C9', 'The given color is invalid'], + ['background_color', '#0082Z9', 'The given color is invalid'], + ['background_color', 'Nextcloud', 'The given color is invalid'], + + ...$urlTests, ]; } - /** - * @dataProvider dataUpdateStylesheetError - * - * @param string $setting - * @param string $value - * @param string $message - */ - public function testUpdateStylesheetError($setting, $value, $message) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataUpdateStylesheetError')] + public function testUpdateStylesheetError(string $setting, string $value, string $message): void { $this->themingDefaults ->expects($this->never()) ->method('set') @@ -195,8 +168,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'message' => $message, ], 'status' => 'error', @@ -206,7 +179,7 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->updateStylesheet($setting, $value)); } - public function testUpdateLogoNoData() { + public function testUpdateLogoNoData(): void { $this->request ->expects($this->once()) ->method('getParam') @@ -226,8 +199,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'message' => 'No file uploaded', ], 'status' => 'failure', @@ -238,7 +211,7 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->uploadImage()); } - public function testUploadInvalidUploadKey() { + public function testUploadInvalidUploadKey(): void { $this->request ->expects($this->once()) ->method('getParam') @@ -256,8 +229,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'message' => 'Invalid key', ], 'status' => 'failure', @@ -271,11 +244,8 @@ class ThemingControllerTest extends TestCase { /** * Checks that trying to upload an SVG favicon without imagemagick * results in an unsupported media type response. - * - * @test - * @return void */ - public function testUploadSVGFaviconWithoutImagemagick() { + public function testUploadSVGFaviconWithoutImagemagick(): void { $this->imageManager ->method('shouldReplaceIcons') ->willReturn(false); @@ -290,7 +260,7 @@ class ThemingControllerTest extends TestCase { ->method('getUploadedFile') ->with('image') ->willReturn([ - 'tmp_name' => __DIR__ . '/../../../../tests/data/testimagelarge.svg', + 'tmp_name' => __DIR__ . '/../../../../tests/data/testimagelarge.svg', 'type' => 'image/svg', 'name' => 'testimagelarge.svg', 'error' => 0, @@ -308,8 +278,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'message' => 'Unsupported image type', ], 'status' => 'failure' @@ -320,7 +290,7 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->uploadImage()); } - public function testUpdateLogoInvalidMimeType() { + public function testUpdateLogoInvalidMimeType(): void { $this->request ->expects($this->once()) ->method('getParam') @@ -331,7 +301,7 @@ class ThemingControllerTest extends TestCase { ->method('getUploadedFile') ->with('image') ->willReturn([ - 'tmp_name' => __DIR__ . '/../../../../tests/data/lorem.txt', + 'tmp_name' => __DIR__ . '/../../../../tests/data/lorem.txt', 'type' => 'application/pdf', 'name' => 'logo.pdf', 'error' => 0, @@ -349,8 +319,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'message' => 'Unsupported image type', ], 'status' => 'failure' @@ -361,7 +331,7 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->uploadImage()); } - public function dataUpdateImages() { + public static function dataUpdateImages(): array { return [ ['image/jpeg', false], ['image/jpeg', true], @@ -372,10 +342,10 @@ class ThemingControllerTest extends TestCase { ]; } - /** @dataProvider dataUpdateImages */ - public function testUpdateLogoNormalLogoUpload($mimeType, $folderExists = true) { - $tmpLogo = \OC::$server->getTempManager()->getTemporaryFolder() . '/logo.svg'; - $destination = \OC::$server->getTempManager()->getTemporaryFolder(); + #[\PHPUnit\Framework\Attributes\DataProvider('dataUpdateImages')] + public function testUpdateLogoNormalLogoUpload(string $mimeType, bool $folderExists = true): void { + $tmpLogo = Server::get(ITempManager::class)->getTemporaryFolder() . '/logo.svg'; + $destination = Server::get(ITempManager::class)->getTemporaryFolder(); touch($tmpLogo); copy(__DIR__ . '/../../../../tests/data/testimage.png', $tmpLogo); @@ -411,8 +381,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'name' => 'logo.svg', 'message' => 'Saved', 'url' => 'imageUrl', @@ -424,9 +394,8 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->uploadImage()); } - /** @dataProvider dataUpdateImages */ - public function testUpdateLogoLoginScreenUpload($folderExists) { - $tmpLogo = \OC::$server->getTempManager()->getTemporaryFolder() . 'logo.png'; + public function testUpdateLogoLoginScreenUpload(): void { + $tmpLogo = Server::get(ITempManager::class)->getTemporaryFolder() . 'logo.png'; touch($tmpLogo); copy(__DIR__ . '/../../../../tests/data/desktopapp.png', $tmpLogo); @@ -461,8 +430,8 @@ class ThemingControllerTest extends TestCase { ->willReturn('imageUrl'); $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'name' => 'logo.svg', 'message' => 'Saved', 'url' => 'imageUrl', @@ -473,11 +442,11 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->uploadImage()); } - public function testUpdateLogoLoginScreenUploadWithInvalidImage() { - $tmpLogo = \OC::$server->getTempManager()->getTemporaryFolder() . '/logo.svg'; + public function testUpdateLogoLoginScreenUploadWithInvalidImage(): void { + $tmpLogo = Server::get(ITempManager::class)->getTemporaryFolder() . '/logo.svg'; touch($tmpLogo); - file_put_contents($tmpLogo, file_get_contents(__DIR__ . '/../../../../tests/data/data.zip')); + file_put_contents($tmpLogo, file_get_contents(__DIR__ . '/../../../../tests/data/data.zip')); $this->request ->expects($this->once()) ->method('getParam') @@ -506,8 +475,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'message' => 'Unsupported image type', ], 'status' => 'failure' @@ -517,7 +486,7 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->uploadImage()); } - public function dataPhpUploadErrors() { + public static function dataPhpUploadErrors(): array { return [ [UPLOAD_ERR_INI_SIZE, 'The uploaded file exceeds the upload_max_filesize directive in php.ini'], [UPLOAD_ERR_FORM_SIZE, 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'], @@ -529,10 +498,8 @@ class ThemingControllerTest extends TestCase { ]; } - /** - * @dataProvider dataPhpUploadErrors - */ - public function testUpdateLogoLoginScreenUploadWithInvalidImageUpload($error, $expectedErrorMessage) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataPhpUploadErrors')] + public function testUpdateLogoLoginScreenUploadWithInvalidImageUpload(int $error, string $expectedErrorMessage): void { $this->request ->expects($this->once()) ->method('getParam') @@ -557,8 +524,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'message' => $expectedErrorMessage, ], 'status' => 'failure' @@ -568,10 +535,8 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->uploadImage()); } - /** - * @dataProvider dataPhpUploadErrors - */ - public function testUpdateLogoUploadWithInvalidImageUpload($error, $expectedErrorMessage) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataPhpUploadErrors')] + public function testUpdateLogoUploadWithInvalidImageUpload($error, $expectedErrorMessage): void { $this->request ->expects($this->once()) ->method('getParam') @@ -596,8 +561,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'message' => $expectedErrorMessage ], 'status' => 'failure' @@ -607,7 +572,7 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->uploadImage()); } - public function testUndo() { + public function testUndo(): void { $this->l10n ->expects($this->once()) ->method('t') @@ -621,8 +586,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'value' => 'MyValue', 'message' => 'Saved' ], @@ -632,15 +597,15 @@ class ThemingControllerTest extends TestCase { $this->assertEquals($expected, $this->themingController->undo('MySetting')); } - public function dataUndoDelete() { + public static function dataUndoDelete(): array { return [ [ 'backgroundMime', 'background' ], [ 'logoMime', 'logo' ] ]; } - /** @dataProvider dataUndoDelete */ - public function testUndoDelete($value, $filename) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataUndoDelete')] + public function testUndoDelete(string $value, string $filename): void { $this->l10n ->expects($this->once()) ->method('t') @@ -654,8 +619,8 @@ class ThemingControllerTest extends TestCase { $expected = new DataResponse( [ - 'data' => - [ + 'data' + => [ 'value' => $value, 'message' => 'Saved', ], @@ -667,16 +632,16 @@ class ThemingControllerTest extends TestCase { - public function testGetLogoNotExistent() { + public function testGetLogoNotExistent(): void { $this->imageManager->method('getImage') ->with($this->equalTo('logo')) ->willThrowException(new NotFoundException()); - $expected = new Http\NotFoundResponse(); + $expected = new NotFoundResponse(); $this->assertEquals($expected, $this->themingController->getImage('logo')); } - public function testGetLogo() { + public function testGetLogo(): void { $file = $this->createMock(ISimpleFile::class); $file->method('getName')->willReturn('logo.svg'); $file->method('getMTime')->willReturn(42); @@ -689,26 +654,26 @@ class ThemingControllerTest extends TestCase { ->with('theming', 'logoMime', '') ->willReturn('text/svg'); - @$expected = new Http\FileDisplayResponse($file); + @$expected = new FileDisplayResponse($file); $expected->cacheFor(3600); $expected->addHeader('Content-Type', 'text/svg'); $expected->addHeader('Content-Disposition', 'attachment; filename="logo"'); - $csp = new Http\ContentSecurityPolicy(); + $csp = new ContentSecurityPolicy(); $csp->allowInlineStyle(); $expected->setContentSecurityPolicy($csp); @$this->assertEquals($expected, $this->themingController->getImage('logo')); } - public function testGetLoginBackgroundNotExistent() { + public function testGetLoginBackgroundNotExistent(): void { $this->imageManager->method('getImage') ->with($this->equalTo('background')) ->willThrowException(new NotFoundException()); - $expected = new Http\NotFoundResponse(); + $expected = new NotFoundResponse(); $this->assertEquals($expected, $this->themingController->getImage('background')); } - public function testGetLoginBackground() { + public function testGetLoginBackground(): void { $file = $this->createMock(ISimpleFile::class); $file->method('getName')->willReturn('background.png'); $file->method('getMTime')->willReturn(42); @@ -722,17 +687,25 @@ class ThemingControllerTest extends TestCase { ->with('theming', 'backgroundMime', '') ->willReturn('image/png'); - @$expected = new Http\FileDisplayResponse($file); + @$expected = new FileDisplayResponse($file); $expected->cacheFor(3600); $expected->addHeader('Content-Type', 'image/png'); $expected->addHeader('Content-Disposition', 'attachment; filename="background"'); - $csp = new Http\ContentSecurityPolicy(); + $csp = new ContentSecurityPolicy(); $csp->allowInlineStyle(); $expected->setContentSecurityPolicy($csp); @$this->assertEquals($expected, $this->themingController->getImage('background')); } - public function testGetManifest() { + public static function dataGetManifest(): array { + return [ + [true], + [false], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetManifest')] + public function testGetManifest(bool $standalone): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -749,18 +722,20 @@ class ThemingControllerTest extends TestCase { $this->urlGenerator ->expects($this->exactly(2)) ->method('linkToRoute') - ->withConsecutive( - ['theming.Icon.getTouchIcon', ['app' => 'core']], - ['theming.Icon.getFavicon', ['app' => 'core']], - )->willReturnOnConsecutiveCalls( - 'touchicon', - 'favicon', - ); - $response = new Http\JSONResponse([ + ->willReturnMap([ + ['theming.Icon.getTouchIcon', ['app' => 'core'], 'touchicon'], + ['theming.Icon.getFavicon', ['app' => 'core'], 'favicon'], + ]); + $this->config + ->expects($this->exactly(2)) + ->method('getSystemValueBool') + ->with('theming.standalone_window.enabled', true) + ->willReturn($standalone); + $response = new JSONResponse([ 'name' => 'Nextcloud', 'start_url' => 'localhost', - 'icons' => - [ + 'icons' + => [ [ 'src' => 'touchicon?v=0', 'type' => 'image/png', @@ -772,7 +747,8 @@ class ThemingControllerTest extends TestCase { 'sizes' => '16x16' ] ], - 'display' => 'standalone', + 'display_override' => [$standalone ? 'minimal-ui' : ''], + 'display' => $standalone ? 'standalone' : 'browser', 'short_name' => 'Nextcloud', 'theme_color' => null, 'background_color' => null, diff --git a/apps/theming/tests/Controller/UserThemeControllerTest.php b/apps/theming/tests/Controller/UserThemeControllerTest.php index 30d5b77bb6c..9a8c1cd19aa 100644 --- a/apps/theming/tests/Controller/UserThemeControllerTest.php +++ b/apps/theming/tests/Controller/UserThemeControllerTest.php @@ -1,24 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Controller; @@ -44,25 +29,17 @@ use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class UserThemeControllerTest extends TestCase { - /** @var UserThemeController */ - private $userThemeController; - - /** @var IRequest|MockObject */ - private $request; - /** @var IConfig|MockObject */ - private $config; - /** @var IUserSession|MockObject */ - private $userSession; - /** @var ThemeService|MockObject */ - private $themesService; - /** @var ThemingDefaults */ - private $themingDefaults; - /** @var BackgroundService|MockObject */ - private $backgroundService; + private IRequest&MockObject $request; + private IConfig&MockObject $config; + private IUserSession&MockObject $userSession; + private ThemesService&MockObject $themesService; + private ThemingDefaults&MockObject $themingDefaults; + private BackgroundService&MockObject $backgroundService; + private UserThemeController $userThemeController; /** @var ITheme[] */ - private $themes; + private array $themes; protected function setUp(): void { $this->request = $this->createMock(IRequest::class); @@ -102,7 +79,7 @@ class UserThemeControllerTest extends TestCase { parent::setUp(); } - public function dataTestThemes() { + public static function dataTestThemes(): array { return [ ['default'], ['light'], @@ -115,13 +92,8 @@ class UserThemeControllerTest extends TestCase { ]; } - /** - * @dataProvider dataTestThemes - * - * @param string $themeId - * @param string $exception - */ - public function testEnableTheme($themeId, ?string $exception = null) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestThemes')] + public function testEnableTheme(string $themeId, ?string $exception = null): void { $this->themesService ->expects($this->any()) ->method('getThemes') @@ -135,13 +107,8 @@ class UserThemeControllerTest extends TestCase { $this->assertEquals($expected, $this->userThemeController->enableTheme($themeId)); } - /** - * @dataProvider dataTestThemes - * - * @param string $themeId - * @param string $exception - */ - public function testDisableTheme($themeId, ?string $exception = null) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestThemes')] + public function testDisableTheme(string $themeId, ?string $exception = null): void { $this->themesService ->expects($this->any()) ->method('getThemes') diff --git a/apps/theming/tests/IconBuilderTest.php b/apps/theming/tests/IconBuilderTest.php index ee4705c77dc..d881e4eb75c 100644 --- a/apps/theming/tests/IconBuilderTest.php +++ b/apps/theming/tests/IconBuilderTest.php @@ -1,29 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Joas Schilling <coding@schilljs.com> - * @author Julius Haertl <jus@bitgrid.net> - * @author Julius Härtl <jus@bitgrid.net> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests; @@ -35,25 +15,18 @@ use OCA\Theming\Util; use OCP\App\IAppManager; use OCP\Files\NotFoundException; use OCP\IConfig; -use PHPUnit\Framework\Error\Warning; +use OCP\ServerVersion; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class IconBuilderTest extends TestCase { - - /** @var IConfig */ - protected $config; - /** @var AppData */ - protected $appData; - /** @var ThemingDefaults */ - protected $themingDefaults; - /** @var Util */ - protected $util; - /** @var ImageManager */ - protected $imageManager; - /** @var IconBuilder */ - protected $iconBuilder; - /** @var IAppManager */ - protected $appManager; + protected IConfig&MockObject $config; + protected AppData&MockObject $appData; + protected ThemingDefaults&MockObject $themingDefaults; + protected ImageManager&MockObject $imageManager; + protected IAppManager&MockObject $appManager; + protected Util $util; + protected IconBuilder $iconBuilder; protected function setUp(): void { parent::setUp(); @@ -63,7 +36,7 @@ class IconBuilderTest extends TestCase { $this->themingDefaults = $this->createMock(ThemingDefaults::class); $this->appManager = $this->createMock(IAppManager::class); $this->imageManager = $this->createMock(ImageManager::class); - $this->util = new Util($this->config, $this->appManager, $this->appData, $this->imageManager); + $this->util = new Util($this->createMock(ServerVersion::class), $this->config, $this->appManager, $this->appData, $this->imageManager); $this->iconBuilder = new IconBuilder($this->themingDefaults, $this->util, $this->imageManager); } @@ -80,7 +53,7 @@ class IconBuilderTest extends TestCase { } } - public function dataRenderAppIcon() { + public static function dataRenderAppIcon(): array { return [ ['core', '#0082c9', 'touch-original.png'], ['core', '#FF0000', 'touch-core-red.png'], @@ -90,13 +63,8 @@ class IconBuilderTest extends TestCase { ]; } - /** - * @dataProvider dataRenderAppIcon - * @param $app - * @param $color - * @param $file - */ - public function testRenderAppIcon($app, $color, $file) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataRenderAppIcon')] + public function testRenderAppIcon(string $app, string $color, string $file): void { $this->checkImagick(); $this->themingDefaults->expects($this->once()) ->method('getColorPrimary') @@ -106,7 +74,7 @@ class IconBuilderTest extends TestCase { ->with('global/images') ->willThrowException(new NotFoundException()); - $expectedIcon = new \Imagick(realpath(dirname(__FILE__)). "/data/" . $file); + $expectedIcon = new \Imagick(realpath(__DIR__) . '/data/' . $file); $icon = $this->iconBuilder->renderAppIcon($app, 512); $this->assertEquals(true, $icon->valid()); @@ -119,13 +87,8 @@ class IconBuilderTest extends TestCase { // cloud be something like $expectedIcon->compareImages($icon, Imagick::METRIC_MEANABSOLUTEERROR)[1]) } - /** - * @dataProvider dataRenderAppIcon - * @param $app - * @param $color - * @param $file - */ - public function testGetTouchIcon($app, $color, $file) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataRenderAppIcon')] + public function testGetTouchIcon(string $app, string $color, string $file): void { $this->checkImagick(); $this->themingDefaults->expects($this->once()) ->method('getColorPrimary') @@ -135,7 +98,7 @@ class IconBuilderTest extends TestCase { ->with('global/images') ->willThrowException(new NotFoundException()); - $expectedIcon = new \Imagick(realpath(dirname(__FILE__)). "/data/" . $file); + $expectedIcon = new \Imagick(realpath(__DIR__) . '/data/' . $file); $icon = new \Imagick(); $icon->readImageBlob($this->iconBuilder->getTouchIcon($app)); @@ -149,13 +112,8 @@ class IconBuilderTest extends TestCase { // cloud be something like $expectedIcon->compareImages($icon, Imagick::METRIC_MEANABSOLUTEERROR)[1]) } - /** - * @dataProvider dataRenderAppIcon - * @param $app - * @param $color - * @param $file - */ - public function testGetFavicon($app, $color, $file) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataRenderAppIcon')] + public function testGetFavicon(string $app, string $color, string $file): void { $this->checkImagick(); $this->imageManager->expects($this->once()) ->method('shouldReplaceIcons') @@ -168,7 +126,7 @@ class IconBuilderTest extends TestCase { ->with('global/images') ->willThrowException(new NotFoundException()); - $expectedIcon = new \Imagick(realpath(dirname(__FILE__)). "/data/" . $file); + $expectedIcon = new \Imagick(realpath(__DIR__) . '/data/' . $file); $actualIcon = $this->iconBuilder->getFavicon($app); $icon = new \Imagick(); @@ -184,10 +142,9 @@ class IconBuilderTest extends TestCase { // cloud be something like $expectedIcon->compareImages($icon, Imagick::METRIC_MEANABSOLUTEERROR)[1]) } - public function testGetFaviconNotFound() { + public function testGetFaviconNotFound(): void { $this->checkImagick(); - $this->expectWarning(Warning::class); - $util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock(); + $util = $this->createMock(Util::class); $iconBuilder = new IconBuilder($this->themingDefaults, $util, $this->imageManager); $this->imageManager->expects($this->once()) ->method('shouldReplaceIcons') @@ -198,10 +155,9 @@ class IconBuilderTest extends TestCase { $this->assertFalse($iconBuilder->getFavicon('noapp')); } - public function testGetTouchIconNotFound() { + public function testGetTouchIconNotFound(): void { $this->checkImagick(); - $this->expectWarning(Warning::class); - $util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock(); + $util = $this->createMock(Util::class); $iconBuilder = new IconBuilder($this->themingDefaults, $util, $this->imageManager); $util->expects($this->once()) ->method('getAppIcon') @@ -209,10 +165,9 @@ class IconBuilderTest extends TestCase { $this->assertFalse($iconBuilder->getTouchIcon('noapp')); } - public function testColorSvgNotFound() { + public function testColorSvgNotFound(): void { $this->checkImagick(); - $this->expectWarning(Warning::class); - $util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock(); + $util = $this->createMock(Util::class); $iconBuilder = new IconBuilder($this->themingDefaults, $util, $this->imageManager); $util->expects($this->once()) ->method('getAppImage') diff --git a/apps/theming/tests/ImageManagerTest.php b/apps/theming/tests/ImageManagerTest.php index 8d42e892448..0c4d555cc00 100644 --- a/apps/theming/tests/ImageManagerTest.php +++ b/apps/theming/tests/ImageManagerTest.php @@ -1,33 +1,14 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Julius Haertl <jus@bitgrid.net> - * @author Julius Härtl <jus@bitgrid.net> - * @author Michael Weimann <mail@michael-weimann.eu> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests; use OCA\Theming\ImageManager; +use OCA\Theming\Service\BackgroundService; use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFile; @@ -41,22 +22,14 @@ use Psr\Log\LoggerInterface; use Test\TestCase; class ImageManagerTest extends TestCase { - /** @var IConfig|MockObject */ - protected $config; - /** @var IAppData|MockObject */ - protected $appData; - /** @var ImageManager */ - protected $imageManager; - /** @var IURLGenerator|MockObject */ - private $urlGenerator; - /** @var ICacheFactory|MockObject */ - private $cacheFactory; - /** @var LoggerInterface|MockObject */ - private $logger; - /** @var ITempManager|MockObject */ - private $tempManager; - /** @var ISimpleFolder|MockObject */ - private $rootFolder; + protected IConfig&MockObject $config; + protected IAppData&MockObject $appData; + private IURLGenerator&MockObject $urlGenerator; + private ICacheFactory&MockObject $cacheFactory; + private LoggerInterface&MockObject $logger; + private ITempManager&MockObject $tempManager; + private ISimpleFolder&MockObject $rootFolder; + protected ImageManager $imageManager; protected function setUp(): void { parent::setUp(); @@ -67,13 +40,15 @@ class ImageManagerTest extends TestCase { $this->logger = $this->createMock(LoggerInterface::class); $this->tempManager = $this->createMock(ITempManager::class); $this->rootFolder = $this->createMock(ISimpleFolder::class); + $backgroundService = $this->createMock(BackgroundService::class); $this->imageManager = new ImageManager( $this->config, $this->appData, $this->urlGenerator, $this->cacheFactory, $this->logger, - $this->tempManager + $this->tempManager, + $backgroundService, ); $this->appData ->expects($this->any()) @@ -109,13 +84,10 @@ class ImageManagerTest extends TestCase { ->willReturn(file_get_contents(__DIR__ . '/../../../tests/data/testimage.png')); $folder->expects($this->exactly(2)) ->method('fileExists') - ->withConsecutive( - ['logo'], - ['logo.png'], - )->willReturnOnConsecutiveCalls( - true, - false, - ); + ->willReturnMap([ + ['logo', true], + ['logo.png', false], + ]); $folder->expects($this->once()) ->method('getFile') ->with('logo') @@ -134,30 +106,27 @@ class ImageManagerTest extends TestCase { } } - public function testGetImageUrl() { + public function testGetImageUrl(): void { $this->checkImagick(); - $file = $this->createMock(ISimpleFile::class); $this->config->expects($this->exactly(2)) ->method('getAppValue') - ->withConsecutive( - ['theming', 'cachebuster', '0'], - ['theming', 'logoMime', ''] - ) - ->willReturn(0); + ->willReturnMap([ + ['theming', 'cachebuster', '0', '0'], + ['theming', 'logoMime', '', '0'], + ]); $this->urlGenerator->expects($this->once()) ->method('linkToRoute') ->willReturn('url-to-image'); $this->assertEquals('url-to-image?v=0', $this->imageManager->getImageUrl('logo', false)); } - public function testGetImageUrlDefault() { + public function testGetImageUrlDefault(): void { $this->config->expects($this->exactly(2)) ->method('getAppValue') - ->withConsecutive( - ['theming', 'cachebuster', '0'], - ['theming', 'logoMime', ''] - ) - ->willReturnOnConsecutiveCalls(0, ''); + ->willReturnMap([ + ['theming', 'cachebuster', '0', '0'], + ['theming', 'logoMime', '', ''], + ]); $this->urlGenerator->expects($this->once()) ->method('imagePath') ->with('core', 'logo/logo.png') @@ -165,23 +134,21 @@ class ImageManagerTest extends TestCase { $this->assertEquals('logo/logo.png?v=0', $this->imageManager->getImageUrl('logo')); } - public function testGetImageUrlAbsolute() { + public function testGetImageUrlAbsolute(): void { $this->checkImagick(); - $file = $this->createMock(ISimpleFile::class); $this->config->expects($this->exactly(2)) ->method('getAppValue') - ->withConsecutive( - ['theming', 'cachebuster', '0'], - ['theming', 'logoMime', ''] - ) - ->willReturnOnConsecutiveCalls(0, 0); + ->willReturnMap([ + ['theming', 'cachebuster', '0', '0'], + ['theming', 'logoMime', '', ''], + ]); $this->urlGenerator->expects($this->any()) ->method('getAbsoluteUrl') ->willReturn('url-to-image-absolute?v=0'); $this->assertEquals('url-to-image-absolute?v=0', $this->imageManager->getImageUrlAbsolute('logo', false)); } - public function testGetImage() { + public function testGetImage(): void { $this->checkImagick(); $this->config->expects($this->once()) ->method('getAppValue')->with('theming', 'logoMime', false) @@ -192,8 +159,8 @@ class ImageManagerTest extends TestCase { } - public function testGetImageUnset() { - $this->expectException(\OCP\Files\NotFoundException::class); + public function testGetImageUnset(): void { + $this->expectException(NotFoundException::class); $this->config->expects($this->once()) ->method('getAppValue')->with('theming', 'logoMime', false) @@ -201,7 +168,7 @@ class ImageManagerTest extends TestCase { $this->imageManager->getImage('logo'); } - public function testGetCacheFolder() { + public function testGetCacheFolder(): void { $folder = $this->createMock(ISimpleFolder::class); $this->config->expects($this->once()) ->method('getAppValue') @@ -213,7 +180,7 @@ class ImageManagerTest extends TestCase { ->willReturn($folder); $this->assertEquals($folder, $this->imageManager->getCacheFolder()); } - public function testGetCacheFolderCreate() { + public function testGetCacheFolderCreate(): void { $folder = $this->createMock(ISimpleFolder::class); $this->config->expects($this->exactly(2)) ->method('getAppValue') @@ -236,7 +203,7 @@ class ImageManagerTest extends TestCase { $this->assertEquals($folder, $this->imageManager->getCacheFolder()); } - public function testGetCachedImage() { + public function testGetCachedImage(): void { $expected = $this->createMock(ISimpleFile::class); $folder = $this->setupCacheFolder(); $folder->expects($this->once()) @@ -247,18 +214,18 @@ class ImageManagerTest extends TestCase { } - public function testGetCachedImageNotFound() { - $this->expectException(\OCP\Files\NotFoundException::class); + public function testGetCachedImageNotFound(): void { + $this->expectException(NotFoundException::class); $folder = $this->setupCacheFolder(); $folder->expects($this->once()) ->method('getFile') ->with('filename') - ->will($this->throwException(new \OCP\Files\NotFoundException())); + ->willThrowException(new NotFoundException()); $image = $this->imageManager->getCachedImage('filename'); } - public function testSetCachedImage() { + public function testSetCachedImage(): void { $folder = $this->setupCacheFolder(); $file = $this->createMock(ISimpleFile::class); $folder->expects($this->once()) @@ -275,7 +242,7 @@ class ImageManagerTest extends TestCase { $this->assertEquals($file, $this->imageManager->setCachedImage('filename', 'filecontent')); } - public function testSetCachedImageCreate() { + public function testSetCachedImageCreate(): void { $folder = $this->setupCacheFolder(); $file = $this->createMock(ISimpleFile::class); $folder->expects($this->once()) @@ -305,7 +272,7 @@ class ImageManagerTest extends TestCase { return $folder; } - public function testCleanup() { + public function testCleanup(): void { $folders = [ $this->createMock(ISimpleFolder::class), $this->createMock(ISimpleFolder::class), @@ -334,7 +301,7 @@ class ImageManagerTest extends TestCase { } - public function dataUpdateImage() { + public static function dataUpdateImage(): array { return [ ['background', __DIR__ . '/../../../tests/data/testimage.png', true, false], ['background', __DIR__ . '/../../../tests/data/testimage.png', false, false], @@ -346,10 +313,8 @@ class ImageManagerTest extends TestCase { ]; } - /** - * @dataProvider dataUpdateImage - */ - public function testUpdateImage($key, $tmpFile, $folderExists, $shouldConvert) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataUpdateImage')] + public function testUpdateImage(string $key, string $tmpFile, bool $folderExists, bool $shouldConvert): void { $file = $this->createMock(ISimpleFile::class); $folder = $this->createMock(ISimpleFolder::class); $oldFile = $this->createMock(ISimpleFile::class); diff --git a/apps/theming/tests/Migration/Version2006Date20240905111627Test.php b/apps/theming/tests/Migration/Version2006Date20240905111627Test.php new file mode 100644 index 00000000000..5f7458db11a --- /dev/null +++ b/apps/theming/tests/Migration/Version2006Date20240905111627Test.php @@ -0,0 +1,182 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\Theming\Tests\Migration; + +use OCA\Theming\Migration\Version2006Date20240905111627; +use OCP\BackgroundJob\IJobList; +use OCP\Config\IUserConfig; +use OCP\IAppConfig; +use OCP\IDBConnection; +use OCP\IUserManager; +use OCP\Migration\IOutput; +use OCP\Server; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +/** + * @group DB + */ +class Version2006Date20240905111627Test extends TestCase { + + private IAppConfig&MockObject $appConfig; + private IDBConnection&MockObject $connection; + private IJobList&MockObject $jobList; + private Version2006Date20240905111627 $migration; + + protected function setUp(): void { + parent::setUp(); + + $this->appConfig = $this->createMock(IAppConfig::class); + $this->connection = $this->createMock(IDBConnection::class); + $this->jobList = $this->createMock(IJobList::class); + $this->migration = new Version2006Date20240905111627( + $this->jobList, + $this->appConfig, + $this->connection, + ); + } + + public function testRestoreSystemColors(): void { + $this->appConfig->expects(self::once()) + ->method('getValueString') + ->with('theming', 'color', '') + ->willReturn('ffab00'); + $this->appConfig->expects(self::once()) + ->method('getValueBool') + ->with('theming', 'disable-user-theming') + ->willReturn(true); + + // expect the color value to be deleted + $this->appConfig->expects(self::once()) + ->method('deleteKey') + ->with('theming', 'color'); + // expect the correct calls to setValueString (setting the new values) + $setValueCalls = []; + $this->appConfig->expects(self::exactly(2)) + ->method('setValueString') + ->willReturnCallback(function () use (&$setValueCalls) { + $setValueCalls[] = func_get_args(); + return true; + }); + + $output = $this->createMock(IOutput::class); + $this->migration->changeSchema($output, fn () => null, []); + + $this->assertEquals([ + ['theming', 'background_color', 'ffab00', false, false], + ['theming', 'primary_color', 'ffab00', false, false], + ], $setValueCalls); + } + + /** + * @group DB + */ + public function testRestoreUserColors(): void { + $this->appConfig->expects(self::once()) + ->method('getValueString') + ->with('theming', 'color', '') + ->willReturn(''); + $this->appConfig->expects(self::once()) + ->method('getValueBool') + ->with('theming', 'disable-user-theming') + ->willReturn(false); + + // Create a user + $manager = Server::get(IUserManager::class); + $user = $manager->createUser('theming_legacy', 'theming_legacy'); + self::assertNotFalse($user); + // Set the users theming value to legacy key + $config = Server::get(IUserConfig::class); + $config->setValueString('theming_legacy', 'theming', 'background_color', 'ffab00'); + + // expect some output + $output = $this->createMock(IOutput::class); + $output->expects(self::exactly(3)) + ->method('info') + ->willReturnCallback(fn ($txt) => match($txt) { + 'No custom system color configured - skipping' => true, + 'Restoring user primary color' => true, + 'Primary color of users restored' => true, + default => self::fail('output.info called with unexpected argument: ' . $txt) + }); + // Create the migration class + $migration = new Version2006Date20240905111627( + $this->jobList, + $this->appConfig, + Server::get(IDBConnection::class), + ); + // Run the migration + $migration->changeSchema($output, fn () => null, []); + + // See new value + $config->clearCache('theming_legacy'); + $newValue = $config->getValueString('theming_legacy', 'theming', 'primary_color'); + self::assertEquals('ffab00', $newValue); + + // cleanup + $user->delete(); + } + + /** + * Ensure only users with background color but no primary color are migrated + * @group DB + */ + public function testRestoreUserColorsWithConflicts(): void { + $this->appConfig->expects(self::once()) + ->method('getValueString') + ->with('theming', 'color', '') + ->willReturn(''); + $this->appConfig->expects(self::once()) + ->method('getValueBool') + ->with('theming', 'disable-user-theming') + ->willReturn(false); + + // Create a user + $manager = Server::get(IUserManager::class); + $legacyUser = $manager->createUser('theming_legacy', 'theming_legacy'); + self::assertNotFalse($legacyUser); + $user = $manager->createUser('theming_no_legacy', 'theming_no_legacy'); + self::assertNotFalse($user); + // Set the users theming value to legacy key + $config = Server::get(IUserConfig::class); + $config->setValueString($user->getUID(), 'theming', 'primary_color', '999999'); + $config->setValueString($user->getUID(), 'theming', 'background_color', '111111'); + $config->setValueString($legacyUser->getUID(), 'theming', 'background_color', 'ffab00'); + + // expect some output + $output = $this->createMock(IOutput::class); + $output->expects(self::exactly(3)) + ->method('info') + ->willReturnCallback(fn ($txt) => match($txt) { + 'No custom system color configured - skipping' => true, + 'Restoring user primary color' => true, + 'Primary color of users restored' => true, + default => self::fail('output.info called with unexpected argument: ' . $txt) + }); + // Create the migration class + $migration = new Version2006Date20240905111627( + $this->jobList, + $this->appConfig, + Server::get(IDBConnection::class), + ); + // Run the migration + $migration->changeSchema($output, fn () => null, []); + + // See new value of only the legacy user + $config->clearCacheAll(); + self::assertEquals('111111', $config->getValueString($user->getUID(), 'theming', 'background_color')); + self::assertEquals('999999', $config->getValueString($user->getUID(), 'theming', 'primary_color')); + self::assertEquals('ffab00', $config->getValueString($legacyUser->getUID(), 'theming', 'primary_color')); + + // cleanup + $legacyUser->delete(); + $user->delete(); + } +} diff --git a/apps/theming/tests/Service/ThemesServiceTest.php b/apps/theming/tests/Service/ThemesServiceTest.php index 6ed49fd1645..354ed1dec85 100644 --- a/apps/theming/tests/Service/ThemesServiceTest.php +++ b/apps/theming/tests/Service/ThemesServiceTest.php @@ -1,24 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Service; @@ -41,25 +26,24 @@ use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserSession; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; class ThemesServiceTest extends TestCase { - /** @var ThemesService */ - private $themesService; + private IUserSession&MockObject $userSession; + private IConfig&MockObject $config; + private LoggerInterface&MockObject $logger; - /** @var IUserSession|MockObject */ - private $userSession; - /** @var IConfig|MockObject */ - private $config; - /** @var ThemingDefaults|MockObject */ - private $themingDefaults; + private ThemingDefaults&MockObject $themingDefaults; + private ThemesService $themesService; /** @var ITheme[] */ - private $themes; + private array $themes; protected function setUp(): void { $this->userSession = $this->createMock(IUserSession::class); $this->config = $this->createMock(IConfig::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->themingDefaults = $this->createMock(ThemingDefaults::class); $this->themingDefaults->expects($this->any()) @@ -75,13 +59,14 @@ class ThemesServiceTest extends TestCase { $this->themesService = new ThemesService( $this->userSession, $this->config, + $this->logger, ...array_values($this->themes) ); parent::setUp(); } - public function testGetThemes() { + public function testGetThemes(): void { $expected = [ 'default', 'light', @@ -93,11 +78,47 @@ class ThemesServiceTest extends TestCase { $this->assertEquals($expected, array_keys($this->themesService->getThemes())); } + public function testGetThemesEnforced(): void { + $this->config->expects($this->once()) + ->method('getSystemValueString') + ->with('enforce_theme', '') + ->willReturn('dark'); + $this->logger->expects($this->never()) + ->method('error'); + + $expected = [ + 'default', + 'dark', + ]; + + $this->assertEquals($expected, array_keys($this->themesService->getThemes())); + } + + public function testGetThemesEnforcedInvalid(): void { + $this->config->expects($this->once()) + ->method('getSystemValueString') + ->with('enforce_theme', '') + ->willReturn('invalid'); + $this->logger->expects($this->once()) + ->method('error') + ->with('Enforced theme not found', ['theme' => 'invalid']); + + $expected = [ + 'default', + 'light', + 'dark', + 'light-highcontrast', + 'dark-highcontrast', + 'opendyslexic', + ]; - public function dataTestEnableTheme() { + $this->assertEquals($expected, array_keys($this->themesService->getThemes())); + } + + public static function dataTestEnableTheme(): array { return [ - ['default', [], ['default']], - ['dark', [], ['dark']], + ['default', ['default'], ['default']], + ['dark', ['default'], ['dark']], ['dark', ['dark'], ['dark']], ['opendyslexic', ['dark'], ['dark', 'opendyslexic']], ['dark', ['light-highcontrast', 'opendyslexic'], ['opendyslexic', 'dark']], @@ -105,13 +126,12 @@ class ThemesServiceTest extends TestCase { } /** - * @dataProvider dataTestEnableTheme * - * @param string $toEnable * @param string[] $enabledThemes * @param string[] $expectedEnabled */ - public function testEnableTheme(string $toEnable, array $enabledThemes, array $expectedEnabled) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestEnableTheme')] + public function testEnableTheme(string $toEnable, array $enabledThemes, array $expectedEnabled): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->any()) ->method('getUser') @@ -122,16 +142,16 @@ class ThemesServiceTest extends TestCase { $this->config->expects($this->once()) ->method('getUserValue') - ->with('user', Application::APP_ID, 'enabled-themes', '[]') + ->with('user', Application::APP_ID, 'enabled-themes', '["default"]') ->willReturn(json_encode($enabledThemes)); $this->assertEquals($expectedEnabled, $this->themesService->enableTheme($this->themes[$toEnable])); } - public function dataTestDisableTheme() { + public static function dataTestDisableTheme(): array { return [ - ['dark', [], []], + ['dark', ['default'], ['default']], ['dark', ['dark'], []], ['opendyslexic', ['dark', 'opendyslexic'], ['dark'], ], ['light-highcontrast', ['opendyslexic'], ['opendyslexic']], @@ -139,13 +159,12 @@ class ThemesServiceTest extends TestCase { } /** - * @dataProvider dataTestDisableTheme * - * @param string $toEnable * @param string[] $enabledThemes * @param string[] $expectedEnabled */ - public function testDisableTheme(string $toDisable, array $enabledThemes, array $expectedEnabled) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestDisableTheme')] + public function testDisableTheme(string $toDisable, array $enabledThemes, array $expectedEnabled): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->any()) ->method('getUser') @@ -156,7 +175,7 @@ class ThemesServiceTest extends TestCase { $this->config->expects($this->once()) ->method('getUserValue') - ->with('user', Application::APP_ID, 'enabled-themes', '[]') + ->with('user', Application::APP_ID, 'enabled-themes', '["default"]') ->willReturn(json_encode($enabledThemes)); @@ -164,7 +183,7 @@ class ThemesServiceTest extends TestCase { } - public function dataTestIsEnabled() { + public static function dataTestIsEnabled(): array { return [ ['dark', [], false], ['dark', ['dark'], true], @@ -174,12 +193,10 @@ class ThemesServiceTest extends TestCase { } /** - * @dataProvider dataTestIsEnabled - * - * @param string $toEnable * @param string[] $enabledThemes */ - public function testIsEnabled(string $themeId, array $enabledThemes, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestIsEnabled')] + public function testIsEnabled(string $themeId, array $enabledThemes, bool $expected): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->any()) ->method('getUser') @@ -190,14 +207,14 @@ class ThemesServiceTest extends TestCase { $this->config->expects($this->once()) ->method('getUserValue') - ->with('user', Application::APP_ID, 'enabled-themes', '[]') + ->with('user', Application::APP_ID, 'enabled-themes', '["default"]') ->willReturn(json_encode($enabledThemes)); $this->assertEquals($expected, $this->themesService->isEnabled($this->themes[$themeId])); } - public function testGetEnabledThemes() { + public function testGetEnabledThemes(): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->any()) ->method('getUser') @@ -209,17 +226,17 @@ class ThemesServiceTest extends TestCase { $this->config->expects($this->once()) ->method('getUserValue') - ->with('user', Application::APP_ID, 'enabled-themes', '[]') - ->willReturn(json_encode([])); + ->with('user', Application::APP_ID, 'enabled-themes', '["default"]') + ->willReturn(json_encode(['default'])); $this->config->expects($this->once()) ->method('getSystemValueString') ->with('enforce_theme', '') ->willReturn(''); - $this->assertEquals([], $this->themesService->getEnabledThemes()); + $this->assertEquals(['default'], $this->themesService->getEnabledThemes()); } - public function testGetEnabledThemesEnforced() { + public function testGetEnabledThemesEnforced(): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->any()) ->method('getUser') @@ -231,7 +248,7 @@ class ThemesServiceTest extends TestCase { $this->config->expects($this->once()) ->method('getUserValue') - ->with('user', Application::APP_ID, 'enabled-themes', '[]') + ->with('user', Application::APP_ID, 'enabled-themes', '["default"]') ->willReturn(json_encode([])); $this->config->expects($this->once()) ->method('getSystemValueString') @@ -242,7 +259,7 @@ class ThemesServiceTest extends TestCase { } - public function dataTestSetEnabledThemes() { + public static function dataTestSetEnabledThemes(): array { return [ [[], []], [['light'], ['light']], @@ -252,12 +269,12 @@ class ThemesServiceTest extends TestCase { } /** - * @dataProvider dataTestSetEnabledThemes * * @param string[] $enabledThemes * @param string[] $expected */ - public function testSetEnabledThemes(array $enabledThemes, array $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestSetEnabledThemes')] + public function testSetEnabledThemes(array $enabledThemes, array $expected): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->any()) ->method('getUser') @@ -290,6 +307,7 @@ class ThemesServiceTest extends TestCase { $this->config, $l10n, $appManager, + null, ), 'light' => new LightTheme( $util, @@ -300,6 +318,7 @@ class ThemesServiceTest extends TestCase { $this->config, $l10n, $appManager, + null, ), 'dark' => new DarkTheme( $util, @@ -310,6 +329,7 @@ class ThemesServiceTest extends TestCase { $this->config, $l10n, $appManager, + null, ), 'light-highcontrast' => new HighContrastTheme( $util, @@ -320,6 +340,7 @@ class ThemesServiceTest extends TestCase { $this->config, $l10n, $appManager, + null, ), 'dark-highcontrast' => new DarkHighContrastTheme( $util, @@ -330,6 +351,7 @@ class ThemesServiceTest extends TestCase { $this->config, $l10n, $appManager, + null, ), 'opendyslexic' => new DyslexiaFont( $util, @@ -340,6 +362,7 @@ class ThemesServiceTest extends TestCase { $this->config, $l10n, $appManager, + null, ), ]; } diff --git a/apps/theming/tests/ServicesTest.php b/apps/theming/tests/ServicesTest.php index 441e5d55044..3971c9b6698 100644 --- a/apps/theming/tests/ServicesTest.php +++ b/apps/theming/tests/ServicesTest.php @@ -1,27 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests; @@ -32,6 +14,7 @@ use OCA\Theming\Settings\PersonalSection; use OCA\Theming\ThemingDefaults; use OCA\Theming\Util; use OCP\AppFramework\App; +use OCP\AppFramework\IAppContainer; use OCP\Capabilities\ICapability; use OCP\IL10N; use OCP\Settings\IIconSection; @@ -45,11 +28,9 @@ use Test\TestCase; * @package OCA\Theming\Tests */ class ServicesTest extends TestCase { - /** @var \OCA\Activity\AppInfo\Application */ - protected $app; + protected App $app; - /** @var \OCP\AppFramework\IAppContainer */ - protected $container; + protected IAppContainer $container; protected function setUp(): void { parent::setUp(); @@ -57,7 +38,7 @@ class ServicesTest extends TestCase { $this->container = $this->app->getContainer(); } - public function queryData() { + public static function queryData(): array { return [ [IL10N::class], @@ -79,15 +60,11 @@ class ServicesTest extends TestCase { ]; } - /** - * @dataProvider queryData - * @param string $service - * @param string $expected - */ - public function testContainerQuery($service, $expected = null) { + #[\PHPUnit\Framework\Attributes\DataProvider('queryData')] + public function testContainerQuery(string $service, ?string $expected = null): void { if ($expected === null) { $expected = $service; } - $this->assertTrue($this->container->query($service) instanceof $expected); + $this->assertInstanceOf($expected, $this->container->query($service)); } } diff --git a/apps/theming/tests/Settings/AdminSectionTest.php b/apps/theming/tests/Settings/AdminSectionTest.php index 80223664ce4..ecb889f264b 100644 --- a/apps/theming/tests/Settings/AdminSectionTest.php +++ b/apps/theming/tests/Settings/AdminSectionTest.php @@ -1,25 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> - * - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Settings; @@ -27,15 +11,13 @@ use OCA\Theming\AppInfo\Application; use OCA\Theming\Settings\AdminSection; use OCP\IL10N; use OCP\IURLGenerator; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class AdminSectionTest extends TestCase { - /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */ - private $url; - /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */ - private $l; - /** @var AdminSection */ - private $section; + private IURLGenerator&MockObject $url; + private IL10N&MockObject $l; + private AdminSection $section; protected function setUp(): void { parent::setUp(); @@ -49,11 +31,11 @@ class AdminSectionTest extends TestCase { ); } - public function testGetID() { + public function testGetID(): void { $this->assertSame('theming', $this->section->getID()); } - public function testGetName() { + public function testGetName(): void { $this->l ->expects($this->once()) ->method('t') @@ -63,11 +45,11 @@ class AdminSectionTest extends TestCase { $this->assertSame('Theming', $this->section->getName()); } - public function testGetPriority() { + public function testGetPriority(): void { $this->assertSame(30, $this->section->getPriority()); } - public function testGetIcon() { + public function testGetIcon(): void { $this->url->expects($this->once()) ->method('imagePath') ->with('theming', 'app-dark.svg') diff --git a/apps/theming/tests/Settings/AdminTest.php b/apps/theming/tests/Settings/AdminTest.php index 8d59ea014a4..277b94900a8 100644 --- a/apps/theming/tests/Settings/AdminTest.php +++ b/apps/theming/tests/Settings/AdminTest.php @@ -1,29 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Settings; @@ -35,17 +15,20 @@ use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; use OCP\IConfig; use OCP\IL10N; +use OCP\INavigationManager; use OCP\IURLGenerator; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class AdminTest extends TestCase { private Admin $admin; - private IConfig $config; - private ThemingDefaults $themingDefaults; - private IInitialState $initialState; - private IURLGenerator $urlGenerator; - private ImageManager $imageManager; - private IL10N $l10n; + private IConfig&MockObject $config; + private ThemingDefaults&MockObject $themingDefaults; + private IInitialState&MockObject $initialState; + private IURLGenerator&MockObject $urlGenerator; + private ImageManager&MockObject $imageManager; + private IL10N&MockObject $l10n; + private INavigationManager&MockObject $navigationManager; protected function setUp(): void { parent::setUp(); @@ -55,6 +38,7 @@ class AdminTest extends TestCase { $this->initialState = $this->createMock(IInitialState::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->imageManager = $this->createMock(ImageManager::class); + $this->navigationManager = $this->createMock(INavigationManager::class); $this->admin = new Admin( Application::APP_ID, @@ -63,11 +47,12 @@ class AdminTest extends TestCase { $this->themingDefaults, $this->initialState, $this->urlGenerator, - $this->imageManager + $this->imageManager, + $this->navigationManager, ); } - public function testGetFormNoErrors() { + public function testGetFormNoErrors(): void { $this->config ->expects($this->once()) ->method('getSystemValue') @@ -102,7 +87,7 @@ class AdminTest extends TestCase { $this->assertEquals($expected, $this->admin->getForm()); } - public function testGetFormWithErrors() { + public function testGetFormWithErrors(): void { $this->config ->expects($this->once()) ->method('getSystemValue') @@ -142,11 +127,11 @@ class AdminTest extends TestCase { $this->assertEquals($expected, $this->admin->getForm()); } - public function testGetSection() { + public function testGetSection(): void { $this->assertSame('theming', $this->admin->getSection()); } - public function testGetPriority() { + public function testGetPriority(): void { $this->assertSame(5, $this->admin->getPriority()); } } diff --git a/apps/theming/tests/Settings/PersonalTest.php b/apps/theming/tests/Settings/PersonalTest.php index 0a9bf4b59c9..9216450ec9c 100644 --- a/apps/theming/tests/Settings/PersonalTest.php +++ b/apps/theming/tests/Settings/PersonalTest.php @@ -1,35 +1,16 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Settings; use OCA\Theming\AppInfo\Application; use OCA\Theming\ImageManager; use OCA\Theming\ITheme; +use OCA\Theming\Service\BackgroundService; use OCA\Theming\Service\ThemesService; use OCA\Theming\Settings\Personal; use OCA\Theming\Themes\DarkHighContrastTheme; @@ -45,20 +26,22 @@ use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; use OCP\IConfig; use OCP\IL10N; +use OCP\INavigationManager; use OCP\IURLGenerator; use OCP\IUserSession; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class PersonalTest extends TestCase { - private IConfig $config; - private ThemesService $themesService; - private IInitialState $initialStateService; - private ThemingDefaults $themingDefaults; - private IAppManager $appManager; + private IConfig&MockObject $config; + private ThemesService&MockObject $themesService; + private IInitialState&MockObject $initialStateService; + private ThemingDefaults&MockObject $themingDefaults; + private INavigationManager&MockObject $navigationManager; private Personal $admin; /** @var ITheme[] */ - private $themes; + private array $themes; protected function setUp(): void { parent::setUp(); @@ -66,7 +49,7 @@ class PersonalTest extends TestCase { $this->themesService = $this->createMock(ThemesService::class); $this->initialStateService = $this->createMock(IInitialState::class); $this->themingDefaults = $this->createMock(ThemingDefaults::class); - $this->appManager = $this->createMock(IAppManager::class); + $this->navigationManager = $this->createMock(INavigationManager::class); $this->initThemes(); @@ -82,12 +65,11 @@ class PersonalTest extends TestCase { $this->themesService, $this->initialStateService, $this->themingDefaults, - $this->appManager, + $this->navigationManager, ); } - - public function dataTestGetForm() { + public function dataTestGetForm(): array { return [ ['', [ $this->formatThemeForm('default'), @@ -105,44 +87,48 @@ class PersonalTest extends TestCase { } /** - * @dataProvider dataTestGetForm - * - * @param string $toEnable * @param string[] $enabledThemes */ - public function testGetForm(string $enforcedTheme, $themesState) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetForm')] + public function testGetForm(string $enforcedTheme, array $themesState): void { $this->config->expects($this->once()) ->method('getSystemValueString') ->with('enforce_theme', '') ->willReturn($enforcedTheme); - $this->config->expects($this->once()) + $this->config->expects($this->any()) ->method('getUserValue') - ->with('admin', 'core', 'apporder') - ->willReturn('[]'); + ->willReturnMap([ + ['admin', 'core', 'apporder', '[]', '[]'], + ['admin', 'theming', 'background_image', BackgroundService::BACKGROUND_DEFAULT], + ]); - $this->appManager->expects($this->once()) - ->method('getDefaultAppForUser') - ->willReturn('forcedapp'); + $this->navigationManager->expects($this->once()) + ->method('getDefaultEntryIdForUser') + ->willReturn('forced_id'); - $this->initialStateService->expects($this->exactly(4)) + $this->initialStateService->expects($this->exactly(8)) ->method('provideInitialState') - ->withConsecutive( + ->willReturnMap([ + ['shippedBackgrounds', BackgroundService::SHIPPED_BACKGROUNDS], + ['themingDefaults'], + ['enableBlurFilter', ''], + ['userBackgroundImage'], ['themes', $themesState], ['enforceTheme', $enforcedTheme], ['isUserThemingDisabled', false], - ['navigationBar', ['userAppOrder' => [], 'enforcedDefaultApp' => 'forcedapp']], - ); + ['navigationBar', ['userAppOrder' => [], 'enforcedDefaultApp' => 'forced_id']], + ]); $expected = new TemplateResponse('theming', 'settings-personal'); $this->assertEquals($expected, $this->admin->getForm()); } - public function testGetSection() { + public function testGetSection(): void { $this->assertSame('theming', $this->admin->getSection()); } - public function testGetPriority() { + public function testGetPriority(): void { $this->assertSame(40, $this->admin->getPriority()); } @@ -174,6 +160,7 @@ class PersonalTest extends TestCase { $config, $l10n, $appManager, + null, ), 'light' => new LightTheme( $util, @@ -184,6 +171,7 @@ class PersonalTest extends TestCase { $config, $l10n, $appManager, + null, ), 'dark' => new DarkTheme( $util, @@ -194,6 +182,7 @@ class PersonalTest extends TestCase { $config, $l10n, $appManager, + null, ), 'light-highcontrast' => new HighContrastTheme( $util, @@ -204,6 +193,7 @@ class PersonalTest extends TestCase { $config, $l10n, $appManager, + null, ), 'dark-highcontrast' => new DarkHighContrastTheme( $util, @@ -214,6 +204,7 @@ class PersonalTest extends TestCase { $config, $l10n, $appManager, + null, ), 'opendyslexic' => new DyslexiaFont( $util, @@ -224,6 +215,7 @@ class PersonalTest extends TestCase { $config, $l10n, $appManager, + null, ), ]; } diff --git a/apps/theming/tests/Themes/AccessibleThemeTestCase.php b/apps/theming/tests/Themes/AccessibleThemeTestCase.php index 6ac2f0e7b49..f516e1f5116 100644 --- a/apps/theming/tests/Themes/AccessibleThemeTestCase.php +++ b/apps/theming/tests/Themes/AccessibleThemeTestCase.php @@ -1,24 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de> - * - * @author Ferdinand Thiessen <opensource@fthiessen.de> - * - * @license AGPL-3.0-or-later - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Themes; @@ -33,10 +18,10 @@ class AccessibleThemeTestCase extends TestCase { /** * Set to true to check for WCAG AAA level accessibility */ - protected bool $WCAGaaa = false; + protected static bool $WCAGaaa = false; - public function dataAccessibilityPairs() { - $textContrast = $this->WCAGaaa ? 7.0 : 4.5; + public static function dataAccessibilityPairs(): array { + $textContrast = self::$WCAGaaa ? 7.0 : 4.5; $elementContrast = 3.0; return [ @@ -162,10 +147,8 @@ class AccessibleThemeTestCase extends TestCase { ]; } - /** - * @dataProvider dataAccessibilityPairs - */ - public function testAccessibilityOfVariables($mainColors, $backgroundColors, $minContrast) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataAccessibilityPairs')] + public function testAccessibilityOfVariables(array $mainColors, array $backgroundColors, float $minContrast): void { if (!isset($this->theme)) { $this->markTestSkipped('You need to setup $this->theme in your setUp function'); } elseif (!isset($this->util)) { diff --git a/apps/theming/tests/Themes/DarkHighContrastThemeTest.php b/apps/theming/tests/Themes/DarkHighContrastThemeTest.php index d3a357bcfe7..d03e8b13300 100644 --- a/apps/theming/tests/Themes/DarkHighContrastThemeTest.php +++ b/apps/theming/tests/Themes/DarkHighContrastThemeTest.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Themes; @@ -35,26 +19,20 @@ use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUserSession; +use OCP\ServerVersion; use PHPUnit\Framework\MockObject\MockObject; class DarkHighContrastThemeTest extends AccessibleThemeTestCase { - /** @var ThemingDefaults|MockObject */ - private $themingDefaults; - /** @var IUserSession|MockObject */ - private $userSession; - /** @var IURLGenerator|MockObject */ - private $urlGenerator; - /** @var ImageManager|MockObject */ - private $imageManager; - /** @var IConfig|MockObject */ - private $config; - /** @var IL10N|MockObject */ - private $l10n; - /** @var IAppManager|MockObject */ - private $appManager; + private ThemingDefaults&MockObject $themingDefaults; + private IUserSession&MockObject $userSession; + private IURLGenerator&MockObject $urlGenerator; + private ImageManager&MockObject $imageManager; + private IConfig&MockObject $config; + private IL10N&MockObject $l10n; + private IAppManager&MockObject $appManager; // !! important: Enable WCAG AAA tests - protected bool $WCAGaaa = true; + protected static bool $WCAGaaa = true; protected function setUp(): void { $this->themingDefaults = $this->createMock(ThemingDefaults::class); @@ -66,6 +44,7 @@ class DarkHighContrastThemeTest extends AccessibleThemeTestCase { $this->appManager = $this->createMock(IAppManager::class); $this->util = new Util( + $this->createMock(ServerVersion::class), $this->config, $this->appManager, $this->createMock(IAppData::class), @@ -81,6 +60,14 @@ class DarkHighContrastThemeTest extends AccessibleThemeTestCase { ->expects($this->any()) ->method('getDefaultColorPrimary') ->willReturn('#0082c9'); + $this->themingDefaults + ->expects($this->any()) + ->method('getColorBackground') + ->willReturn('#0082c9'); + $this->themingDefaults + ->expects($this->any()) + ->method('getDefaultColorBackground') + ->willReturn('#0082c9'); $this->themingDefaults ->expects($this->any()) @@ -110,33 +97,34 @@ class DarkHighContrastThemeTest extends AccessibleThemeTestCase { $this->config, $this->l10n, $this->appManager, + null, ); parent::setUp(); } - public function testGetId() { + public function testGetId(): void { $this->assertEquals('dark-highcontrast', $this->theme->getId()); } - public function testGetType() { + public function testGetType(): void { $this->assertEquals(ITheme::TYPE_THEME, $this->theme->getType()); } - public function testGetTitle() { + public function testGetTitle(): void { $this->assertEquals('Dark theme with high contrast mode', $this->theme->getTitle()); } - public function testGetEnableLabel() { + public function testGetEnableLabel(): void { $this->assertEquals('Enable dark high contrast mode', $this->theme->getEnableLabel()); } - public function testGetDescription() { + public function testGetDescription(): void { $this->assertEquals('Similar to the high contrast mode, but with dark colours.', $this->theme->getDescription()); } - public function testGetMediaQuery() { + public function testGetMediaQuery(): void { $this->assertEquals('(prefers-color-scheme: dark) and (prefers-contrast: more)', $this->theme->getMediaQuery()); } } diff --git a/apps/theming/tests/Themes/DarkThemeTest.php b/apps/theming/tests/Themes/DarkThemeTest.php index 1a50e08d0f5..656779b5b24 100644 --- a/apps/theming/tests/Themes/DarkThemeTest.php +++ b/apps/theming/tests/Themes/DarkThemeTest.php @@ -1,24 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Themes; @@ -35,23 +20,17 @@ use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUserSession; +use OCP\ServerVersion; use PHPUnit\Framework\MockObject\MockObject; class DarkThemeTest extends AccessibleThemeTestCase { - /** @var ThemingDefaults|MockObject */ - private $themingDefaults; - /** @var IUserSession|MockObject */ - private $userSession; - /** @var IURLGenerator|MockObject */ - private $urlGenerator; - /** @var ImageManager|MockObject */ - private $imageManager; - /** @var IConfig|MockObject */ - private $config; - /** @var IL10N|MockObject */ - private $l10n; - /** @var IAppManager|MockObject */ - private $appManager; + private ThemingDefaults&MockObject $themingDefaults; + private IUserSession&MockObject $userSession; + private IURLGenerator&MockObject $urlGenerator; + private ImageManager&MockObject $imageManager; + private IConfig&MockObject $config; + private IL10N&MockObject $l10n; + private IAppManager&MockObject $appManager; protected function setUp(): void { $this->themingDefaults = $this->createMock(ThemingDefaults::class); @@ -63,6 +42,7 @@ class DarkThemeTest extends AccessibleThemeTestCase { $this->appManager = $this->createMock(IAppManager::class); $this->util = new Util( + $this->createMock(ServerVersion::class), $this->config, $this->appManager, $this->createMock(IAppData::class), @@ -78,6 +58,14 @@ class DarkThemeTest extends AccessibleThemeTestCase { ->expects($this->any()) ->method('getDefaultColorPrimary') ->willReturn('#0082c9'); + $this->themingDefaults + ->expects($this->any()) + ->method('getColorBackground') + ->willReturn('#0082c9'); + $this->themingDefaults + ->expects($this->any()) + ->method('getDefaultColorBackground') + ->willReturn('#0082c9'); $this->themingDefaults ->expects($this->any()) @@ -107,37 +95,38 @@ class DarkThemeTest extends AccessibleThemeTestCase { $this->config, $this->l10n, $this->appManager, + null, ); parent::setUp(); } - public function testGetId() { + public function testGetId(): void { $this->assertEquals('dark', $this->theme->getId()); } - public function testGetType() { + public function testGetType(): void { $this->assertEquals(ITheme::TYPE_THEME, $this->theme->getType()); } - public function testGetTitle() { + public function testGetTitle(): void { $this->assertEquals('Dark theme', $this->theme->getTitle()); } - public function testGetEnableLabel() { + public function testGetEnableLabel(): void { $this->assertEquals('Enable dark theme', $this->theme->getEnableLabel()); } - public function testGetDescription() { + public function testGetDescription(): void { $this->assertEquals('A dark theme to ease your eyes by reducing the overall luminosity and brightness.', $this->theme->getDescription()); } - public function testGetMediaQuery() { + public function testGetMediaQuery(): void { $this->assertEquals('(prefers-color-scheme: dark)', $this->theme->getMediaQuery()); } - public function testGetCustomCss() { + public function testGetCustomCss(): void { $this->assertEquals('', $this->theme->getCustomCss()); } } diff --git a/apps/theming/tests/Themes/DefaultThemeTest.php b/apps/theming/tests/Themes/DefaultThemeTest.php index 7e823cb4843..d2606ffc275 100644 --- a/apps/theming/tests/Themes/DefaultThemeTest.php +++ b/apps/theming/tests/Themes/DefaultThemeTest.php @@ -1,24 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Themes; @@ -35,23 +20,17 @@ use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUserSession; +use OCP\ServerVersion; use PHPUnit\Framework\MockObject\MockObject; class DefaultThemeTest extends AccessibleThemeTestCase { - /** @var ThemingDefaults|MockObject */ - private $themingDefaults; - /** @var IUserSession|MockObject */ - private $userSession; - /** @var IURLGenerator|MockObject */ - private $urlGenerator; - /** @var ImageManager|MockObject */ - private $imageManager; - /** @var IConfig|MockObject */ - private $config; - /** @var IL10N|MockObject */ - private $l10n; - /** @var IAppManager|MockObject */ - private $appManager; + private ThemingDefaults&MockObject $themingDefaults; + private IUserSession&MockObject $userSession; + private IURLGenerator&MockObject $urlGenerator; + private ImageManager&MockObject $imageManager; + private IConfig&MockObject $config; + private IL10N&MockObject $l10n; + private IAppManager&MockObject $appManager; protected function setUp(): void { $this->themingDefaults = $this->createMock(ThemingDefaults::class); @@ -63,21 +42,34 @@ class DefaultThemeTest extends AccessibleThemeTestCase { $this->appManager = $this->createMock(IAppManager::class); $this->util = new Util( + $this->createMock(ServerVersion::class), $this->config, $this->appManager, $this->createMock(IAppData::class), $this->imageManager ); + $defaultBackground = BackgroundService::SHIPPED_BACKGROUNDS[BackgroundService::DEFAULT_BACKGROUND_IMAGE]; + $this->themingDefaults ->expects($this->any()) ->method('getColorPrimary') - ->willReturn('#0082c9'); + ->willReturn($defaultBackground['primary_color']); + + $this->themingDefaults + ->expects($this->any()) + ->method('getColorBackground') + ->willReturn($defaultBackground['background_color']); $this->themingDefaults ->expects($this->any()) ->method('getDefaultColorPrimary') - ->willReturn('#0082c9'); + ->willReturn($defaultBackground['primary_color']); + + $this->themingDefaults + ->expects($this->any()) + ->method('getDefaultColorBackground') + ->willReturn($defaultBackground['background_color']); $this->themingDefaults ->expects($this->any()) @@ -107,37 +99,38 @@ class DefaultThemeTest extends AccessibleThemeTestCase { $this->config, $this->l10n, $this->appManager, + null, ); parent::setUp(); } - public function testGetId() { + public function testGetId(): void { $this->assertEquals('default', $this->theme->getId()); } - public function testGetType() { + public function testGetType(): void { $this->assertEquals(ITheme::TYPE_THEME, $this->theme->getType()); } - public function testGetTitle() { + public function testGetTitle(): void { $this->assertEquals('System default theme', $this->theme->getTitle()); } - public function testGetEnableLabel() { + public function testGetEnableLabel(): void { $this->assertEquals('Enable the system default', $this->theme->getEnableLabel()); } - public function testGetDescription() { + public function testGetDescription(): void { $this->assertEquals('Using the default system appearance.', $this->theme->getDescription()); } - public function testGetMediaQuery() { + public function testGetMediaQuery(): void { $this->assertEquals('', $this->theme->getMediaQuery()); } - public function testGetCustomCss() { + public function testGetCustomCss(): void { $this->assertEquals('', $this->theme->getCustomCss()); } @@ -145,17 +138,19 @@ class DefaultThemeTest extends AccessibleThemeTestCase { * Ensure parity between the default theme and the static generated file * @see ThemingController.php:313 */ - public function testThemindDisabledFallbackCss() { + public function testThemindDisabledFallbackCss(): void { // Generate variables $variables = ''; foreach ($this->theme->getCSSVariables() as $variable => $value) { $variables .= " $variable: $value;" . PHP_EOL; }; - $css = ":root {" . PHP_EOL . "$variables}" . PHP_EOL; + $css = "\n:root {" . PHP_EOL . "$variables}" . PHP_EOL; $fallbackCss = file_get_contents(__DIR__ . '/../../css/default.css'); // Remove comments $fallbackCss = preg_replace('/\s*\/\*[\s\S]*?\*\//m', '', $fallbackCss); + // Remove blank lines + $fallbackCss = preg_replace('/\s*\n\n/', "\n", $fallbackCss); $this->assertEquals($css, $fallbackCss); } diff --git a/apps/theming/tests/Themes/DyslexiaFontTest.php b/apps/theming/tests/Themes/DyslexiaFontTest.php index 7a55d168fea..7d56fb4b1be 100644 --- a/apps/theming/tests/Themes/DyslexiaFontTest.php +++ b/apps/theming/tests/Themes/DyslexiaFontTest.php @@ -1,28 +1,14 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Service; use OC\Route\Router; +use OC\URLGenerator; use OCA\Theming\ImageManager; use OCA\Theming\ITheme; use OCA\Theming\Themes\DyslexiaFont; @@ -36,24 +22,18 @@ use OCP\IL10N; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUserSession; +use OCP\ServerVersion; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class DyslexiaFontTest extends TestCase { - /** @var ThemingDefaults|MockObject */ - private $themingDefaults; - /** @var IUserSession|MockObject */ - private $userSession; - /** @var IURLGenerator|MockObject */ - private $urlGenerator; - /** @var ImageManager|MockObject */ - private $imageManager; - /** @var IConfig|MockObject */ - private $config; - /** @var IL10N|MockObject */ - private $l10n; - /** @var IAppManager|MockObject */ - private $appManager; + private ThemingDefaults&MockObject $themingDefaults; + private IUserSession&MockObject $userSession; + private IURLGenerator $urlGenerator; + private ImageManager&MockObject $imageManager; + private IConfig&MockObject $config; + private IL10N&MockObject $l10n; + private IAppManager&MockObject $appManager; private DyslexiaFont $dyslexiaFont; @@ -66,6 +46,7 @@ class DyslexiaFontTest extends TestCase { $this->appManager = $this->createMock(IAppManager::class); $util = new Util( + $this->createMock(ServerVersion::class), $this->config, $this->appManager, $this->createMock(IAppData::class), @@ -76,7 +57,7 @@ class DyslexiaFontTest extends TestCase { $cacheFactory = $this->createMock(ICacheFactory::class); $request = $this->createMock(IRequest::class); $router = $this->createMock(Router::class); - $this->urlGenerator = new \OC\URLGenerator( + $this->urlGenerator = new URLGenerator( $this->config, $userSession, $cacheFactory, @@ -94,6 +75,16 @@ class DyslexiaFontTest extends TestCase { ->method('getDefaultColorPrimary') ->willReturn('#0082c9'); + $this->themingDefaults + ->expects($this->any()) + ->method('getColorBackground') + ->willReturn('#0082c9'); + + $this->themingDefaults + ->expects($this->any()) + ->method('getDefaultColorBackground') + ->willReturn('#0082c9'); + $this->l10n ->expects($this->any()) ->method('t') @@ -110,41 +101,42 @@ class DyslexiaFontTest extends TestCase { $this->config, $this->l10n, $this->appManager, + null, ); parent::setUp(); } - public function testGetId() { + public function testGetId(): void { $this->assertEquals('opendyslexic', $this->dyslexiaFont->getId()); } - public function testGetType() { + public function testGetType(): void { $this->assertEquals(ITheme::TYPE_FONT, $this->dyslexiaFont->getType()); } - public function testGetTitle() { + public function testGetTitle(): void { $this->assertNotEmpty($this->dyslexiaFont->getTitle()); } - public function testGetEnableLabel() { + public function testGetEnableLabel(): void { $this->assertNotEmpty($this->dyslexiaFont->getEnableLabel()); } - public function testGetDescription() { + public function testGetDescription(): void { $this->assertNotEmpty($this->dyslexiaFont->getDescription()); } - public function testGetMediaQuery() { + public function testGetMediaQuery(): void { $this->assertEquals('', $this->dyslexiaFont->getMediaQuery()); } - public function testGetCSSVariables() { + public function testGetCSSVariables(): void { $this->assertStringStartsWith('OpenDyslexic', $this->dyslexiaFont->getCSSVariables()['--font-face']); } - public function dataTestGetCustomCss() { + public static function dataTestGetCustomCss(): array { return [ ['', true], ['', false], @@ -154,22 +146,18 @@ class DyslexiaFontTest extends TestCase { } /** - * @dataProvider dataTestGetCustomCss - * * Ensure the fonts are always loaded from the web root * despite having url rewriting enabled or not - * - * @param string $webRoot - * @param bool $prettyUrlsEnabled */ - public function testGetCustomCss($webRoot, $prettyUrlsEnabled) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestGetCustomCss')] + public function testGetCustomCss(string $webRoot, bool $prettyUrlsEnabled): void { \OC::$WEBROOT = $webRoot; $this->config->expects($this->any()) ->method('getSystemValue') ->with('htaccess.IgnoreFrontController', false) ->willReturn($prettyUrlsEnabled); - $this->assertStringContainsString("'$webRoot/apps/theming/fonts/OpenDyslexic-Regular.woff'", $this->dyslexiaFont->getCustomCss()); + $this->assertStringContainsString("'$webRoot/apps/theming/fonts/OpenDyslexic-Regular.otf'", $this->dyslexiaFont->getCustomCss()); $this->assertStringNotContainsString('index.php', $this->dyslexiaFont->getCustomCss()); } } diff --git a/apps/theming/tests/Themes/HighContrastThemeTest.php b/apps/theming/tests/Themes/HighContrastThemeTest.php index 991f56512e3..94f87d7433b 100644 --- a/apps/theming/tests/Themes/HighContrastThemeTest.php +++ b/apps/theming/tests/Themes/HighContrastThemeTest.php @@ -1,24 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests\Themes; @@ -35,26 +20,20 @@ use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUserSession; +use OCP\ServerVersion; use PHPUnit\Framework\MockObject\MockObject; class HighContrastThemeTest extends AccessibleThemeTestCase { - /** @var ThemingDefaults|MockObject */ - private $themingDefaults; - /** @var IUserSession|MockObject */ - private $userSession; - /** @var IURLGenerator|MockObject */ - private $urlGenerator; - /** @var ImageManager|MockObject */ - private $imageManager; - /** @var IConfig|MockObject */ - private $config; - /** @var IL10N|MockObject */ - private $l10n; - /** @var IAppManager|MockObject */ - private $appManager; + private ThemingDefaults&MockObject $themingDefaults; + private IUserSession&MockObject $userSession; + private IURLGenerator&MockObject $urlGenerator; + private ImageManager&MockObject $imageManager; + private IConfig&MockObject $config; + private IL10N&MockObject $l10n; + private IAppManager&MockObject $appManager; // !! important: Enable WCAG AAA tests - protected bool $WCAGaaa = true; + protected static bool $WCAGaaa = true; protected function setUp(): void { $this->themingDefaults = $this->createMock(ThemingDefaults::class); @@ -66,6 +45,7 @@ class HighContrastThemeTest extends AccessibleThemeTestCase { $this->appManager = $this->createMock(IAppManager::class); $this->util = new Util( + $this->createMock(ServerVersion::class), $this->config, $this->appManager, $this->createMock(IAppData::class), @@ -81,6 +61,14 @@ class HighContrastThemeTest extends AccessibleThemeTestCase { ->expects($this->any()) ->method('getDefaultColorPrimary') ->willReturn('#0082c9'); + $this->themingDefaults + ->expects($this->any()) + ->method('getColorBackground') + ->willReturn('#0082c9'); + $this->themingDefaults + ->expects($this->any()) + ->method('getDefaultColorBackground') + ->willReturn('#0082c9'); $this->themingDefaults ->expects($this->any()) @@ -110,33 +98,34 @@ class HighContrastThemeTest extends AccessibleThemeTestCase { $this->config, $this->l10n, $this->appManager, + null, ); parent::setUp(); } - public function testGetId() { + public function testGetId(): void { $this->assertEquals('light-highcontrast', $this->theme->getId()); } - public function testGetType() { + public function testGetType(): void { $this->assertEquals(ITheme::TYPE_THEME, $this->theme->getType()); } - public function testGetTitle() { + public function testGetTitle(): void { $this->assertEquals('High contrast mode', $this->theme->getTitle()); } - public function testGetEnableLabel() { + public function testGetEnableLabel(): void { $this->assertEquals('Enable high contrast mode', $this->theme->getEnableLabel()); } - public function testGetDescription() { + public function testGetDescription(): void { $this->assertEquals('A high contrast mode to ease your navigation. Visual quality will be reduced but clarity will be increased.', $this->theme->getDescription()); } - public function testGetMediaQuery() { + public function testGetMediaQuery(): void { $this->assertEquals('(prefers-contrast: more)', $this->theme->getMediaQuery()); } } diff --git a/apps/theming/tests/ThemingDefaultsTest.php b/apps/theming/tests/ThemingDefaultsTest.php index cf6b6492c11..1acd12f12fa 100644 --- a/apps/theming/tests/ThemingDefaultsTest.php +++ b/apps/theming/tests/ThemingDefaultsTest.php @@ -1,36 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Guillaume COMPAGNON <gcompagnon@outlook.com> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Julius Haertl <jus@bitgrid.net> - * @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 Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests; @@ -39,8 +12,8 @@ use OCA\Theming\Service\BackgroundService; use OCA\Theming\ThemingDefaults; use OCA\Theming\Util; use OCP\App\IAppManager; -use OCP\Files\IAppData; use OCP\Files\NotFoundException; +use OCP\IAppConfig; use OCP\ICache; use OCP\ICacheFactory; use OCP\IConfig; @@ -49,38 +22,28 @@ use OCP\INavigationManager; use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserSession; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class ThemingDefaultsTest extends TestCase { - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $config; - /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */ - private $l10n; - /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */ - private $userSession; - /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */ - private $urlGenerator; - /** @var \OC_Defaults|\PHPUnit\Framework\MockObject\MockObject */ - private $defaults; - /** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ - private $appData; - /** @var ICacheFactory|\PHPUnit\Framework\MockObject\MockObject */ - private $cacheFactory; - /** @var ThemingDefaults */ - private $template; - /** @var Util|\PHPUnit\Framework\MockObject\MockObject */ - private $util; - /** @var ICache|\PHPUnit\Framework\MockObject\MockObject */ - private $cache; - /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */ - private $appManager; - /** @var ImageManager|\PHPUnit\Framework\MockObject\MockObject */ - private $imageManager; - /** @var INavigationManager|\PHPUnit\Framework\MockObject\MockObject */ - private $navigationManager; + private IAppConfig&MockObject $appConfig; + private IConfig&MockObject $config; + private \OC_Defaults $defaults; + private IL10N|MockObject $l10n; + private IUserSession&MockObject $userSession; + private IURLGenerator&MockObject $urlGenerator; + private ICacheFactory&MockObject $cacheFactory; + private Util&MockObject $util; + private ICache&MockObject $cache; + private IAppManager&MockObject $appManager; + private ImageManager&MockObject $imageManager; + private INavigationManager&MockObject $navigationManager; + private BackgroundService&MockObject $backgroundService; + private ThemingDefaults $template; protected function setUp(): void { parent::setUp(); + $this->appConfig = $this->createMock(IAppConfig::class); $this->config = $this->createMock(IConfig::class); $this->l10n = $this->createMock(IL10N::class); $this->userSession = $this->createMock(IUserSession::class); @@ -91,6 +54,7 @@ class ThemingDefaultsTest extends TestCase { $this->imageManager = $this->createMock(ImageManager::class); $this->appManager = $this->createMock(IAppManager::class); $this->navigationManager = $this->createMock(INavigationManager::class); + $this->backgroundService = $this->createMock(BackgroundService::class); $this->defaults = new \OC_Defaults(); $this->urlGenerator ->expects($this->any()) @@ -98,6 +62,7 @@ class ThemingDefaultsTest extends TestCase { ->willReturn(''); $this->template = new ThemingDefaults( $this->config, + $this->appConfig, $this->l10n, $this->userSession, $this->urlGenerator, @@ -105,11 +70,12 @@ class ThemingDefaultsTest extends TestCase { $this->util, $this->imageManager, $this->appManager, - $this->navigationManager + $this->navigationManager, + $this->backgroundService, ); } - public function testGetNameWithDefault() { + public function testGetNameWithDefault(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -119,7 +85,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('Nextcloud', $this->template->getName()); } - public function testGetNameWithCustom() { + public function testGetNameWithCustom(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -129,7 +95,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('MyCustomCloud', $this->template->getName()); } - public function testGetHTMLNameWithDefault() { + public function testGetHTMLNameWithDefault(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -139,7 +105,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('Nextcloud', $this->template->getHTMLName()); } - public function testGetHTMLNameWithCustom() { + public function testGetHTMLNameWithCustom(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -149,7 +115,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('MyCustomCloud', $this->template->getHTMLName()); } - public function testGetTitleWithDefault() { + public function testGetTitleWithDefault(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -159,7 +125,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('Nextcloud', $this->template->getTitle()); } - public function testGetTitleWithCustom() { + public function testGetTitleWithCustom(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -170,7 +136,7 @@ class ThemingDefaultsTest extends TestCase { } - public function testGetEntityWithDefault() { + public function testGetEntityWithDefault(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -180,7 +146,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('Nextcloud', $this->template->getEntity()); } - public function testGetEntityWithCustom() { + public function testGetEntityWithCustom(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -190,7 +156,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('MyCustomCloud', $this->template->getEntity()); } - public function testGetBaseUrlWithDefault() { + public function testGetBaseUrlWithDefault(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -200,7 +166,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals($this->defaults->getBaseUrl(), $this->template->getBaseUrl()); } - public function testGetBaseUrlWithCustom() { + public function testGetBaseUrlWithCustom(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -210,18 +176,15 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('https://example.com/', $this->template->getBaseUrl()); } - public function legalUrlProvider() { + public static function legalUrlProvider(): array { return [ - [ '' ], - [ 'https://example.com/legal.html'] + [''], + ['https://example.com/legal.html'], ]; } - /** - * @param $imprintUrl - * @dataProvider legalUrlProvider - */ - public function testGetImprintURL($imprintUrl) { + #[\PHPUnit\Framework\Attributes\DataProvider('legalUrlProvider')] + public function testGetImprintURL(string $imprintUrl): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -231,11 +194,8 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals($imprintUrl, $this->template->getImprintUrl()); } - /** - * @param $privacyUrl - * @dataProvider legalUrlProvider - */ - public function testGetPrivacyURL($privacyUrl) { + #[\PHPUnit\Framework\Attributes\DataProvider('legalUrlProvider')] + public function testGetPrivacyURL(string $privacyUrl): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -245,7 +205,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals($privacyUrl, $this->template->getPrivacyUrl()); } - public function testGetSloganWithDefault() { + public function testGetSloganWithDefault(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -255,7 +215,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals($this->defaults->getSlogan(), $this->template->getSlogan()); } - public function testGetSloganWithCustom() { + public function testGetSloganWithCustom(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -265,7 +225,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('My custom Slogan', $this->template->getSlogan()); } - public function testGetShortFooter() { + public function testGetShortFooter(): void { $this->config ->expects($this->exactly(5)) ->method('getAppValue') @@ -280,7 +240,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan', $this->template->getShortFooter()); } - public function testGetShortFooterEmptyUrl() { + public function testGetShortFooterEmptyUrl(): void { $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]); $this->config ->expects($this->exactly(5)) @@ -296,7 +256,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('<span class="entity-name">Name</span> – Slogan', $this->template->getShortFooter()); } - public function testGetShortFooterEmptySlogan() { + public function testGetShortFooterEmptySlogan(): void { $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]); $this->config ->expects($this->exactly(5)) @@ -312,7 +272,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a>', $this->template->getShortFooter()); } - public function testGetShortFooterImprint() { + public function testGetShortFooterImprint(): void { $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]); $this->config ->expects($this->exactly(5)) @@ -330,10 +290,10 @@ class ThemingDefaultsTest extends TestCase { ->method('t') ->willReturnArgument(0); - $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><a href="https://example.com/imprint" class="legal" target="_blank" rel="noreferrer noopener">Legal notice</a>', $this->template->getShortFooter()); + $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><span class="footer__legal-links"><a href="https://example.com/imprint" class="legal" target="_blank" rel="noreferrer noopener">Legal notice</a></span>', $this->template->getShortFooter()); } - public function testGetShortFooterPrivacy() { + public function testGetShortFooterPrivacy(): void { $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]); $this->config ->expects($this->exactly(5)) @@ -351,10 +311,10 @@ class ThemingDefaultsTest extends TestCase { ->method('t') ->willReturnArgument(0); - $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><a href="https://example.com/privacy" class="legal" target="_blank" rel="noreferrer noopener">Privacy policy</a>', $this->template->getShortFooter()); + $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><span class="footer__legal-links"><a href="https://example.com/privacy" class="legal" target="_blank" rel="noreferrer noopener">Privacy policy</a></span>', $this->template->getShortFooter()); } - public function testGetShortFooterAllLegalLinks() { + public function testGetShortFooterAllLegalLinks(): void { $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]); $this->config ->expects($this->exactly(5)) @@ -372,21 +332,18 @@ class ThemingDefaultsTest extends TestCase { ->method('t') ->willReturnArgument(0); - $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><a href="https://example.com/imprint" class="legal" target="_blank" rel="noreferrer noopener">Legal notice</a> · <a href="https://example.com/privacy" class="legal" target="_blank" rel="noreferrer noopener">Privacy policy</a>', $this->template->getShortFooter()); + $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><span class="footer__legal-links"><a href="https://example.com/imprint" class="legal" target="_blank" rel="noreferrer noopener">Legal notice</a> · <a href="https://example.com/privacy" class="legal" target="_blank" rel="noreferrer noopener">Privacy policy</a></span>', $this->template->getShortFooter()); } - public function invalidLegalUrlProvider() { + public static function invalidLegalUrlProvider(): array { return [ ['example.com/legal'], # missing scheme ['https:///legal'], # missing host ]; } - /** - * @param $invalidImprintUrl - * @dataProvider invalidLegalUrlProvider - */ - public function testGetShortFooterInvalidImprint($invalidImprintUrl) { + #[\PHPUnit\Framework\Attributes\DataProvider('invalidLegalUrlProvider')] + public function testGetShortFooterInvalidImprint(string $invalidImprintUrl): void { $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]); $this->config ->expects($this->exactly(5)) @@ -402,11 +359,8 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan', $this->template->getShortFooter()); } - /** - * @param $invalidPrivacyUrl - * @dataProvider invalidLegalUrlProvider - */ - public function testGetShortFooterInvalidPrivacy($invalidPrivacyUrl) { + #[\PHPUnit\Framework\Attributes\DataProvider('invalidLegalUrlProvider')] + public function testGetShortFooterInvalidPrivacy(string $invalidPrivacyUrl): void { $this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]); $this->config ->expects($this->exactly(5)) @@ -422,109 +376,79 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan', $this->template->getShortFooter()); } - public function testGetColorPrimaryWithDefault() { - $this->config - ->expects($this->exactly(2)) - ->method('getAppValue') - ->willReturnMap([ - ['theming', 'disable-user-theming', 'no', 'no'], - ['theming', 'color', '', $this->defaults->getColorPrimary()], - ]); + public function testGetColorPrimaryWithDefault(): void { + $this->appConfig + ->expects(self::once()) + ->method('getValueBool') + ->with('theming', 'disable-user-theming') + ->willReturn(false); + $this->appConfig + ->expects(self::once()) + ->method('getValueString') + ->with('theming', 'primary_color', '') + ->willReturn($this->defaults->getColorPrimary()); $this->assertEquals($this->defaults->getColorPrimary(), $this->template->getColorPrimary()); } - public function testGetColorPrimaryWithCustom() { - $this->config - ->expects($this->exactly(2)) - ->method('getAppValue') - ->willReturnMap([ - ['theming', 'disable-user-theming', 'no', 'no'], - ['theming', 'color', '', '#fff'], - ]); + public function testGetColorPrimaryWithCustom(): void { + $this->appConfig + ->expects(self::once()) + ->method('getValueBool') + ->with('theming', 'disable-user-theming') + ->willReturn(false); + $this->appConfig + ->expects(self::once()) + ->method('getValueString') + ->with('theming', 'primary_color', '') + ->willReturn('#fff'); $this->assertEquals('#fff', $this->template->getColorPrimary()); } - public function testGetColorPrimaryWithDefaultBackground() { - $user = $this->createMock(IUser::class); - $this->userSession->expects($this->any()) - ->method('getUser') - ->willReturn($user); - $user->expects($this->any()) - ->method('getUID') - ->willReturn('user'); - $this->config - ->expects($this->exactly(2)) - ->method('getAppValue') - ->willReturnMap([ - ['theming', 'disable-user-theming', 'no', 'no'], - ['theming', 'color', '', ''], - ]); - $this->config - ->expects($this->once()) - ->method('getUserValue') - ->with('user', 'theming', 'background_color') - ->willReturn(''); - - $this->assertEquals(BackgroundService::DEFAULT_COLOR, $this->template->getColorPrimary()); - } - - public function testGetColorPrimaryWithCustomBackground() { - $backgroundIndex = 2; - $background = array_values(BackgroundService::SHIPPED_BACKGROUNDS)[$backgroundIndex]; - - $user = $this->createMock(IUser::class); - $this->userSession->expects($this->any()) - ->method('getUser') - ->willReturn($user); - $user->expects($this->any()) - ->method('getUID') - ->willReturn('user'); - - $this->config - ->expects($this->once()) - ->method('getUserValue') - ->with('user', 'theming', 'background_color', '') - ->willReturn($background['primary_color']); - - $this->config - ->expects($this->exactly(2)) - ->method('getAppValue') - ->willReturnMap([ - ['theming', 'color', '', ''], - ['theming', 'disable-user-theming', 'no', 'no'], - ]); - - $this->assertEquals($background['primary_color'], $this->template->getColorPrimary()); - } - - public function testGetColorPrimaryWithCustomBackgroundColor() { - $user = $this->createMock(IUser::class); - $this->userSession->expects($this->any()) - ->method('getUser') - ->willReturn($user); - $user->expects($this->any()) - ->method('getUID') - ->willReturn('user'); - - $this->config - ->expects($this->once()) - ->method('getUserValue') - ->with('user', 'theming', 'background_color', '') - ->willReturn('#fff'); - $this->config - ->expects($this->exactly(2)) - ->method('getAppValue') - ->willReturnMap([ - ['theming', 'color', '', ''], - ['theming', 'disable-user-theming', 'no', 'no'], - ]); - - $this->assertEquals('#fff', $this->template->getColorPrimary()); + public static function dataGetColorPrimary(): array { + return [ + 'with fallback default' => [ + 'disableTheming' => false, + 'primaryColor' => '', + 'userPrimaryColor' => '', + 'expected' => BackgroundService::DEFAULT_COLOR, + ], + 'with custom admin primary' => [ + 'disableTheming' => false, + 'primaryColor' => '#aaa', + 'userPrimaryColor' => '', + 'expected' => '#aaa', + ], + 'with custom invalid admin primary' => [ + 'disableTheming' => false, + 'primaryColor' => 'invalid', + 'userPrimaryColor' => '', + 'expected' => BackgroundService::DEFAULT_COLOR, + ], + 'with custom invalid user primary' => [ + 'disableTheming' => false, + 'primaryColor' => '', + 'userPrimaryColor' => 'invalid-name', + 'expected' => BackgroundService::DEFAULT_COLOR, + ], + 'with custom user primary' => [ + 'disableTheming' => false, + 'primaryColor' => '', + 'userPrimaryColor' => '#bbb', + 'expected' => '#bbb', + ], + 'with disabled user theming primary' => [ + 'disableTheming' => true, + 'primaryColor' => '#aaa', + 'userPrimaryColor' => '#bbb', + 'expected' => '#aaa', + ], + ]; } - public function testGetColorPrimaryWithInvalidCustomBackgroundColor() { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetColorPrimary')] + public function testGetColorPrimary(bool $disableTheming, string $primaryColor, string $userPrimaryColor, string $expected): void { $user = $this->createMock(IUser::class); $this->userSession->expects($this->any()) ->method('getUser') @@ -532,31 +456,38 @@ class ThemingDefaultsTest extends TestCase { $user->expects($this->any()) ->method('getUID') ->willReturn('user'); - + $this->appConfig + ->expects(self::any()) + ->method('getValueBool') + ->with('theming', 'disable-user-theming') + ->willReturn($disableTheming); + $this->appConfig + ->expects(self::any()) + ->method('getValueString') + ->with('theming', 'primary_color', '') + ->willReturn($primaryColor); $this->config - ->expects($this->once()) + ->expects($this->any()) ->method('getUserValue') - ->with('user', 'theming', 'background_color', '') - ->willReturn('nextcloud'); - $this->config - ->expects($this->exactly(3)) - ->method('getAppValue') - ->willReturnMap([ - ['theming', 'color', '', ''], - ['theming', 'disable-user-theming', 'no', 'no'], - ]); + ->with('user', 'theming', 'primary_color', '') + ->willReturn($userPrimaryColor); - $this->assertEquals($this->template->getDefaultColorPrimary(), $this->template->getColorPrimary()); + $this->assertEquals($expected, $this->template->getColorPrimary()); } - public function testSet() { + public function testSet(): void { + $expectedCalls = [ + ['theming', 'MySetting', 'MyValue'], + ['theming', 'cachebuster', 16], + ]; + $i = 0; $this->config ->expects($this->exactly(2)) ->method('setAppValue') - ->withConsecutive( - ['theming', 'MySetting', 'MyValue'], - ['theming', 'cachebuster', 16], - ); + ->willReturnCallback(function () use ($expectedCalls, &$i): void { + $this->assertEquals($expectedCalls[$i], func_get_args()); + $i++; + }); $this->config ->expects($this->once()) ->method('getAppValue') @@ -565,11 +496,10 @@ class ThemingDefaultsTest extends TestCase { $this->cacheFactory ->expects($this->exactly(2)) ->method('createDistributed') - ->withConsecutive( - ['theming-'], - ['imagePath'], - ) - ->willReturn($this->cache); + ->willReturnMap([ + ['theming-', $this->cache], + ['imagePath', $this->cache], + ]); $this->cache ->expects($this->any()) ->method('clear') @@ -577,7 +507,7 @@ class ThemingDefaultsTest extends TestCase { $this->template->set('MySetting', 'MyValue'); } - public function testUndoName() { + public function testUndoName(): void { $this->config ->expects($this->once()) ->method('deleteAppValue') @@ -585,13 +515,10 @@ class ThemingDefaultsTest extends TestCase { $this->config ->expects($this->exactly(2)) ->method('getAppValue') - ->withConsecutive( - ['theming', 'cachebuster', '0'], - ['theming', 'name', 'Nextcloud'], - )->willReturnOnConsecutiveCalls( - '15', - 'Nextcloud', - ); + ->willReturnMap([ + ['theming', 'cachebuster', '0', '15'], + ['theming', 'name', 'Nextcloud', 'Nextcloud'], + ]); $this->config ->expects($this->once()) ->method('setAppValue') @@ -600,7 +527,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertSame('Nextcloud', $this->template->undo('name')); } - public function testUndoBaseUrl() { + public function testUndoBaseUrl(): void { $this->config ->expects($this->once()) ->method('deleteAppValue') @@ -608,13 +535,10 @@ class ThemingDefaultsTest extends TestCase { $this->config ->expects($this->exactly(2)) ->method('getAppValue') - ->withConsecutive( - ['theming', 'cachebuster', '0'], - ['theming', 'url', $this->defaults->getBaseUrl()], - )->willReturnOnConsecutiveCalls( - '15', - $this->defaults->getBaseUrl(), - ); + ->willReturnMap([ + ['theming', 'cachebuster', '0', '15'], + ['theming', 'url', $this->defaults->getBaseUrl(), $this->defaults->getBaseUrl()], + ]); $this->config ->expects($this->once()) ->method('setAppValue') @@ -623,7 +547,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertSame($this->defaults->getBaseUrl(), $this->template->undo('url')); } - public function testUndoSlogan() { + public function testUndoSlogan(): void { $this->config ->expects($this->once()) ->method('deleteAppValue') @@ -631,13 +555,10 @@ class ThemingDefaultsTest extends TestCase { $this->config ->expects($this->exactly(2)) ->method('getAppValue') - ->withConsecutive( - ['theming', 'cachebuster', '0'], - ['theming', 'slogan', $this->defaults->getSlogan()], - )->willReturnOnConsecutiveCalls( - '15', - $this->defaults->getSlogan(), - ); + ->willReturnMap([ + ['theming', 'cachebuster', '0', '15'], + ['theming', 'slogan', $this->defaults->getSlogan(), $this->defaults->getSlogan()], + ]); $this->config ->expects($this->once()) ->method('setAppValue') @@ -646,30 +567,25 @@ class ThemingDefaultsTest extends TestCase { $this->assertSame($this->defaults->getSlogan(), $this->template->undo('slogan')); } - public function testUndoColor() { + public function testUndoPrimaryColor(): void { $this->config ->expects($this->once()) ->method('deleteAppValue') - ->with('theming', 'color'); + ->with('theming', 'primary_color'); $this->config - ->expects($this->exactly(2)) + ->expects($this->once()) ->method('getAppValue') - ->withConsecutive( - ['theming', 'cachebuster', '0'], - ['theming', 'color', null], - )->willReturnOnConsecutiveCalls( - '15', - $this->defaults->getColorPrimary(), - ); + ->with('theming', 'cachebuster', '0') + ->willReturn('15'); $this->config ->expects($this->once()) ->method('setAppValue') ->with('theming', 'cachebuster', 16); - $this->assertSame($this->defaults->getColorPrimary(), $this->template->undo('color')); + $this->assertSame($this->defaults->getColorPrimary(), $this->template->undo('primary_color')); } - public function testUndoDefaultAction() { + public function testUndoDefaultAction(): void { $this->config ->expects($this->once()) ->method('deleteAppValue') @@ -687,7 +603,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertSame('', $this->template->undo('defaultitem')); } - public function testGetBackground() { + public function testGetBackground(): void { $this->imageManager ->expects($this->once()) ->method('getImageUrl') @@ -704,13 +620,10 @@ class ThemingDefaultsTest extends TestCase { $this->config ->expects($this->exactly(2)) ->method('getAppValue') - ->withConsecutive( - ['theming', 'logoMime'], - ['theming', 'cachebuster', '0'], - )->willReturnOnConsecutiveCalls( - '', - '0' - ); + ->willReturnMap([ + ['theming', 'logoMime', '', ''], + ['theming', 'cachebuster', '0', '0'], + ]); $this->urlGenerator->expects($this->once()) ->method('imagePath') ->with('core', $withName) @@ -718,25 +631,22 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('core-logo?v=0', $this->template->getLogo($useSvg)); } - public function testGetLogoDefaultWithSvg() { + public function testGetLogoDefaultWithSvg(): void { $this->getLogoHelper('logo/logo.svg', true); } - public function testGetLogoDefaultWithoutSvg() { + public function testGetLogoDefaultWithoutSvg(): void { $this->getLogoHelper('logo/logo.png', false); } - public function testGetLogoCustom() { + public function testGetLogoCustom(): void { $this->config ->expects($this->exactly(2)) ->method('getAppValue') - ->withConsecutive( - ['theming', 'logoMime', false], - ['theming', 'cachebuster', '0'], - )->willReturnOnConsecutiveCalls( - 'image/svg+xml', - '0', - ); + ->willReturnMap([ + ['theming', 'logoMime', '', 'image/svg+xml'], + ['theming', 'cachebuster', '0', '0'], + ]); $this->urlGenerator->expects($this->once()) ->method('linkToRoute') ->with('theming.Theming.getImage') @@ -744,7 +654,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('custom-logo' . '?v=0', $this->template->getLogo()); } - public function testGetScssVariablesCached() { + public function testGetScssVariablesCached(): void { $this->config->expects($this->any())->method('getAppValue')->with('theming', 'cachebuster', '0')->willReturn('1'); $this->cacheFactory->expects($this->once()) ->method('createDistributed') @@ -754,7 +664,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals(['foo' => 'bar'], $this->template->getScssVariables()); } - public function testGetScssVariables() { + public function testGetScssVariables(): void { $this->config ->expects($this->any()) ->method('getAppValue') @@ -764,8 +674,14 @@ class ThemingDefaultsTest extends TestCase { ['theming', 'backgroundMime', '', 'jpeg'], ['theming', 'logoheaderMime', '', 'jpeg'], ['theming', 'faviconMime', '', 'jpeg'], - ['theming', 'color', '', $this->defaults->getColorPrimary()], - ['theming', 'color', $this->defaults->getColorPrimary(), $this->defaults->getColorPrimary()], + ]); + + $this->appConfig + ->expects(self::atLeastOnce()) + ->method('getValueString') + ->willReturnMap([ + ['theming', 'primary_color', '', false, $this->defaults->getColorPrimary()], + ['theming', 'primary_color', $this->defaults->getColorPrimary(), false, $this->defaults->getColorPrimary()], ]); $this->util->expects($this->any())->method('invertTextColor')->with($this->defaults->getColorPrimary())->willReturn(false); @@ -803,7 +719,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals($expected, $this->template->getScssVariables()); } - public function testGetDefaultAndroidURL() { + public function testGetDefaultAndroidURL(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -813,7 +729,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('https://play.google.com/store/apps/details?id=com.nextcloud.client', $this->template->getAndroidClientUrl()); } - public function testGetCustomAndroidURL() { + public function testGetCustomAndroidURL(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -823,7 +739,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('https://play.google.com/store/apps/details?id=com.mycloud.client', $this->template->getAndroidClientUrl()); } - public function testGetDefaultiOSURL() { + public function testGetDefaultiOSURL(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -833,7 +749,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('https://geo.itunes.apple.com/us/app/nextcloud/id1125420102?mt=8', $this->template->getiOSClientUrl()); } - public function testGetCustomiOSURL() { + public function testGetCustomiOSURL(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -843,7 +759,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('https://geo.itunes.apple.com/us/app/nextcloud/id1234567890?mt=8', $this->template->getiOSClientUrl()); } - public function testGetDefaultiTunesAppId() { + public function testGetDefaultiTunesAppId(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -853,7 +769,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('1125420102', $this->template->getiTunesAppId()); } - public function testGetCustomiTunesAppId() { + public function testGetCustomiTunesAppId(): void { $this->config ->expects($this->once()) ->method('getAppValue') @@ -863,7 +779,7 @@ class ThemingDefaultsTest extends TestCase { $this->assertEquals('1234567890', $this->template->getiTunesAppId()); } - public function dataReplaceImagePath() { + public static function dataReplaceImagePath(): array { return [ ['core', 'test.png', false], ['core', 'manifest.json'], @@ -872,8 +788,8 @@ class ThemingDefaultsTest extends TestCase { ]; } - /** @dataProvider dataReplaceImagePath */ - public function testReplaceImagePath($app, $image, $result = 'themingRoute?v=1234abcd') { + #[\PHPUnit\Framework\Attributes\DataProvider('dataReplaceImagePath')] + public function testReplaceImagePath(string $app, string $image, string|bool $result = 'themingRoute?v=1234abcd'): void { $this->cache->expects($this->any()) ->method('get') ->with('shouldReplaceIcons') diff --git a/apps/theming/tests/UtilTest.php b/apps/theming/tests/UtilTest.php index 857e9fff6a5..1e944027e32 100644 --- a/apps/theming/tests/UtilTest.php +++ b/apps/theming/tests/UtilTest.php @@ -1,29 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Julius Haertl <jus@bitgrid.net> - * @author Julius Härtl <jus@bitgrid.net> - * @author Michael Weimann <mail@michael-weimann.eu> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * 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 - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Theming\Tests; @@ -35,32 +15,29 @@ use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFile; use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IConfig; +use OCP\Server; +use OCP\ServerVersion; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class UtilTest extends TestCase { - /** @var Util */ - protected $util; - /** @var IConfig|MockObject */ - protected $config; - /** @var IAppData|MockObject */ - protected $appData; - /** @var IAppManager|MockObject */ - protected $appManager; - /** @var ImageManager|MockObject */ - protected $imageManager; + protected Util $util; + protected IConfig&MockObject $config; + protected IAppData&MockObject $appData; + protected IAppManager $appManager; + protected ImageManager&MockObject $imageManager; protected function setUp(): void { parent::setUp(); $this->config = $this->createMock(IConfig::class); $this->appData = $this->createMock(IAppData::class); - $this->appManager = $this->createMock(IAppManager::class); + $this->appManager = Server::get(IAppManager::class); $this->imageManager = $this->createMock(ImageManager::class); - $this->util = new Util($this->config, $this->appManager, $this->appData, $this->imageManager); + $this->util = new Util($this->createMock(ServerVersion::class), $this->config, $this->appManager, $this->appData, $this->imageManager); } - public function dataColorContrast() { + public static function dataColorContrast(): array { return [ ['#ffffff', '#FFFFFF', 1], ['#000000', '#000000', 1], @@ -71,14 +48,12 @@ class UtilTest extends TestCase { ]; } - /** - * @dataProvider dataColorContrast - */ - public function testColorContrast(string $color1, string $color2, $contrast) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataColorContrast')] + public function testColorContrast(string $color1, string $color2, int|float $contrast): void { $this->assertEqualsWithDelta($contrast, $this->util->colorContrast($color1, $color2), .001); } - public function dataInvertTextColor() { + public static function dataInvertTextColor(): array { return [ ['#ffffff', true], ['#000000', false], @@ -86,111 +61,103 @@ class UtilTest extends TestCase { ['#ffff00', true], ]; } - /** - * @dataProvider dataInvertTextColor - */ - public function testInvertTextColor($color, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataInvertTextColor')] + public function testInvertTextColor(string $color, bool $expected): void { $invert = $this->util->invertTextColor($color); $this->assertEquals($expected, $invert); } - public function testCalculateLuminanceLight() { + public function testCalculateLuminanceLight(): void { $luminance = $this->util->calculateLuminance('#ffffff'); $this->assertEquals(1, $luminance); } - public function testCalculateLuminanceDark() { + public function testCalculateLuminanceDark(): void { $luminance = $this->util->calculateLuminance('#000000'); $this->assertEquals(0, $luminance); } - public function testCalculateLuminanceLightShorthand() { + public function testCalculateLuminanceLightShorthand(): void { $luminance = $this->util->calculateLuminance('#fff'); $this->assertEquals(1, $luminance); } - public function testCalculateLuminanceDarkShorthand() { + public function testCalculateLuminanceDarkShorthand(): void { $luminance = $this->util->calculateLuminance('#000'); $this->assertEquals(0, $luminance); } - public function testInvertTextColorInvalid() { + public function testInvertTextColorInvalid(): void { $this->expectException(\Exception::class); $this->util->invertTextColor('aaabbbcccddd123'); } - public function testInvertTextColorEmpty() { + public function testInvertTextColorEmpty(): void { $this->expectException(\Exception::class); $this->util->invertTextColor(''); } - public function testElementColorDefaultBlack() { - $elementColor = $this->util->elementColor("#000000"); + public function testElementColorDefaultBlack(): void { + $elementColor = $this->util->elementColor('#000000'); $this->assertEquals('#4d4d4d', $elementColor); } - public function testElementColorDefaultWhite() { - $elementColor = $this->util->elementColor("#ffffff"); + public function testElementColorDefaultWhite(): void { + $elementColor = $this->util->elementColor('#ffffff'); $this->assertEquals('#b3b3b3', $elementColor); } - public function testElementColorBlackOnDarkBackground() { - $elementColor = $this->util->elementColor("#000000", false); + public function testElementColorBlackOnDarkBackground(): void { + $elementColor = $this->util->elementColor('#000000', false); $this->assertEquals('#4d4d4d', $elementColor); } - public function testElementColorBlackOnBrightBackground() { - $elementColor = $this->util->elementColor("#000000", true); + public function testElementColorBlackOnBrightBackground(): void { + $elementColor = $this->util->elementColor('#000000', true); $this->assertEquals('#000000', $elementColor); } - public function testElementColorWhiteOnBrightBackground() { + public function testElementColorWhiteOnBrightBackground(): void { $elementColor = $this->util->elementColor('#ffffff', true); $this->assertEquals('#b3b3b3', $elementColor); } - public function testElementColorWhiteOnDarkBackground() { + public function testElementColorWhiteOnDarkBackground(): void { $elementColor = $this->util->elementColor('#ffffff', false); $this->assertEquals('#ffffff', $elementColor); } - public function testGenerateRadioButtonWhite() { + public function testGenerateRadioButtonWhite(): void { $button = $this->util->generateRadioButton('#ffffff'); $expected = 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTYiIHdpZHRoPSIxNiI+PHBhdGggZD0iTTggMWE3IDcgMCAwIDAtNyA3IDcgNyAwIDAgMCA3IDcgNyA3IDAgMCAwIDctNyA3IDcgMCAwIDAtNy03em0wIDFhNiA2IDAgMCAxIDYgNiA2IDYgMCAwIDEtNiA2IDYgNiAwIDAgMS02LTYgNiA2IDAgMCAxIDYtNnptMCAyYTQgNCAwIDEgMCAwIDggNCA0IDAgMCAwIDAtOHoiIGZpbGw9IiNmZmZmZmYiLz48L3N2Zz4='; $this->assertEquals($expected, $button); } - public function testGenerateRadioButtonBlack() { + public function testGenerateRadioButtonBlack(): void { $button = $this->util->generateRadioButton('#000000'); $expected = 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTYiIHdpZHRoPSIxNiI+PHBhdGggZD0iTTggMWE3IDcgMCAwIDAtNyA3IDcgNyAwIDAgMCA3IDcgNyA3IDAgMCAwIDctNyA3IDcgMCAwIDAtNy03em0wIDFhNiA2IDAgMCAxIDYgNiA2IDYgMCAwIDEtNiA2IDYgNiAwIDAgMS02LTYgNiA2IDAgMCAxIDYtNnptMCAyYTQgNCAwIDEgMCAwIDggNCA0IDAgMCAwIDAtOHoiIGZpbGw9IiMwMDAwMDAiLz48L3N2Zz4='; $this->assertEquals($expected, $button); } - /** - * @dataProvider dataGetAppIcon - */ - public function testGetAppIcon($app, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetAppIcon')] + public function testGetAppIcon(string $app, string $expected): void { $this->appData->expects($this->any()) ->method('getFolder') ->with('global/images') ->willThrowException(new NotFoundException()); - $this->appManager->expects($this->once()) - ->method('getAppPath') - ->with($app) - ->willReturn(\OC_App::getAppPath($app)); $icon = $this->util->getAppIcon($app); $this->assertEquals($expected, $icon); } - public function dataGetAppIcon() { + public static function dataGetAppIcon(): array { return [ - ['user_ldap', \OC_App::getAppPath('user_ldap') . '/img/app.svg'], + ['user_ldap', Server::get(IAppManager::class)->getAppPath('user_ldap') . '/img/app.svg'], ['noapplikethis', \OC::$SERVERROOT . '/core/img/logo/logo.svg'], - ['comments', \OC_App::getAppPath('comments') . '/img/comments.svg'], + ['comments', Server::get(IAppManager::class)->getAppPath('comments') . '/img/comments.svg'], ]; } - public function testGetAppIconThemed() { + public function testGetAppIconThemed(): void { $file = $this->createMock(ISimpleFile::class); $folder = $this->createMock(ISimpleFolder::class); $folder->expects($this->once()) @@ -205,20 +172,12 @@ class UtilTest extends TestCase { $this->assertEquals($file, $icon); } - /** - * @dataProvider dataGetAppImage - */ - public function testGetAppImage($app, $image, $expected) { - if ($app !== 'core') { - $this->appManager->expects($this->once()) - ->method('getAppPath') - ->with($app) - ->willReturn(\OC_App::getAppPath($app)); - } + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetAppImage')] + public function testGetAppImage(string $app, string $image, string|bool $expected): void { $this->assertEquals($expected, $this->util->getAppImage($app, $image)); } - public function dataGetAppImage() { + public static function dataGetAppImage(): array { return [ ['core', 'logo/logo.svg', \OC::$SERVERROOT . '/core/img/logo/logo.svg'], ['files', 'folder', \OC::$SERVERROOT . '/apps/files/img/folder.svg'], @@ -227,14 +186,14 @@ class UtilTest extends TestCase { ]; } - public function testColorizeSvg() { - $input = "#0082c9 #0082C9 #000000 #FFFFFF"; - $expected = "#AAAAAA #AAAAAA #000000 #FFFFFF"; + public function testColorizeSvg(): void { + $input = '#0082c9 #0082C9 #000000 #FFFFFF'; + $expected = '#AAAAAA #AAAAAA #000000 #FFFFFF'; $result = $this->util->colorizeSvg($input, '#AAAAAA'); $this->assertEquals($expected, $result); } - public function testIsAlreadyThemedFalse() { + public function testIsAlreadyThemedFalse(): void { $this->config->expects($this->once()) ->method('getSystemValue') ->with('theme', '') @@ -243,7 +202,7 @@ class UtilTest extends TestCase { $this->assertFalse($actual); } - public function testIsAlreadyThemedTrue() { + public function testIsAlreadyThemedTrue(): void { $this->config->expects($this->once()) ->method('getSystemValue') ->with('theme', '') @@ -252,17 +211,15 @@ class UtilTest extends TestCase { $this->assertTrue($actual); } - public function dataIsBackgroundThemed() { + public static function dataIsBackgroundThemed(): array { return [ ['', false], ['png', true], ['backgroundColor', false], ]; } - /** - * @dataProvider dataIsBackgroundThemed - */ - public function testIsBackgroundThemed($backgroundMime, $expected) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataIsBackgroundThemed')] + public function testIsBackgroundThemed(string $backgroundMime, bool $expected): void { $this->config->expects($this->once()) ->method('getAppValue') ->with('theming', 'backgroundMime', '') |