123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- <?php
- /**
- * @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/>.
- *
- */
- namespace OCA\Theming\Tests;
- use OCA\Theming\ImageManager;
- 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 {
- /** @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 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);
- $this->imageManager = new ImageManager(
- $this->config,
- $this->appData,
- $this->urlGenerator,
- $this->cacheFactory,
- $this->logger,
- $this->tempManager
- );
- $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')
- ->withConsecutive(
- ['logo'],
- ['logo.png'],
- )->willReturnOnConsecutiveCalls(
- true,
- 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() {
- $this->checkImagick();
- $file = $this->createMock(ISimpleFile::class);
- $this->config->expects($this->exactly(2))
- ->method('getAppValue')
- ->withConsecutive(
- ['theming', 'cachebuster', '0'],
- ['theming', 'logoMime', '']
- )
- ->willReturn(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() {
- $this->config->expects($this->exactly(2))
- ->method('getAppValue')
- ->withConsecutive(
- ['theming', 'cachebuster', '0'],
- ['theming', 'logoMime', '']
- )
- ->willReturnOnConsecutiveCalls(0, '');
- $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() {
- $this->checkImagick();
- $file = $this->createMock(ISimpleFile::class);
- $this->config->expects($this->exactly(2))
- ->method('getAppValue')
- ->withConsecutive(
- ['theming', 'cachebuster', '0'],
- ['theming', 'logoMime', '']
- )
- ->willReturnOnConsecutiveCalls(0, 0);
- $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() {
- $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() {
- $this->expectException(\OCP\Files\NotFoundException::class);
- $this->config->expects($this->once())
- ->method('getAppValue')->with('theming', 'logoMime', false)
- ->willReturn(false);
- $this->imageManager->getImage('logo');
- }
- public function testGetCacheFolder() {
- $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() {
- $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() {
- $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() {
- $this->expectException(\OCP\Files\NotFoundException::class);
- $folder = $this->setupCacheFolder();
- $folder->expects($this->once())
- ->method('getFile')
- ->with('filename')
- ->will($this->throwException(new \OCP\Files\NotFoundException()));
- $image = $this->imageManager->getCachedImage('filename');
- }
- public function testSetCachedImage() {
- $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() {
- $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() {
- $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 function dataUpdateImage() {
- 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],
- ];
- }
- /**
- * @dataProvider dataUpdateImage
- */
- public function testUpdateImage($key, $tmpFile, $folderExists, $shouldConvert) {
- $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');
- }
- }
|