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 15b041b9f..000000000
Binary files a/tests/samples/fpdf and /dev/null differ
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 377725d85..000000000
Binary files a/tests/samples/imagick and /dev/null differ
diff --git a/tests/samples/jpg b/tests/samples/jpg
deleted file mode 100644
index dd46e24a9..000000000
--- a/tests/samples/jpg
+++ /dev/null
@@ -1 +0,0 @@
-data:image/jpg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2OTApLCBxdWFsaXR5ID0gODUK/9sAQwAFAwQEBAMFBAQEBQUFBgcMCAcHBwcPCwsJDBEPEhIRDxERExYcFxMUGhURERghGBodHR8fHxMXIiQiHiQcHh8e/9sAQwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e/8AAEQgAkQCRAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A+y6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigDxn9pr46f8KW/wCEf/4pb+3f7Z+0/wDMQ+zeT5Plf9M33Z832xt7548Z/wCG5/8Aql3/AJX/AP7no/4Kaf8ANPv+4l/7a16n4O8NfBnw1+zv4W8aeNPBnhKO0j8P6bNf382gRXEjPLFEu9tsbOzM7jJwTk5Pc0AeWf8ADc//AFS7/wAr/wD9z0f8Nz/9Uu/8r/8A9z12f/Cy/wBjb/oG+DP/AAjJP/kaum+HF9+zF8RNcm0Twd4Y8GanfwWzXUkX/CKiHbErKpbMkCj7zqMZzz9aAOA8Cftlf8JR440Hwz/wrj7J/a+pW9j9o/tvf5Xmyqm/b5A3Y3ZxkZx1FemftNfHT/hS3/CP/wDFLf27/bP2n/mIfZvJ8nyv+mb7s+b7Y2988fLPxJ0nStD/AG+NL0vRNMstMsIPEmh+Va2cCwxR7ltWO1FAAyxJOB1JNfYHx08S/Brw7/Y//C27bRZvtHn/ANm/2jozX+Nvl+btxE+z70eemeOuOADzL4JftW/8LK+J+keCv+EC/sr+0fO/0v8AtfzvL8uCSX7nkrnOzHUYzn2r6Zr4T+H3gvU/AHx4/wCF5apo8Oj/AAqF9e39nqcLRmNLK7SVLMrbRkzKrefCAnlgqG+YKAcfY3w48e+E/iJoc2t+DtW/tOwguWtZJfs8sO2VVViuJFU/ddTnGOfrQB5N+zj+0h/wuHxxeeGf+EM/sT7Npr332j+0/tG7bLEmzb5SYz5uc57dOeMX42/tW/8ACtfifq/gr/hAv7V/s7yf9L/tfyfM8yCOX7nktjG/HU5xn2rxn/gnF/yW/Wf+xbn/APSm2qH452lrf/t/QWN9bQ3Vpc+INEhngmjDxyo0VoGRlPDKQSCDwQaAO5/4bn/6pd/5X/8A7no/4bn/AOqXf+V//wC569m+JsH7OPw1/s//AITXwj4M0r+0fN+yf8Uuk3meXs3/AOqhbGN6dcZzx3rjP+Fl/sbf9A3wZ/4Rkn/yNQBxn/Dc/wD1S7/yv/8A3PXpv7OP7SH/AAuHxxeeGf8AhDP7E+zaa999o/tP7Ru2yxJs2+UmM+bnOe3TnjpvhxonwA+Imhza34O8FeDNTsILlrWSX/hGo4dsqqrFcSRKfuupzjHP1r5Z/wCCcX/Jb9Z/7Fuf/wBKbagD7/ooooAKKKKACiiigD4z/wCCmn/NPv8AuJf+2tdn8ZP+Uedj/wBi3oX/AKMtK4z/AIKaf80+/wC4l/7a16zqXgrVfiJ+xdoHg7RLiyt7/UPDejeVJeOyxL5Yt5TuKqx+6hxgHnH1oA/Nqvpn/gnF/wAlv1n/ALFuf/0ptqP+GKvin/0H/Bn/AIGXP/yPXsH7Jv7PXjT4TfEXUPEfiPU/D91aXOkSWSJYTzPIHaaFwSHiQbcRt3zkjigDx/4yf8pDLH/sZNC/9F2ldn/wU0/5p9/3Ev8A21rjPjJ/ykMsf+xk0L/0XaV9Aftg/BTxV8Yf+EW/4RnUNFtP7I+1/aP7RmlTd5vk7duyN848ps5x1HXsAdN4b8FaV8RP2VfCng7W7i9t7DUPDelebJZuqyr5ccEo2llYfeQZyDxn618//Efxrqv7JmuQ/Dn4c29lquk6jbLrc02vo01ws8jNCyq0LRKE226EAqTktzjAHM/8MVfFP/oP+DP/AAMuf/kevqD9k34X6/8ACb4dah4c8R3mmXV3c6vJeo9hI7xhGhhQAl0Q7sxt2xgjmgA+Cn7PXgv4TeKrnxH4c1PxBdXdzYvZOl/PC8YRnjckBIkO7Ma98YJ4r5f+Mn/KQyx/7GTQv/RdpX3/AF8AfGT/AJSGWP8A2Mmhf+i7SgDs/wDgpp/zT7/uJf8AtrXxnX6M/tg/BTxV8Yf+EW/4RnUNFtP7I+1/aP7RmlTd5vk7duyN848ps5x1HXt8/wD/AAxV8U/+g/4M/wDAy5/+R6APZv8AgnF/yRDWf+xkn/8ASa2rxn/gnF/yW/Wf+xbn/wDSm2r6g/ZN+F+v/Cb4dah4c8R3mmXV3c6vJeo9hI7xhGhhQAl0Q7sxt2xgjmvl/wD4Jxf8lv1n/sW5/wD0ptqAPv8AooooAKKKKACiiigD5N/4KHeE/FXij/hBv+EZ8Na1rf2b+0PtH9nWMtx5W77Nt3bFO3O1sZ64PpXkuheN/wBrrQ9DsNE0vRvGdvYafbR2trF/wh6t5cUahUXLW5JwoAyST619TftNfHT/AIUt/wAI/wD8Ut/bv9s/af8AmIfZvJ8nyv8Apm+7Pm+2NvfPHjP/AA3P/wBUu/8AK/8A/c9AHGf8LL/bJ/6BvjP/AMIyP/5Go/4WX+2T/wBA3xn/AOEZH/8AI1dn/wANz/8AVLv/ACv/AP3PX2ZQB+cHg7w18ZvEv7RHhbxp408GeLZLuTxBps1/fzaBLbxqkUsS722xqiqqIMnAGBk9zX1B+2D4l+Mvh3/hFv8AhUltrU32j7X/AGl/Z2jLf42+T5W7MT7PvSY6Z5644PGX7SH/AAjv7Q0Hwk/4Qz7V5upWFj/aX9p7MfaVhO/yvKP3fN6b+dvUZ42f2mvjp/wpb/hH/wDilv7d/tn7T/zEPs3k+T5X/TN92fN9sbe+eADmfib8an0X9mUX9h470W3+JUGm6eLu0M1s17FeGSFbpHtWB2uuZQyFBsweBjjZ/Yp8e+LPiJ8LNT1vxjq39p38Gty2scv2eKHbEsEDBcRqo+87HOM8/SvnP42/Avzvhhq/7QP/AAlO3+3PJ13+xf7Pz5H2+eNvK8/zPm2efjd5Y3bei549m/4Jxf8AJENZ/wCxkn/9JragCH9k3xf8ftf+IuoWfxUtPEEOippEksDX/h9bKP7QJoQoDiFMtsMny56ZOOOPH/2ofCPxN/4al1nxf4Q8HeJrv7Nc2F1YX9no8txF5sVtAQykIyNtdMEHIyCD3FfWf7R3xX/4U94Hs/E39g/239p1JLH7P9s+z7d0Ur792x848rGMd+vHOz8EvHX/AAsr4YaR41/sv+yv7R87/RPtHneX5c8kX39q5zsz0GM496APjP8A4WX+2T/0DfGf/hGR/wDyNR/wsv8AbJ/6BvjP/wAIyP8A+Rq+mf2mvjp/wpb/AIR//ilv7d/tn7T/AMxD7N5Pk+V/0zfdnzfbG3vnjxn/AIbn/wCqXf8Alf8A/uegDjP+Fl/tk/8AQN8Z/wDhGR//ACNXQfsDeCPGnhr4w6tfeI/CHiDRrSTw/NCk9/ps1vGzm4tyEDOoBbCscdcA+lfSf7OPxX/4XD4HvPE39g/2J9m1J7H7P9s+0btsUT792xMZ83GMduvPHGfs4/tIf8Lh8cXnhn/hDP7E+zaa999o/tP7Ru2yxJs2+UmM+bnOe3TngA9/ooooAKKKKACiiigD4z/4Kaf80+/7iX/trXqfg7w18GfDX7O/hbxp408GeEo7SPw/ps1/fzaBFcSM8sUS722xs7MzuMnBOTk9zXln/BTT/mn3/cS/9ta7P4yf8o87H/sW9C/9GWlAHkHxr+Gq/GTxVbeJ/wBnnwrpl74VtbFLC7ksIoNMjF6rySODFN5TM3lyw/OFIIIGflIHiX/C2Pin/wBFL8Z/+D25/wDi6634KftC+NPhN4VufDnhzTPD91aXN896738EzyB2SNCAUlQbcRr2zknmvp//AIYq+Fn/AEH/ABn/AOBlt/8AI9AHn/ww8efC/Xvgrb6Vqt1Zan8adQtru2sNQu9Nkl1JtReSVLEi+aM7XXNuEkMg8vC8rt49A/Zl+Fvjub/hIP8AhoHQv+Eix9m/sX/hIbuDV/I/1vn+VueTyt37nd03bV67eKWvfsv+Afhrod/8RtC1fxNc6t4VtpNbsYb25ge3kntVM0ayKkKsULIAwVlJGcEHmvJv+G1fin/0APBn/gHc/wDyRQB9J/tl2lrYfsqeJrGxtobW0torCGCCGMJHEi3luFRVHCqAAABwAK5L/gnF/wAkQ1n/ALGSf/0mtq0/2kNbuvEv7Dtx4jvo4Y7vVdI0i9nSEERq8s9q7BQSSFyxxkk47msz/gnF/wAkQ1n/ALGSf/0mtqAPAP2cfinpE3ji8X47+KL3X/DQ01za22vifVbdLzzYtjrEwkCuI/OAfaMBmGfmwfobxd+0J8DrD4TeIPD3gHxTDpN2dIvItJt9N0i6tFiuHjcoYysKrGxkbO7IwTnPevz5r6//AGd/2X/APxE+DuheMdb1fxNb3+ofaPNjs7mBYl8u4liG0NCx+6gzknnP0oA5n9mX4peBJv8AhIP+Ggdd/wCEix9m/sX/AISG0n1fyP8AW+f5W5JPK3fud3TdtXrt45/xZ+zz8TvFPirVvE/gjwXDN4V1e+mv9EkhvbS3jeymcyQFYmkVo1MbJhCqlRwQMYr6G/4Yq+Fn/Qf8Z/8AgZbf/I9Y3wU+NfiqH4/WPwIXT9FPhrRbm80S2ujDL9teCxhlWJnfzNhciBNxCAHJwF4wAH7OPinQv2dvA954K+Md9/wjOv3upPqlvaeU95vtXiiiWTfbCRBl4ZRtJDfLnGCCfMv+CcX/ACW/Wf8AsW5//Sm2o/4KO/8AJb9G/wCxbg/9KbmvqD4Kfs9eC/hN4qufEfhzU/EF1d3Ni9k6X88LxhGeNyQEiQ7sxr3xgnigD1+iiigAooooAKKKKACviD4lfsifEnxL8RfEviOx1vwlHaarq91ewJNdXAkVJZmdQwEBAbDDOCRnua9G/bn+KXjv4a/8Id/whWu/2V/aP277X/okE3meX9n2f61Gxje/TGc89q8TsPit+1/f2NvfWNv4turS5iWaCeHwhE8cqMMq6sLbDKQQQRwQaAPqb9k34X6/8Jvh1qHhzxHeaZdXdzq8l6j2EjvGEaGFACXRDuzG3bGCOa8//ZN/Z68afCb4i6h4j8R6n4furS50iSyRLCeZ5A7TQuCQ8SDbiNu+ckcV4/8A8LL/AGyf+gb4z/8ACMj/APkaj/hZf7ZP/QN8Z/8AhGR//I1AHsHj79nrxpr/AO1RbfFSz1Pw/HosWr6betBLPMLnZbLAHAURFdx8psfNjkZI7ep/HT41+Ffg9/Y//CTafrV3/a/n/Z/7Ohifb5Xl7t2+RMZ81cYz0PTv8meAvjz8fP8Ahc/hjwh4v1+9tPtOt2Nrf2F5ottby+VLLGCrAwq67kfIIwcEEdjX2Z8Tfhb4E+JX9n/8JroX9q/2d5v2T/S54fL8zZv/ANU65zsTrnGOO9AHw18b/gp4qm0DxB8d11DRR4a1q5Gt21qZpftqQX06tErp5ewOBOm4ByBg4LcZ5/4Kfs9eNPiz4VufEfhzU/D9raW189k6X88ySF1SNyQEicbcSL3zkHivrL9pW98I3v7Pet/C3wJqumaprVpFZ6fY+H9OvVu78C2uYd0YhVmlZo0iYtkEgIxPQmuf/Yp1bSvhr8LNT0L4janZeDdWn1uW7hsdfnWwuJIGggRZVjmKsULI6hgMEowzkGgC7/wUd/5Iho3/AGMkH/pNc10H7KOt2vhr9jjSPEd9HNJaaVY6nezpCAZGSK6uXYKCQC2FOMkDPcV5/wDt8+N/BfiX4PaTY+HPF/h/WbuPxBDM8FhqUNxIqC3uAXKoxIXLKM9MketeDfA74peO5NQ8LfCR9dz4K1TUotLvNN+yQfvbW6uMXEfm7PNG4SyfMHDDdwRgYAPZvib/AMZg/wBn/wDCtP8AiUf8Il5v2/8A4SH9x5n2vZ5fleR5ucfZpN27bjK4zk48s/ZR0S68Nftj6R4cvpIZLvSr7U7Kd4STGzxWtyjFSQCVypxkA47Cvbfjp4T8VfBP+x/+Gb/DWtWP9s+f/bv9nWMuq7/J8v7Pu85ZfLx5s+Nu3dk5ztGPka18ZeN/DHxRu/GSXk2neMIr65luZprOMSR3Eu9Zw0TptVvncFSowTwBjgA9s/4KO/8AJb9G/wCxbg/9Kbmvv+vk39nHwtoX7RPge88a/GOx/wCEm1+y1J9Lt7vzXs9lqkUUqx7LYxocPNKdxBb5sZwAB9ZUAFFFFABRRRQAUUUUAfGf/BTT/mn3/cS/9ta9mtvHX/Ctf2QfDXjX+y/7V/s7w3pH+ifaPJ8zzEt4vv7Wxjfnoc4x714z/wAFNP8Amn3/AHEv/bWuz+Mn/KPOx/7FvQv/AEZaUAcZ/wANz/8AVLv/ACv/AP3PXpv7OP7SH/C4fHF54Z/4Qz+xPs2mvffaP7T+0btssSbNvlJjPm5znt054/Oavpn/AIJxf8lv1n/sW5//AEptqAD4yf8AKQyx/wCxk0L/ANF2lff9fAHxk/5SGWP/AGMmhf8Aou0r03/god4s8VeF/wDhBv8AhGfEutaJ9p/tD7R/Z19Lb+bt+zbd2xhuxubGemT60AfP9z46/wCFa/tfeJfGv9l/2r/Z3iTV/wDRPtHk+Z5j3EX39rYxvz0OcY96xv2jviv/AMLh8cWfib+wf7E+zaalj9n+2faN22WV9+7YmM+bjGO3Xnjufg/8N/EXh7xbo3xg+MGgQ3HgCeJ9Q1LUtSlh1BZxdQsIZJIQzyuzSzRHlCQTuOMEj3n/AIWX+xt/0DfBn/hGSf8AyNQBxn/DDH/VUf8Aygf/AHRXjNt4F/4Vr+194a8Ff2p/av8AZ3iTSP8AS/s/k+Z5j28v3NzYxvx1OcZ9q+rP2+fEOv8Ahr4PaTfeHNc1PRruTxBDC89hdvbyMht7glCyEErlVOOmQPSrv7Jvh7QPFPwX8K+N/E+h6ZrniqWWeaTW9RtEub93iu5ViczuDIWRURVO7KhFAxgUAe818NftUfs3/wDCO6R41+Lf/CZ/avN1Jr7+zf7M2Y+03ajZ5vmn7vm9dnO3oM8dn/wUO8WeKvC//CDf8Iz4l1rRPtP9ofaP7Ovpbfzdv2bbu2MN2NzYz0yfWvP/AIV6d8VtLvNF8e/GzUNa1H4Sy2wutQOr6v8A2laTRTQkWrPaeZI7/vpICAYyVbDHG3IAOZ/Zx/aQ/wCFPeB7zwz/AMIZ/bf2nUnvvtH9p/Z9u6KJNm3ynzjys5z36cc/TP7OP7SH/C4fHF54Z/4Qz+xPs2mvffaP7T+0btssSbNvlJjPm5znt0548G+Nfw1X4yeKrbxP+zz4V0y98K2tilhdyWEUGmRi9V5JHBim8pmby5YfnCkEEDPykD7Y8N+CPBfhq+e+8OeEPD+jXckRheew02G3kZCQShZFBK5VTjpkD0oA6CiiigAooooAKKKKAPjP/gpp/wA0+/7iX/trXufhvwVpXxE/ZV8KeDtbuL23sNQ8N6V5slm6rKvlxwSjaWVh95BnIPGfrXM/tg/BTxV8Yf8AhFv+EZ1DRbT+yPtf2j+0ZpU3eb5O3bsjfOPKbOcdR17fP/8AwxV8U/8AoP8Agz/wMuf/AJHoA9m/4Yq+Fn/Qf8Z/+Blt/wDI9d18FP2evBfwm8VXPiPw5qfiC6u7mxeydL+eF4wjPG5ICRId2Y174wTxXy//AMMVfFP/AKD/AIM/8DLn/wCR6P8Ahir4p/8AQf8ABn/gZc//ACPQAfGT/lIZY/8AYyaF/wCi7Suz/wCCmn/NPv8AuJf+2tZnw1/ZE+JPhr4i+GvEd9rfhKS00rV7W9nSG6uDIyRTK7BQYAC2FOMkDPcV7B+2D8FPFXxh/wCEW/4RnUNFtP7I+1/aP7RmlTd5vk7duyN848ps5x1HXsAfI3iX9oXxpr/wai+Fd5pnh+PRYrG0slnigmFzstjGUJYyldx8pc/Ljk4A7eP19s/s7/sv+Pvh38YtC8Y63q/hm4sNP+0ebHZ3M7St5lvLENoaFR95xnJHGfpXQftZfs9eNPiz8RdP8R+HNT8P2tpbaRHZOl/PMkhdZpnJASJxtxIvfOQeKAOF+HHjXVf2s9cm+HPxGt7LStJ062bW4ZtARobhp42WFVZpmlUptuHJAUHIXnGQdTTPihr/AMG/jbov7PXhiz0y88K2mr2NlHd6jG8l+UvHjmlJdHSPcGuHC/u8ABcg8k9N+yb+z140+E3xF1DxH4j1Pw/dWlzpElkiWE8zyB2mhcEh4kG3Ebd85I4r3/4laJdeJfh14l8OWMkMd3qukXVlA8xIjV5YWRSxAJC5YZwCcdjQB8p/8FNP+aff9xL/ANta5P4OfFDX/jIvh39nrxPZ6ZZ+FbuxSyku9OjeO/CWcHnREO7vHuLW6Bv3eCC2AOCPef2Pvgp4q+D3/CU/8JNqGi3f9r/ZPs/9nTSvt8rzt27fGmM+auMZ6Hp39/oA4b4KfC/QPhN4VufDnhy81O6tLm+e9d7+RHkDskaEAoiDbiNe2ck814z+yb+0L40+LPxF1Dw54j0zw/a2ltpEl6j2EEySF1mhQAl5XG3Ejds5A5r6fooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/Z
diff --git a/tests/samples/json b/tests/samples/json
deleted file mode 100644
index 56837ea1b..000000000
--- a/tests/samples/json
+++ /dev/null
@@ -1 +0,0 @@
-[[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],[256,256,256,256,2052,2052,2052,2052,2052,2052,2052,8,2112,2050,2,2,2050,8,2052,2052,2052,2052,2052,2052,2052,256,256,256,256],[256,256,256,256,2052,4,4,4,4,4,2052,8,64,2050,2,2,2050,8,2052,4,4,4,4,4,2052,256,256,256,256],[256,256,256,256,2052,4,3072,3072,3072,4,2052,8,2112,2,2050,2,2050,8,2052,4,3072,3072,3072,4,2052,256,256,256,256],[256,256,256,256,2052,4,3072,3072,3072,4,2052,8,2112,2,2,2050,2,8,2052,4,3072,3072,3072,4,2052,256,256,256,256],[256,256,256,256,2052,4,3072,3072,3072,4,2052,8,2112,2050,2050,2,2,8,2052,4,3072,3072,3072,4,2052,256,256,256,256],[256,256,256,256,2052,4,4,4,4,4,2052,8,64,2,2,2,2,8,2052,4,4,4,4,4,2052,256,256,256,256],[256,256,256,256,2052,2052,2052,2052,2052,2052,2052,8,2080,32,2080,32,2080,8,2052,2052,2052,2052,2052,2052,2052,256,256,256,256],[256,256,256,256,8,8,8,8,8,8,8,8,64,2050,2050,2,2,8,8,8,8,8,8,8,8,256,256,256,256],[256,256,256,256,2112,2112,2112,2112,64,64,2080,64,2112,2,2050,2,2,2112,64,64,2112,2112,2112,64,2112,256,256,256,256],[256,256,256,256,2050,2,2,2050,2050,2050,32,2050,2,2,2050,2,2050,2,2,2050,2,2050,2050,2,2050,256,256,256,256],[256,256,256,256,2050,2,2050,2,2050,2050,2080,2,2,2,2050,2,2050,2050,2050,2050,2050,2,2,2050,2050,256,256,256,256],[256,256,256,256,2050,2,2050,2050,2,2,32,2050,2050,2,2050,2,2050,2050,2,2,2,2050,2,2050,2,256,256,256,256],[256,256,256,256,2,2050,2050,2,2050,2,2080,2,2,2050,2050,2050,2,2050,2,2,2050,2050,2,2050,2,256,256,256,256],[256,256,256,256,8,8,8,8,8,8,8,8,2049,2,2050,2,2,2050,2,2050,2,2050,2,2050,2,256,256,256,256],[256,256,256,256,2052,2052,2052,2052,2052,2052,2052,8,64,2,2050,2,2,2050,2050,2,2050,2050,2050,2,2,256,256,256,256],[256,256,256,256,2052,4,4,4,4,4,2052,8,64,2050,2,2050,2050,2050,2050,2,2,2050,2050,2,2,256,256,256,256],[256,256,256,256,2052,4,3072,3072,3072,4,2052,8,64,2050,2050,2050,2,2,2050,2,2,2,2050,2050,2050,256,256,256,256],[256,256,256,256,2052,4,3072,3072,3072,4,2052,8,2112,2050,2,2,2,2050,2,2,2050,2050,2,2050,2,256,256,256,256],[256,256,256,256,2052,4,3072,3072,3072,4,2052,8,2112,2,2050,2050,2,2050,2,2,2050,2,2050,2,2,256,256,256,256],[256,256,256,256,2052,4,4,4,4,4,2052,8,2112,2050,2050,2050,2050,2,2050,2,2050,2050,2,2,2050,256,256,256,256],[256,256,256,256,2052,2052,2052,2052,2052,2052,2052,8,2112,2050,2,2050,2050,2,2,2050,2,2,2,2,2,256,256,256,256],[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256],[256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256]]
diff --git a/tests/samples/png b/tests/samples/png
deleted file mode 100644
index 34148d735..000000000
--- a/tests/samples/png
+++ /dev/null
@@ -1 +0,0 @@
-data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJEAAACRCAIAAABMus10AAAABnRSTlMA/wD/AP83WBt9AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACd0lEQVR4nO3dQW7jIABA0fFo7n/ldFnJC0sMBvu3762bJtUXMnUwHJ/P5w8pf5/+AAzTrEezHs16NOvRrEezHs16NOvRrEezHs16NOvRrEezHs16NOvRrEeznn8zLz6O467Pce20aOX6fa9XuJxeO/SbbzSzDMc469GsR7MezXqm5iAnNy5vHZplrJs4bPuLhhhnPZr1aNajWc+dc5CToavu0NV+6F7GU/OIdQ8cGWc9mvVo1qNZz8I5yFO2TUmeYpz1aNajWY9mPT9hDjKzPKTIOOvRrEezHs16Fs5B1l38n5pWvGQ6Y5z1aNajWY9mPXfOQbY9VDKzHmToq5ltf9EQ46xHsx7NejTrOV7yv/0M38Xwdpr1aNajWc9j+4PcuIvHzKO6626LrFsaa5z1aNajWY9mPfv2BzldhGd2AJm5gM9MOp7a0OzEOOvRrEezHs169u0PMnQB3/ZA7Utumgwxzno069GsR7Oefc/mzkwrtq34uHGrtJnffM0469GsR7MezXqm5iAzx7hse3pl3eKRpxhnPZr1aNajWc9j58XM3DXYtle79SDcQ7MezXo060mem7ttecg717AYZz2a9WjWo1lP8tzc6x9ed7fCfRD+k2Y9mvVo1pM8N3fmfbftALJuHa1x1qNZj2Y9mvUkz6y78fJ+4+LXbef1Gmc9mvVo1qNZT3IOcjLzeM6697UehG+a9WjWo1lP8tzck3WLR2Yez5n54WvGWY9mPZr1aNaTPDf32szK0XW3NnwX86tp1qNZj2Y9P+Hc3N/GOOvRrEezHs16NOvRrEezHs16NOvRrEezHs16NOvRrEezHs16NOvRrEezni+wifc/oOyB/wAAAABJRU5ErkJggg==
diff --git a/tests/samples/svg b/tests/samples/svg
deleted file mode 100644
index d7ae394f5..000000000
--- a/tests/samples/svg
+++ /dev/null
@@ -1 +0,0 @@
-data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBjbGFzcz0icXItc3ZnIHFyY29kZSIgdmlld0JveD0iMCAwIDI5IDI5IiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+DQo8cGF0aCBjbGFzcz0icXItMjA0OSBkYXJrIHFyY29kZSIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIxIiBkPSJNMTIgMTcgaDEgdjEgaC0xWiIvPg0KPHBhdGggY2xhc3M9InFyLTIwNTAgZGFyayBxcmNvZGUiIGZpbGw9IiMwMDAiIGZpbGwtb3BhY2l0eT0iMSIgZD0iTTEzIDQgaDEgdjEgaC0xWiBNMTYgNCBoMSB2MSBoLTFaIE0xMyA1IGgxIHYxIGgtMVogTTE2IDUgaDEgdjEgaC0xWiBNMTQgNiBoMSB2MSBoLTFaIE0xNiA2IGgxIHYxIGgtMVogTTE1IDcgaDEgdjEgaC0xWiBNMTMgOCBoMSB2MSBoLTFaIE0xNCA4IGgxIHYxIGgtMVogTTEzIDExIGgxIHYxIGgtMVogTTE0IDExIGgxIHYxIGgtMVogTTE0IDEyIGgxIHYxIGgtMVogTTQgMTMgaDEgdjEgaC0xWiBNNyAxMyBoMSB2MSBoLTFaIE04IDEzIGgxIHYxIGgtMVogTTkgMTMgaDEgdjEgaC0xWiBNMTEgMTMgaDEgdjEgaC0xWiBNMTQgMTMgaDEgdjEgaC0xWiBNMTYgMTMgaDEgdjEgaC0xWiBNMTkgMTMgaDEgdjEgaC0xWiBNMjEgMTMgaDEgdjEgaC0xWiBNMjIgMTMgaDEgdjEgaC0xWiBNMjQgMTMgaDEgdjEgaC0xWiBNNCAxNCBoMSB2MSBoLTFaIE02IDE0IGgxIHYxIGgtMVogTTggMTQgaDEgdjEgaC0xWiBNOSAxNCBoMSB2MSBoLTFaIE0xNCAxNCBoMSB2MSBoLTFaIE0xNiAxNCBoMSB2MSBoLTFaIE0xNyAxNCBoMSB2MSBoLTFaIE0xOCAxNCBoMSB2MSBoLTFaIE0xOSAxNCBoMSB2MSBoLTFaIE0yMCAxNCBoMSB2MSBoLTFaIE0yMyAxNCBoMSB2MSBoLTFaIE0yNCAxNCBoMSB2MSBoLTFaIE00IDE1IGgxIHYxIGgtMVogTTYgMTUgaDEgdjEgaC0xWiBNNyAxNSBoMSB2MSBoLTFaIE0xMSAxNSBoMSB2MSBoLTFaIE0xMiAxNSBoMSB2MSBoLTFaIE0xNCAxNSBoMSB2MSBoLTFaIE0xNiAxNSBoMSB2MSBoLTFaIE0xNyAxNSBoMSB2MSBoLTFaIE0yMSAxNSBoMSB2MSBoLTFaIE0yMyAxNSBoMSB2MSBoLTFaIE01IDE2IGgxIHYxIGgtMVogTTYgMTYgaDEgdjEgaC0xWiBNOCAxNiBoMSB2MSBoLTFaIE0xMyAxNiBoMSB2MSBoLTFaIE0xNCAxNiBoMSB2MSBoLTFaIE0xNSAxNiBoMSB2MSBoLTFaIE0xNyAxNiBoMSB2MSBoLTFaIE0yMCAxNiBoMSB2MSBoLTFaIE0yMSAxNiBoMSB2MSBoLTFaIE0yMyAxNiBoMSB2MSBoLTFaIE0xNCAxNyBoMSB2MSBoLTFaIE0xNyAxNyBoMSB2MSBoLTFaIE0xOSAxNyBoMSB2MSBoLTFaIE0yMSAxNyBoMSB2MSBoLTFaIE0yMyAxNyBoMSB2MSBoLTFaIE0xNCAxOCBoMSB2MSBoLTFaIE0xNyAxOCBoMSB2MSBoLTFaIE0xOCAxOCBoMSB2MSBoLTFaIE0yMCAxOCBoMSB2MSBoLTFaIE0yMSAxOCBoMSB2MSBoLTFaIE0yMiAxOCBoMSB2MSBoLTFaIE0xMyAxOSBoMSB2MSBoLTFaIE0xNSAxOSBoMSB2MSBoLTFaIE0xNiAxOSBoMSB2MSBoLTFaIE0xNyAxOSBoMSB2MSBoLTFaIE0xOCAxOSBoMSB2MSBoLTFaIE0yMSAxOSBoMSB2MSBoLTFaIE0yMiAxOSBoMSB2MSBoLTFaIE0xMyAyMCBoMSB2MSBoLTFaIE0xNCAyMCBoMSB2MSBoLTFaIE0xNSAyMCBoMSB2MSBoLTFaIE0xOCAyMCBoMSB2MSBoLTFaIE0yMiAyMCBoMSB2MSBoLTFaIE0yMyAyMCBoMSB2MSBoLTFaIE0yNCAyMCBoMSB2MSBoLTFaIE0xMyAyMSBoMSB2MSBoLTFaIE0xNyAyMSBoMSB2MSBoLTFaIE0yMCAyMSBoMSB2MSBoLTFaIE0yMSAyMSBoMSB2MSBoLTFaIE0yMyAyMSBoMSB2MSBoLTFaIE0xNCAyMiBoMSB2MSBoLTFaIE0xNSAyMiBoMSB2MSBoLTFaIE0xNyAyMiBoMSB2MSBoLTFaIE0yMCAyMiBoMSB2MSBoLTFaIE0yMiAyMiBoMSB2MSBoLTFaIE0xMyAyMyBoMSB2MSBoLTFaIE0xNCAyMyBoMSB2MSBoLTFaIE0xNSAyMyBoMSB2MSBoLTFaIE0xNiAyMyBoMSB2MSBoLTFaIE0xOCAyMyBoMSB2MSBoLTFaIE0yMCAyMyBoMSB2MSBoLTFaIE0yMSAyMyBoMSB2MSBoLTFaIE0yNCAyMyBoMSB2MSBoLTFaIE0xMyAyNCBoMSB2MSBoLTFaIE0xNSAyNCBoMSB2MSBoLTFaIE0xNiAyNCBoMSB2MSBoLTFaIE0xOSAyNCBoMSB2MSBoLTFaIi8+DQo8cGF0aCBjbGFzcz0icXItMjA1MiBkYXJrIHFyY29kZSIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIxIiBkPSJNNCA0IGgxIHYxIGgtMVogTTUgNCBoMSB2MSBoLTFaIE02IDQgaDEgdjEgaC0xWiBNNyA0IGgxIHYxIGgtMVogTTggNCBoMSB2MSBoLTFaIE05IDQgaDEgdjEgaC0xWiBNMTAgNCBoMSB2MSBoLTFaIE0xOCA0IGgxIHYxIGgtMVogTTE5IDQgaDEgdjEgaC0xWiBNMjAgNCBoMSB2MSBoLTFaIE0yMSA0IGgxIHYxIGgtMVogTTIyIDQgaDEgdjEgaC0xWiBNMjMgNCBoMSB2MSBoLTFaIE0yNCA0IGgxIHYxIGgtMVogTTQgNSBoMSB2MSBoLTFaIE0xMCA1IGgxIHYxIGgtMVogTTE4IDUgaDEgdjEgaC0xWiBNMjQgNSBoMSB2MSBoLTFaIE00IDYgaDEgdjEgaC0xWiBNMTAgNiBoMSB2MSBoLTFaIE0xOCA2IGgxIHYxIGgtMVogTTI0IDYgaDEgdjEgaC0xWiBNNCA3IGgxIHYxIGgtMVogTTEwIDcgaDEgdjEgaC0xWiBNMTggNyBoMSB2MSBoLTFaIE0yNCA3IGgxIHYxIGgtMVogTTQgOCBoMSB2MSBoLTFaIE0xMCA4IGgxIHYxIGgtMVogTTE4IDggaDEgdjEgaC0xWiBNMjQgOCBoMSB2MSBoLTFaIE00IDkgaDEgdjEgaC0xWiBNMTAgOSBoMSB2MSBoLTFaIE0xOCA5IGgxIHYxIGgtMVogTTI0IDkgaDEgdjEgaC0xWiBNNCAxMCBoMSB2MSBoLTFaIE01IDEwIGgxIHYxIGgtMVogTTYgMTAgaDEgdjEgaC0xWiBNNyAxMCBoMSB2MSBoLTFaIE04IDEwIGgxIHYxIGgtMVogTTkgMTAgaDEgdjEgaC0xWiBNMTAgMTAgaDEgdjEgaC0xWiBNMTggMTAgaDEgdjEgaC0xWiBNMTkgMTAgaDEgdjEgaC0xWiBNMjAgMTAgaDEgdjEgaC0xWiBNMjEgMTAgaDEgdjEgaC0xWiBNMjIgMTAgaDEgdjEgaC0xWiBNMjMgMTAgaDEgdjEgaC0xWiBNMjQgMTAgaDEgdjEgaC0xWiBNNCAxOCBoMSB2MSBoLTFaIE01IDE4IGgxIHYxIGgtMVogTTYgMTggaDEgdjEgaC0xWiBNNyAxOCBoMSB2MSBoLTFaIE04IDE4IGgxIHYxIGgtMVogTTkgMTggaDEgdjEgaC0xWiBNMTAgMTggaDEgdjEgaC0xWiBNNCAxOSBoMSB2MSBoLTFaIE0xMCAxOSBoMSB2MSBoLTFaIE00IDIwIGgxIHYxIGgtMVogTTEwIDIwIGgxIHYxIGgtMVogTTQgMjEgaDEgdjEgaC0xWiBNMTAgMjEgaDEgdjEgaC0xWiBNNCAyMiBoMSB2MSBoLTFaIE0xMCAyMiBoMSB2MSBoLTFaIE00IDIzIGgxIHYxIGgtMVogTTEwIDIzIGgxIHYxIGgtMVogTTQgMjQgaDEgdjEgaC0xWiBNNSAyNCBoMSB2MSBoLTFaIE02IDI0IGgxIHYxIGgtMVogTTcgMjQgaDEgdjEgaC0xWiBNOCAyNCBoMSB2MSBoLTFaIE05IDI0IGgxIHYxIGgtMVogTTEwIDI0IGgxIHYxIGgtMVoiLz4NCjxwYXRoIGNsYXNzPSJxci0yMDgwIGRhcmsgcXJjb2RlIiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9IjEiIGQ9Ik0xMiAxMCBoMSB2MSBoLTFaIE0xNCAxMCBoMSB2MSBoLTFaIE0xNiAxMCBoMSB2MSBoLTFaIE0xMCAxMiBoMSB2MSBoLTFaIE0xMCAxNCBoMSB2MSBoLTFaIE0xMCAxNiBoMSB2MSBoLTFaIi8+DQo8cGF0aCBjbGFzcz0icXItMjExMiBkYXJrIHFyY29kZSIgZmlsbD0iIzAwMCIgZmlsbC1vcGFjaXR5PSIxIiBkPSJNMTIgNCBoMSB2MSBoLTFaIE0xMiA2IGgxIHYxIGgtMVogTTEyIDcgaDEgdjEgaC0xWiBNMTIgOCBoMSB2MSBoLTFaIE00IDEyIGgxIHYxIGgtMVogTTUgMTIgaDEgdjEgaC0xWiBNNiAxMiBoMSB2MSBoLTFaIE03IDEyIGgxIHYxIGgtMVogTTEyIDEyIGgxIHYxIGgtMVogTTE3IDEyIGgxIHYxIGgtMVogTTIwIDEyIGgxIHYxIGgtMVogTTIxIDEyIGgxIHYxIGgtMVogTTIyIDEyIGgxIHYxIGgtMVogTTI0IDEyIGgxIHYxIGgtMVogTTEyIDIxIGgxIHYxIGgtMVogTTEyIDIyIGgxIHYxIGgtMVogTTEyIDIzIGgxIHYxIGgtMVogTTEyIDI0IGgxIHYxIGgtMVoiLz4NCjxwYXRoIGNsYXNzPSJxci0zMDcyIGRhcmsgcXJjb2RlIiBmaWxsPSIjMDAwIiBmaWxsLW9wYWNpdHk9IjEiIGQ9Ik02IDYgaDEgdjEgaC0xWiBNNyA2IGgxIHYxIGgtMVogTTggNiBoMSB2MSBoLTFaIE0yMCA2IGgxIHYxIGgtMVogTTIxIDYgaDEgdjEgaC0xWiBNMjIgNiBoMSB2MSBoLTFaIE02IDcgaDEgdjEgaC0xWiBNNyA3IGgxIHYxIGgtMVogTTggNyBoMSB2MSBoLTFaIE0yMCA3IGgxIHYxIGgtMVogTTIxIDcgaDEgdjEgaC0xWiBNMjIgNyBoMSB2MSBoLTFaIE02IDggaDEgdjEgaC0xWiBNNyA4IGgxIHYxIGgtMVogTTggOCBoMSB2MSBoLTFaIE0yMCA4IGgxIHYxIGgtMVogTTIxIDggaDEgdjEgaC0xWiBNMjIgOCBoMSB2MSBoLTFaIE02IDIwIGgxIHYxIGgtMVogTTcgMjAgaDEgdjEgaC0xWiBNOCAyMCBoMSB2MSBoLTFaIE02IDIxIGgxIHYxIGgtMVogTTcgMjEgaDEgdjEgaC0xWiBNOCAyMSBoMSB2MSBoLTFaIE02IDIyIGgxIHYxIGgtMVogTTcgMjIgaDEgdjEgaC0xWiBNOCAyMiBoMSB2MSBoLTFaIi8+DQo8L3N2Zz4NCg==
diff --git a/tests/samples/text b/tests/samples/text
deleted file mode 100644
index 23a7098f9..000000000
--- a/tests/samples/text
+++ /dev/null
@@ -1,29 +0,0 @@
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕🔴🔴🔴🔴🔴🔴🔴⭕🔴🔴⭕⭕🔴⭕🔴🔴🔴🔴🔴🔴🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕🔴⭕⭕🔴⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴⭕🔴⭕🔴⭕🔴⭕🔴🔴🔴⭕🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴⭕⭕🔴⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴🔴🔴⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴🔴🔴🔴🔴🔴🔴⭕🔴⭕🔴⭕🔴⭕🔴🔴🔴🔴🔴🔴🔴⭕⭕⭕⭕
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕🔴🔴⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕🔴🔴🔴🔴⭕⭕🔴⭕🔴⭕🔴⭕⭕🔴⭕⭕🔴🔴🔴⭕🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕⭕🔴🔴🔴⭕🔴⭕⭕🔴⭕🔴⭕⭕🔴⭕🔴🔴⭕🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕🔴⭕🔴🔴🔴⭕⭕⭕🔴⭕🔴🔴🔴🔴🔴⭕⭕🔴🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕🔴🔴⭕⭕⭕🔴🔴⭕🔴⭕🔴🔴⭕⭕⭕🔴⭕🔴⭕⭕⭕⭕⭕
-⭕⭕⭕⭕⭕🔴🔴⭕🔴⭕🔴⭕⭕🔴🔴🔴⭕🔴⭕⭕🔴🔴⭕🔴⭕⭕⭕⭕⭕
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕🔴⭕🔴⭕⭕🔴⭕🔴⭕🔴⭕🔴⭕⭕⭕⭕⭕
-⭕⭕⭕⭕🔴🔴🔴🔴🔴🔴🔴⭕⭕⭕🔴⭕⭕🔴🔴⭕🔴🔴🔴⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕🔴⭕🔴🔴🔴🔴⭕⭕🔴🔴⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕⭕🔴🔴🔴⭕⭕🔴⭕⭕⭕🔴🔴🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴🔴⭕⭕⭕🔴⭕⭕🔴🔴⭕🔴⭕⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴⭕🔴🔴⭕🔴⭕⭕🔴⭕🔴⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕🔴🔴🔴🔴🔴⭕🔴⭕🔴🔴⭕⭕🔴⭕⭕⭕⭕
-⭕⭕⭕⭕🔴🔴🔴🔴🔴🔴🔴⭕🔴🔴⭕🔴🔴⭕⭕🔴⭕⭕⭕⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
-⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