diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index a28c61b..b33d114 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -35,8 +35,8 @@ jobs: ${{ runner.os }}-php-${{ matrix.php-version }}- - name: Install Dependencies run: composer install --no-scripts --no-ansi --no-interaction --no-progress - - name: Run Unit tests - run: vendor/bin/phpunit -v --whitelist ./src tests + - name: Run atoum unit tests + run: vendor/bin/atoum -d tests - name: Run PHP Code Sniffer run: vendor/bin/phpcs -p ./src - name: Run PHPStan diff --git a/.gitignore b/.gitignore index 17b7d11..8a7ba18 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# +# Roadiz +# +/pimple.json # Ignore Google webmaster tool verification /google*.html diff --git a/LICENSE.md b/LICENSE.md index 8e18fa6..d4d8a00 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright © 2024 Ambroise Maupate +Copyright © 2023 Ambroise Maupate Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8858814 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +test: + vendor/bin/atoum -d tests + vendor/bin/phpstan analyse -c phpstan.neon + vendor/bin/phpcs --report=full --report-file=./report.txt -p ./src + +dev-test: + vendor/bin/atoum -d tests -l + +phpcs: + vendor/bin/phpcs --report=full --report-file=./report.txt -p ./src + +phpcbf: + vendor/bin/phpcbf --report=full --report-file=./report.txt -p ./src diff --git a/composer.json b/composer.json index 1b6941d..3e27fae 100644 --- a/composer.json +++ b/composer.json @@ -25,27 +25,26 @@ "ext-zip": "*", "ext-simplexml": "*", "ext-fileinfo": "*", - "doctrine/orm": "~2.19.0", + "doctrine/orm": "~2.17.0", "enshrined/svg-sanitize": "^0.15", "guzzlehttp/guzzle": "^7.2.0", "guzzlehttp/psr7": "^2.0", "intervention/image": "^2.5", "league/flysystem": "^3.0", "monolog/monolog": "^1.24.0 || ^2.1.1", - "symfony/asset": "6.4.*", - "symfony/console": "6.4.*", - "symfony/event-dispatcher": "6.4.*", - "symfony/filesystem": "6.4.*", - "symfony/finder": "6.4.*", - "symfony/http-foundation": "6.4.*", - "symfony/options-resolver": "6.4.*", - "symfony/serializer": "6.4.*", + "symfony/asset": "5.4.*", + "symfony/console": "5.4.*", + "symfony/event-dispatcher": "5.4.*", + "symfony/filesystem": "5.4.*", + "symfony/finder": "5.4.*", + "symfony/http-foundation": "5.4.*", + "symfony/options-resolver": "5.4.*", + "symfony/serializer": "5.4.*", "twig/twig": "^3.1" }, "require-dev": { "php-coveralls/php-coveralls": "^2.4", - "phpunit/phpunit": "^9.5", - "api-platform/metadata": "^3.2.12", + "atoum/atoum": "^4.0.0", "squizlabs/php_codesniffer": "^3.5", "phpstan/phpstan": "^1.5.3", "phpstan/phpstan-doctrine": "^1.3" @@ -55,11 +54,6 @@ "RZ\\Roadiz\\Documents\\": "src/" } }, - "autoload-dev": { - "psr-4": { - "RZ\\Roadiz\\Documents\\Tests\\": "tests/" - } - }, "config": { "allow-plugins": { "composer/package-versions-deprecated": true, @@ -68,8 +62,8 @@ }, "extra": { "branch-alias": { - "dev-master": "2.3.x-dev", - "dev-develop": "2.4.x-dev" + "dev-master": "2.2.x-dev", + "dev-develop": "2.3.x-dev" } } } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..125a0d4 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +version: "3" +services: + test80: + image: roadiz/php80-runner + working_dir: /build + command: > + bash -c " + composer install -o && + make test" + volumes: + - ./:/build diff --git a/phpstan.neon b/phpstan.neon index 943ac93..f4a94cf 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 7 + level: max paths: - src excludePaths: @@ -7,8 +7,6 @@ parameters: - */bower_components/* - */static/* ignoreErrors: - - identifier: missingType.iterableValue - - identifier: missingType.generics - '#Call to an undefined method Doctrine\\Persistence\\ObjectRepository#' - '#Call to an undefined method Doctrine\\Persistence\\ObjectManager#' - '#Call to an undefined method Doctrine\\ORM\\EntityRepository#' @@ -22,6 +20,8 @@ parameters: - '#but returns Doctrine\\Common\\Collections\\ReadableCollection]+>#' - '#does not accept Doctrine\\Common\\Collections\\ReadableCollection]+>#' reportUnmatchedIgnoredErrors: false + checkMissingIterableValueType: false + checkGenericClassInNonGenericObjectType: false includes: - vendor/phpstan/phpstan-doctrine/extension.neon diff --git a/src/Console/DocumentClearFolderCommand.php b/src/Console/DocumentClearFolderCommand.php index e52f187..a16a63b 100644 --- a/src/Console/DocumentClearFolderCommand.php +++ b/src/Console/DocumentClearFolderCommand.php @@ -36,9 +36,9 @@ protected function getDocumentQueryBuilder(FolderInterface $folder): QueryBuilde protected function execute(InputInterface $input, OutputInterface $output): int { $this->io = new SymfonyStyle($input, $output); - $folderId = $input->getArgument('folderId'); - if (!\is_numeric($folderId) || $folderId <= 0) { + $folderId = intval($input->getArgument('folderId')); + if ($folderId <= 0) { throw new \InvalidArgumentException('Folder ID must be a valid ID'); } $em = $this->getManager(); diff --git a/src/DocumentArchiver.php b/src/DocumentArchiver.php index e29f746..2ab4782 100644 --- a/src/DocumentArchiver.php +++ b/src/DocumentArchiver.php @@ -16,8 +16,11 @@ */ final class DocumentArchiver { - public function __construct(private readonly FilesystemOperator $documentsStorage) + private FilesystemOperator $documentsStorage; + + public function __construct(FilesystemOperator $documentsStorage) { + $this->documentsStorage = $documentsStorage; } /** diff --git a/src/DownscaleImageManager.php b/src/DownscaleImageManager.php index f141b3a..aea311c 100644 --- a/src/DownscaleImageManager.php +++ b/src/DownscaleImageManager.php @@ -16,14 +16,27 @@ final class DownscaleImageManager { + protected EntityManagerInterface $em; + protected ?LoggerInterface $logger; + protected int $maxPixelSize = 0; + protected string $rawImageSuffix = ".raw"; + protected ImageManager $imageManager; + private FilesystemOperator $documentsStorage; + public function __construct( - private readonly EntityManagerInterface $em, - private readonly FilesystemOperator $documentsStorage, - private readonly ImageManager $imageManager, - private readonly ?LoggerInterface $logger = null, - private readonly int $maxPixelSize = 0, - private readonly string $rawImageSuffix = ".raw" + EntityManagerInterface $em, + FilesystemOperator $documentsStorage, + ImageManager $imageManager, + ?LoggerInterface $logger = null, + int $maxPixelSize = 0, + string $rawImageSuffix = ".raw" ) { + $this->maxPixelSize = $maxPixelSize; + $this->rawImageSuffix = $rawImageSuffix; + $this->em = $em; + $this->logger = $logger; + $this->imageManager = $imageManager; + $this->documentsStorage = $documentsStorage; } /** diff --git a/src/Exceptions/DocumentWithoutFileException.php b/src/Exceptions/DocumentWithoutFileException.php index b8cd068..9d93c0b 100644 --- a/src/Exceptions/DocumentWithoutFileException.php +++ b/src/Exceptions/DocumentWithoutFileException.php @@ -8,11 +8,17 @@ final class DocumentWithoutFileException extends \RuntimeException { - public function __construct(private readonly DocumentInterface $document) + private DocumentInterface $document; + + public function __construct(DocumentInterface $document) { + $this->document = $document; parent::__construct(sprintf('Document (%s) does not have a file on system.', (string) $document)); } + /** + * @return DocumentInterface + */ public function getDocument(): DocumentInterface { return $this->document; diff --git a/src/Models/DocumentTrait.php b/src/Models/DocumentTrait.php index 9ed46e3..f2b568b 100644 --- a/src/Models/DocumentTrait.php +++ b/src/Models/DocumentTrait.php @@ -4,7 +4,6 @@ namespace RZ\Roadiz\Documents\Models; -use ApiPlatform\Metadata\ApiProperty; use Symfony\Component\Serializer\Annotation as SymfonySerializer; trait DocumentTrait @@ -13,7 +12,6 @@ trait DocumentTrait * Associate mime type to simple types. * * - code - * - text * - image * - word * - video @@ -23,116 +21,86 @@ trait DocumentTrait * - excel * - powerpoint * - font - * - 3d * * @var array * @internal */ #[SymfonySerializer\Ignore()] protected static array $mimeToIcon = [ - // Code + 'text/html' => 'code', 'application/javascript' => 'code', - 'application/json' => 'code', - 'application/ld+json' => 'code', 'text/css' => 'code', - 'text/html' => 'code', + 'text/rtf' => 'word', 'text/xml' => 'code', - // Text - 'text/plain' => 'text', - // Images types - 'image/avif' => 'image', - 'image/bmp' => 'image', + 'image/png' => 'image', + 'image/jpeg' => 'image', 'image/gif' => 'image', + 'image/tiff' => 'image', + 'image/webp' => 'image', + 'image/avif' => 'image', 'image/heic' => 'image', 'image/heif' => 'image', - 'image/jpeg' => 'image', - 'image/png' => 'image', - 'image/svg' => 'image', - 'image/svg+xml' => 'image', - 'image/tiff' => 'image', 'image/vnd.microsoft.icon' => 'image', - 'image/webp' => 'image', 'image/x-icon' => 'image', - // PDF 'application/pdf' => 'pdf', // Audio types + 'audio/mpeg' => 'audio', + 'audio/x-m4a' => 'audio', + 'audio/x-wav' => 'audio', + 'audio/wav' => 'audio', 'audio/aac' => 'audio', - 'audio/ac3' => 'audio', - 'audio/eac3' => 'audio', - 'audio/flac' => 'audio', - 'audio/matroska' => 'audio', 'audio/mp4' => 'audio', - 'audio/mpeg' => 'audio', + 'audio/webm' => 'audio', 'audio/ogg' => 'audio', 'audio/vorbis' => 'audio', - 'audio/wav' => 'audio', - 'audio/webm' => 'audio', - 'audio/x-m4a' => 'audio', + 'audio/ac3' => 'audio', 'audio/x-matroska' => 'audio', - 'audio/x-wav' => 'audio', // Video types 'application/ogg' => 'video', - 'video/3gpp' => 'video', - 'video/3gpp-tt' => 'video', - 'video/3gpp2' => 'video', - 'video/VP8' => 'video', - 'video/matroska' => 'video', - 'video/matroska-3d' => 'video', - 'video/mp4' => 'video', - 'video/mpeg' => 'video', 'video/ogg' => 'video', - 'video/quicktime' => 'video', 'video/webm' => 'video', - 'video/x-flv' => 'video', + 'video/mpeg' => 'video', + 'video/mp4' => 'video', 'video/x-m4v' => 'video', + 'video/quicktime' => 'video', + 'video/x-flv' => 'video', + 'video/3gpp' => 'video', + 'video/3gpp2' => 'video', + 'video/3gpp-tt' => 'video', + 'video/VP8' => 'video', 'video/x-matroska' => 'video', // Epub type 'application/epub+zip' => 'epub', // Archives types 'application/gzip' => 'archive', + 'application/zip' => 'archive', + 'application/x-bzip2' => 'archive', + 'application/x-tar' => 'archive', 'application/x-7z-compressed' => 'archive', 'application/x-apple-diskimage' => 'archive', - 'application/x-bzip2' => 'archive', 'application/x-rar-compressed' => 'archive', - 'application/x-tar' => 'archive', - 'application/zip' => 'archive', // Office types 'application/msword' => 'word', 'application/vnd.ms-excel' => 'excel', 'application/vnd.ms-office' => 'excel', 'application/vnd.ms-powerpoint' => 'powerpoint', - 'application/vnd.oasis.opendocument.presentation' => 'powerpoint', - 'application/vnd.oasis.opendocument.spreadsheet' => 'excel', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'word', 'application/vnd.oasis.opendocument.text ' => 'word', - 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'powerpoint', - 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'powerpoint', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'excel', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'word', - 'text/rtf' => 'word', + 'application/vnd.oasis.opendocument.spreadsheet' => 'excel', + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'powerpoint', + 'application/vnd.oasis.opendocument.presentation' => 'powerpoint', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'powerpoint', // Fonts types + 'image/svg+xml' => 'font', + 'application/x-font-ttf' => 'font', + 'application/x-font-truetype' => 'font', + 'application/x-font-opentype' => 'font', 'application/font-woff' => 'font', - 'application/font-woff2' => 'font', 'application/vnd.ms-fontobject' => 'font', - 'application/x-font-opentype' => 'font', - 'application/x-font-truetype' => 'font', - 'application/x-font-ttf' => 'font', 'font/opentype' => 'font', 'font/ttf' => 'font', - 'font/woff' => 'font', - 'font/woff2' => 'font', - // 3d - 'model/gltf+binary' => '3d', - 'model/gltf+json' => '3d', - 'model/gltf-binary' => '3d', - 'model/mtl' => '3d', - 'model/obj' => '3d', - 'model/stl' => '3d', - 'model/u3d' => '3d', - 'model/vnd.gltf+json' => '3d', - 'model/vnd.gltf.binary' => '3d', - 'model/vnd.usda' => '3d', - 'model/vnd.usdz+zip' => '3d', ]; /** @@ -309,14 +277,14 @@ protected function initDocumentTrait(): void #[ SymfonySerializer\Groups(["document", "document_display", "nodes_sources", "tag", "attribute"]), SymfonySerializer\SerializedName("processable"), - ApiProperty( - description: 'Document can be processed as an image for resampling and other image operations.', - writable: false, - ) ] public function isProcessable(): bool { - return $this->isImage() && in_array($this->getMimeType(), static::$processableMimeTypes, true); + if ($this->isImage() && in_array($this->getMimeType(), static::$processableMimeTypes)) { + return true; + } + + return false; } #[ diff --git a/src/Packages.php b/src/Packages.php new file mode 100644 index 0000000..910d552 --- /dev/null +++ b/src/Packages.php @@ -0,0 +1,366 @@ +requestStackContext = new RequestStackContext($requestStack); + $this->requestStack = $requestStack; + $this->fileAware = $fileAware; + $this->staticDomain = $staticDomain; + $this->versionStrategy = $versionStrategy; + $this->ready = false; + } + + /** + * Defer creating package collection not to create error + * when warming up cache on dependency injection. + * These packages need a valid Request object. + */ + protected function initializePackages(): void + { + $this->setDefaultPackage($this->getDefaultPackage()); + $packages = [ + static::DOCUMENTS => $this->getDocumentPackage(), + static::PUBLIC_PATH => $this->getPublicPathPackage(), + static::PRIVATE_PATH => $this->getPrivatePathPackage(), + static::FONTS_PATH => $this->getFontsPathPackage(), + ]; + if (null !== $this->getRequest()) { + $packages = array_merge($packages, [ + static::ABSOLUTE => $this->getAbsoluteDefaultPackage(), + static::ABSOLUTE_DOCUMENTS => $this->getAbsoluteDocumentPackage(), + ]); + } + foreach ($packages as $name => $package) { + $this->addPackage((string) $name, $package); + } + $this->ready = true; + } + + /** + * @inheritDoc + */ + public function getPackage($name = null): PackageInterface + { + if (false === $this->ready) { + $this->initializePackages(); + } + + return parent::getPackage($name); + } + + /** + * @return bool + */ + public function useStaticDomain(): bool + { + return $this->staticDomain != ""; + } + + /** + * @return string + */ + protected function getStaticDomainAndPort(): string + { + /* + * Add non-default port to static domain. + */ + $staticDomainAndPort = $this->staticDomain; + $request = $this->getRequest(); + if ( + null !== $request + && (($this->requestStackContext->isSecure() && $request->getPort() != 443) + || (!$this->requestStackContext->isSecure() && $request->getPort() != 80)) + ) { + $staticDomainAndPort .= ':' . $request->getPort(); + } + + /* + * If no protocol, use https as default + */ + if ( + !preg_match("~^//~i", $staticDomainAndPort) + && !preg_match("~^(?:f|ht)tps?://~i", $staticDomainAndPort) + ) { + $staticDomainAndPort = "https://" . $staticDomainAndPort; + } + + return $staticDomainAndPort; + } + + /** + * @return PathPackage|UrlPackage + */ + protected function getDefaultPackage(): PathPackage|UrlPackage + { + if ($this->useStaticDomain()) { + return new UrlPackage( + $this->getStaticDomainAndPort(), + $this->versionStrategy + ); + } + + return new PathPackage( + '/', + $this->versionStrategy, + $this->requestStackContext + ); + } + + /** + * @return PathPackage|UrlPackage + */ + protected function getAbsoluteDefaultPackage(): PathPackage|UrlPackage + { + if ($this->useStaticDomain()) { + return $this->getDefaultPackage(); + } + $scheme = ''; + if (null !== $this->getRequest()) { + $scheme = $this->getRequest()->getSchemeAndHttpHost(); + } + return new UrlPackage( + $scheme . $this->requestStackContext->getBasePath(), + $this->versionStrategy + ); + } + + /** + * @return PathPackage|UrlPackage + */ + protected function getDocumentPackage(): PathPackage|UrlPackage + { + if ($this->useStaticDomain()) { + return new UrlPackage( + $this->getStaticDomainAndPort() . $this->fileAware->getPublicFilesBasePath(), + $this->versionStrategy + ); + } + + return new PathPackage( + $this->fileAware->getPublicFilesBasePath(), + $this->versionStrategy, + $this->requestStackContext + ); + } + + /** + * @return PathPackage|UrlPackage + */ + protected function getAbsoluteDocumentPackage(): PathPackage|UrlPackage + { + if ($this->useStaticDomain()) { + return $this->getDocumentPackage(); + } + $scheme = ''; + if (null !== $this->getRequest()) { + $scheme = $this->getRequest()->getSchemeAndHttpHost(); + } + return new UrlPackage( + $scheme . $this->requestStackContext->getBasePath() . $this->fileAware->getPublicFilesBasePath(), + $this->versionStrategy + ); + } + + /** + * @return PathPackage + */ + protected function getPublicPathPackage(): PathPackage + { + return new PathPackage( + $this->fileAware->getPublicFilesPath(), + $this->versionStrategy + ); + } + + /** + * @return PathPackage + */ + protected function getPrivatePathPackage(): PathPackage + { + return new PathPackage( + $this->fileAware->getPrivateFilesPath(), + $this->versionStrategy + ); + } + + /** + * @return PathPackage + */ + protected function getFontsPathPackage(): PathPackage + { + return new PathPackage( + $this->fileAware->getFontsFilesPath(), + $this->versionStrategy + ); + } + + /** + * Shortcut for $this->getUrl($relativePath, static::FONTS_PATH). + * + * @param string $relativePath + * @return string + * @deprecated Use FilesystemOperator font.storage instead to support external filesystems. + */ + public function getFontsPath(string $relativePath): string + { + return $this->getUrl($relativePath, static::FONTS_PATH); + } + + /** + * Shortcut for $this->getUrl($relativePath, static::PUBLIC_PATH). + * + * @param string $relativePath + * @return string + * @deprecated Use FilesystemOperator documents.storage instead to support external filesystems. + */ + public function getPublicFilesPath(string $relativePath): string + { + return $this->getUrl($relativePath, static::PUBLIC_PATH); + } + + /** + * Shortcut for $this->getUrl($relativePath, static::PRIVATE_PATH). + * + * @param string $relativePath + * @return string + * @deprecated Use FilesystemOperator documents.storage instead to support external filesystems. + */ + public function getPrivateFilesPath(string $relativePath): string + { + return $this->getUrl($relativePath, static::PRIVATE_PATH); + } + + /** + * @param DocumentInterface $document + * @return string Document file absolute path according if document is private or not. + * @throws DocumentWithoutFileException + * @deprecated Use FilesystemOperator documents.storage instead to support external filesystems. + */ + public function getDocumentFilePath(DocumentInterface $document): string + { + if (!$document->isLocal()) { + throw new DocumentWithoutFileException($document); + } + if ($document->isPrivate()) { + return $this->getPrivateFilesPath($document->getRelativePath() ?? ''); + } + return $this->getPublicFilesPath($document->getRelativePath() ?? ''); + } + + /** + * @param DocumentInterface $document + * @return string Document folder absolute path according if document is private or not. + * @throws DocumentWithoutFileException + * @deprecated Use FilesystemOperator documents.storage instead to support external filesystems. + */ + public function getDocumentFolderPath(DocumentInterface $document): string + { + if (!$document->isLocal()) { + throw new DocumentWithoutFileException($document); + } + if ($document->isPrivate()) { + return $this->getPrivateFilesPath($document->getFolder()); + } + return $this->getPublicFilesPath($document->getFolder()); + } + + /** + * @return string + * @deprecated Use FilesystemOperator documents.storage instead to support external filesystems. + */ + public function getStaticDomain(): string + { + return $this->staticDomain; + } + + /** + * @param string $staticDomain + * @return Packages + * @deprecated Use FilesystemOperator documents.storage instead to support external filesystems. + */ + public function setStaticDomain(string $staticDomain): Packages + { + $this->staticDomain = $staticDomain; + return $this; + } + + /** + * @return null|Request + */ + protected function getRequest(): ?Request + { + return $this->requestStack->getMainRequest(); + } +} diff --git a/src/SvgSizeResolver.php b/src/SvgSizeResolver.php index b460c56..42d85b1 100644 --- a/src/SvgSizeResolver.php +++ b/src/SvgSizeResolver.php @@ -11,13 +11,15 @@ final class SvgSizeResolver { + private DocumentInterface $document; private ?\DOMDocument $xmlDocument = null; private ?\DOMNode $svgNode = null; + private FilesystemOperator $documentsStorage; - public function __construct( - private readonly DocumentInterface $document, - private readonly FilesystemOperator $documentsStorage - ) { + public function __construct(DocumentInterface $document, FilesystemOperator $documentsStorage) + { + $this->document = $document; + $this->documentsStorage = $documentsStorage; } /** diff --git a/src/TwigExtension/DocumentExtension.php b/src/TwigExtension/DocumentExtension.php index 390944e..7165552 100644 --- a/src/TwigExtension/DocumentExtension.php +++ b/src/TwigExtension/DocumentExtension.php @@ -22,6 +22,11 @@ */ final class DocumentExtension extends AbstractExtension { + private bool $throwExceptions; + private RendererInterface $renderer; + private EmbedFinderFactory $embedFinderFactory; + private FilesystemOperator $documentsStorage; + /** * @param RendererInterface $renderer * @param EmbedFinderFactory $embedFinderFactory @@ -29,11 +34,15 @@ final class DocumentExtension extends AbstractExtension * @param bool $throwExceptions Trigger exception if using filter on NULL values (default: false) */ public function __construct( - private readonly RendererInterface $renderer, - private readonly EmbedFinderFactory $embedFinderFactory, - private readonly FilesystemOperator $documentsStorage, - private readonly bool $throwExceptions = false + RendererInterface $renderer, + EmbedFinderFactory $embedFinderFactory, + FilesystemOperator $documentsStorage, + bool $throwExceptions = false ) { + $this->throwExceptions = $throwExceptions; + $this->renderer = $renderer; + $this->embedFinderFactory = $embedFinderFactory; + $this->documentsStorage = $documentsStorage; } /** diff --git a/tests/MediaFinders/SimpleVimeoEmbedFinder.php b/tests/MediaFinders/SimpleVimeoEmbedFinder.php deleted file mode 100644 index 050b382..0000000 --- a/tests/MediaFinders/SimpleVimeoEmbedFinder.php +++ /dev/null @@ -1,28 +0,0 @@ -[\n\r\t\s]+\<#', '><', $body); - } - - protected function getUrlGenerator(): DocumentUrlGeneratorInterface - { - return new DummyDocumentUrlGenerator(); - } - - protected function getFilesystemOperator(): FilesystemOperator - { - return new MountManager([ - 'public' => new Filesystem( - new LocalFilesystemAdapter(dirname(__DIR__) . '/../files/'), - publicUrlGenerator: new class () implements PublicUrlGenerator - { - public function publicUrl(string $path, Config $config): string - { - return '/files/' . $path; - } - } - ), - 'private' => new Filesystem( - new LocalFilesystemAdapter(dirname(__DIR__) . '/../files/'), - publicUrlGenerator: new class () implements PublicUrlGenerator - { - public function publicUrl(string $path, Config $config): string - { - return '/files/' . $path; - } - } - ) - ]); - } - - protected function getEnvironment(): Environment - { - $loader = new FilesystemLoader([ - dirname(__DIR__) . '/../src/Resources/views' - ]); - return new Environment($loader, [ - 'autoescape' => false - ]); - } - - - - /** - * @return EmbedFinderFactory - */ - protected function getEmbedFinderFactory(): EmbedFinderFactory - { - return new EmbedFinderFactory([ - 'youtube' => SimpleYoutubeEmbedFinder::class, - 'vimeo' => SimpleVimeoEmbedFinder::class, - ]); - } - - public function assertHtmlTidyEquals(string $expected, string $actual, string $message = ''): void - { - $this->assertEquals( - $this->htmlTidy($expected), - $this->htmlTidy($actual), - $message - ); - } -} diff --git a/tests/Renderer/AudioRendererTest.php b/tests/Renderer/AudioRendererTest.php deleted file mode 100644 index e97a701..0000000 --- a/tests/Renderer/AudioRendererTest.php +++ /dev/null @@ -1,139 +0,0 @@ -getFilesystemOperator(), - $this->getDocumentFinder(), - $this->getEnvironment(), - $this->getUrlGenerator() - ); - } - - public function testSupports(): void - { - /** @var DocumentInterface $mockValidDocument */ - $mockValidDocument = new SimpleDocument(); - $mockValidDocument->setFilename('file.mp3'); - $mockValidDocument->setMimeType('audio/mpeg'); - - /** @var DocumentInterface $mockInvalidDocument */ - $mockInvalidDocument = new SimpleDocument(); - $mockInvalidDocument->setFilename('file.jpg'); - $mockInvalidDocument->setMimeType('image/jpeg'); - - $renderer = $this->getRenderer(); - - $this->assertIsString($mockValidDocument->getMimeType()); - $this->assertEquals('audio/mpeg', $mockValidDocument->getMimeType()); - $this->assertIsBool($renderer->supports($mockValidDocument, [])); - $this->assertTrue($renderer->supports($mockValidDocument, [])); - - $this->assertIsString($mockInvalidDocument->getMimeType()); - $this->assertEquals('image/jpeg', $mockInvalidDocument->getMimeType()); - $this->assertIsBool($renderer->supports($mockInvalidDocument, [])); - $this->assertFalse($renderer->supports($mockInvalidDocument, [])); - } - - public function testRender(): void - { - /** @var DocumentInterface $mockDocument */ - $mockDocument = new SimpleDocument(); - $mockDocument->setFilename('file.mp3'); - $mockDocument->setFolder('folder'); - $mockDocument->setMimeType('audio/mpeg'); - - /** @var DocumentInterface $mockDocument2 */ - $mockDocument2 = new SimpleDocument(); - $mockDocument2->setFilename('file2.mp3'); - $mockDocument2->setFolder('folder'); - $mockDocument2->setMimeType('audio/mpeg'); - - - $renderer = $this->getRenderer(); - $this->assertHtmlTidyEquals((<< - - -

