545 lines
15 KiB
PHP
545 lines
15 KiB
PHP
<?php
|
|
/**
|
|
* Nextcloud - Gallery
|
|
*
|
|
*
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
* later. See the COPYING file.
|
|
*
|
|
* @author Olivier Paroz <galleryapps@oparoz.com>
|
|
*
|
|
* @copyright Olivier Paroz 2017
|
|
*/
|
|
|
|
namespace OCA\Gallery\Tests\Controller;
|
|
|
|
use OCP\IRequest;
|
|
use OCP\IURLGenerator;
|
|
use OCP\ILogger;
|
|
use OCP\Files\File;
|
|
|
|
use OCP\AppFramework\IAppContainer;
|
|
use OCP\AppFramework\Http;
|
|
use OCP\AppFramework\Http\JSONResponse;
|
|
|
|
use OCA\Gallery\AppInfo\Application;
|
|
use OCA\Gallery\Controller\PreviewController;
|
|
use OCA\Gallery\Http\ImageResponse;
|
|
use OCA\Gallery\Service\ConfigService;
|
|
use OCA\Gallery\Service\ThumbnailService;
|
|
use OCA\Gallery\Service\PreviewService;
|
|
use OCA\Gallery\Service\DownloadService;
|
|
use OCA\Gallery\Utility\EventSource;
|
|
use OCA\Gallery\Service\NotFoundServiceException;
|
|
use OCA\Gallery\Service\InternalServerErrorServiceException;
|
|
|
|
/**
|
|
* Class PreviewControllerTest
|
|
*
|
|
* @package OCA\Gallery\Controller
|
|
*/
|
|
class PreviewControllerTest extends \OCA\Gallery\Tests\GalleryUnitTest {
|
|
|
|
/** @var IAppContainer */
|
|
protected $container;
|
|
/** @var string */
|
|
protected $appName = 'gallery';
|
|
/** @var IRequest */
|
|
protected $request;
|
|
/** @var PreviewController */
|
|
protected $controller;
|
|
/** @var IURLGenerator */
|
|
protected $urlGenerator;
|
|
/** @var ConfigService */
|
|
protected $configService;
|
|
/** @var ThumbnailService */
|
|
protected $thumbnailService;
|
|
/** @var PreviewService */
|
|
protected $previewService;
|
|
/** @var DownloadService */
|
|
protected $downloadService;
|
|
/** @var EventSource */
|
|
protected $eventSource;
|
|
/** @var ILogger */
|
|
protected $logger;
|
|
|
|
/**
|
|
* Test set up
|
|
*/
|
|
public function setUp() {
|
|
parent::setUp();
|
|
|
|
$app = new Application;
|
|
$this->container = $app->getContainer();
|
|
$this->container['UserFolder'] = $this->getMockBuilder('OCP\Files\Folder')
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$this->request = $this->getMockBuilder('\OCP\IRequest')
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$this->urlGenerator = $this->getMockBuilder('\OCP\IURLGenerator')
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$this->configService = $this->getMockBuilder('\OCA\Gallery\Service\ConfigService')
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$this->thumbnailService = $this->getMockBuilder('\OCA\Gallery\Service\ThumbnailService')
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$this->previewService = $this->getMockBuilder('\OCA\Gallery\Service\PreviewService')
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$this->downloadService = $this->getMockBuilder('\OCA\Gallery\Service\DownloadService')
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$this->eventSource = $this->getMockBuilder('\OCA\Gallery\Utility\EventSource')
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$this->logger = $this->getMockBuilder('\OCP\ILogger')
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$this->controller = new PreviewController(
|
|
$this->appName,
|
|
$this->request,
|
|
$this->urlGenerator,
|
|
$this->configService,
|
|
$this->thumbnailService,
|
|
$this->previewService,
|
|
$this->downloadService,
|
|
$this->eventSource,
|
|
$this->logger
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @expectedException \Exception
|
|
*/
|
|
public function testGetThumbnailsWillDie() {
|
|
$square = true;
|
|
$scale = 2.5;
|
|
$thumbnailId = 1234;
|
|
|
|
$file = $this->mockJpgFile($thumbnailId);
|
|
$this->mockGetFile($this->previewService, $thumbnailId, $file);
|
|
|
|
$this->controller->getThumbnails($thumbnailId, $square, $scale);
|
|
}
|
|
|
|
public function testEventSourceSend() {
|
|
$thumbnailId = 1234;
|
|
$file = $this->mockFile($thumbnailId);
|
|
$preview = $this->mockBase64PreviewData($file);
|
|
|
|
$event = 'preview';
|
|
$message = 'event: ' . $event . PHP_EOL .
|
|
'data: ' . json_encode($preview) . PHP_EOL .
|
|
PHP_EOL;
|
|
$this->mockEventSourceSend($event, $preview, $message);
|
|
|
|
$this->assertSame($message, $this->eventSource->send('preview', $preview));
|
|
}
|
|
|
|
/**
|
|
* @todo Really base64 encode the preview instead of just passing around the binary content
|
|
*/
|
|
public function testGetThumbnail() {
|
|
$square = true;
|
|
$scale = 2.5;
|
|
$width = 400;
|
|
$height = 400;
|
|
$aspect = !$square;
|
|
$animatedPreview = false;
|
|
$base64Encode = true;
|
|
$thumbnailId = 1234;
|
|
$thumbnailSpecs = [
|
|
$width,
|
|
$height,
|
|
$aspect,
|
|
$animatedPreview,
|
|
$base64Encode
|
|
];
|
|
$this->mockGetThumbnailSpecs($square, $scale, $thumbnailSpecs);
|
|
/** @type File $file */
|
|
$file = $this->mockJpgFile($thumbnailId);
|
|
$mockedPreview =
|
|
$this->mockGetData(
|
|
$thumbnailId, $file, $width, $height, $aspect, $animatedPreview, $base64Encode
|
|
);
|
|
|
|
list($preview, $status) = self::invokePrivate(
|
|
$this->controller, 'getThumbnail', [$thumbnailId, $square, $scale]
|
|
);
|
|
|
|
$this->assertEquals(Http::STATUS_OK, $status);
|
|
$this->assertEquals($mockedPreview, $preview);
|
|
}
|
|
|
|
public function testGetBrokenThumbnail() {
|
|
$square = true;
|
|
$scale = 2.5;
|
|
$width = 400;
|
|
$height = 400;
|
|
$aspect = !$square;
|
|
$animatedPreview = false;
|
|
$base64Encode = true;
|
|
$thumbnailId = 1234;
|
|
$thumbnailSpecs = [
|
|
$width,
|
|
$height,
|
|
$aspect,
|
|
$animatedPreview,
|
|
$base64Encode
|
|
];
|
|
$this->mockGetThumbnailSpecs($square, $scale, $thumbnailSpecs);
|
|
|
|
/** @type File $file */
|
|
$file = $this->mockJpgFile($thumbnailId);
|
|
$this->mockGetDataWithBrokenPreview(
|
|
$thumbnailId, $file, $width, $height, $aspect, $animatedPreview, $base64Encode
|
|
);
|
|
|
|
list($preview, $status) = self::invokePrivate(
|
|
$this->controller, 'getThumbnail', [$thumbnailId, $square, $scale]
|
|
);
|
|
|
|
$this->assertEquals(Http::STATUS_INTERNAL_SERVER_ERROR, $status);
|
|
$this->assertNull($preview['preview']);
|
|
$this->assertEquals($file->getMimeType(), $preview['mimetype']);
|
|
}
|
|
|
|
public function testGetThumbnailWithBrokenSetup() {
|
|
$square = true;
|
|
$scale = 2.5;
|
|
$thumbnailId = 1234;
|
|
$animatedPreview = false;
|
|
|
|
/** @type File $file */
|
|
$file = $this->mockGetDataWithBrokenSetup($thumbnailId, $animatedPreview);
|
|
$this->mockIsPreviewRequiredThrowsException($file, $animatedPreview);
|
|
|
|
list($preview, $status) = self::invokePrivate(
|
|
$this->controller, 'getThumbnail', [$thumbnailId, $square, $scale]
|
|
);
|
|
|
|
$this->assertEquals(Http::STATUS_INTERNAL_SERVER_ERROR, $status);
|
|
$this->assertNull($preview['preview']);
|
|
$this->assertEquals($file->getMimeType(), $preview['mimetype']);
|
|
}
|
|
|
|
public function testGetPreview() {
|
|
$fileId = 1234;
|
|
$width = 1024;
|
|
$height = 768;
|
|
|
|
/** @type File $file */
|
|
$file = $this->mockJpgFile($fileId);
|
|
$preview = $this->mockGetData($fileId, $file, $width, $height);
|
|
$preview['name'] = $file->getName();
|
|
|
|
/** @type ImageResponse $response */
|
|
$response = $this->controller->getPreview($fileId, $width, $height);
|
|
|
|
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
|
|
|
|
// Media type of a JPG preview is always PNG
|
|
$this->assertEquals(
|
|
'image/png; charset=utf-8', $response->getHeaders()['Content-type']
|
|
);
|
|
}
|
|
|
|
public function testGetPreviewWithWrongId() {
|
|
$fileId = 99999;
|
|
$width = 1024;
|
|
$height = 768;
|
|
|
|
$exception = new NotFoundServiceException('Not found');
|
|
$this->mockGetFileWithBadFile($this->previewService, $fileId, $exception);
|
|
|
|
$errorResponse = $this->jsonErrorMessage(Http::STATUS_NOT_FOUND);
|
|
|
|
$response = $this->controller->getPreview($fileId, $width, $height);
|
|
|
|
$this->assertEquals($errorResponse->getStatus(), $response->getStatus());
|
|
$this->assertEquals($errorResponse->getData()['success'], $response->getData()['success']);
|
|
}
|
|
|
|
public function testGetPreviewWithBrokenGif() {
|
|
$fileId = 1234;
|
|
$width = 1024;
|
|
$height = 768;
|
|
|
|
/** @type File $file */
|
|
$file = $this->mockAnimatedGifFile($fileId);
|
|
$this->mockGetDataWithEmptyPreview($fileId, $file, $width, $height);
|
|
|
|
$errorResponse = $this->jsonErrorMessage(Http::STATUS_INTERNAL_SERVER_ERROR);
|
|
|
|
$response = $this->controller->getPreview($fileId, $width, $height);
|
|
|
|
$this->assertEquals($errorResponse->getStatus(), $response->getStatus());
|
|
$this->assertEquals($errorResponse->getData()['success'], $response->getData()['success']);
|
|
}
|
|
|
|
/**
|
|
* Mocks Preview->getData
|
|
*
|
|
* @param int $fileId the ID of the file of which we need a large preview of
|
|
* @param File $file
|
|
* @param int $width
|
|
* @param int $height
|
|
* @param bool $keepAspect
|
|
* @param bool $animatedPreview
|
|
* @param bool $base64Encode
|
|
* @param bool $previewRequired
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function mockGetData(
|
|
$fileId, $file, $width, $height, $keepAspect = true, $animatedPreview = true,
|
|
$base64Encode = false, $previewRequired = true
|
|
) {
|
|
$this->mockGetFile($this->previewService, $fileId, $file);
|
|
|
|
$this->mockIsPreviewRequired($file, $animatedPreview, $previewRequired);
|
|
$previewData = $this->mockPreviewData($file, $previewRequired);
|
|
|
|
if ($previewRequired) {
|
|
$this->mockCreatePreview(
|
|
$file, $width, $height, $keepAspect, $base64Encode, $previewData
|
|
);
|
|
} else {
|
|
$this->mockDownloadFile($file, $base64Encode, $previewData);
|
|
}
|
|
|
|
return $previewData;
|
|
}
|
|
|
|
/**
|
|
* Mocks Preview->getData
|
|
*
|
|
* @param int $fileId the ID of the file of which we need a large preview of
|
|
* @param File $file
|
|
* @param int $width
|
|
* @param int $height
|
|
* @param bool $keepAspect
|
|
* @param bool $animatedPreview
|
|
* @param bool $base64Encode
|
|
*
|
|
* @return array
|
|
*/
|
|
private function mockGetDataWithBrokenPreview(
|
|
$fileId, $file, $width, $height, $keepAspect = true, $animatedPreview = true,
|
|
$base64Encode = false
|
|
) {
|
|
$this->mockGetFile($this->previewService, $fileId, $file);
|
|
|
|
$this->mockIsPreviewRequired($file, $animatedPreview, true);
|
|
|
|
$this->mockCreatePreviewThrowsException($file, $width, $height, $keepAspect, $base64Encode);
|
|
}
|
|
|
|
/**
|
|
* Mocks Preview->getData
|
|
*
|
|
* @param int $fileId the ID of the file of which we need a large preview of
|
|
* @param File $file
|
|
* @param int $width
|
|
* @param int $height
|
|
* @param bool $keepAspect
|
|
* @param bool $animatedPreview
|
|
* @param bool $base64Encode
|
|
*
|
|
* @return array
|
|
*/
|
|
private function mockGetDataWithEmptyPreview(
|
|
$fileId, $file, $width, $height, $keepAspect = true, $animatedPreview = true,
|
|
$base64Encode = false
|
|
) {
|
|
$this->mockGetFile($this->previewService, $fileId, $file);
|
|
|
|
$this->mockIsPreviewRequired($file, $animatedPreview, true);
|
|
|
|
$this->mockCreatePreview($file, $width, $height, $keepAspect, $base64Encode, null);
|
|
}
|
|
|
|
/**
|
|
* @param int $fileId
|
|
* @param bool $animatedPreview
|
|
*
|
|
* @return object|\PHPUnit_Framework_MockObject_MockObject
|
|
*/
|
|
private function mockGetDataWithBrokenSetup($fileId, $animatedPreview) {
|
|
$file = $this->mockJpgFile($fileId);
|
|
$this->mockGetFile($this->previewService, $fileId, $file);
|
|
|
|
$this->mockIsPreviewRequiredThrowsException($file, $animatedPreview);
|
|
|
|
return $file;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param object|\PHPUnit_Framework_MockObject_MockObject $file
|
|
* @param bool $animatedPreview
|
|
* @param bool $response
|
|
*/
|
|
private function mockIsPreviewRequired($file, $animatedPreview, $response) {
|
|
$this->previewService->expects($this->once())
|
|
->method('isPreviewRequired')
|
|
->with(
|
|
$this->equalTo($file),
|
|
$this->equalTo($animatedPreview)
|
|
)
|
|
->willReturn($response);
|
|
}
|
|
|
|
/**
|
|
* @param object|\PHPUnit_Framework_MockObject_MockObject $file
|
|
* @param bool $animatedPreview
|
|
*/
|
|
private function mockIsPreviewRequiredThrowsException($file, $animatedPreview) {
|
|
$exception = new InternalServerErrorServiceException('Broken');
|
|
$this->previewService->expects($this->once())
|
|
->method('isPreviewRequired')
|
|
->with(
|
|
$this->equalTo($file),
|
|
$this->equalTo($animatedPreview)
|
|
)
|
|
->willThrowException($exception);
|
|
}
|
|
|
|
/**
|
|
* @param File $file
|
|
* @param bool $previewRequired
|
|
*
|
|
* @return array <string,mixed>
|
|
*/
|
|
private function mockPreviewData($file, $previewRequired) {
|
|
$mimeType = $previewRequired ? 'image/png' : $file->getMimeType();
|
|
|
|
$preview = [
|
|
'preview' => $file->getContent(), // Not a real preview, but it's not important
|
|
'mimetype' => $mimeType,
|
|
];
|
|
|
|
return $preview;
|
|
}
|
|
|
|
/**
|
|
* @param object|\PHPUnit_Framework_MockObject_MockObject $file
|
|
*
|
|
* @return array<string,mixed>
|
|
*/
|
|
private function mockBase64PreviewData($file) {
|
|
$preview = [
|
|
'preview' => base64_encode($file->getContent()),
|
|
// Not a real preview, but it's not important
|
|
'mimetype' => 'image/png', //Most previews are PNGs
|
|
];
|
|
|
|
return $preview;
|
|
}
|
|
|
|
/**
|
|
* @param File $file
|
|
* @param int $width
|
|
* @param int $height
|
|
* @param bool $keepAspect
|
|
* @param bool $base64Encode
|
|
* @param array $preview
|
|
*/
|
|
private function mockCreatePreview($file, $width, $height, $keepAspect, $base64Encode, $preview
|
|
) {
|
|
$this->previewService->expects($this->once())
|
|
->method('createPreview')
|
|
->with(
|
|
$this->equalTo($file),
|
|
$this->equalTo($width),
|
|
$this->equalTo($height),
|
|
$this->equalTo($keepAspect),
|
|
$this->equalTo($base64Encode)
|
|
)
|
|
->willReturn($preview);
|
|
}
|
|
|
|
/**
|
|
* @param File $file
|
|
* @param int $width
|
|
* @param int $height
|
|
* @param bool $keepAspect
|
|
* @param bool $base64Encode
|
|
*/
|
|
private function mockCreatePreviewThrowsException(
|
|
$file, $width, $height, $keepAspect, $base64Encode
|
|
) {
|
|
$exception = new InternalServerErrorServiceException('Encryption ate your file');
|
|
$this->previewService->expects($this->once())
|
|
->method('createPreview')
|
|
->with(
|
|
$this->equalTo($file),
|
|
$this->equalTo($width),
|
|
$this->equalTo($height),
|
|
$this->equalTo($keepAspect),
|
|
$this->equalTo($base64Encode)
|
|
)
|
|
->willthrowException($exception);
|
|
}
|
|
|
|
/**
|
|
* @param $file
|
|
* @param $base64Encode
|
|
* @param $preview
|
|
*/
|
|
private function mockDownloadFile($file, $base64Encode, $preview) {
|
|
$this->downloadService->expects($this->once())
|
|
->method('downloadFile')
|
|
->with(
|
|
$this->equalTo($file),
|
|
$this->equalTo($base64Encode)
|
|
)
|
|
->willReturn($preview);
|
|
}
|
|
|
|
/**
|
|
* @param $event
|
|
* @param $data
|
|
* @param $message
|
|
*/
|
|
private function mockEventSourceSend($event, $data, $message) {
|
|
$this->eventSource->expects($this->once())
|
|
->method('send')
|
|
->with(
|
|
$event,
|
|
$data
|
|
)
|
|
->willReturn($message);
|
|
|
|
}
|
|
|
|
/**
|
|
* @param $square
|
|
* @param $scale
|
|
* @param $array
|
|
*/
|
|
private function mockGetThumbnailSpecs($square, $scale, $array) {
|
|
$this->thumbnailService->expects($this->once())
|
|
->method('getThumbnailSpecs')
|
|
->with(
|
|
$square,
|
|
$scale
|
|
)
|
|
->willReturn($array);
|
|
|
|
}
|
|
|
|
private function jsonErrorMessage($code) {
|
|
return new JSONResponse(
|
|
[
|
|
'message' => "I'm truly sorry, but we were unable to generate a preview for this file",
|
|
'success' => false
|
|
], $code
|
|
);
|
|
}
|
|
|
|
}
|