From 164116fa39d1ee02d1a5d82122897ad4a3622bab Mon Sep 17 00:00:00 2001 From: codemasher Date: Sun, 12 Dec 2021 23:40:44 +0100 Subject: [PATCH] :bath: output (+test) simplification & cleanup --- src/Output/{QRImage.php => QRGdImage.php} | 81 +++++------------- src/Output/QRImagick.php | 2 + src/Output/QRMarkup.php | 31 ++++++- src/Output/QROutputAbstract.php | 42 ++------- src/Output/QRString.php | 26 +++++- src/QRCode.php | 46 ++++------ tests/Output/QRFpdfTest.php | 46 ++-------- tests/Output/QRGdImageGIFTest.php | 22 +++++ tests/Output/QRGdImageJPGTest.php | 22 +++++ tests/Output/QRGdImagePNGTest.php | 22 +++++ ...mageTest.php => QRGdImageTestAbstract.php} | 35 ++------ tests/Output/QRImagickTest.php | 32 ++----- tests/Output/QRMarkupHTMLTest.php | 22 +++++ tests/Output/QRMarkupSVGTest.php | 22 +++++ ...arkupTest.php => QRMarkupTestAbstract.php} | 26 ++---- tests/Output/QROutputTestAbstract.php | 64 +++----------- tests/Output/QRStringJSONTest.php | 40 +++++++++ tests/Output/QRStringTEXTTest.php | 41 +++++++++ tests/Output/QRStringTest.php | 74 ---------------- tests/Output/QRStringTestAbstract.php | 22 +++++ tests/samples/custom | 45 ---------- tests/samples/fpdf | Bin 2859 -> 0 bytes tests/samples/gif | 1 - tests/samples/html | 31 ------- tests/samples/imagick | Bin 348 -> 0 bytes tests/samples/jpg | 1 - tests/samples/json | 1 - tests/samples/png | 1 - tests/samples/svg | 1 - tests/samples/text | 29 ------- 30 files changed, 354 insertions(+), 474 deletions(-) rename src/Output/{QRImage.php => QRGdImage.php} (78%) create mode 100644 tests/Output/QRGdImageGIFTest.php create mode 100644 tests/Output/QRGdImageJPGTest.php create mode 100644 tests/Output/QRGdImagePNGTest.php rename tests/Output/{QRImageTest.php => QRGdImageTestAbstract.php} (57%) create mode 100644 tests/Output/QRMarkupHTMLTest.php create mode 100644 tests/Output/QRMarkupSVGTest.php rename tests/Output/{QRMarkupTest.php => QRMarkupTestAbstract.php} (56%) create mode 100644 tests/Output/QRStringJSONTest.php create mode 100644 tests/Output/QRStringTEXTTest.php delete mode 100644 tests/Output/QRStringTest.php create mode 100644 tests/Output/QRStringTestAbstract.php delete mode 100644 tests/samples/custom delete mode 100644 tests/samples/fpdf delete mode 100644 tests/samples/gif delete mode 100644 tests/samples/html delete mode 100644 tests/samples/imagick delete mode 100644 tests/samples/jpg delete mode 100644 tests/samples/json delete mode 100644 tests/samples/png delete mode 100644 tests/samples/svg delete mode 100644 tests/samples/text diff --git a/src/Output/QRImage.php b/src/Output/QRGdImage.php similarity index 78% rename from src/Output/QRImage.php rename to src/Output/QRGdImage.php index 471a11ce9..fac2f09ca 100644 --- a/src/Output/QRImage.php +++ b/src/Output/QRGdImage.php @@ -1,6 +1,6 @@ @@ -15,11 +15,10 @@ namespace chillerlan\QRCode\Output; use chillerlan\QRCode\Data\QRMatrix; use chillerlan\QRCode\QRCode; use chillerlan\Settings\SettingsContainerInterface; -use ErrorException, Exception; - +use ErrorException, Throwable; use function array_values, count, extension_loaded, imagecolorallocate, imagecolortransparent, imagecreatetruecolor, - imagedestroy, imagefilledellipse, imagefilledrectangle, imagegif, imagejpeg, imagepng, imagescale, in_array, - is_array, ob_end_clean, ob_get_contents, ob_start, range, restore_error_handler, set_error_handler; + imagedestroy, imagefilledellipse, imagefilledrectangle, imagegif, imagejpeg, imagepng, imagescale, is_array, + max, min, ob_end_clean, ob_get_contents, ob_start, restore_error_handler, set_error_handler; use const IMG_BICUBIC; /** @@ -27,19 +26,7 @@ use const IMG_BICUBIC; * * @see http://php.net/manual/book.image.php */ -class QRImage extends QROutputAbstract{ - - /** - * GD image types that support transparency - * - * @var string[] - */ - protected const TRANSPARENCY_TYPES = [ - QRCode::OUTPUT_IMAGE_PNG, - QRCode::OUTPUT_IMAGE_GIF, - ]; - - protected string $defaultMode = QRCode::OUTPUT_IMAGE_PNG; +class QRGdImage extends QROutputAbstract{ /** * The GD image resource @@ -115,7 +102,7 @@ class QRImage extends QROutputAbstract{ /** @phan-suppress-next-line PhanParamTooFewInternalUnpack */ $background = imagecolorallocate($this->image, ...$tbg); - if($this->options->imageTransparent && in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){ + if($this->options->imageTransparent && $this->options->outputType !== QRCode::OUTPUT_IMAGE_JPG){ imagecolortransparent($this->image, $background); } @@ -188,11 +175,24 @@ class QRImage extends QROutputAbstract{ ob_start(); try{ - $this->{$this->outputMode ?? $this->defaultMode}(); + + switch($this->options->outputType){ + case QRCode::OUTPUT_IMAGE_GIF: + imagegif($this->image); + break; + case QRCode::OUTPUT_IMAGE_JPG: + imagejpeg($this->image, null, max(0, min(100, $this->options->jpegQuality))); + break; + // silently default to png output + case QRCode::OUTPUT_IMAGE_PNG: + default: + imagepng($this->image, null, max(-1, min(9, $this->options->pngCompression))); + } + } // not going to cover edge cases // @codeCoverageIgnoreStart - catch(Exception $e){ + catch(Throwable $e){ throw new QRCodeOutputException($e->getMessage()); } // @codeCoverageIgnoreEnd @@ -205,43 +205,4 @@ class QRImage extends QROutputAbstract{ return $imageData; } - /** - * PNG output - * - * @return void - */ - protected function png():void{ - imagepng( - $this->image, - null, - in_array($this->options->pngCompression, range(-1, 9), true) - ? $this->options->pngCompression - : -1 - ); - } - - /** - * Jiff - like... JitHub! - * - * @return void - */ - protected function gif():void{ - imagegif($this->image); - } - - /** - * JPG output - * - * @return void - */ - protected function jpg():void{ - imagejpeg( - $this->image, - null, - in_array($this->options->jpegQuality, range(0, 100), true) - ? $this->options->jpegQuality - : 85 - ); - } - } diff --git a/src/Output/QRImagick.php b/src/Output/QRImagick.php index 3e46ed8e1..762707774 100644 --- a/src/Output/QRImagick.php +++ b/src/Output/QRImagick.php @@ -80,6 +80,8 @@ class QRImagick extends QROutputAbstract{ $this->options->imagickFormat ); + $this->imagick->setImageType(Imagick::IMGTYPE_TRUECOLOR); + $this->drawImage(); if($this->options->returnResource){ diff --git a/src/Output/QRMarkup.php b/src/Output/QRMarkup.php index eef52bdee..dbacdfc8a 100644 --- a/src/Output/QRMarkup.php +++ b/src/Output/QRMarkup.php @@ -43,10 +43,33 @@ class QRMarkup extends QROutputAbstract{ return $isDark ? $this->options->markupDark : $this->options->markupLight; } + /** + * @inheritDoc + */ + public function dump(string $file = null){ + $file ??= $this->options->cachefile; + $saveToFile = $file !== null; + + switch($this->options->outputType){ + case QRCode::OUTPUT_MARKUP_HTML: + $data = $this->html($saveToFile); + break; + case QRCode::OUTPUT_MARKUP_SVG: + default: + $data = $this->svg($saveToFile); + } + + if($saveToFile){ + $this->saveToFile($data, $file); + } + + return $data; + } + /** * HTML output */ - protected function html(string $file = null):string{ + protected function html(bool $saveToFile):string{ $html = empty($this->options->cssClass) ? '
' @@ -66,7 +89,7 @@ class QRMarkup extends QROutputAbstract{ $html .= '
'.$this->options->eol; - if($file !== null){ + if($saveToFile){ return sprintf( 'QR Code%s', $this->options->eol.$html @@ -83,7 +106,7 @@ class QRMarkup extends QROutputAbstract{ * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg * @see https://www.sarasoueidan.com/demos/interactive-svg-coordinate-system/ */ - protected function svg(string $file = null):string{ + protected function svg(bool $saveToFile):string{ $svg = $this->svgHeader(); if(!empty($this->options->svgDefs)){ @@ -96,7 +119,7 @@ class QRMarkup extends QROutputAbstract{ $svg .= sprintf('%1$s%1$s', $this->options->eol); // transform to data URI only when not saving to file - if($file === null && $this->options->imageBase64){ + if(!$saveToFile && $this->options->imageBase64){ $svg = $this->base64encode($svg, 'image/svg+xml'); } diff --git a/src/Output/QROutputAbstract.php b/src/Output/QROutputAbstract.php index 6aa552c14..fc3fe148c 100644 --- a/src/Output/QROutputAbstract.php +++ b/src/Output/QROutputAbstract.php @@ -10,9 +10,9 @@ namespace chillerlan\QRCode\Output; -use chillerlan\QRCode\{Data\QRMatrix, QRCode}; +use chillerlan\QRCode\Data\QRMatrix; use chillerlan\Settings\SettingsContainerInterface; -use function base64_encode, dirname, file_put_contents, get_called_class, in_array, is_writable, sprintf; +use function base64_encode, dirname, file_put_contents, is_writable, sprintf; /** * common output abstract @@ -26,18 +26,6 @@ abstract class QROutputAbstract implements QROutputInterface{ */ protected int $moduleCount; - /** - * the current output mode - * - * @see \chillerlan\QRCode\QROptions::$outputType - */ - protected string $outputMode; - - /** - * the default output mode of the current output module - */ - protected string $defaultMode; - /** * the current scaling for a QR pixel * @@ -74,11 +62,6 @@ abstract class QROutputAbstract implements QROutputInterface{ $this->moduleCount = $this->matrix->size(); $this->scale = $this->options->scale; $this->length = $this->moduleCount * $this->scale; - $class = get_called_class(); - - if(isset(QRCode::OUTPUT_MODES[$class]) && in_array($this->options->outputType, QRCode::OUTPUT_MODES[$class])){ - $this->outputMode = $this->options->outputType; - } $this->setModuleValues(); } @@ -136,30 +119,15 @@ abstract class QROutputAbstract implements QROutputInterface{ * * @throws \chillerlan\QRCode\Output\QRCodeOutputException */ - protected function saveToFile(string $data, string $file):bool{ + protected function saveToFile(string $data, string $file):void{ if(!is_writable(dirname($file))){ throw new QRCodeOutputException(sprintf('Cannot write data to cache file: %s', $file)); } - return (bool)file_put_contents($file, $data); - } - - /** - * @inheritDoc - */ - public function dump(string $file = null){ - $file ??= $this->options->cachefile; - - // call the built-in output method with the optional file path as parameter - // to make the called method aware if a cache file was given - $data = $this->{$this->outputMode ?? $this->defaultMode}($file); - - if($file !== null){ - $this->saveToFile($data, $file); + if(file_put_contents($file, $data) === false){ + throw new QRCodeOutputException(sprintf('Cannot write data to cache file: %s (file_put_contents error)', $file)); } - - return $data; } } diff --git a/src/Output/QRString.php b/src/Output/QRString.php index a70c51568..35cb24028 100644 --- a/src/Output/QRString.php +++ b/src/Output/QRString.php @@ -45,10 +45,32 @@ class QRString extends QROutputAbstract{ return $isDark ? $this->options->textDark : $this->options->textLight; } + /** + * @inheritDoc + */ + public function dump(string $file = null):string{ + $file ??= $this->options->cachefile; + + switch($this->options->outputType){ + case QRCode::OUTPUT_STRING_TEXT: + $data = $this->text(); + break; + case QRCode::OUTPUT_STRING_JSON: + default: + $data = $this->json(); + } + + if($file !== null){ + $this->saveToFile($data, $file); + } + + return $data; + } + /** * string output */ - protected function text(string $file = null):string{ + protected function text():string{ $str = []; foreach($this->matrix->matrix() as $row){ @@ -67,7 +89,7 @@ class QRString extends QROutputAbstract{ /** * JSON output */ - protected function json(string $file = null):string{ + protected function json():string{ return json_encode($this->matrix->matrix()); } diff --git a/src/QRCode.php b/src/QRCode.php index 9101969c8..75f1f6fc8 100755 --- a/src/QRCode.php +++ b/src/QRCode.php @@ -11,9 +11,9 @@ namespace chillerlan\QRCode; use chillerlan\QRCode\Common\{EccLevel, ECICharset, MaskPattern, Mode}; -use chillerlan\QRCode\Data\{AlphaNum, Byte, ECI, Kanji, Number, QRData, QRCodeDataException, QRDataModeInterface, QRMatrix}; +use chillerlan\QRCode\Data\{AlphaNum, Byte, ECI, Kanji, Number, QRCodeDataException, QRData, QRDataModeInterface, QRMatrix}; use chillerlan\QRCode\Decoder\{Decoder, DecoderResult, LuminanceSourceInterface}; -use chillerlan\QRCode\Output\{QRCodeOutputException, QRFpdf, QRImage, QRImagick, QRMarkup, QROutputInterface, QRString}; +use chillerlan\QRCode\Output\{QRCodeOutputException, QRFpdf, QRGdImage, QRImagick, QRMarkup, QROutputInterface, QRString}; use chillerlan\Settings\SettingsContainerInterface; use function class_exists, class_implements, in_array, mb_convert_encoding, mb_detect_encoding; @@ -68,30 +68,20 @@ class QRCode{ public const OUTPUT_CUSTOM = 'custom'; /** - * Map of built-in output modules => capabilities + * Map of built-in output modes => modules * - * @var string[][] + * @var string[] */ public const OUTPUT_MODES = [ - QRMarkup::class => [ - self::OUTPUT_MARKUP_SVG, - self::OUTPUT_MARKUP_HTML, - ], - QRImage::class => [ - self::OUTPUT_IMAGE_PNG, - self::OUTPUT_IMAGE_GIF, - self::OUTPUT_IMAGE_JPG, - ], - QRString::class => [ - self::OUTPUT_STRING_JSON, - self::OUTPUT_STRING_TEXT, - ], - QRImagick::class => [ - self::OUTPUT_IMAGICK, - ], - QRFpdf::class => [ - self::OUTPUT_FPDF, - ], + self::OUTPUT_MARKUP_SVG => QRMarkup::class, + self::OUTPUT_MARKUP_HTML => QRMarkup::class, + self::OUTPUT_IMAGE_PNG => QRGdImage::class, + self::OUTPUT_IMAGE_GIF => QRGdImage::class, + self::OUTPUT_IMAGE_JPG => QRGdImage::class, + self::OUTPUT_STRING_JSON => QRString::class, + self::OUTPUT_STRING_TEXT => QRString::class, + self::OUTPUT_IMAGICK => QRImagick::class, + self::OUTPUT_FPDF => QRFpdf::class, ]; /** @@ -135,9 +125,7 @@ class QRCode{ break; } - } - } return $this->initOutputInterface()->dump($file); @@ -189,12 +177,10 @@ class QRCode{ return $this->initCustomOutputInterface(); } - foreach($this::OUTPUT_MODES as $outputInterface => $modes){ - - if(in_array($this->options->outputType, $modes)){ - return new $outputInterface($this->options, $this->getMatrix()); - } + $outputInterface = $this::OUTPUT_MODES[$this->options->outputType] ?? false; + if($outputInterface){ + return new $outputInterface($this->options, $this->getMatrix()); } throw new QRCodeOutputException('invalid output type'); diff --git a/tests/Output/QRFpdfTest.php b/tests/Output/QRFpdfTest.php index b0fbdba63..6248406b3 100644 --- a/tests/Output/QRFpdfTest.php +++ b/tests/Output/QRFpdfTest.php @@ -11,45 +11,32 @@ namespace chillerlan\QRCodeTest\Output; use FPDF; -use chillerlan\QRCode\{QRCode, QROptions}; +use chillerlan\QRCode\QRCode; use chillerlan\QRCode\Data\QRMatrix; -use chillerlan\QRCode\Output\{QRFpdf, QROutputInterface}; +use chillerlan\QRCode\Output\QRFpdf; -use function class_exists, substr; +use function class_exists; /** * Tests the QRFpdf output module */ final class QRFpdfTest extends QROutputTestAbstract{ + protected string $FQN = QRFpdf::class; + protected string $type = QRCode::OUTPUT_FPDF; + /** * @inheritDoc */ protected function setUp():void{ if(!class_exists(FPDF::class)){ - $this->markTestSkipped('FPDF not available'); + $this::markTestSkipped('FPDF not available'); } parent::setUp(); } - /** - * @inheritDoc - */ - protected function getOutputInterface(QROptions $options):QROutputInterface{ - return new QRFpdf($options, $this->matrix); - } - - /** - * @inheritDoc - */ - public function types():array{ - return [ - 'fpdf' => [QRCode::OUTPUT_FPDF], - ]; - } - /** * @inheritDoc */ @@ -61,30 +48,15 @@ final class QRFpdfTest extends QROutputTestAbstract{ QRMatrix::M_DATA => [255, 255, 255], ]; - $this->outputInterface = $this->getOutputInterface($this->options); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); $this->outputInterface->dump(); $this::assertTrue(true); // tricking the code coverage } - /** - * @inheritDoc - * @dataProvider types - */ - public function testRenderImage(string $type):void{ - $this->options->outputType = $type; - $this->options->imageBase64 = false; - - // substr() to avoid CreationDate - $expected = substr(file_get_contents(__DIR__.'/../samples/'.$type), 0, 2500); - $actual = substr((new QRCode($this->options))->render('test'), 0, 2500); - - $this::assertSame($expected, $actual); - } - public function testOutputGetResource():void{ $this->options->returnResource = true; - $this->outputInterface = $this->getOutputInterface($this->options); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); $this::assertInstanceOf(FPDF::class, $this->outputInterface->dump()); } diff --git a/tests/Output/QRGdImageGIFTest.php b/tests/Output/QRGdImageGIFTest.php new file mode 100644 index 000000000..1a2694752 --- /dev/null +++ b/tests/Output/QRGdImageGIFTest.php @@ -0,0 +1,22 @@ + + * @copyright 2021 smiley + * @license MIT + */ + +namespace chillerlan\QRCodeTest\Output; + +use chillerlan\QRCode\QRCode; + +/** + * + */ +final class QRGdImageGIFTest extends QRGdImageTestAbstract{ + + protected string $type = QRCode::OUTPUT_IMAGE_GIF; + +} diff --git a/tests/Output/QRGdImageJPGTest.php b/tests/Output/QRGdImageJPGTest.php new file mode 100644 index 000000000..27fd5b43b --- /dev/null +++ b/tests/Output/QRGdImageJPGTest.php @@ -0,0 +1,22 @@ + + * @copyright 2021 smiley + * @license MIT + */ + +namespace chillerlan\QRCodeTest\Output; + +use chillerlan\QRCode\QRCode; + +/** + * + */ +final class QRGdImageJPGTest extends QRGdImageTestAbstract{ + + protected string $type = QRCode::OUTPUT_IMAGE_JPG; + +} diff --git a/tests/Output/QRGdImagePNGTest.php b/tests/Output/QRGdImagePNGTest.php new file mode 100644 index 000000000..61d221612 --- /dev/null +++ b/tests/Output/QRGdImagePNGTest.php @@ -0,0 +1,22 @@ + + * @copyright 2021 smiley + * @license MIT + */ + +namespace chillerlan\QRCodeTest\Output; + +use chillerlan\QRCode\QRCode; + +/** + * + */ +final class QRGdImagePNGTest extends QRGdImageTestAbstract{ + + protected string $type = QRCode::OUTPUT_IMAGE_PNG; + +} diff --git a/tests/Output/QRImageTest.php b/tests/Output/QRGdImageTestAbstract.php similarity index 57% rename from tests/Output/QRImageTest.php rename to tests/Output/QRGdImageTestAbstract.php index 27e42702e..815c89c36 100644 --- a/tests/Output/QRImageTest.php +++ b/tests/Output/QRGdImageTestAbstract.php @@ -1,6 +1,6 @@ @@ -11,14 +11,15 @@ namespace chillerlan\QRCodeTest\Output; use chillerlan\QRCode\Data\QRMatrix; -use chillerlan\QRCode\{QRCode, QROptions}; -use chillerlan\QRCode\Output\{QROutputInterface, QRImage}; +use chillerlan\QRCode\Output\QRGdImage; use const PHP_MAJOR_VERSION; /** - * Tests the QRImage output module + * Tests the QRGdImage output module */ -final class QRImageTest extends QROutputTestAbstract{ +abstract class QRGdImageTestAbstract extends QROutputTestAbstract{ + + protected string $FQN = QRGdImage::class; /** * @inheritDoc @@ -26,30 +27,12 @@ final class QRImageTest extends QROutputTestAbstract{ protected function setUp():void{ if(!extension_loaded('gd')){ - $this->markTestSkipped('ext-gd not loaded'); + $this::markTestSkipped('ext-gd not loaded'); } parent::setUp(); } - /** - * @inheritDoc - */ - protected function getOutputInterface(QROptions $options):QROutputInterface{ - return new QRImage($options, $this->matrix); - } - - /** - * @inheritDoc - */ - public function types():array{ - return [ - 'png' => [QRCode::OUTPUT_IMAGE_PNG], - 'gif' => [QRCode::OUTPUT_IMAGE_GIF], - 'jpg' => [QRCode::OUTPUT_IMAGE_JPG], - ]; - } - /** * @inheritDoc */ @@ -61,7 +44,7 @@ final class QRImageTest extends QROutputTestAbstract{ QRMatrix::M_DATA => [255, 255, 255], ]; - $this->outputInterface = $this->getOutputInterface($this->options); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); $this->outputInterface->dump(); $this::assertTrue(true); // tricking the code coverage @@ -72,7 +55,7 @@ final class QRImageTest extends QROutputTestAbstract{ */ public function testOutputGetResource():void{ $this->options->returnResource = true; - $this->outputInterface = $this->getOutputInterface($this->options); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); $actual = $this->outputInterface->dump(); diff --git a/tests/Output/QRImagickTest.php b/tests/Output/QRImagickTest.php index 7c7431adc..ab2792e2d 100644 --- a/tests/Output/QRImagickTest.php +++ b/tests/Output/QRImagickTest.php @@ -13,44 +13,31 @@ namespace chillerlan\QRCodeTest\Output; -use Imagick; +use chillerlan\QRCode\QRCode; use chillerlan\QRCode\Data\QRMatrix; -use chillerlan\QRCode\{QRCode, QROptions}; -use chillerlan\QRCode\Output\{QROutputInterface, QRImagick}; +use chillerlan\QRCode\Output\QRImagick; +use Imagick; /** * Tests the QRImagick output module */ final class QRImagickTest extends QROutputTestAbstract{ + protected string $FQN = QRImagick::class; + protected string $type = QRCode::OUTPUT_IMAGICK; + /** * @inheritDoc */ protected function setUp():void{ if(!extension_loaded('imagick')){ - $this->markTestSkipped('ext-imagick not loaded'); + $this::markTestSkipped('ext-imagick not loaded'); } parent::setUp(); } - /** - * @inheritDoc - */ - protected function getOutputInterface(QROptions $options):QROutputInterface{ - return new QRImagick($options, $this->matrix); - } - - /** - * @inheritDoc - */ - public function types():array{ - return [ - 'imagick' => [QRCode::OUTPUT_IMAGICK], - ]; - } - /** * @inheritDoc */ @@ -62,7 +49,7 @@ final class QRImagickTest extends QROutputTestAbstract{ QRMatrix::M_DATA => '#ECF9BE', ]; - $this->outputInterface = $this->getOutputInterface($this->options); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); $this->outputInterface->dump(); $this::assertTrue(true); // tricking the code coverage @@ -70,10 +57,9 @@ final class QRImagickTest extends QROutputTestAbstract{ public function testOutputGetResource():void{ $this->options->returnResource = true; - $this->outputInterface = $this->getOutputInterface($this->options); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); $this::assertInstanceOf(Imagick::class, $this->outputInterface->dump()); } - } diff --git a/tests/Output/QRMarkupHTMLTest.php b/tests/Output/QRMarkupHTMLTest.php new file mode 100644 index 000000000..497620fed --- /dev/null +++ b/tests/Output/QRMarkupHTMLTest.php @@ -0,0 +1,22 @@ + + * @copyright 2021 smiley + * @license MIT + */ + +namespace chillerlan\QRCodeTest\Output; + +use chillerlan\QRCode\QRCode; + +/** + * + */ +final class QRMarkupHTMLTest extends QRMarkupTestAbstract{ + + protected string $type = QRCode::OUTPUT_MARKUP_HTML; + +} diff --git a/tests/Output/QRMarkupSVGTest.php b/tests/Output/QRMarkupSVGTest.php new file mode 100644 index 000000000..f55b141d8 --- /dev/null +++ b/tests/Output/QRMarkupSVGTest.php @@ -0,0 +1,22 @@ + + * @copyright 2021 smiley + * @license MIT + */ + +namespace chillerlan\QRCodeTest\Output; + +use chillerlan\QRCode\QRCode; + +/** + * + */ +final class QRMarkupSVGTest extends QRMarkupTestAbstract{ + + protected string $type = QRCode::OUTPUT_MARKUP_SVG; + +} diff --git a/tests/Output/QRMarkupTest.php b/tests/Output/QRMarkupTestAbstract.php similarity index 56% rename from tests/Output/QRMarkupTest.php rename to tests/Output/QRMarkupTestAbstract.php index 87e63a925..329f2e219 100644 --- a/tests/Output/QRMarkupTest.php +++ b/tests/Output/QRMarkupTestAbstract.php @@ -1,6 +1,6 @@ @@ -10,31 +10,15 @@ namespace chillerlan\QRCodeTest\Output; -use chillerlan\QRCode\{QRCode, QROptions}; use chillerlan\QRCode\Data\QRMatrix; -use chillerlan\QRCode\Output\{QROutputInterface, QRMarkup}; +use chillerlan\QRCode\Output\QRMarkup; /** * Tests the QRMarkup output module */ -final class QRMarkupTest extends QROutputTestAbstract{ +abstract class QRMarkupTestAbstract extends QROutputTestAbstract{ - /** - * @inheritDoc - */ - protected function getOutputInterface(QROptions $options):QROutputInterface{ - return new QRMarkup($options, $this->matrix); - } - - /** - * @inheritDoc - */ - public function types():array{ - return [ - 'html' => [QRCode::OUTPUT_MARKUP_HTML], - 'svg' => [QRCode::OUTPUT_MARKUP_SVG], - ]; - } + protected string $FQN = QRMarkup::class; /** * @inheritDoc @@ -48,7 +32,7 @@ final class QRMarkupTest extends QROutputTestAbstract{ QRMatrix::M_DATA => '#ECF9BE', ]; - $this->outputInterface = $this->getOutputInterface($this->options); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); $data = $this->outputInterface->dump(); $this::assertStringContainsString('#4A6000', $data); $this::assertStringContainsString('#ECF9BE', $data); diff --git a/tests/Output/QROutputTestAbstract.php b/tests/Output/QROutputTestAbstract.php index b46f72c7e..49b4ae72e 100644 --- a/tests/Output/QROutputTestAbstract.php +++ b/tests/Output/QROutputTestAbstract.php @@ -10,15 +10,13 @@ namespace chillerlan\QRCodeTest\Output; -use chillerlan\QRCode\{QRCode, QROptions}; +use chillerlan\QRCode\QROptions; use chillerlan\QRCode\Common\MaskPattern; use chillerlan\QRCode\Data\{Byte, QRData, QRMatrix}; use chillerlan\QRCode\Output\{QRCodeOutputException, QROutputInterface}; use PHPUnit\Framework\TestCase; -use function file_exists, in_array, mkdir; - -use const PHP_OS_FAMILY, PHP_VERSION_ID; +use function file_exists, mkdir; /** * Test abstract for the several (built-in) output modules, @@ -31,6 +29,8 @@ abstract class QROutputTestAbstract extends TestCase{ protected QROutputInterface $outputInterface; protected QRMatrix $matrix; protected string $builddir = __DIR__.'/../../.build/output_test'; + protected string $FQN; + protected string $type; /** * Attempts to create a directory under /.build and instances several required objects @@ -41,16 +41,13 @@ abstract class QROutputTestAbstract extends TestCase{ mkdir($this->builddir, 0777, true); } - $this->options = new QROptions; - $this->matrix = (new QRData($this->options, [new Byte('testdata')])) - ->writeMatrix(new MaskPattern(MaskPattern::PATTERN_010)); - $this->outputInterface = $this->getOutputInterface($this->options); - } + $this->options = new QROptions; + $this->options->outputType = $this->type; - /** - * Returns a QROutputInterface instance with the given options and using $this->matrix - */ - abstract protected function getOutputInterface(QROptions $options):QROutputInterface; + $this->matrix = (new QRData($this->options, [new Byte('testdata')])) + ->writeMatrix(new MaskPattern(MaskPattern::PATTERN_010)); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); + } /** * Validate the instance of the interface @@ -67,7 +64,7 @@ abstract class QROutputTestAbstract extends TestCase{ $this->expectExceptionMessage('Cannot write data to cache file: /foo/bar.test'); $this->options->cachefile = '/foo/bar.test'; - $this->outputInterface = $this->getOutputInterface($this->options); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); $this->outputInterface->dump(); } @@ -80,49 +77,16 @@ abstract class QROutputTestAbstract extends TestCase{ * additional, non-essential, potentially inaccurate coverage tests */ - /** - * @see testStringOutput() - * @return string[][] - */ - abstract public function types():array; - /** * coverage of the built-in output modules - * - * @dataProvider types */ - public function testStringOutput(string $type):void{ - $this->options->outputType = $type; - $this->options->cachefile = $this->builddir.'/test.'.$type; + public function testRenderToCacheFile():void{ + $this->options->cachefile = $this->builddir.'/test.'.$this->type; $this->options->imageBase64 = false; - $this->outputInterface = $this->getOutputInterface($this->options); + $this->outputInterface = new $this->FQN($this->options, $this->matrix); $data = $this->outputInterface->dump(); // creates the cache file $this::assertSame($data, file_get_contents($this->options->cachefile)); } - /** - * covers the built-in output modules, tests against pre-rendered data - * - * @dataProvider types - */ - public function testRenderImage(string $type):void{ - - // may fail on CI, different PHP (platform) versions produce different output - // the samples were generated on php-7.4.3-Win32-vc15-x64 - if( - (PHP_OS_FAMILY !== 'Windows' || PHP_VERSION_ID >= 80100) - && in_array($type, [QRCode::OUTPUT_IMAGE_JPG, QRCode::OUTPUT_IMAGICK, QRCode::OUTPUT_MARKUP_SVG]) - ){ - $this::markTestSkipped('may fail on CI'); - } - - $this->options->outputType = $type; - - $this::assertSame( - trim(file_get_contents(__DIR__.'/../samples/'.$type)), - trim((new QRCode($this->options))->render('test')) - ); - } - } diff --git a/tests/Output/QRStringJSONTest.php b/tests/Output/QRStringJSONTest.php new file mode 100644 index 000000000..8ba71c1e9 --- /dev/null +++ b/tests/Output/QRStringJSONTest.php @@ -0,0 +1,40 @@ + + * @copyright 2021 smiley + * @license MIT + */ + +namespace chillerlan\QRCodeTest\Output; + +use chillerlan\QRCode\QRCode; +use function extension_loaded; + +/** + * + */ +final class QRStringJSONTest extends QRStringTestAbstract{ + + protected string $type = QRCode::OUTPUT_STRING_JSON; + + /** + * @inheritDoc + */ + protected function setUp():void{ + // just in case someone's running this on some weird disto that's been compiled without ext-json + if(!extension_loaded('json')){ + $this::markTestSkipped('ext-json not loaded'); + } + + parent::setUp(); + } + + + public function testSetModuleValues():void{ + $this::markTestSkipped('N/A'); + } + +} diff --git a/tests/Output/QRStringTEXTTest.php b/tests/Output/QRStringTEXTTest.php new file mode 100644 index 000000000..2ef223835 --- /dev/null +++ b/tests/Output/QRStringTEXTTest.php @@ -0,0 +1,41 @@ + + * @copyright 2021 smiley + * @license MIT + */ + +namespace chillerlan\QRCodeTest\Output; + +use chillerlan\QRCode\Data\QRMatrix; +use chillerlan\QRCode\QRCode; + +/** + * + */ +final class QRStringTEXTTest extends QRStringTestAbstract{ + + protected string $type = QRCode::OUTPUT_STRING_TEXT; + + /** + * @inheritDoc + */ + public function testSetModuleValues():void{ + + $this->options->moduleValues = [ + // data + QRMatrix::M_DATA | QRMatrix::IS_DARK => 'A', + QRMatrix::M_DATA => 'B', + ]; + + $this->outputInterface = new $this->FQN($this->options, $this->matrix); + $data = $this->outputInterface->dump(); + + $this::assertStringContainsString('A', $data); + $this::assertStringContainsString('B', $data); + } + +} diff --git a/tests/Output/QRStringTest.php b/tests/Output/QRStringTest.php deleted file mode 100644 index e525944b9..000000000 --- a/tests/Output/QRStringTest.php +++ /dev/null @@ -1,74 +0,0 @@ - - * @copyright 2017 Smiley - * @license MIT - */ - -namespace chillerlan\QRCodeTest\Output; - -use chillerlan\QRCode\{QRCode, QROptions}; -use chillerlan\QRCode\Common\EccLevel; -use chillerlan\QRCode\Data\QRMatrix; -use chillerlan\QRCode\Output\{QROutputInterface, QRString}; -use chillerlan\QRCodeExamples\MyCustomOutput; - -/** - * Tests the QRString output module - */ -final class QRStringTest extends QROutputTestAbstract{ - - /** - * @inheritDoc - */ - protected function getOutputInterface(QROptions $options):QROutputInterface{ - return new QRString($options, $this->matrix); - } - - /** - * @inheritDoc - */ - public function types():array{ - return [ - 'json' => [QRCode::OUTPUT_STRING_JSON], - 'text' => [QRCode::OUTPUT_STRING_TEXT], - ]; - } - - /** - * @inheritDoc - */ - public function testSetModuleValues():void{ - - $this->options->moduleValues = [ - // data - QRMatrix::M_DATA | QRMatrix::IS_DARK => 'A', - QRMatrix::M_DATA => 'B', - ]; - - $this->outputInterface = $this->getOutputInterface($this->options); - $data = $this->outputInterface->dump(); - - $this::assertStringContainsString('A', $data); - $this::assertStringContainsString('B', $data); - } - - /** - * covers the custom output functionality via an example - */ - public function testCustomOutput():void{ - $this->options->version = 5; - $this->options->eccLevel = EccLevel::L; - $this->options->outputType = QRCode::OUTPUT_CUSTOM; - $this->options->outputInterface = MyCustomOutput::class; - - $this::assertSame( - file_get_contents(__DIR__.'/../samples/custom'), - (new QRCode($this->options))->render('test') - ); - } - -} diff --git a/tests/Output/QRStringTestAbstract.php b/tests/Output/QRStringTestAbstract.php new file mode 100644 index 000000000..18e13e52d --- /dev/null +++ b/tests/Output/QRStringTestAbstract.php @@ -0,0 +1,22 @@ + + * @copyright 2017 Smiley + * @license MIT + */ + +namespace chillerlan\QRCodeTest\Output; + +use chillerlan\QRCode\Output\QRString; + +/** + * Tests the QRString output module + */ +abstract class QRStringTestAbstract extends QROutputTestAbstract{ + + protected string $FQN = QRString::class; + +} diff --git a/tests/samples/custom b/tests/samples/custom deleted file mode 100644 index e19a64352..000000000 --- a/tests/samples/custom +++ /dev/null @@ -1,45 +0,0 @@ -000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000 -000011111110111010000101111010000011111110000 -000010000010111000001101011000001010000010000 -000010111010101101011000001101011010111010000 -000010111010110100111110010100111010111010000 -000010111010000001101011000001101010111010000 -000010000010100111110010100111110010000010000 -000011111110101010101010101010101011111110000 -000000000000010010100111110010100000000000000 -000011001110000101111010000101111001011110000 -000000000000111010000101111010000111100010000 -000001011010100111110010100111110011001010000 -000010000101111101011000001101011110011110000 -000000011010100011000001101011000101110100000 -000011001100001001101011000001101010011010000 -000010110111110000001101011000001100110100000 -000010000100100010100111110010100001100100000 -000011111110111101111010000101111010100110000 -000011010000111010000101111010000111100100000 -000010101111111111110010100111110011001000000 -000010110001110101011000001101011110011010000 -000001001111100011000001101011000101110010000 -000011000100110001101011000001101010011100000 -000001000011001000001101011000001100110000000 -000011101001011010100111110010100001100000000 -000010111010001101111010000101111010100110000 -000011100000001010000101111010000111100000000 -000000001110110111110010100111110011001000000 -000000011001011101011000001101011110011100000 -000011111110101011000001101011001111110110000 -000000000000110001101011000001101000111100000 -000011111110001000001101011000011010110000000 -000010000010101010100111110010101000100100000 -000010111010111101111010000101111111100110000 -000010111010011010000101111010001101100010000 -000010111010000111110010100111100101101100000 -000010000010101101011000001101001100111100000 -000011111110101011000001101011000110010110000 -000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000 diff --git a/tests/samples/fpdf b/tests/samples/fpdf deleted file mode 100644 index 15b041b9fdc195e53018eff953e82a81c828652c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2859 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 diff --git a/tests/samples/gif b/tests/samples/gif deleted file mode 100644 index aff9a0fa9..000000000 --- a/tests/samples/gif +++ /dev/null @@ -1 +0,0 @@ -data:image/gif;base64,R0lGODlhkQCRAIAAAAQCBP///yH5BAEAAAEALAAAAACRAJEAAAL+jI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8YhMKpfMpvOpBEin1Kr1ek1gpY6qdgsOU1niMviL7Y4R5raV7I4D0NmGly13w/Nm+tu+dsDXtjcY5nfHkGhgWFY4x7GoIOlXGRmYQnmhKYg56clZEToyOjF6CuqJURrCGoE6pRaLN7vh+nH7AMsFWMuouglcIklIy9vpG0CcmlyMfJzJLGb5DFlN/dvcZ2wdre3Ija0s3T3+PR2+sgx+nd7+ng1tjg6Psk4fX36vT464JX5i3xl3+WTJE+esoDpyA+vtKodwW72ADP8RnAfxYkT+dgpVCLToUFjHBR/TaDRRsk7IZAAvJsT4yJ/Jlfh0VZw50t5NlTlfGuTHEebCc4dcSoSQ8s9ElDuV9jxqk2jDnBSlgnwa9KdMnkI9iqSQa9VXU2NblX11VkPYXgeZsgz2FsRaRWk9zCVZV2xcUXkv7QXb18LdT39FNKq5b+NhnDoXM05s1DHXqpIh0wRaObDazJaxyuM8WC9ozKQVg4bC1ilqHVNX52jt+gbs2DVm087nM/Lnrw9bh4YbR6vujEur+dacgY/wy8vxBv0tOE/zrlRPGr9KvXHw1Kanb1UNne/flw9bXu6snThu7OWtewaPXLR6jMfH9+PODT3l+eT+ed+naxVRMaVWX1vM4XedgEPtFuBkCK4nx0/hAaZggg4CyKAhEsYHXGn5YTfdYhsWZlaFEF7oXIaDjGggCejlhiFpyhHIYXQNzvedabnot6CMdRXoI4kHvpAUWY81ZaSKMRQpAZA5NvmfC0yideSNSXpIg5Pu0ceef1W22IKWxZ0In31f4tjji14itmaZYD6ipplsyukmml6daR6ZPFqI5W17vtfdbYA+mN2fUBgap5KCFtpmoGMeGiVhig4p5WhvbgmkbZVaeiWLQaIYpqV2VsfndxN2IOqo2T3J56l+jdYpjTe6akuNpL4HI5k2TNheqyB+KKQ3l1IJZlKachn+bHqoNgpsTazOwCuzvjL2rAzGRmqqtEhBtV+2JkpaVIxXHmtYU4hyu6W3w+JiLrbNqpYnuOSWqKKYKYZ777i/DtPut/M+am+os0b6763ITrppvV1aCSWdhnb7bqLwElotreIpjOe7scb4sFsYcyXxud8u2S/CjGYsbro9qtvnySBruyoM1/qLJKbuEllyy1Ma3PGd60b1sR7D9SqsqiEepiPMENc68HM1p+yz0YSKOLTSHksNtZ5Q7QwunJlVvK/BO6QKNrUqvyZq2aBanB5nak/86Nhpa0x31ovejXfeeu/Nd99+/w144IIPTnjhhh+OeOKKL854444/DnnkkhcCXgAAOw== diff --git a/tests/samples/html b/tests/samples/html deleted file mode 100644 index 13fe6b531..000000000 --- a/tests/samples/html +++ /dev/null @@ -1,31 +0,0 @@ -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/samples/imagick b/tests/samples/imagick deleted file mode 100644 index 377725d856bdb02eb79fc401f99e4ca3aebae79b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 348 zcmV-i0i*tjP)!W9m00004XF*Lt006O% z3;baP0000WV@Og>004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv00G^K6QlqD0NF`IK~zY`?bb04gdh+F&@mR29${{x7bAhhi>)`|2$mMc*+002 zS?6aVLJrh-1-n5S3+K uKQyXt9!Pe+zXfOi`;BjAzx;1J*4W