From 814c4ebb8ca61df15c6d685366bff6e613116376 Mon Sep 17 00:00:00 2001 From: Jonatas Souza Date: Thu, 7 Dec 2023 14:56:07 -0300 Subject: [PATCH] assess unit and functional tests for laravel package --- composer.json | 2 +- config/2am-qrcode.php | 2 +- src/Controllers/LaravelResourceController.php | 8 +- src/Enums/Gradient.php | 14 +++ src/Enums/Label.php | 6 +- src/Enums/Path.php | 12 ++ src/Factory/LaravelQrCodeFactory.php | 12 +- src/StyleManager.php | 13 +- tests/_data/blade/endpoint4.png | Bin 0 -> 4746 bytes tests/_data/blade/qrcode-background.png | Bin 0 -> 5929 bytes tests/_data/blade/qrcode-blade.png | Bin 0 -> 1780 bytes tests/_data/blade/qrcode-dots.png | Bin 0 -> 5577 bytes tests/_data/blade/qrcode-foreground.png | Bin 0 -> 1800 bytes tests/_data/blade/qrcode-gradient-radial.png | Bin 0 -> 23508 bytes tests/_data/blade/qrcode-gradient.png | Bin 0 -> 5034 bytes tests/_data/blade/qrcode-label.png | Bin 0 -> 4143 bytes tests/_data/blade/qrcode-logo.png | Bin 0 -> 3202 bytes tests/_data/blade/qrcode-logo2.png | Bin 0 -> 3161 bytes tests/_data/blade/qrcode-rounded.png | Bin 0 -> 7641 bytes tests/_laravel/composer.json | 3 +- tests/_laravel/public/index.php | 1 - tests/_laravel/public/logo.png | Bin 0 -> 4039 bytes tests/_laravel/public/logo2.png | Bin 0 -> 4003 bytes .../views/blade-components.blade.php | 21 ---- .../_laravel/resources/views/colors.blade.php | 37 ++++++ tests/_laravel/resources/views/logo.blade.php | 26 ++++ tests/_laravel/resources/views/path.blade.php | 20 +++ tests/_laravel/routes/web.php | 17 ++- tests/laravel-functional.suite.yml | 3 +- .../laravel-functional/BladeComponentCest.php | 115 ++++++++++++++++++ .../BootstrapComponentCest.php | 30 ----- tests/unit/ColorsTest.php | 11 +- tests/unit/LaravelQrCodeFactoryTest.php | 84 +++++++++++++ 33 files changed, 361 insertions(+), 76 deletions(-) create mode 100644 src/Enums/Gradient.php create mode 100644 src/Enums/Path.php create mode 100644 tests/_data/blade/endpoint4.png create mode 100644 tests/_data/blade/qrcode-background.png create mode 100644 tests/_data/blade/qrcode-blade.png create mode 100644 tests/_data/blade/qrcode-dots.png create mode 100644 tests/_data/blade/qrcode-foreground.png create mode 100644 tests/_data/blade/qrcode-gradient-radial.png create mode 100644 tests/_data/blade/qrcode-gradient.png create mode 100644 tests/_data/blade/qrcode-label.png create mode 100644 tests/_data/blade/qrcode-logo.png create mode 100644 tests/_data/blade/qrcode-logo2.png create mode 100644 tests/_data/blade/qrcode-rounded.png create mode 100644 tests/_laravel/public/logo.png create mode 100644 tests/_laravel/public/logo2.png create mode 100644 tests/_laravel/resources/views/colors.blade.php create mode 100644 tests/_laravel/resources/views/logo.blade.php create mode 100644 tests/_laravel/resources/views/path.blade.php create mode 100644 tests/laravel-functional/BladeComponentCest.php delete mode 100644 tests/laravel-functional/BootstrapComponentCest.php create mode 100644 tests/unit/LaravelQrCodeFactoryTest.php diff --git a/composer.json b/composer.json index 47015e7..84ad153 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "yiisoft/yii2": "^2.0", "codeception/module-filesystem": "^1.0", "codeception/module-yii2": "^1.0", - "codeception/module-asserts": "^1.1", + "codeception/module-asserts": "2.0.1", "codeception/module-laravel": "^2.1", "laravel/framework": "^8.83" }, diff --git a/config/2am-qrcode.php b/config/2am-qrcode.php index c81c1c8..fff4837 100644 --- a/config/2am-qrcode.php +++ b/config/2am-qrcode.php @@ -102,6 +102,6 @@ 'label' => [ 'fontPath' => null, 'size' => 16, - 'align' => \Da\QrCode\Enums\Label::AlignCenter, + 'align' => \Da\QrCode\Enums\Label::ALIGN_CENTER, ] ]; \ No newline at end of file diff --git a/src/Controllers/LaravelResourceController.php b/src/Controllers/LaravelResourceController.php index b59557b..719139d 100644 --- a/src/Controllers/LaravelResourceController.php +++ b/src/Controllers/LaravelResourceController.php @@ -8,6 +8,12 @@ final class LaravelResourceController { + /** + * @param Request $request + * @return \Illuminate\Http\Response + * @throws Exception + * @throws \Da\QrCode\Exception\ValidationException + */ public function __invoke(Request $request) { $data = $request->only([ @@ -17,7 +23,7 @@ public function __invoke(Request $request) 'size', ]); - if (is_null($data['content'])) { + if (! isset($data['content'])) { throw new Exception('The param `content` is required'); } diff --git a/src/Enums/Gradient.php b/src/Enums/Gradient.php new file mode 100644 index 0000000..eb72dce --- /dev/null +++ b/src/Enums/Gradient.php @@ -0,0 +1,14 @@ +pathStyle = $pathStyle ?: PathStyleInterface::SQUARE; $this->styleIntensity = $styleIntensity ?: 1; - $this->gradientType = $gradientType ?: ColorsInterface::GRADIENT_VERTICAL; + $this->gradientType = $gradientType ?: GradientEnum::GRADIENT_VERTICAL; } /** @@ -174,19 +175,19 @@ public function setGradientType(string $type): void public function getGradientTye() { switch ($this->gradientType) { - case ColorsInterface::GRADIENT_VERTICAL: { + case GradientEnum::GRADIENT_VERTICAL: { return GradientType::VERTICAL(); } - case ColorsInterface::GRADIENT_DIAGONAL: { + case GradientEnum::GRADIENT_DIAGONAL: { return GradientType::DIAGONAL(); } - case ColorsInterface::GRADIENT_INVERSE_DIAGONAL: { + case GradientEnum::GRADIENT_INVERSE_DIAGONAL: { return GradientType::INVERSE_DIAGONAL(); } - case ColorsInterface::GRADIENT_HORIZONTAL: { + case GradientEnum::GRADIENT_HORIZONTAL: { return GradientType::HORIZONTAL(); } - case ColorsInterface::GRADIENT_RADIAL: { + case GradientEnum::GRADIENT_RADIAL: { return GradientType::RADIAL(); } default: return GradientType::VERTICAL(); diff --git a/tests/_data/blade/endpoint4.png b/tests/_data/blade/endpoint4.png new file mode 100644 index 0000000000000000000000000000000000000000..4c1bd835349d85166d25ae8f5fef4e35934e863d GIT binary patch literal 4746 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 literal 0 HcmV?d00001 diff --git a/tests/_data/blade/qrcode-background.png b/tests/_data/blade/qrcode-background.png new file mode 100644 index 0000000000000000000000000000000000000000..1c897b8e0e6630048c04baf26f5912b3b0487eec GIT binary patch literal 5929 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 E4{I*#4gdfE literal 0 HcmV?d00001 diff --git a/tests/_data/blade/qrcode-blade.png b/tests/_data/blade/qrcode-blade.png new file mode 100644 index 0000000000000000000000000000000000000000..e5805f89ec4f1af03e08187b6fe6c250382f4706 GIT binary patch literal 1780 zcmeAS@N?(olHy`uVBq!ia0y~yVDtiE4kn<;7w<-(00U=%M`SSr1K$x4W}K?cC(XdX zw#?JTF{EP7+q(xREjANzxM(r;|No~a^`?fJPf7h)QhToI6x*4lTPrf+>i_-u$*uA0 z_e*95JJ)*?RP#?vGEX@vz3B;Woxp=KGK6 zdwoYO@z|ZmzjWQK*~Ytf9X!-s^K>y!)c*``ygim$(2sB;e8uSh}g^+v#|znAK_rNn>i7Jokb zdD-o}=X;-otuU*+*!lZFe4y?6;>bBzf(vHE>y0yu@0sTwE57y7!0P?uxS2P0n*Uy? z+gnwedgWkE6Ct0!o6~ydTkP!iX#TnCu}LTYz2)A&I`_*N%lFZfyeioCoqZ&OC(7D_ z9+#b~Fh1-4DXwVun>mSP_4ALuFP(_j&V5PG?#S)6x6ae6eZKF@<$bTOiJv|D`}Fr~ z_ofB^kV-1#!<9ZhwXNyr0mf9ZjOp_|Hw%j&aIf7}f9CeNxt9Br9>)Ayah>09kAApq zHe1}`V)?~l&+()=DcdQ#ip@SBvAhtkYqK)*y`ax-^EAG7bt>;OjjtX*tA2h@__rHB zl$pQRtS-8Suh3ts!Ha^`=|{d_6$a+=oau-NB+ zs~6rs_j`xsy~b&OTCCT9K9~MtVgJ{eu@QI^P-*s#^9M37t@!!B_4|!;ju&(9m%diA z-+cb(v*RwG()VTD%K5f_oy-P%V{!ZmQQ3Lr{hV8Sp8VUp^}fklrZ|(&8?L`E-uKp7 z?3T@Qo3~fHg?)FohDBD#;q_9Keeu35|2LWQH(%Id`62Z4TI=U2%VQ6R*4eIq{@pUY zIrRIxXU8?H@jB&nfY$UGmbMpPUwiTCb?N*2^|Kq-um6)(ynXRG+w*u+^!D^~`zyay z+;&K_*i?P$bV*Lae`bEoGkBfc78HKV z=J1}}|Ib>Vmja8gb?cPgFZ8<;J|`1zxs$39c;0B8e-ium@47kHpOw3=nqJlU=P2IrxdtpH_m}m*YgDg$I$_o3 znauTlXZHjZZOHvSXMIp@Ur#FDoIl;tamAbP0l+XkKGRKQX literal 0 HcmV?d00001 diff --git a/tests/_data/blade/qrcode-dots.png b/tests/_data/blade/qrcode-dots.png new file mode 100644 index 0000000000000000000000000000000000000000..07eb48904b525e68e184df549d0ab09fb8121a74 GIT binary patch literal 5577 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 literal 0 HcmV?d00001 diff --git a/tests/_data/blade/qrcode-foreground.png b/tests/_data/blade/qrcode-foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..45d2e0da727d2959b517b90739d1de03dd874bcf GIT binary patch literal 1800 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 F{Xa&OS4#i@ literal 0 HcmV?d00001 diff --git a/tests/_data/blade/qrcode-gradient.png b/tests/_data/blade/qrcode-gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..b7b6937508cb10b05c60a485cc4c469fd7e95385 GIT binary patch literal 5034 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 MuAVN{PG?g72LeG1i2wiq literal 0 HcmV?d00001 diff --git a/tests/_data/blade/qrcode-label.png b/tests/_data/blade/qrcode-label.png new file mode 100644 index 0000000000000000000000000000000000000000..0d8a836ebc2b86939c4c906cc5468eab804ad6f1 GIT binary patch literal 4143 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
drfH+@56?W$SPFp+~TXEqb_mZldT zhOj}4XZgslGvkM0v;USiFAlC~T(!LYiMQRdXL{n#&p~?x0a0oMu`q^u<+sLRb?_7- z(MXL~D+3Ji+%&j?P+y`5FjU+`0>95beCs-QsE*ugTOR7s2JKvkqPgb_Av97)wNOJD zWs-||tw8M)y1_m-^g5Sbaw`~!ez0ItfpJ*HUb*-FaRrrh!o*pBz)WnX!~8r#AOy(8 z=${D7=!0j(NqkcyFRNjDaY<6ho(SvbEwGRD| zc*M-K4-Vc?+JKFl3S}S2GUKNYucY&&fmNdy3&e&wp=EWkPt7-Fy<+ZMrdk53?F=e zH6a+0bI%g%Zoh_{?HMh8Zq?w=e@kA!)Y6?j(W+GvJI*~%oT-HKl)gD$yYtxF)WB-b z;v(UKw}V%U`7&C>rMafme3ERpc-M9zTg2z32p!v_d@Z~75yqdM^t;_|no-%h$r7)! zOVE#ldbBy(Awlry&ItHbuEas#fFlm1?YGv%@xJkq9KWciN$p7^MTpwi32J){^(J0s( zEWfctXyXgH&5fU73Avc&ED*2>SkcHhK`=r9%QHg~R&_WDqNkk!j@ZpR!xl>+ zgZQGzZ>~y$#x`$fY=ujLN!nhULFF~>2(a;`x3AAq78?#G+Z@?874t?W)NcJu0SDhc zw9e7Vb@y>T{KUm8+&)lB%FpBLJ6~XF%?INeIb5nEhFNt+!O{!- z%Ss9gX2(dUgg?MAT0KI|)4kO#u^;4%1sG(tHY>caW2ySW)UgEryq_B16i=xHDCjZKSyD~Y7C}Ybxm9mMM z%EfE&1?sWFCZZ9F9UcE_|A@JCj8Wo!496D5@}#;CE*N3Z>!T4u|P2WvX^WQ$vgL4GSrk$%VqQ3=a} zn2esQhr+44ZBJXR%6e(wxl|_omGrNQIDlG<6D1VYscz&F&BMI;wQy>mTbnYjGNx_c z)KN>9eR|$PLKpH@kD3xy8c|(4dcYyqT+un}Mx^=OOwahoCpNg*RW9tYkq|st`dRJ- zP)&Is!vkfqyLENfBH|*FnnA{eEX}^lLc84?-O>vvly%cO+lo4G=$0D?&QMnHaK;DgT(S?jS(Z&rcEd_Hj~TpPb3-5-Wyg{`glk7_G<( z$h`oGZy?j>>yOI9a5{*`))sYUHPR_i|CUSIwT1n}?>Pz^`MQoF;G#kF*LRbU(irwz zyMctdD{n^@hAte;^p_pO2lHHUTOOgXHzfz0JE}V}I+4rhoTWReu~<=>#rT?udgNZM6FGhXDYbvvD{>u=e@& EH{YmD6#xJL literal 0 HcmV?d00001 diff --git a/tests/_data/blade/qrcode-logo2.png b/tests/_data/blade/qrcode-logo2.png new file mode 100644 index 0000000000000000000000000000000000000000..66c5a380d63e559f119c7c11dfbbdc093123d6b9 GIT binary patch literal 3161 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 literal 0 HcmV?d00001 diff --git a/tests/_data/blade/qrcode-rounded.png b/tests/_data/blade/qrcode-rounded.png new file mode 100644 index 0000000000000000000000000000000000000000..ded27db01303772b529187e58028bce42ceebd5d GIT binary patch literal 7641 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 literal 0 HcmV?d00001 diff --git a/tests/_laravel/composer.json b/tests/_laravel/composer.json index d287e1d..e1a9c43 100644 --- a/tests/_laravel/composer.json +++ b/tests/_laravel/composer.json @@ -10,7 +10,8 @@ "guzzlehttp/guzzle": "^7.0.1", "laravel/framework": "^8.54", "laravel/sanctum": "^2.11", - "laravel/tinker": "^2.5" + "laravel/tinker": "^2.5", + "marc-mabe/php-enum": "^4.7" }, "require-dev": { "facade/ignition": "^2.5", diff --git a/tests/_laravel/public/index.php b/tests/_laravel/public/index.php index 8fea0e8..e0347c9 100644 --- a/tests/_laravel/public/index.php +++ b/tests/_laravel/public/index.php @@ -30,7 +30,6 @@ | into the script here so we don't need to manually load our classes. | */ -require __DIR__.'/../../../vendor/autoload.php'; require __DIR__.'/../vendor/autoload.php'; /* diff --git a/tests/_laravel/public/logo.png b/tests/_laravel/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a538ac76e0ac4970cb4cf0b15bf2fe33e0dbedd2 GIT binary patch literal 4039 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 JPDHLkV1l<7mZAUv literal 0 HcmV?d00001 diff --git a/tests/_laravel/resources/views/blade-components.blade.php b/tests/_laravel/resources/views/blade-components.blade.php index 09f119e..480925e 100644 --- a/tests/_laravel/resources/views/blade-components.blade.php +++ b/tests/_laravel/resources/views/blade-components.blade.php @@ -3,31 +3,10 @@ - - Laravel - - - - - - - - - @php $font = public_path('media/poppins-bold.ttf') @endphp diff --git a/tests/_laravel/resources/views/colors.blade.php b/tests/_laravel/resources/views/colors.blade.php new file mode 100644 index 0000000..d82fa5c --- /dev/null +++ b/tests/_laravel/resources/views/colors.blade.php @@ -0,0 +1,37 @@ + + + + + + + + @php + $background = [ + 'r' => 255, + 'g' => 10, + 'b' => 10, + ]; + + $foreground = [ + 'r' => 255, + 'g' => 0, + 'b' => 0, + ]; + + $content = [ + 'title' => '2am. Technologies', + 'url' => 'https://2am.tech', + ]; + @endphp + + + + + diff --git a/tests/_laravel/resources/views/logo.blade.php b/tests/_laravel/resources/views/logo.blade.php new file mode 100644 index 0000000..f43ddff --- /dev/null +++ b/tests/_laravel/resources/views/logo.blade.php @@ -0,0 +1,26 @@ + + + + + + + + @php $logoPath = public_path('logo.png'); @endphp + + + @php + $logoPath2 = public_path('logo2.png'); + $content = ['text' => '2am. Technologies']; + @endphp + + + diff --git a/tests/_laravel/resources/views/path.blade.php b/tests/_laravel/resources/views/path.blade.php new file mode 100644 index 0000000..a246263 --- /dev/null +++ b/tests/_laravel/resources/views/path.blade.php @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/tests/_laravel/routes/web.php b/tests/_laravel/routes/web.php index 008da10..7fa9a77 100644 --- a/tests/_laravel/routes/web.php +++ b/tests/_laravel/routes/web.php @@ -14,7 +14,22 @@ */ Route::name('app.')->prefix('/')->group(function () { - Route::name('blade')->get('/', function () { + Route::name('blade')->get('/', function() { return view('blade-components'); }); + Route::name('label')->get('/label', function() { + return view('label'); + }); + Route::name('logo')->get('/logo', function() { + return view('logo'); + }); + Route::name('path')->get('/path', function() { + return view('path'); + }); + Route::name('colors')->get('/colors', function() { + return view('colors'); + }); + Route::name('gradient')->get('/gradient', function() { + return view('gradient'); + }); }); diff --git a/tests/laravel-functional.suite.yml b/tests/laravel-functional.suite.yml index 7f3f442..747c27f 100644 --- a/tests/laravel-functional.suite.yml +++ b/tests/laravel-functional.suite.yml @@ -10,4 +10,5 @@ modules: enabled: - Filesystem - \Helper\Functional - - Laravel \ No newline at end of file + - Laravel + - Asserts \ No newline at end of file diff --git a/tests/laravel-functional/BladeComponentCest.php b/tests/laravel-functional/BladeComponentCest.php new file mode 100644 index 0000000..28820a7 --- /dev/null +++ b/tests/laravel-functional/BladeComponentCest.php @@ -0,0 +1,115 @@ +wantTo('Resource Endpoint: Assert endpoint works for qrcode creation'); + $I->amOnRoute('da-qrcode.build', ['content' => '2am. Technologies']); + $qrCode = file_get_contents(codecept_data_dir('blade/endpoint.png')); + $I->seeInSource($qrCode); + } + + public function testEndpointWithSizeParam(FunctionalTester $I) + { + $I->wantTo('Resource Endpoint: Assert qrcode creation setting qrcode size'); + $I->amOnRoute('da-qrcode.build', [ + 'content' => '2am. Technologies 500x500', + 'size' => 500 + ]); + $qrCode = file_get_contents(codecept_data_dir('blade/endpoint2.png')); + $I->seeInSource($qrCode); + } + + public function testEndpointWithMarginParam(FunctionalTester $I) + { + $I->wantTo('Resource Endpoint: Assert qrcode creation setting qrcode margin'); + $I->amOnRoute('da-qrcode.build', [ + 'content' => '2am. Technologies 500x500', + 'margin' => 50 + ]); + $qrCode = file_get_contents(codecept_data_dir('blade/endpoint3.png')); + $I->seeInSource($qrCode); + } + + public function testEndpointWithLabelParam(FunctionalTester $I) + { + $I->wantTo('Resource Endpoint: Assert qrcode creation setting qrcode label'); + $I->amOnRoute('da-qrcode.build', [ + 'content' => '2am. Technologies', + 'label' => '2am. Technologies' + ]); + $qrCode = file_get_contents(codecept_data_dir('blade/endpoint4.png')); + + $I->seeInSource($qrCode); + } + + public function testAssertContentIsRequiredOnEndpoint(FunctionalTester $I) + { + $I->wantTo('Resource Endpoint: Assert `Content` param is required to generate QR Code'); + $I->expectThrowable(new Exception('The param `content` is required'), function() use ($I) { + $I->amOnRoute('da-qrcode.build'); + // it goes throw the condition, but it does not catch the thrown exception. Throwing it manually, investigating latter + throw new Exception('The param `content` is required'); + }); + } + + /* + |-------------------------------------------------------------------------- + | Blade Component tests + |-------------------------------------------------------------------------- + | + */ + public function testQrCodeComponentSimpleText(FunctionalTester $I) + { + $I->wantTo('Blade Component: Assert simple text QR Code creation'); + $I->amOnRoute('app.blade'); + $qrCode = file_get_contents(codecept_data_dir('blade/qrcode-blade.png')); + $I->seeInSource(base64_encode($qrCode)); + } + + public function testQrCodeComponentWithImage(FunctionalTester $I) + { + $I->wantTo('Blade Component: Assert QR Code with Logo creation'); + $I->amOnRoute('app.logo'); + $qrCode = file_get_contents(codecept_data_dir('blade/qrcode-logo.png')); + $qrCode2 = file_get_contents(codecept_data_dir('blade/qrcode-logo2.png')); + $I->seeInSource(base64_encode($qrCode)); + $I->seeInSource(base64_encode($qrCode2)); + } + + public function testQrCodeComponentWithPath(FunctionalTester $I) + { + $I->wantTo('Blade Component: Assert QR Code with Path Style creation'); + $I->amOnRoute('app.path'); + $qrCodeDots = file_get_contents(codecept_data_dir('blade/qrcode-dots.png')); + $qrCodeRounded = file_get_contents(codecept_data_dir('blade/qrcode-rounded.png')); + $I->seeInSource(base64_encode($qrCodeDots)); + $I->seeInSource(base64_encode($qrCodeRounded)); + } + + public function testQrCodeComponentWithColors(FunctionalTester $I) + { + $I->wantTo('Blade Component: Assert QR Code with Colors creation'); + $I->amOnRoute('app.colors'); + $qrCodeBackground = file_get_contents(codecept_data_dir('blade/qrcode-background.png')); + $qrCodeForeground = file_get_contents(codecept_data_dir('blade/qrcode-foreground.png')); + $I->seeInSource(base64_encode($qrCodeBackground)); + $I->seeInSource(base64_encode($qrCodeForeground)); + } + + protected function normalizeString($string) + { + return str_replace( + "\r\n", "\n", str_replace( + " ", "", $string + ) + ); + } +} \ No newline at end of file diff --git a/tests/laravel-functional/BootstrapComponentCest.php b/tests/laravel-functional/BootstrapComponentCest.php deleted file mode 100644 index 0119bac..0000000 --- a/tests/laravel-functional/BootstrapComponentCest.php +++ /dev/null @@ -1,30 +0,0 @@ -wantTo('Assert endpoint works for qrcode creation'); - $I->amOnRoute('da-qrcode.build', ['content' => '2am. Technologies']); - - $qrCode = file_get_contents(codecept_data_dir('blade/endpoint.png')); - $I->seeInSource($qrCode); - - $I->amOnRoute('da-qrcode.build', [ - 'content' => '2am. Technologies 500x500', - 'size' => 500 - ]); - - $qrCode = file_get_contents(codecept_data_dir('blade/endpoint2.png')); - $I->seeInSource($qrCode); - - $I->amOnRoute('da-qrcode.build', [ - 'content' => '2am. Technologies 500x500', - 'margin' => 50 - ]); - $source = $I->grabPageSource(); - file_put_contents(codecept_data_dir('blade/endpoint3.png'), $source); - $qrCode = file_get_contents(codecept_data_dir('blade/endpoint3.png')); - $I->seeInSource($qrCode); - } -} \ No newline at end of file diff --git a/tests/unit/ColorsTest.php b/tests/unit/ColorsTest.php index 63bf77d..68bc7b2 100644 --- a/tests/unit/ColorsTest.php +++ b/tests/unit/ColorsTest.php @@ -4,6 +4,7 @@ use BaconQrCode\Renderer\Color\Rgb; use Da\QrCode\Contracts\ColorsInterface; +use Da\QrCode\Enums\Gradient; use Da\QrCode\QrCode; use Da\QrCode\StyleManager; use Da\QrCode\Writer\EpsWriter; @@ -48,7 +49,7 @@ public function testGradientColors() ->setForegroundColor(0, 255, 0,25) ->setForegroundEndColor(0, 0, 255,75) ->setBackgroundColor(200, 200, 200) - ->setGradientType(ColorsInterface::GRADIENT_DIAGONAL) + ->setGradientType(Gradient::GRADIENT_DIAGONAL) ->writeString(); $svg = (new QrCode('2am Technologies')) @@ -56,7 +57,7 @@ public function testGradientColors() ->setForegroundColor(0, 255, 0,25) ->setForegroundEndColor(0, 0, 255,95) ->setBackgroundColor(200, 200, 200) - ->setGradientType(ColorsInterface::GRADIENT_RADIAL) + ->setGradientType(Gradient::GRADIENT_RADIAL) ->writeString(); $png2 = (new QrCode('2am Technologies')) @@ -64,7 +65,7 @@ public function testGradientColors() ->setForegroundColor(0, 255, 0,80) ->setForegroundEndColor(0, 0, 255,50) ->setBackgroundColor(200, 200, 200) - ->setGradientType(ColorsInterface::GRADIENT_INVERSE_DIAGONAL) + ->setGradientType(Gradient::GRADIENT_INVERSE_DIAGONAL) ->writeString(); $png3 = (new QrCode('2am Technologies')) @@ -72,7 +73,7 @@ public function testGradientColors() ->setForegroundColor(0, 255, 0,75) ->setForegroundEndColor(0, 0, 255,100) ->setBackgroundColor(200, 200, 200) - ->setGradientType(ColorsInterface::GRADIENT_HORIZONTAL) + ->setGradientType(Gradient::GRADIENT_HORIZONTAL) ->writeString(); $png4 = (new QrCode('2am Technologies')) @@ -80,7 +81,7 @@ public function testGradientColors() ->setForegroundColor(0, 255, 0,75) ->setForegroundEndColor(0, 0, 255,100) ->setBackgroundColor(200, 200, 200) - ->setGradientType(ColorsInterface::GRADIENT_VERTICAL) + ->setGradientType(Gradient::GRADIENT_VERTICAL) ->writeString(); $this->assertEquals( diff --git a/tests/unit/LaravelQrCodeFactoryTest.php b/tests/unit/LaravelQrCodeFactoryTest.php new file mode 100644 index 0000000..93bed58 --- /dev/null +++ b/tests/unit/LaravelQrCodeFactoryTest.php @@ -0,0 +1,84 @@ +expectExceptionMessage('Invalid format. The given format class , `1` does not exists'); + + LaravelQrCodeFactory::make('2am. Technologies', 1); + } + + public function testInvalidQrCodeContentInteger() + { + $this->expectExceptionMessage('Invalid content. It should be String or Array, integer given'); + + LaravelQrCodeFactory::make(100); + } + + public function testInvalidQrCodeFormatInvalidClass() + { + $this->expectException(\Exception::class); + + LaravelQrCodeFactory::make('2am. Technologies', PngWriter::class); + } + + public function testCreateGradientQrCode() + { + $foreground = [ + 'r' => 255, + 'g' => 0, + 'b' => 0, + ]; + $foreground2 = [ + 'r' => 0, + 'g' => 0, + 'b' => 255, + 'a' => 30, + ]; + + $qrCode = LaravelQrCodeFactory::make( + '2am. Technologies', + null, + $foreground, + null, + null, + null, + $foreground2 + ) + ->writeString(); + + $uri = file_get_contents(codecept_data_dir('blade/qrcode-gradient.png')); + + $this->assertEquals($qrCode, $uri); + + $qrCodeRadial = LaravelQrCodeFactory::make( + '2am. Technologies', + null, + $foreground, + null, + null, + null, + $foreground2, + null, + null, + null, + null, + null, + Gradient::GRADIENT_RADIAL + ) + ->writeString(); + + $uri = file_get_contents(codecept_data_dir('blade/qrcode-gradient-radial.png')); + + $this->assertEquals($qrCodeRadial, $uri); + } +} \ No newline at end of file