Your browser does not support native audio.

- -EOT - ), ($renderer->render($mockDocument, []))); - - - $this->assertHtmlTidyEquals((<< - -

Your browser does not support native audio.

- -EOT - ), ($renderer->render($mockDocument2, []))); - - - $this->assertHtmlTidyEquals((<< - - -

Your browser does not support native audio.

- -EOT - ), ($renderer->render($mockDocument, [ - 'controls' => true, - 'loop' => true, - 'autoplay' => true, - ]))); - - - $this->assertHtmlTidyEquals((<< - - -

Your browser does not support native audio.

- -EOT - ), ($renderer->render($mockDocument, [ - 'controls' => false - ]))); - } - - /** - * @return DocumentFinderInterface - */ - private function getDocumentFinder(): DocumentFinderInterface - { - $finder = new ArrayDocumentFinder(); - - $finder->addDocument( - (new SimpleDocument()) - ->setFilename('file.mp3') - ->setFolder('folder') - ->setMimeType('audio/mpeg') - ); - $finder->addDocument( - (new SimpleDocument()) - ->setFilename('file.ogg') - ->setFolder('folder') - ->setMimeType('audio/ogg') - ); - $finder->addDocument( - (new SimpleDocument()) - ->setFilename('file2.mp3') - ->setFolder('folder') - ->setMimeType('audio/mpeg') - ); - - return $finder; - } -} diff --git a/tests/Renderer/ChainRendererTest.php b/tests/Renderer/ChainRendererTest.php deleted file mode 100644 index 5fb5eac..0000000 --- a/tests/Renderer/ChainRendererTest.php +++ /dev/null @@ -1,104 +0,0 @@ -getFilesystemOperator()), - new Renderer\SvgRenderer($this->getFilesystemOperator()), - new Renderer\PdfRenderer($this->getFilesystemOperator(), $this->getEnvironment(), $this->getUrlGenerator()), - new Renderer\ImageRenderer($this->getFilesystemOperator(), $this->getEmbedFinderFactory(), $this->getEnvironment(), $this->getUrlGenerator()), - new Renderer\PictureRenderer($this->getFilesystemOperator(), $this->getEmbedFinderFactory(), $this->getEnvironment(), $this->getUrlGenerator()), - new Renderer\EmbedRenderer($this->getEmbedFinderFactory()), - ]); - } - - public function testRender(): void - { - $mockSvgDocument = new SimpleDocument(); - $mockSvgDocument->setFilename('file.svg'); - $mockSvgDocument->setFolder('folder'); - $mockSvgDocument->setMimeType('image/svg'); - - $mockPdfDocument = new SimpleDocument(); - $mockPdfDocument->setFilename('file.pdf'); - $mockPdfDocument->setFolder('folder'); - $mockPdfDocument->setMimeType('application/pdf'); - - $mockDocumentYoutube = new SimpleDocument(); - $mockDocumentYoutube->setFilename('poster.jpg'); - $mockDocumentYoutube->setEmbedId('xxxxxxx'); - $mockDocumentYoutube->setEmbedPlatform('youtube'); - $mockDocumentYoutube->setMimeType('image/jpeg'); - - $mockPictureDocument = new SimpleDocument(); - $mockPictureDocument->setFilename('file.jpg'); - $mockPictureDocument->setFolder('folder'); - $mockPictureDocument->setMimeType('image/jpeg'); - - $renderer = $this->getRenderer(); - - $this->assertHtmlTidyEquals( - '

Your browser does not support PDF native viewer.

', - ($renderer->render($mockPdfDocument, [ - 'embed' => true - ])) - ); - - $this->assertHtmlTidyEquals( - '

Your browser does not support PDF native viewer.

', - ($renderer->render($mockPdfDocument, ['absolute' => true, 'embed' => true])) - ); - - $this->assertHtmlTidyEquals( - '', - ($renderer->render($mockSvgDocument, [])) - ); - - $this->assertHtmlTidyEquals( - (<< - - -EOT - ), - ($renderer->render($mockSvgDocument, ['inline' => true])) - ); - - $this->assertIsBool($mockDocumentYoutube->isEmbed()); - $this->assertTrue($mockDocumentYoutube->isEmbed()); - - $this->assertHtmlTidyEquals( - (<< -EOT - ), - ($renderer->render($mockDocumentYoutube, ['embed' => true])) - ); - - $this->assertHtmlTidyEquals( - (<< - - -file.jpg - -EOT - ), - ($renderer->render($mockPictureDocument, [ - 'width' => 300, - 'picture' => true - ])) - ); - } -} diff --git a/tests/Renderer/InlineSvgRendererTest.php b/tests/Renderer/InlineSvgRendererTest.php deleted file mode 100644 index 651fe00..0000000 --- a/tests/Renderer/InlineSvgRendererTest.php +++ /dev/null @@ -1,72 +0,0 @@ -getFilesystemOperator() - ); - } - - public function testSupports(): void - { - $mockValidDocument = new SimpleDocument(); - $mockInvalidDocument = new SimpleDocument(); - - $mockValidDocument->setFilename('file.svg'); - $mockValidDocument->setMimeType('image/svg'); - - $mockInvalidDocument->setFilename('file.jpg'); - $mockInvalidDocument->setMimeType('image/jpeg'); - - $renderer = $this->getRenderer(); - - $this->assertEquals( - 'image/svg', - $mockValidDocument->getMimeType() - ); - - $this->assertTrue($renderer->supports($mockValidDocument, ['inline' => true])); - $this->assertFalse($renderer->supports($mockValidDocument, ['inline' => false])); - - $this->assertEquals( - 'image/jpeg', - $mockInvalidDocument->getMimeType() - ); - $this->assertFalse($renderer->supports($mockInvalidDocument, [])); - } - - public function testRender(): void - { - $mockDocument = new SimpleDocument(); - - $mockDocument->setFilename('file.svg'); - $mockDocument->setFolder('folder'); - $mockDocument->setMimeType('image/svg'); - - $renderer = $this->getRenderer(); - - $this->assertEquals( - 'image/svg', - $mockDocument->getMimeType() - ); - - $this->assertHtmlTidyEquals( - << - - -EOT - , - $renderer->render($mockDocument, ['inline' => true]) - ); - } -} diff --git a/tests/Renderer/PdfRendererTest.php b/tests/Renderer/PdfRendererTest.php deleted file mode 100644 index 931a04c..0000000 --- a/tests/Renderer/PdfRendererTest.php +++ /dev/null @@ -1,71 +0,0 @@ -getFilesystemOperator(), - $this->getEnvironment(), - $this->getUrlGenerator() - ); - } - public function testSupports(): void - { - $mockValidDocument = new SimpleDocument(); - $mockValidDocument->setFilename('file.pdf'); - $mockValidDocument->setMimeType('application/pdf'); - - $mockInvalidDocument = new SimpleDocument(); - $mockInvalidDocument->setFilename('file.jpg'); - $mockInvalidDocument->setMimeType('image/jpeg'); - - $renderer = $this->getRenderer(); - - $this->assertEquals( - 'application/pdf', - $mockValidDocument->getMimeType() - ); - $this->assertTrue( - $renderer->supports($mockValidDocument, [ - 'embed' => true - ]) - ); - - $this->assertEquals( - 'image/jpeg', - $mockInvalidDocument->getMimeType() - ); - $this->assertFalse( - $renderer->supports($mockInvalidDocument, []) - ); - } - - public function testRender(): void - { - $mockDocument = new SimpleDocument(); - $mockDocument->setFilename('file.pdf'); - $mockDocument->setFolder('folder'); - $mockDocument->setMimeType('application/pdf'); - - $renderer = $this->getRenderer(); - - $this->assertEquals( - 'application/pdf', - $mockDocument->getMimeType() - ); - $this->assertHtmlTidyEquals( - '

Your browser does not support PDF native viewer.

', - $renderer->render($mockDocument, [ - 'embed' => true - ]) - ); - } -} diff --git a/tests/Renderer/SvgRendererTest.php b/tests/Renderer/SvgRendererTest.php deleted file mode 100644 index 232f2a1..0000000 --- a/tests/Renderer/SvgRendererTest.php +++ /dev/null @@ -1,75 +0,0 @@ -getFilesystemOperator() - ); - } - - public function testSupports(): void - { - $mockValidDocument = new SimpleDocument(); - $mockInvalidDocument = new SimpleDocument(); - - $mockValidDocument->setFilename('file.svg'); - $mockValidDocument->setMimeType('image/svg+xml'); - - $mockInvalidDocument->setFilename('file.jpg'); - $mockInvalidDocument->setMimeType('image/jpeg'); - - $renderer = $this->getRenderer(); - - $this->assertIsString($mockValidDocument->getMimeType()); - $this->assertEquals( - 'image/svg+xml', - $mockValidDocument->getMimeType() - ); - - $this->assertTrue( - $renderer->supports($mockValidDocument, []) - ); - $this->assertTrue( - $renderer->supports($mockValidDocument, ['inline' => false]) - ); - $this->assertFalse( - $renderer->supports($mockValidDocument, ['inline' => true]) - ); - $this->assertFalse( - $renderer->supports($mockInvalidDocument, []) - ); - } - - public function testRender(): void - { - /** @var DocumentInterface $mockDocument */ - $mockDocument = new SimpleDocument(); - - $mockDocument->setFilename('file2.svg'); - $mockDocument->setFolder('folder'); - $mockDocument->setMimeType('image/svg+xml'); - - $renderer = $this->getRenderer(); - $this->assertEquals( - 'image/svg+xml', - $mockDocument->getMimeType() - ); - $this->assertHtmlTidyEquals( - << -EOT - , - $renderer->render($mockDocument, []) - ); - } -} diff --git a/tests/Renderer/VideoRendererTest.php b/tests/Renderer/VideoRendererTest.php deleted file mode 100644 index e311a4e..0000000 --- a/tests/Renderer/VideoRendererTest.php +++ /dev/null @@ -1,170 +0,0 @@ -getFilesystemOperator(), - $this->getDocumentFinder(), - $this->getEnvironment(), - $this->getUrlGenerator() - ); - } - - public function testSupports(): void - { - $mockValidDocument = new SimpleDocument(); - $mockValidDocument->setFilename('file.mp4'); - $mockValidDocument->setMimeType('video/mp4'); - - $mockInvalidDocument = new SimpleDocument(); - $mockInvalidDocument->setFilename('file.jpg'); - $mockInvalidDocument->setMimeType('image/jpeg'); - - $renderer = $this->getRenderer(); - - $this->assertEquals( - 'video/mp4', - $mockValidDocument->getMimeType() - ); - $this->assertTrue( - $renderer->supports($mockValidDocument, []) - ); - $this->assertEquals( - 'image/jpeg', - $mockInvalidDocument->getMimeType() - ); - $this->assertFalse( - $renderer->supports($mockInvalidDocument, []) - ); - } - - public function testRender(): void - { - $mockDocument = new SimpleDocument(); - $mockDocument->setFilename('file.mp4'); - $mockDocument->setFolder('folder'); - $mockDocument->setMimeType('video/mp4'); - - $mockDocument2 = new SimpleDocument(); - $mockDocument2->setFilename('file2.ogg'); - $mockDocument2->setFolder('folder'); - $mockDocument2->setMimeType('video/ogg'); - - $renderer = $this->getRenderer(); - - $this->assertEquals( - 'video/mp4', - $mockDocument->getMimeType() - ); - - $this->assertHtmlTidyEquals( - << - - -

Your browser does not support native video.

- -EOT - , - $renderer->render($mockDocument, []) - ); - - $this->assertHtmlTidyEquals( - << - -

Your browser does not support native video.

- -EOT - , - $renderer->render($mockDocument2, []) - ); - - $this->assertHtmlTidyEquals( - << - - -

Your browser does not support native video.

- -EOT - , - $renderer->render($mockDocument, [ - 'controls' => true, - 'loop' => true, - 'autoplay' => true, - ]) - ); - - $this->assertHtmlTidyEquals( - << - - -

Your browser does not support native video.

- -EOT - , - $renderer->render($mockDocument, [ - 'controls' => true, - 'loop' => true, - 'autoplay' => true, - 'muted' => true, - ]) - ); - - $this->assertHtmlTidyEquals( - << - - -

Your browser does not support native video.

- -EOT - , - $renderer->render($mockDocument, [ - 'controls' => false - ]) - ); - } - - /** - * @return DocumentFinderInterface - */ - private function getDocumentFinder(): DocumentFinderInterface - { - $finder = new ArrayDocumentFinder(); - - $finder->addDocument( - (new SimpleDocument()) - ->setFilename('file.mp4') - ->setFolder('folder') - ->setMimeType('video/mp4') - ); - $finder->addDocument( - (new SimpleDocument()) - ->setFilename('file.webm') - ->setFolder('folder') - ->setMimeType('video/webm') - ); - $finder->addDocument( - (new SimpleDocument()) - ->setFilename('file2.ogg') - ->setFolder('folder') - ->setMimeType('video/ogg') - ); - - return $finder; - } -} diff --git a/tests/Roadiz/Document/Renderer/AudioRenderer.php b/tests/Roadiz/Document/Renderer/AudioRenderer.php new file mode 100644 index 0000000..5dedc95 --- /dev/null +++ b/tests/Roadiz/Document/Renderer/AudioRenderer.php @@ -0,0 +1,207 @@ +setFilename('file.mp3'); + $mockValidDocument->setMimeType('audio/mpeg'); + + /** @var DocumentInterface $mockInvalidDocument */ + $mockInvalidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockInvalidDocument->setFilename('file.jpg'); + $mockInvalidDocument->setMimeType('image/jpeg'); + + $this + ->given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getDocumentFinder(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($mockValidDocument->getMimeType()) + ->isEqualTo('audio/mpeg') + ->boolean($renderer->supports($mockValidDocument, [])) + ->isEqualTo(true) + ->string($mockInvalidDocument->getMimeType()) + ->isEqualTo('image/jpeg') + ->boolean($renderer->supports($mockInvalidDocument, [])) + ->isEqualTo(false); + } + + public function testRender() + { + /** @var DocumentInterface $mockDocument */ + $mockDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockDocument->setFilename('file.mp3'); + $mockDocument->setFolder('folder'); + $mockDocument->setMimeType('audio/mpeg'); + + /** @var DocumentInterface $mockDocument2 */ + $mockDocument2 = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockDocument2->setFilename('file2.mp3'); + $mockDocument2->setFolder('folder'); + $mockDocument2->setMimeType('audio/mpeg'); + + $this + ->given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getDocumentFinder(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($mockDocument->getMimeType()) + ->isEqualTo('audio/mpeg') + ->string($this->htmlTidy($renderer->render($mockDocument, []))) + ->isEqualTo($this->htmlTidy(<< + + +

Your browser does not support native audio.

+ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument2, []))) + ->isEqualTo($this->htmlTidy(<< + +

Your browser does not support native audio.

+ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ + 'controls' => true, + 'loop' => true, + 'autoplay' => true, + ]))) + ->isEqualTo($this->htmlTidy(<< + + +

Your browser does not support native audio.

+ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ + 'controls' => false + ]))) + ->isEqualTo($this->htmlTidy(<< + + +

Your browser does not support native audio.

+ +EOT + )) + ; + } + + /** + * @return DocumentFinderInterface + */ + private function getDocumentFinder(): DocumentFinderInterface + { + $finder = new ArrayDocumentFinder(); + + $finder->addDocument( + (new \mock\RZ\Roadiz\Documents\Models\SimpleDocument()) + ->setFilename('file.mp3') + ->setFolder('folder') + ->setMimeType('audio/mpeg') + ); + $finder->addDocument( + (new \mock\RZ\Roadiz\Documents\Models\SimpleDocument()) + ->setFilename('file.ogg') + ->setFolder('folder') + ->setMimeType('audio/ogg') + ); + $finder->addDocument( + (new \mock\RZ\Roadiz\Documents\Models\SimpleDocument()) + ->setFilename('file2.mp3') + ->setFolder('folder') + ->setMimeType('audio/mpeg') + ); + + return $finder; + } + + /** + * @return DocumentUrlGeneratorInterface + */ + private function getUrlGenerator(): DocumentUrlGeneratorInterface + { + return new \mock\RZ\Roadiz\Documents\UrlGenerators\DummyDocumentUrlGenerator(); + } + + private function getFilesystemOperator(): FilesystemOperator + { + return new MountManager([ + 'public' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ), + 'private' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ) + ]); + } + + private function getEnvironment(): Environment + { + $loader = new FilesystemLoader([ + dirname(__DIR__) . '/../../../src/Resources/views' + ]); + return new Environment($loader, [ + 'autoescape' => false + ]); + } + + /** + * @param string $body + * + * @return string + */ + private function htmlTidy(string $body): string + { + $body = preg_replace('#[\n\r\t\s]{2,}#', ' ', $body); + $body = str_replace("/", '/', $body); + $body = html_entity_decode($body); + return preg_replace('#\>[\n\r\t\s]+\<#', '><', $body); + } +} diff --git a/tests/Roadiz/Document/Renderer/ChainRenderer.php b/tests/Roadiz/Document/Renderer/ChainRenderer.php new file mode 100644 index 0000000..1e2bd38 --- /dev/null +++ b/tests/Roadiz/Document/Renderer/ChainRenderer.php @@ -0,0 +1,169 @@ +setFilename('file.svg'); + $mockSvgDocument->setFolder('folder'); + $mockSvgDocument->setMimeType('image/svg'); + + /** @var DocumentInterface $mockPdfDocument */ + $mockPdfDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockPdfDocument->setFilename('file.pdf'); + $mockPdfDocument->setFolder('folder'); + $mockPdfDocument->setMimeType('application/pdf'); + + /** @var DocumentInterface $mockDocumentYoutube */ + $mockDocumentYoutube = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockDocumentYoutube->setFilename('poster.jpg'); + $mockDocumentYoutube->setEmbedId('xxxxxxx'); + $mockDocumentYoutube->setEmbedPlatform('youtube'); + $mockDocumentYoutube->setMimeType('image/jpeg'); + + /** @var DocumentInterface $mockPictureDocument */ + $mockPictureDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockPictureDocument->setFilename('file.jpg'); + $mockPictureDocument->setFolder('folder'); + $mockPictureDocument->setMimeType('image/jpeg'); + + $renderers = [ + new Renderer\InlineSvgRenderer($this->getFilesystemOperator()), + new Renderer\SvgRenderer($this->getFilesystemOperator()), + new Renderer\PdfRenderer($this->getFilesystemOperator(), $this->getEnvironment(), $this->getUrlGenerator()), + new Renderer\ImageRenderer($this->getFilesystemOperator(), $this->getEmbedFinderFactory(), $this->getEnvironment(), $this->getUrlGenerator()), + new Renderer\PictureRenderer($this->getFilesystemOperator(), $this->getEmbedFinderFactory(), $this->getEnvironment(), $this->getUrlGenerator()), + new Renderer\EmbedRenderer($this->getEmbedFinderFactory()), + ]; + + $this + ->given($renderer = $this->newTestedInstance($renderers)) + ->then + ->string($this->htmlTidy($renderer->render($mockPdfDocument, [ + 'embed' => true + ]))) + ->isEqualTo('

Your browser does not support PDF native viewer.

') + ->string($this->htmlTidy($renderer->render($mockPdfDocument, ['absolute' => true, 'embed' => true]))) + ->isEqualTo('

Your browser does not support PDF native viewer.

') + ->string($this->htmlTidy($renderer->render($mockSvgDocument, []))) + ->isEqualTo($this->htmlTidy(<< +EOT + )) + ->string($this->htmlTidy($renderer->render($mockSvgDocument, ['inline' => true]))) + ->isEqualTo($this->htmlTidy(<< + + +EOT + )) + ->boolean($mockDocumentYoutube->isEmbed()) + ->isEqualTo(true) + ->string($this->htmlTidy($renderer->render($mockDocumentYoutube, ['embed' => true]))) + ->isEqualTo($this->htmlTidy(<< +EOT + )) + ->string($this->htmlTidy($renderer->render($mockPictureDocument, [ + 'width' => 300, + 'picture' => true + ]))) + ->isEqualTo($this->htmlTidy(<< + + +file.jpg + +EOT + )) + ; + } + + private function htmlTidy(string $body): string + { + $body = preg_replace('#[\n\r\t\s]{2,}#', ' ', $body); + $body = str_replace("/", '/', $body); + $body = html_entity_decode($body); + return preg_replace('#\>[\n\r\t\s]+\<#', '><', $body); + } + + /** + * @return DocumentUrlGeneratorInterface + */ + private function getUrlGenerator(): DocumentUrlGeneratorInterface + { + return new \mock\RZ\Roadiz\Documents\UrlGenerators\DummyDocumentUrlGenerator(); + } + + private function getFilesystemOperator(): FilesystemOperator + { + return new MountManager([ + 'public' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ), + 'private' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ) + ]); + } + + private function getEnvironment(): Environment + { + $loader = new FilesystemLoader([ + dirname(__DIR__) . '/../../../src/Resources/views' + ]); + return new Environment($loader, [ + 'autoescape' => false + ]); + } + + /** + * @return EmbedFinderFactory + */ + private function getEmbedFinderFactory(): EmbedFinderFactory + { + return new EmbedFinderFactory([ + 'youtube' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractYoutubeEmbedFinder::class, + 'vimeo' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractVimeoEmbedFinder::class, + 'dailymotion' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractDailymotionEmbedFinder::class, + 'soundcloud' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractSoundcloudEmbedFinder::class, + ]); + } +} diff --git a/tests/Renderer/EmbedRendererTest.php b/tests/Roadiz/Document/Renderer/EmbedRenderer.php similarity index 50% rename from tests/Renderer/EmbedRendererTest.php rename to tests/Roadiz/Document/Renderer/EmbedRenderer.php index 60b6e18..aca35b6 100644 --- a/tests/Renderer/EmbedRendererTest.php +++ b/tests/Roadiz/Document/Renderer/EmbedRenderer.php @@ -1,174 +1,180 @@ getEmbedFinderFactory()); - } - - public function testSupports(): void + public function testSupports() { - $mockValidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockValidDocument */ + $mockValidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockValidDocument->setFilename('poster.jpg'); $mockValidDocument->setEmbedId('xxxxxxx'); $mockValidDocument->setEmbedPlatform('youtube'); $mockValidDocument->setMimeType('image/jpeg'); - $mockInvalidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockInvalidDocument */ + $mockInvalidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockInvalidDocument->setFilename('file.jpg'); $mockInvalidDocument->setMimeType('image/jpeg'); - $mockExternalInvalidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockExternalInvalidDocument */ + $mockExternalInvalidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockExternalInvalidDocument->setFilename('file.jpg'); $mockExternalInvalidDocument->setMimeType('image/jpeg'); $mockExternalInvalidDocument->setEmbedId('xxxxx'); $mockExternalInvalidDocument->setEmbedPlatform('getty'); - $renderer = $this->getRenderer(); - - $this->assertIsBool($mockValidDocument->isEmbed()); - $this->assertTrue($mockValidDocument->isEmbed()); - - $this->assertFalse($renderer->supports($mockValidDocument, [])); - $this->assertTrue($renderer->supports($mockValidDocument, ['embed' => true])); - $this->assertFalse($renderer->supports($mockExternalInvalidDocument, ['embed' => true])); - $this->assertFalse($mockInvalidDocument->isEmbed()); - $this->assertFalse($renderer->supports($mockInvalidDocument, [])); - $this->assertFalse($renderer->supports($mockInvalidDocument, ['embed' => true])); + $this + ->given($renderer = $this->newTestedInstance( + $this->getEmbedFinderFactory() + )) + ->then + ->boolean($mockValidDocument->isEmbed()) + ->isEqualTo(true) + ->boolean($renderer->supports($mockValidDocument, [])) + ->isEqualTo(false) + ->boolean($renderer->supports($mockValidDocument, ['embed' => true])) + ->isEqualTo(true) + ->boolean($renderer->supports($mockExternalInvalidDocument, ['embed' => true])) + ->isEqualTo(false) + ->boolean($mockInvalidDocument->isEmbed()) + ->isEqualTo(false) + ->boolean($renderer->supports($mockInvalidDocument, [])) + ->isEqualTo(false) + ->boolean($renderer->supports($mockInvalidDocument, ['embed' => true])) + ->isEqualTo(false) + ; } - public function testRender(): void + public function testRender() { - $mockDocumentYoutube = new SimpleDocument(); + /** @var DocumentInterface $mockDocumentYoutube */ + $mockDocumentYoutube = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockDocumentYoutube->setFilename('poster.jpg'); $mockDocumentYoutube->setEmbedId('xxxxxxx'); $mockDocumentYoutube->setEmbedPlatform('youtube'); $mockDocumentYoutube->setMimeType('image/jpeg'); - $mockDocumentVimeo = new SimpleDocument(); + /** @var DocumentInterface $mockDocumentVimeo */ + $mockDocumentVimeo = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockDocumentVimeo->setFilename('poster.jpg'); $mockDocumentVimeo->setEmbedId('0000000'); $mockDocumentVimeo->setEmbedPlatform('vimeo'); $mockDocumentVimeo->setMimeType('image/jpeg'); - $renderer = $this->getRenderer(); - - $this->assertIsBool($mockDocumentYoutube->isEmbed()); - $this->assertTrue($mockDocumentYoutube->isEmbed()); - - $this->assertHtmlTidyEquals( - (<<given($renderer = $this->newTestedInstance( + $this->getEmbedFinderFactory() + )) + ->then + ->boolean($mockDocumentYoutube->isEmbed()) + ->isEqualTo(true) + ->string($renderer->render($mockDocumentYoutube, ['embed' => true])) + ->isEqualTo($this->htmlTidy(<< EOT - ), - $renderer->render($mockDocumentYoutube, ['embed' => true]) - ); - - $this->assertHtmlTidyEquals( - (<<string($renderer->render($mockDocumentYoutube, [ + 'embed' => true, + 'loading' => 'lazy' + ])) + ->isEqualTo($this->htmlTidy(<< EOT - ), - $renderer->render($mockDocumentYoutube, [ + )) + ->string($renderer->render($mockDocumentYoutube, [ 'embed' => true, - 'loading' => 'lazy' - ]) - ); - - $this->assertHtmlTidyEquals( - (<< 500 + // height is auto calculated based on 16/10 ratio + ])) + ->isEqualTo($this->htmlTidy(<< EOT - ), - $renderer->render($mockDocumentYoutube, [ + )) + ->string($renderer->render($mockDocumentYoutube, [ 'embed' => true, - 'width' => 500 - // height is auto calculated based on 16/10 ratio - ]) - ); - - $this->assertHtmlTidyEquals( - (<< 500, + 'height' => 500 + ])) + ->isEqualTo($this->htmlTidy(<< EOT - ), - $renderer->render($mockDocumentYoutube, [ + )) + ->string($renderer->render($mockDocumentYoutube, [ 'embed' => true, - 'width' => 500, - 'height' => 500 - ]) - ); - - $this->assertHtmlTidyEquals( - (<< true, + ])) + ->isEqualTo($this->htmlTidy(<< EOT - ), - $renderer->render($mockDocumentYoutube, [ - 'embed' => true, - 'autoplay' => true, - ]) - ); - - - $this->assertIsBool($mockDocumentVimeo->isEmbed()); - $this->assertTrue($mockDocumentVimeo->isEmbed()); - - $this->assertHtmlTidyEquals( - (<<boolean($mockDocumentVimeo->isEmbed()) + ->isEqualTo(true) + ->string($renderer->render($mockDocumentVimeo, ['embed' => true])) + ->isEqualTo($this->htmlTidy(<< EOT - ), - $renderer->render($mockDocumentVimeo, ['embed' => true]) - ); - - $this->assertHtmlTidyEquals( - (<<string($renderer->render($mockDocumentVimeo, [ + 'embed' => true, + 'autoplay' => true, + 'automute' => true, + ])) + ->isEqualTo($this->htmlTidy(<< EOT - ), - $renderer->render($mockDocumentVimeo, [ + )) + ->string($renderer->render($mockDocumentVimeo, [ 'embed' => true, 'autoplay' => true, - 'automute' => true, - ]) - ); - - $this->assertHtmlTidyEquals( - (<< "1", // Hack background conflict option with background color + ])) + ->isEqualTo($this->htmlTidy(<< EOT - ), - $renderer->render($mockDocumentVimeo, [ - 'embed' => true, - 'autoplay' => true, - 'background' => "1", // Hack background conflict option with background color - ]) - ); + )) + ; + } + + /** + * @return EmbedFinderFactory + */ + private function getEmbedFinderFactory(): EmbedFinderFactory + { + return new EmbedFinderFactory([ + 'youtube' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractYoutubeEmbedFinder::class, + 'vimeo' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractVimeoEmbedFinder::class, + 'dailymotion' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractDailymotionEmbedFinder::class, + 'soundcloud' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractSoundcloudEmbedFinder::class, + ]); + } + + private function htmlTidy(string $body): string + { + $body = preg_replace('#[\n\r\t\s]{2,}#', ' ', $body); + return preg_replace('#\>[\n\r\t\s]+\<#', '><', $body); } } diff --git a/tests/Renderer/ImageRendererTest.php b/tests/Roadiz/Document/Renderer/ImageRenderer.php similarity index 52% rename from tests/Renderer/ImageRendererTest.php rename to tests/Roadiz/Document/Renderer/ImageRenderer.php index a0be991..91800bb 100644 --- a/tests/Renderer/ImageRendererTest.php +++ b/tests/Roadiz/Document/Renderer/ImageRenderer.php @@ -1,107 +1,120 @@ getFilesystemOperator(), - $this->getEmbedFinderFactory(), - $this->getEnvironment(), - $this->getUrlGenerator() - ); - } - - public function testSupports(): void + public function testSupports() { - $mockValidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockValidDocument */ + $mockValidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockValidDocument->setFilename('file.jpg'); $mockValidDocument->setMimeType('image/jpeg'); - $mockExternalValidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockExternalValidDocument */ + $mockExternalValidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockExternalValidDocument->setFilename('file.jpg'); $mockExternalValidDocument->setMimeType('image/jpeg'); $mockExternalValidDocument->setEmbedId('xxxxx'); $mockExternalValidDocument->setEmbedPlatform('getty'); - $mockInvalidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockInvalidDocument */ + $mockInvalidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockInvalidDocument->setFilename('file.psd'); $mockInvalidDocument->setMimeType('image/vnd.adobe.photoshop'); - $renderer = $this->getRenderer(); - - $this->assertIsString($mockValidDocument->getMimeType()); - $this->assertEquals( - 'image/jpeg', - $mockValidDocument->getMimeType() - ); - $this->assertTrue($renderer->supports($mockValidDocument, [])); - $this->assertTrue($renderer->supports($mockValidDocument, ['embed' => true])); - $this->assertTrue($renderer->supports($mockExternalValidDocument, ['embed' => true])); - $this->assertFalse($renderer->supports($mockValidDocument, ['picture' => true])); - $this->assertEquals( - 'image/vnd.adobe.photoshop', - $mockInvalidDocument->getMimeType() - ); - $this->assertFalse($renderer->supports($mockInvalidDocument, [])); + $this + ->given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getEmbedFinderFactory(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($mockValidDocument->getMimeType()) + ->isEqualTo('image/jpeg') + ->boolean($renderer->supports($mockValidDocument, [])) + ->isEqualTo(true) + ->boolean($renderer->supports($mockValidDocument, ['embed' => true])) + ->isEqualTo(true) + ->boolean($renderer->supports($mockExternalValidDocument, ['embed' => true])) + ->isEqualTo(true) + ->boolean($renderer->supports($mockValidDocument, ['picture' => true])) + ->isEqualTo(false) + ->string($mockInvalidDocument->getMimeType()) + ->isEqualTo('image/vnd.adobe.photoshop') + ->boolean($renderer->supports($mockInvalidDocument, [])) + ->isEqualTo(false); } - public function testRender(): void + public function testRender() { - $mockDocument = new SimpleDocument(); + /** @var DocumentInterface $mockDocument */ + $mockDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockDocument->setFilename('file.jpg'); $mockDocument->setFolder('folder'); $mockDocument->setMimeType('image/jpeg'); - $renderer = $this->getRenderer(); - - $this->assertHtmlTidyEquals( - <<given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getEmbedFinderFactory(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($this->htmlTidy($renderer->render($mockDocument, ['noProcess' => true]))) + ->isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, ['noProcess' => true]) - ); - - $this->assertHtmlTidyEquals( - <<string($this->htmlTidy($renderer->render($mockDocument, ['absolute' => true, 'noProcess' => true]))) + ->isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, ['absolute' => true, 'noProcess' => true]) - ); - - $this->assertHtmlTidyEquals( - <<string($this->htmlTidy($renderer->render($mockDocument, [ + 'width' => 300, + 'absolute' => true + ]))) + ->isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, [ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, + 'class' => 'awesome-image responsive', 'absolute' => true - ]) - ); - - $this->assertHtmlTidyEquals( - <<isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, [ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, - 'class' => 'awesome-image responsive', - 'absolute' => true - ]) - ); - - $this->assertHtmlTidyEquals( - << true + ]))) + ->contains('noscript') + ->isEqualTo($this->htmlTidy(<< src="/assets/w300-q90/folder/file.jpg" width="300" /> -EOT, - $renderer->render($mockDocument, [ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, - 'lazyload' => true - ]) - ); - - $this->assertHtmlTidyEquals( - << true, + 'fallback' => 'https://test.test/fallback.png' + ]))) + ->contains('noscript') + ->isEqualTo($this->htmlTidy(<< src="/assets/w300-q90/folder/file.jpg" width="300" /> -EOT, - $renderer->render($mockDocument, [ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, - 'lazyload' => true, 'fallback' => 'https://test.test/fallback.png' - ]) - ); - - $this->assertHtmlTidyEquals( - <<isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, [ - 'width' => 300, - 'fallback' => 'https://test.test/fallback.png' - ]) - ); - - $this->assertHtmlTidyEquals( - <<string($this->htmlTidy($renderer->render($mockDocument, [ + 'fit' => '600x400', + 'quality' => 70 + ]))) + ->isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, [ - 'fit' => '600x400', - 'quality' => 70 - ]) - ); - - $this->assertHtmlTidyEquals( - <<string($this->htmlTidy($renderer->render($mockDocument, [ + 'width' => 300, + 'lazyload' => true, + 'class' => 'awesome-image responsive', + ]))) + ->contains('noscript') + ->isEqualTo($this->htmlTidy(<< width="300" class="awesome-image responsive" /> -EOT, - $renderer->render($mockDocument, [ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, - 'lazyload' => true, - 'class' => 'awesome-image responsive', - ]) - ); - - $this->assertHtmlTidyEquals( - << [[ + 'format' => [ + 'width' => 300 + ], + 'rule' => '1x' + ],[ + 'format' => [ + 'width' => 600 + ], + 'rule' => '2x' + ]] + ]))) + ->isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, [ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, 'srcset' => [[ 'format' => [ @@ -205,27 +221,29 @@ class="awesome-image responsive" /> 'width' => 600 ], 'rule' => '2x' - ]] - ]) - ); - - $this->assertHtmlTidyEquals( - << [ + '(max-width: 767px) 300px', + '(min-width: 768px) 400px' + ] + ]))) + ->isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, [ - 'width' => 300, +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ + 'fit' => '600x400', 'srcset' => [[ 'format' => [ - 'width' => 300 + 'fit' => '600x400', ], 'rule' => '1x' ],[ 'format' => [ - 'width' => 600 + 'fit' => '1200x800', ], 'rule' => '2x' ]], @@ -233,19 +251,19 @@ class="awesome-image responsive" /> '(max-width: 767px) 300px', '(min-width: 768px) 400px' ] - ]) - ); - - $this->assertHtmlTidyEquals( - <<isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, [ +EOT + )) + + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', + 'loading' => 'lazy', 'srcset' => [[ 'format' => [ 'fit' => '600x400', @@ -261,21 +279,19 @@ class="awesome-image responsive" /> '(max-width: 767px) 300px', '(min-width: 768px) 400px' ] - ]) - ); - - $this->assertHtmlTidyEquals( - <<isEqualTo($this->htmlTidy(<< -EOT, - $renderer->render($mockDocument, [ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', - 'loading' => 'lazy', + 'lazyload' => true, 'srcset' => [[ 'format' => [ 'fit' => '600x400', @@ -291,11 +307,9 @@ class="awesome-image responsive" /> '(max-width: 767px) 300px', '(min-width: 768px) 400px' ] - ]) - ); - - $this->assertHtmlTidyEquals( - <<contains('noscript') + ->isEqualTo($this->htmlTidy(<< sizes="(max-width: 767px) 300px, (min-width: 768px) 400px" data-ratio="1.5" /> -EOT, - $renderer->render($mockDocument, [ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', 'lazyload' => true, + 'loading' => 'lazy', 'srcset' => [[ 'format' => [ 'fit' => '600x400', @@ -329,11 +345,9 @@ class="lazyload" /> '(max-width: 767px) 300px', '(min-width: 768px) 400px' ] - ]) - ); - - $this->assertHtmlTidyEquals( - <<contains('noscript') + ->isEqualTo($this->htmlTidy(<< loading="lazy" data-ratio="1.5" /> -EOT, - $renderer->render($mockDocument, [ - 'fit' => '600x400', - 'lazyload' => true, - 'loading' => 'lazy', - 'srcset' => [[ - 'format' => [ - 'fit' => '600x400', - ], - 'rule' => '1x' - ],[ - 'format' => [ - 'fit' => '1200x800', - ], - 'rule' => '2x' - ]], - 'sizes' => [ - '(max-width: 767px) 300px', - '(min-width: 768px) 400px' - ] - ]) - ); +EOT + )) + ; + } + + /** + * @return \RZ\Roadiz\Documents\UrlGenerators\DocumentUrlGeneratorInterface + */ + private function getUrlGenerator(): DocumentUrlGeneratorInterface + { + return new \mock\RZ\Roadiz\Documents\UrlGenerators\DummyDocumentUrlGenerator(); + } + + private function getFilesystemOperator(): FilesystemOperator + { + return new MountManager([ + 'public' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ), + 'private' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ) + ]); + } + + private function htmlTidy(string $body): string + { + $body = preg_replace('#[\n\r\s]{2,}#', ' ', $body); + $body = str_replace("/", '/', $body); + $body = html_entity_decode($body); + return preg_replace('#\>[\n\r\s]+\<#', '><', $body); + } + + private function getEnvironment(): Environment + { + $loader = new FilesystemLoader([ + dirname(__DIR__) . '/../../../src/Resources/views' + ]); + return new Environment($loader, [ + 'autoescape' => false, + 'debug' => true + ]); + } + + /** + * @return \RZ\Roadiz\Documents\MediaFinders\EmbedFinderFactory + */ + private function getEmbedFinderFactory(): EmbedFinderFactory + { + return new EmbedFinderFactory([ + 'youtube' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractYoutubeEmbedFinder::class, + 'vimeo' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractVimeoEmbedFinder::class, + 'dailymotion' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractDailymotionEmbedFinder::class, + 'soundcloud' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractSoundcloudEmbedFinder::class, + ]); } } diff --git a/tests/Roadiz/Document/Renderer/InlineSvgRenderer.php b/tests/Roadiz/Document/Renderer/InlineSvgRenderer.php new file mode 100644 index 0000000..0eb6178 --- /dev/null +++ b/tests/Roadiz/Document/Renderer/InlineSvgRenderer.php @@ -0,0 +1,100 @@ +setFilename('file.svg'); + $mockValidDocument->setMimeType('image/svg'); + + $mockInvalidDocument->setFilename('file.jpg'); + $mockInvalidDocument->setMimeType('image/jpeg'); + + $this + ->given($renderer = $this->newTestedInstance($this->getFilesystemOperator())) + ->then + ->string($mockValidDocument->getMimeType()) + ->isEqualTo('image/svg') + ->boolean($renderer->supports($mockValidDocument, ['inline' => false])) + ->isEqualTo(false) + ->boolean($renderer->supports($mockValidDocument, ['inline' => true])) + ->isEqualTo(true) + ->string($mockInvalidDocument->getMimeType()) + ->isEqualTo('image/jpeg') + ->boolean($renderer->supports($mockInvalidDocument, [])) + ->isEqualTo(false); + } + + public function testRender() + { + /** @var DocumentInterface $mockDocument */ + $mockDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + + $mockDocument->setFilename('file.svg'); + $mockDocument->setFolder('folder'); + $mockDocument->setMimeType('image/svg'); + + $this + ->given($renderer = $this->newTestedInstance($this->getFilesystemOperator())) + ->then + ->string($mockDocument->getMimeType()) + ->isEqualTo('image/svg') + ->string($renderer->render($mockDocument, ['inline' => true])) + ->isEqualTo($this->htmlTidy(<< + + +EOT +)); + } + + private function htmlTidy(string $body): string + { + return preg_replace('#\>[\n\r\s]+\<#', '><', $body); + } + + private function getFilesystemOperator(): FilesystemOperator + { + return new MountManager([ + 'public' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ), + 'private' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ) + ]); + } +} diff --git a/tests/Roadiz/Document/Renderer/PdfRenderer.php b/tests/Roadiz/Document/Renderer/PdfRenderer.php new file mode 100644 index 0000000..14f4247 --- /dev/null +++ b/tests/Roadiz/Document/Renderer/PdfRenderer.php @@ -0,0 +1,129 @@ +setFilename('file.pdf'); + $mockValidDocument->setMimeType('application/pdf'); + + /** @var DocumentInterface $mockInvalidDocument */ + $mockInvalidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockInvalidDocument->setFilename('file.jpg'); + $mockInvalidDocument->setMimeType('image/jpeg'); + + $this + ->given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($mockValidDocument->getMimeType()) + ->isEqualTo('application/pdf') + ->boolean($renderer->supports($mockValidDocument, [ + 'embed' => true + ])) + ->isEqualTo(true) + ->string($mockInvalidDocument->getMimeType()) + ->isEqualTo('image/jpeg') + ->boolean($renderer->supports($mockInvalidDocument, [])) + ->isEqualTo(false); + } + + public function testRender() + { + /** @var DocumentInterface $mockDocument */ + $mockDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockDocument->setFilename('file.pdf'); + $mockDocument->setFolder('folder'); + $mockDocument->setMimeType('application/pdf'); + + $this + ->given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($mockDocument->getMimeType()) + ->isEqualTo('application/pdf') + ->string($this->htmlTidy($renderer->render($mockDocument, [ + 'embed' => true + ]))) + ->isEqualTo($this->htmlTidy( + '

Your browser does not support PDF native viewer.

' + )); + } + + /** + * @return DocumentUrlGeneratorInterface + */ + private function getUrlGenerator(): DocumentUrlGeneratorInterface + { + return new \mock\RZ\Roadiz\Documents\UrlGenerators\DummyDocumentUrlGenerator(); + } + + private function getFilesystemOperator(): FilesystemOperator + { + return new MountManager([ + 'public' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ), + 'private' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ) + ]); + } + + private function getEnvironment(): Environment + { + $loader = new FilesystemLoader([ + dirname(__DIR__) . '/../../../src/Resources/views' + ]); + return new Environment($loader, [ + 'autoescape' => false + ]); + } + + private function htmlTidy(string $body): string + { + $body = preg_replace('#[\n\r\s]{2,}#', ' ', $body); + $body = str_replace("/", '/', $body); + $body = html_entity_decode($body); + return preg_replace('#\>[\n\r\s]+\<#', '><', $body); + } +} diff --git a/tests/Renderer/PictureRendererTest.php b/tests/Roadiz/Document/Renderer/PictureRenderer.php similarity index 70% rename from tests/Renderer/PictureRendererTest.php rename to tests/Roadiz/Document/Renderer/PictureRenderer.php index 829ce0e..dd1ff0d 100644 --- a/tests/Renderer/PictureRendererTest.php +++ b/tests/Roadiz/Document/Renderer/PictureRenderer.php @@ -1,226 +1,222 @@ getFilesystemOperator(), - $this->getEmbedFinderFactory(), - $this->getEnvironment(), - $this->getUrlGenerator() - ); - } - - public function testIsEmbeddable(): void + public function testIsEmbeddable() { - $mockExternalValidDocument = new SimpleDocument(); + /** @var \RZ\Roadiz\Documents\Models\DocumentInterface $mockExternalValidDocument */ + $mockExternalValidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockExternalValidDocument->setFilename('file.jpg'); $mockExternalValidDocument->setMimeType('image/jpeg'); $mockExternalValidDocument->setEmbedId('xxxxx'); $mockExternalValidDocument->setEmbedPlatform('getty'); - $mockYoutubeDocument = new SimpleDocument(); + /** @var DocumentInterface $mockYoutubeDocument */ + $mockYoutubeDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockYoutubeDocument->setFilename('file.jpg'); $mockYoutubeDocument->setMimeType('image/jpeg'); $mockYoutubeDocument->setEmbedId('xxxxx'); $mockYoutubeDocument->setEmbedPlatform('youtube'); - $mockValidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockValidDocument */ + $mockValidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockValidDocument->setFilename('file.jpg'); $mockValidDocument->setMimeType('image/jpeg'); - $renderer = $this->getRenderer(); - - $this->assertFalse( - $renderer->isEmbeddable($mockExternalValidDocument, ['embed' => true]) - ); - $this->assertFalse( - $renderer->isEmbeddable($mockValidDocument, ['embed' => true]) - ); - $this->assertFalse( - $renderer->isEmbeddable($mockValidDocument, []) - ); - $this->assertFalse( - $renderer->isEmbeddable($mockYoutubeDocument, []) - ); - $this->assertTrue( - $renderer->isEmbeddable($mockYoutubeDocument, ['embed' => true]) - ); + $this + ->given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getEmbedFinderFactory(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->boolean($renderer->isEmbeddable($mockExternalValidDocument, ['embed' => true])) + ->isEqualTo(false) + ->boolean($renderer->isEmbeddable($mockValidDocument, ['embed' => true])) + ->isEqualTo(false) + ->boolean($renderer->isEmbeddable($mockValidDocument, [])) + ->isEqualTo(false) + ->boolean($renderer->isEmbeddable($mockYoutubeDocument, [])) + ->isEqualTo(false) + ->boolean($renderer->isEmbeddable($mockYoutubeDocument, ['embed' => true])) + ->isEqualTo(true) + ; } - public function testSupports(): void + public function testSupports() { - $mockValidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockValidDocument */ + $mockValidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockValidDocument->setFilename('file.jpg'); $mockValidDocument->setMimeType('image/jpeg'); - $mockInvalidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockInvalidDocument */ + $mockInvalidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockInvalidDocument->setFilename('file.psd'); $mockInvalidDocument->setMimeType('image/vnd.adobe.photoshop'); - $mockExternalValidDocument = new SimpleDocument(); + /** @var DocumentInterface $mockExternalValidDocument */ + $mockExternalValidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockExternalValidDocument->setFilename('file.jpg'); $mockExternalValidDocument->setMimeType('image/jpeg'); $mockExternalValidDocument->setEmbedId('xxxxx'); $mockExternalValidDocument->setEmbedPlatform('getty'); - $renderer = $this->getRenderer(); - - $this->assertEquals( - 'image/jpeg', - $mockValidDocument->getMimeType() - ); - $this->assertFalse( - $renderer->supports($mockValidDocument, []) - ); - $this->assertTrue( - $renderer->supports($mockValidDocument, ['picture' => true]) - ); - $this->assertFalse( - $renderer->isEmbeddable($mockExternalValidDocument, ['picture' => true, 'embed' => true]) - ); - $this->assertTrue( - $mockExternalValidDocument->isImage() - ); - $this->assertTrue( - $renderer->supports($mockExternalValidDocument, ['picture' => true, 'embed' => true]) - ); - $this->assertTrue( - $renderer->supports($mockValidDocument, [ + $this + ->given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getEmbedFinderFactory(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($mockValidDocument->getMimeType()) + ->isEqualTo('image/jpeg') + ->boolean($renderer->supports($mockValidDocument, [])) + ->isEqualTo(false) + ->boolean($renderer->supports($mockValidDocument, ['picture' => true])) + ->isEqualTo(true) + ->boolean($renderer->isEmbeddable($mockExternalValidDocument, ['picture' => true, 'embed' => true])) + ->isEqualTo(false) + ->boolean($mockExternalValidDocument->isImage()) + ->isEqualTo(true) + ->boolean($renderer->supports($mockExternalValidDocument, ['picture' => true, 'embed' => true])) + ->isEqualTo(true) + ->boolean($renderer->supports($mockValidDocument, [ 'picture' => true, 'embed' => true, - ]) - ); - $this->assertEquals( - 'image/vnd.adobe.photoshop', - $mockInvalidDocument->getMimeType() - ); - $this->assertFalse( - $renderer->supports($mockInvalidDocument, []) - ); + ])) + ->isEqualTo(true) + ->string($mockInvalidDocument->getMimeType()) + ->isEqualTo('image/vnd.adobe.photoshop') + ->boolean($renderer->supports($mockInvalidDocument, [])) + ->isEqualTo(false); } - public function testRender(): void + public function testRender() { - $mockDocument = new SimpleDocument(); + /** @var DocumentInterface $mockDocument */ + $mockDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockDocument->setFilename('file.jpg'); $mockDocument->setFolder('folder'); $mockDocument->setMimeType('image/jpeg'); - $mockWebpDocument = new SimpleDocument(); + /** @var DocumentInterface $mockWebpDocument */ + $mockWebpDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); $mockWebpDocument->setFilename('file.webp'); $mockWebpDocument->setFolder('folder'); $mockWebpDocument->setMimeType('image/webp'); - $renderer = $this->getRenderer(); - - $this->assertHtmlTidyEquals( - <<given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getEmbedFinderFactory(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($this->htmlTidy($renderer->render($mockDocument, [ + 'noProcess' => true, + 'picture' => true + ]))) + ->isEqualTo($this->htmlTidy(<< file.jpg EOT - , - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'noProcess' => true, - 'picture' => true - ]) - ); - - $this->assertHtmlTidyEquals( - << true, + 'loading' => 'lazy', + ]))) + ->isEqualTo($this->htmlTidy(<< file.jpg EOT - , - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockWebpDocument, [ 'noProcess' => true, - 'picture' => true, - 'loading' => 'lazy', - ]) - ); - - $this->assertHtmlTidyEquals( - << true + ]))) + ->isEqualTo($this->htmlTidy(<< file.webp EOT - , - $renderer->render($mockWebpDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ + 'absolute' => true, 'noProcess' => true, 'picture' => true - ]) - ); - - $this->assertHtmlTidyEquals( - <<isEqualTo($this->htmlTidy(<< file.jpg EOT - , - $renderer->render($mockDocument, [ - 'absolute' => true, - 'noProcess' => true, - 'picture' => true - ]) - ); - - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, 'absolute' => true, 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< file.jpg EOT - ); - - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, 'class' => 'awesome-image responsive', 'absolute' => true, 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< file.jpg EOT - ); - - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, 'lazyload' => true, 'picture' => true - ]), - <<endWith('') + ->isEqualTo($this->htmlTidy(<< EOT - ); - - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, 'lazyload' => true, 'picture' => true, 'fallback' => 'https://test.test/fallback.png' - ]), - <<endWith('') + ->isEqualTo($this->htmlTidy(<< @@ -275,14 +270,13 @@ class="lazyload" /> EOT - ); - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, 'fallback' => 'https://test.test/fallback.png', 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< @@ -291,15 +285,15 @@ class="lazyload" /> width="300" /> EOT - ); - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, 'lazyload' => true, 'class' => 'awesome-image responsive', 'picture' => true - ]), - <<endWith('') + ->isEqualTo($this->htmlTidy(<< EOT - ); - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, 'srcset' => [[ 'format' => [ 'width' => 300 ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'width' => 600 ], 'rule' => '2x' ]], 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< @@ -355,16 +348,15 @@ class="awesome-image responsive" /> width="300" /> EOT - ); - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'width' => 300, 'srcset' => [[ 'format' => [ 'width' => 300 ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'width' => 600 ], @@ -375,8 +367,8 @@ class="awesome-image responsive" /> '(min-width: 768px) 400px' ], 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< sizes="(max-width: 767px) 300px, (min-width: 768px) 400px" /> EOT - ); - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', 'srcset' => [[ 'format' => [ 'fit' => '600x400', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '1200x800', ], @@ -410,8 +401,8 @@ class="awesome-image responsive" /> '(min-width: 768px) 400px' ], 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< data-ratio="1.5" /> EOT - ); + )) - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', 'loading' => 'lazy', 'srcset' => [[ @@ -437,7 +427,7 @@ class="awesome-image responsive" /> 'fit' => '600x400', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '1200x800', ], @@ -448,8 +438,8 @@ class="awesome-image responsive" /> '(min-width: 768px) 400px' ], 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< data-ratio="1.5" /> EOT - ); - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', 'lazyload' => true, 'srcset' => [[ @@ -475,15 +464,16 @@ class="awesome-image responsive" /> 'fit' => '600x400', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '2x' ]], 'picture' => true - ]), - <<endWith('') + ->isEqualTo($this->htmlTidy(<< EOT - ); - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', 'lazyload' => true, 'fallback' => 'https://test.test/fallback.png', @@ -526,15 +515,16 @@ class="lazyload" /> 'fit' => '600x400', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '2x' ]], 'picture' => true - ]), - <<endWith('') + ->isEqualTo($this->htmlTidy(<< EOT - ); - - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', 'media' => [[ 'srcset' => [[ @@ -577,7 +565,7 @@ class="lazyload" /> 'fit' => '600x400', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '1200x800', ], @@ -586,8 +574,8 @@ class="lazyload" /> 'rule' => '(min-width: 600px)' ]], 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< height="400" /> EOT - ); - - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', 'media' => [[ 'srcset' => [[ @@ -613,20 +599,20 @@ class="lazyload" /> 'fit' => '600x400', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '2x' ]], 'rule' => '(min-width: 600px)' - ], [ + ],[ 'srcset' => [[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '2400x1600', ], @@ -635,8 +621,8 @@ class="lazyload" /> 'rule' => '(min-width: 1200px)' ]], 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< height="400" /> EOT - ); - - $this->assertHtmlTidyEquals( - $renderer->render($mockDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ 'fit' => '600x400', 'loading' => 'lazy', 'media' => [[ @@ -671,20 +655,20 @@ class="lazyload" /> 'fit' => '600x400', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '2x' ]], 'rule' => '(min-width: 600px)' - ], [ + ],[ 'srcset' => [[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '2400x1600', ], @@ -693,8 +677,8 @@ class="lazyload" /> 'rule' => '(min-width: 1200px)' ]], 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< height="400" /> EOT - ); - $this->assertHtmlTidyEquals( - $renderer->render($mockWebpDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockWebpDocument, [ 'fit' => '600x400', 'lazyload' => true, 'fallback' => 'FALLBACK', @@ -730,20 +713,20 @@ class="lazyload" /> 'fit' => '600x400', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '2x' ]], 'rule' => '(min-width: 600px)' - ], [ + ],[ 'srcset' => [[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '2400x1600', ], @@ -752,8 +735,8 @@ class="lazyload" /> 'rule' => '(min-width: 1200px)' ]], 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< EOT - ); - $this->assertHtmlTidyEquals( - $renderer->render($mockWebpDocument, [ + )) + ->string($this->htmlTidy($renderer->render($mockWebpDocument, [ 'fit' => '600x400', 'lazyload' => true, 'loading' => 'lazy', @@ -804,20 +786,20 @@ class="lazyload" /> 'fit' => '600x400', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '2x' ]], 'rule' => '(min-width: 600px)' - ], [ + ],[ 'srcset' => [[ 'format' => [ 'fit' => '1200x800', ], 'rule' => '1x' - ], [ + ],[ 'format' => [ 'fit' => '2400x1600', ], @@ -826,8 +808,8 @@ class="lazyload" /> 'rule' => '(min-width: 1200px)' ]], 'picture' => true - ]), - <<isEqualTo($this->htmlTidy(<< EOT - ); + )) + ; + } + + /** + * @return \RZ\Roadiz\Documents\UrlGenerators\DocumentUrlGeneratorInterface + */ + private function getUrlGenerator(): DocumentUrlGeneratorInterface + { + return new \mock\RZ\Roadiz\Documents\UrlGenerators\DummyDocumentUrlGenerator(); + } + + private function getFilesystemOperator(): FilesystemOperator + { + return new MountManager([ + 'public' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ), + 'private' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ) + ]); + } + + private function htmlTidy(string $body): string + { + $body = preg_replace('#[\n\r\s]{2,}#', ' ', $body); + $body = str_replace("/", '/', $body); + $body = html_entity_decode($body); + return preg_replace('#\>[\n\r\s]+\<#', '><', $body); + } + + private function getEnvironment(): Environment + { + $loader = new FilesystemLoader([ + dirname(__DIR__) . '/../../../src/Resources/views' + ]); + return new Environment($loader, [ + 'autoescape' => false, + 'debug' => true + ]); + } + + /** + * @return \RZ\Roadiz\Documents\MediaFinders\EmbedFinderFactory + */ + private function getEmbedFinderFactory(): EmbedFinderFactory + { + return new EmbedFinderFactory([ + 'youtube' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractYoutubeEmbedFinder::class, + 'vimeo' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractVimeoEmbedFinder::class, + 'dailymotion' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractDailymotionEmbedFinder::class, + 'soundcloud' => \mock\RZ\Roadiz\Documents\MediaFinders\AbstractSoundcloudEmbedFinder::class, + ]); } } diff --git a/tests/Roadiz/Document/Renderer/SvgRenderer.php b/tests/Roadiz/Document/Renderer/SvgRenderer.php new file mode 100644 index 0000000..6871d90 --- /dev/null +++ b/tests/Roadiz/Document/Renderer/SvgRenderer.php @@ -0,0 +1,95 @@ +setFilename('file.svg'); + $mockValidDocument->setMimeType('image/svg+xml'); + + $mockInvalidDocument->setFilename('file.jpg'); + $mockInvalidDocument->setMimeType('image/jpeg'); + + $this + ->given($renderer = $this->newTestedInstance($this->getFilesystemOperator())) + ->then + ->string($mockValidDocument->getMimeType()) + ->isEqualTo('image/svg+xml') + ->boolean($renderer->supports($mockValidDocument, [])) + ->isEqualTo(true) + ->boolean($renderer->supports($mockValidDocument, ['inline' => false])) + ->isEqualTo(true) + ->boolean($renderer->supports($mockValidDocument, ['inline' => true])) + ->isEqualTo(false) + ->string($mockInvalidDocument->getMimeType()) + ->isEqualTo('image/jpeg') + ->boolean($renderer->supports($mockInvalidDocument, [])) + ->isEqualTo(false); + } + + public function testRender() + { + /** @var DocumentInterface $mockDocument */ + $mockDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + + $mockDocument->setFilename('file2.svg'); + $mockDocument->setFolder('folder'); + $mockDocument->setMimeType('image/svg+xml'); + + $this + ->given($renderer = $this->newTestedInstance($this->getFilesystemOperator())) + ->then + ->string($mockDocument->getMimeType()) + ->isEqualTo('image/svg+xml') + ->string($renderer->render($mockDocument, [])) + ->isEqualTo(<< +EOT +); + } + + private function getFilesystemOperator(): FilesystemOperator + { + return new MountManager([ + 'public' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ), + 'private' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ) + ]); + } +} diff --git a/tests/Roadiz/Document/Renderer/VideoRenderer.php b/tests/Roadiz/Document/Renderer/VideoRenderer.php new file mode 100644 index 0000000..a514976 --- /dev/null +++ b/tests/Roadiz/Document/Renderer/VideoRenderer.php @@ -0,0 +1,216 @@ +setFilename('file.mp4'); + $mockValidDocument->setMimeType('video/mp4'); + + /** @var DocumentInterface $mockInvalidDocument */ + $mockInvalidDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockInvalidDocument->setFilename('file.jpg'); + $mockInvalidDocument->setMimeType('image/jpeg'); + + $this + ->given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getDocumentFinder(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($mockValidDocument->getMimeType()) + ->isEqualTo('video/mp4') + ->boolean($renderer->supports($mockValidDocument, [])) + ->isEqualTo(true) + ->string($mockInvalidDocument->getMimeType()) + ->isEqualTo('image/jpeg') + ->boolean($renderer->supports($mockInvalidDocument, [])) + ->isEqualTo(false); + } + + public function testRender() + { + /** @var DocumentInterface $mockDocument */ + $mockDocument = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockDocument->setFilename('file.mp4'); + $mockDocument->setFolder('folder'); + $mockDocument->setMimeType('video/mp4'); + + /** @var DocumentInterface $mockDocument2 */ + $mockDocument2 = new \mock\RZ\Roadiz\Documents\Models\SimpleDocument(); + $mockDocument2->setFilename('file2.ogg'); + $mockDocument2->setFolder('folder'); + $mockDocument2->setMimeType('video/ogg'); + + $this + ->given($renderer = $this->newTestedInstance( + $this->getFilesystemOperator(), + $this->getDocumentFinder(), + $this->getEnvironment(), + $this->getUrlGenerator() + )) + ->then + ->string($mockDocument->getMimeType()) + ->isEqualTo('video/mp4') + ->string($this->htmlTidy($renderer->render($mockDocument, []))) + ->isEqualTo($this->htmlTidy(<< + + +

Your browser does not support native video.

+ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument2, []))) + ->isEqualTo($this->htmlTidy(<< + +

Your browser does not support native video.

+ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ + 'controls' => true, + 'loop' => true, + 'autoplay' => true, + ]))) + ->isEqualTo($this->htmlTidy(<< + + +

Your browser does not support native video.

+ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ + 'controls' => true, + 'loop' => true, + 'autoplay' => true, + 'muted' => true, + ]))) + ->isEqualTo($this->htmlTidy(<< + + +

Your browser does not support native video.

+ +EOT + )) + ->string($this->htmlTidy($renderer->render($mockDocument, [ + 'controls' => false + ]))) + ->isEqualTo($this->htmlTidy(<< + + +

Your browser does not support native video.

+ +EOT + )) + ; + } + + /** + * @return DocumentFinderInterface + */ + private function getDocumentFinder(): DocumentFinderInterface + { + $finder = new ArrayDocumentFinder(); + + $finder->addDocument( + (new \mock\RZ\Roadiz\Documents\Models\SimpleDocument()) + ->setFilename('file.mp4') + ->setFolder('folder') + ->setMimeType('video/mp4') + ); + $finder->addDocument( + (new \mock\RZ\Roadiz\Documents\Models\SimpleDocument()) + ->setFilename('file.webm') + ->setFolder('folder') + ->setMimeType('video/webm') + ); + $finder->addDocument( + (new \mock\RZ\Roadiz\Documents\Models\SimpleDocument()) + ->setFilename('file2.ogg') + ->setFolder('folder') + ->setMimeType('video/ogg') + ); + + return $finder; + } + + /** + * @return DocumentUrlGeneratorInterface + */ + private function getUrlGenerator(): DocumentUrlGeneratorInterface + { + return new \mock\RZ\Roadiz\Documents\UrlGenerators\DummyDocumentUrlGenerator(); + } + + private function getFilesystemOperator(): FilesystemOperator + { + return new MountManager([ + 'public' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ), + 'private' => new Filesystem( + new LocalFilesystemAdapter(dirname(__DIR__) . '/../../../files/'), + publicUrlGenerator: new class() implements PublicUrlGenerator + { + public function publicUrl(string $path, Config $config): string + { + return '/files/' . $path; + } + } + ) + ]); + } + + private function getEnvironment(): Environment + { + $loader = new FilesystemLoader([ + dirname(__DIR__) . '/../../../src/Resources/views' + ]); + return new Environment($loader, [ + 'autoescape' => false + ]); + } + + private function htmlTidy(string $body): string + { + $body = preg_replace('#[\n\r\s]{2,}#', ' ', $body); + $body = str_replace("/", '/', $body); + $body = html_entity_decode($body); + return preg_replace('#\>[\n\r\s]+\<#', '><', $body); + } +}