aboutsummaryrefslogtreecommitdiffstats
path: root/apps/theming/tests/ImageManagerTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'apps/theming/tests/ImageManagerTest.php')
-rw-r--r--apps/theming/tests/ImageManagerTest.php383
1 files changed, 383 insertions, 0 deletions
diff --git a/apps/theming/tests/ImageManagerTest.php b/apps/theming/tests/ImageManagerTest.php
new file mode 100644
index 00000000000..0c4d555cc00
--- /dev/null
+++ b/apps/theming/tests/ImageManagerTest.php
@@ -0,0 +1,383 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * 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;
+use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\ICacheFactory;
+use OCP\IConfig;
+use OCP\ITempManager;
+use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class ImageManagerTest extends TestCase {
+ 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();
+ $this->config = $this->createMock(IConfig::class);
+ $this->appData = $this->createMock(IAppData::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
+ $this->cacheFactory = $this->createMock(ICacheFactory::class);
+ $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,
+ $backgroundService,
+ );
+ $this->appData
+ ->expects($this->any())
+ ->method('getFolder')
+ ->with('global')
+ ->willReturn($this->rootFolder);
+ }
+
+ private function checkImagick() {
+ if (!extension_loaded('imagick')) {
+ $this->markTestSkipped('Imagemagick is required for dynamic icon generation.');
+ }
+ $checkImagick = new \Imagick();
+ if (empty($checkImagick->queryFormats('SVG'))) {
+ $this->markTestSkipped('No SVG provider present.');
+ }
+ if (empty($checkImagick->queryFormats('PNG'))) {
+ $this->markTestSkipped('No PNG provider present.');
+ }
+ }
+
+ public function mockGetImage($key, $file) {
+ /** @var MockObject $folder */
+ $folder = $this->createMock(ISimpleFolder::class);
+ if ($file === null) {
+ $folder->expects($this->once())
+ ->method('getFile')
+ ->with('logo')
+ ->willThrowException(new NotFoundException());
+ } else {
+ $file->expects($this->once())
+ ->method('getContent')
+ ->willReturn(file_get_contents(__DIR__ . '/../../../tests/data/testimage.png'));
+ $folder->expects($this->exactly(2))
+ ->method('fileExists')
+ ->willReturnMap([
+ ['logo', true],
+ ['logo.png', false],
+ ]);
+ $folder->expects($this->once())
+ ->method('getFile')
+ ->with('logo')
+ ->willReturn($file);
+ $newFile = $this->createMock(ISimpleFile::class);
+ $folder->expects($this->once())
+ ->method('newFile')
+ ->with('logo.png')
+ ->willReturn($newFile);
+ $newFile->expects($this->once())
+ ->method('putContent');
+ $this->rootFolder->expects($this->once())
+ ->method('getFolder')
+ ->with('images')
+ ->willReturn($folder);
+ }
+ }
+
+ public function testGetImageUrl(): void {
+ $this->checkImagick();
+ $this->config->expects($this->exactly(2))
+ ->method('getAppValue')
+ ->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(): void {
+ $this->config->expects($this->exactly(2))
+ ->method('getAppValue')
+ ->willReturnMap([
+ ['theming', 'cachebuster', '0', '0'],
+ ['theming', 'logoMime', '', ''],
+ ]);
+ $this->urlGenerator->expects($this->once())
+ ->method('imagePath')
+ ->with('core', 'logo/logo.png')
+ ->willReturn('logo/logo.png');
+ $this->assertEquals('logo/logo.png?v=0', $this->imageManager->getImageUrl('logo'));
+ }
+
+ public function testGetImageUrlAbsolute(): void {
+ $this->checkImagick();
+ $this->config->expects($this->exactly(2))
+ ->method('getAppValue')
+ ->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(): void {
+ $this->checkImagick();
+ $this->config->expects($this->once())
+ ->method('getAppValue')->with('theming', 'logoMime', false)
+ ->willReturn('png');
+ $file = $this->createMock(ISimpleFile::class);
+ $this->mockGetImage('logo', $file);
+ $this->assertEquals($file, $this->imageManager->getImage('logo', false));
+ }
+
+
+ public function testGetImageUnset(): void {
+ $this->expectException(NotFoundException::class);
+
+ $this->config->expects($this->once())
+ ->method('getAppValue')->with('theming', 'logoMime', false)
+ ->willReturn(false);
+ $this->imageManager->getImage('logo');
+ }
+
+ public function testGetCacheFolder(): void {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('0');
+ $this->rootFolder->expects($this->once())
+ ->method('getFolder')
+ ->with('0')
+ ->willReturn($folder);
+ $this->assertEquals($folder, $this->imageManager->getCacheFolder());
+ }
+ public function testGetCacheFolderCreate(): void {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->config->expects($this->exactly(2))
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('0');
+ $this->rootFolder->expects($this->exactly(2))
+ ->method('getFolder')
+ ->with('0')
+ ->willReturnOnConsecutiveCalls(
+ $this->throwException(new NotFoundException()),
+ $folder,
+ );
+ $this->rootFolder->expects($this->once())
+ ->method('newFolder')
+ ->with('0')
+ ->willReturn($folder);
+ $this->rootFolder->expects($this->once())
+ ->method('getDirectoryListing')
+ ->willReturn([]);
+ $this->assertEquals($folder, $this->imageManager->getCacheFolder());
+ }
+
+ public function testGetCachedImage(): void {
+ $expected = $this->createMock(ISimpleFile::class);
+ $folder = $this->setupCacheFolder();
+ $folder->expects($this->once())
+ ->method('getFile')
+ ->with('filename')
+ ->willReturn($expected);
+ $this->assertEquals($expected, $this->imageManager->getCachedImage('filename'));
+ }
+
+
+ public function testGetCachedImageNotFound(): void {
+ $this->expectException(NotFoundException::class);
+
+ $folder = $this->setupCacheFolder();
+ $folder->expects($this->once())
+ ->method('getFile')
+ ->with('filename')
+ ->willThrowException(new NotFoundException());
+ $image = $this->imageManager->getCachedImage('filename');
+ }
+
+ public function testSetCachedImage(): void {
+ $folder = $this->setupCacheFolder();
+ $file = $this->createMock(ISimpleFile::class);
+ $folder->expects($this->once())
+ ->method('fileExists')
+ ->with('filename')
+ ->willReturn(true);
+ $folder->expects($this->once())
+ ->method('getFile')
+ ->with('filename')
+ ->willReturn($file);
+ $file->expects($this->once())
+ ->method('putContent')
+ ->with('filecontent');
+ $this->assertEquals($file, $this->imageManager->setCachedImage('filename', 'filecontent'));
+ }
+
+ public function testSetCachedImageCreate(): void {
+ $folder = $this->setupCacheFolder();
+ $file = $this->createMock(ISimpleFile::class);
+ $folder->expects($this->once())
+ ->method('fileExists')
+ ->with('filename')
+ ->willReturn(false);
+ $folder->expects($this->once())
+ ->method('newFile')
+ ->with('filename')
+ ->willReturn($file);
+ $file->expects($this->once())
+ ->method('putContent')
+ ->with('filecontent');
+ $this->assertEquals($file, $this->imageManager->setCachedImage('filename', 'filecontent'));
+ }
+
+ private function setupCacheFolder() {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('0');
+ $this->rootFolder->expects($this->once())
+ ->method('getFolder')
+ ->with('0')
+ ->willReturn($folder);
+ return $folder;
+ }
+
+ public function testCleanup(): void {
+ $folders = [
+ $this->createMock(ISimpleFolder::class),
+ $this->createMock(ISimpleFolder::class),
+ $this->createMock(ISimpleFolder::class)
+ ];
+ foreach ($folders as $index => $folder) {
+ $folder->expects($this->any())
+ ->method('getName')
+ ->willReturn("$index");
+ }
+ $folders[0]->expects($this->once())->method('delete');
+ $folders[1]->expects($this->once())->method('delete');
+ $folders[2]->expects($this->never())->method('delete');
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('2');
+ $this->rootFolder->expects($this->once())
+ ->method('getDirectoryListing')
+ ->willReturn($folders);
+ $this->rootFolder->expects($this->once())
+ ->method('getFolder')
+ ->with('2')
+ ->willReturn($folders[2]);
+ $this->imageManager->cleanup();
+ }
+
+
+ public static function dataUpdateImage(): array {
+ return [
+ ['background', __DIR__ . '/../../../tests/data/testimage.png', true, false],
+ ['background', __DIR__ . '/../../../tests/data/testimage.png', false, false],
+ ['background', __DIR__ . '/../../../tests/data/testimage.jpg', true, false],
+ ['background', __DIR__ . '/../../../tests/data/testimage.webp', true, false],
+ ['background', __DIR__ . '/../../../tests/data/testimage-large.jpg', true, true],
+ ['background', __DIR__ . '/../../../tests/data/testimage-wide.png', true, true],
+ ['logo', __DIR__ . '/../../../tests/data/testimagelarge.svg', true, false],
+ ];
+ }
+
+ #[\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);
+ $folder->expects($this->any())
+ ->method('getFile')
+ ->willReturn($oldFile);
+
+ if ($folderExists) {
+ $this->rootFolder
+ ->expects($this->any())
+ ->method('getFolder')
+ ->with('images')
+ ->willReturn($folder);
+ } else {
+ $this->rootFolder
+ ->expects($this->any())
+ ->method('getFolder')
+ ->with('images')
+ ->willThrowException(new NotFoundException());
+ $this->rootFolder
+ ->expects($this->any())
+ ->method('newFolder')
+ ->with('images')
+ ->willReturn($folder);
+ }
+
+ $folder->expects($this->once())
+ ->method('newFile')
+ ->with($key)
+ ->willReturn($file);
+
+ if ($shouldConvert) {
+ $this->tempManager->expects($this->once())
+ ->method('getTemporaryFile')
+ ->willReturn('/tmp/randomtempfile-theming');
+ }
+
+ $this->imageManager->updateImage($key, $tmpFile);
+ }
+
+ public function testUnsupportedImageType(): void {
+ $this->expectException(\Exception::class);
+ $this->expectExceptionMessage('Unsupported image type: text/plain');
+
+ $file = $this->createMock(ISimpleFile::class);
+ $folder = $this->createMock(ISimpleFolder::class);
+ $oldFile = $this->createMock(ISimpleFile::class);
+
+ $folder->expects($this->any())
+ ->method('getFile')
+ ->willReturn($oldFile);
+
+ $this->rootFolder
+ ->expects($this->any())
+ ->method('getFolder')
+ ->with('images')
+ ->willReturn($folder);
+
+ $folder->expects($this->once())
+ ->method('newFile')
+ ->with('favicon')
+ ->willReturn($file);
+
+ $this->imageManager->updateImage('favicon', __DIR__ . '/../../../tests/data/lorem.txt');
+ }
+}