Compare commits
1 Commits
master
...
acd9bfc2b3
| Author | SHA1 | Date | |
|---|---|---|---|
|
acd9bfc2b3
|
30
README.md
30
README.md
@@ -1,34 +1,6 @@
|
||||
symfony_example_app
|
||||
===================
|
||||
|
||||
Generátor QR kódů pro platby z https://topapi.top-test.cz
|
||||
|
||||
Quick setup
|
||||
-----------
|
||||
```bash
|
||||
# git clone https://git.nanobyte.cz/nanobyte-public/symfony_example_app.git
|
||||
# cd symfony_example_app
|
||||
# docker compose run --build php-fpm composer install
|
||||
# docker compose up --build
|
||||
```
|
||||
|
||||
- aplikace je dostupná na http://localhost:8000/
|
||||
- na adrese http://localhost:3000/explore je běžící grafana (s loki a tempo)
|
||||
- aplikace je nastavená (i na lokálu, běžně bych to nastavil až na devech/stage/PROD) aby posílala logy do lokiho a tracing do tempa pomocí otel protokolu
|
||||
|
||||
TODO:
|
||||
-----
|
||||
- [ ] Chybí speciální slovník nebo vypnutí slovníku pro testy
|
||||
- [ ] V reálný aplikaci bych použil Mockery, nicméně tady mě to přijde zbytečný
|
||||
- [ ] Nastavení cache ideálně v memcached/redis etc.
|
||||
- [ ] Vyhezkat OTEL logs, OTEL tracing
|
||||
- [ ] CI pipelines
|
||||
- [ ] k8s deployment
|
||||
- [ ] prometheus country na počet requestů/api (počet 200OK/500ERR)
|
||||
- [ ] Je dost na zvážení zda nezobrazit výsledek remote validace (response_create_400.json) a nenechat uživatele špatné hodnoty opravit. Ovšem znamená to že lokální validátory jsou špatně, chybu by bylo vhodné zalogovat do Sentry (do logu etc.) a opravit ji...
|
||||
- [ ] Na produkci bych statický content rozhodně netlačil přes app container ale přes static nginx container (asset-map:compile -> copy do nginx static containeru)
|
||||
- [ ] xdebug v dockeru
|
||||
|
||||
Poznámky
|
||||
--------
|
||||
- Nejsem kodér (a javascript developer), nevypadá to nijak extra ;-)
|
||||
- [ ] Vylepsit OTEL logs
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"ext-iconv": "*",
|
||||
"grpc/grpc": "^1.57",
|
||||
"guzzlehttp/promises": "*",
|
||||
"nubium/this-should-never-happen-exception": "^1.0",
|
||||
"nyholm/psr7": "*",
|
||||
"open-telemetry/exporter-otlp": "^1.0",
|
||||
"open-telemetry/opentelemetry-auto-symfony": "^1.0@beta",
|
||||
|
||||
43
composer.lock
generated
43
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "60708df22ad1ee4eca712d46f8e02c3b",
|
||||
"content-hash": "61ab226932ff1cf0567a22bbf802e20c",
|
||||
"packages": [
|
||||
{
|
||||
"name": "clue/stream-filter",
|
||||
@@ -658,47 +658,6 @@
|
||||
],
|
||||
"time": "2023-10-27T15:32:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nubium/this-should-never-happen-exception",
|
||||
"version": "v1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nubium/this-should-never-happen-exception.git",
|
||||
"reference": "3ed1b6f725881c527050c235e2503a8300427b86"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nubium/this-should-never-happen-exception/zipball/3ed1b6f725881c527050c235e2503a8300427b86",
|
||||
"reference": "3ed1b6f725881c527050c235e2503a8300427b86",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"jakub-onderka/php-parallel-lint": "~1.0",
|
||||
"phpstan/phpstan": "~0.9"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Nubium\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jiri Travnicek",
|
||||
"email": "jiri.travnicek@nubium.cz"
|
||||
}
|
||||
],
|
||||
"description": "Extend this exception and throw it anytime something unexpected happens.",
|
||||
"support": {
|
||||
"issues": "https://github.com/nubium/this-should-never-happen-exception/issues",
|
||||
"source": "https://github.com/nubium/this-should-never-happen-exception/tree/master"
|
||||
},
|
||||
"time": "2018-03-27T10:16:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nyholm/psr7",
|
||||
"version": "1.8.1",
|
||||
|
||||
@@ -31,7 +31,7 @@ services:
|
||||
arguments:
|
||||
$available_currencies: '%app.currencies%'
|
||||
|
||||
App\Service\StubQRCodeProvider:
|
||||
App\Service\StubQRCodeGenerator:
|
||||
arguments:
|
||||
$imagePath: '%kernel.project_dir%/assets/images/wip.png'
|
||||
|
||||
@@ -39,15 +39,8 @@ services:
|
||||
arguments:
|
||||
$username: '%app.usetreno.username%'
|
||||
$password: '%app.usetreno.password%'
|
||||
$retryCount: 2
|
||||
$retryWaitSeconds: 0.5
|
||||
|
||||
App\Service\Remote\UsetrenoQRCodeProvider:
|
||||
arguments:
|
||||
$retryCount: 2
|
||||
$retryWaitSeconds: 0.5
|
||||
|
||||
App\Service\CachedQRCodeProvider:
|
||||
App\Service\CachedQRCodeGenerator:
|
||||
arguments:
|
||||
$innerGenerator: '@App\Service\Remote\UsetrenoQRCodeProvider'
|
||||
$cacheDuration: 'PT60S'
|
||||
@@ -55,7 +48,7 @@ services:
|
||||
|
||||
App\Service\CurrencyListerInterface: '@App\Service\StaticCurrencyLister'
|
||||
App\Service\QRCodeQROptionsProviderInterface: '@App\Service\QRCodeQROptionsDefaultProvider'
|
||||
App\Service\QRCodeProviderInterface: '@App\Service\CachedQRCodeProvider'
|
||||
App\Service\QRCodeGeneratorInterface: '@App\Service\CachedQRCodeGenerator'
|
||||
|
||||
# add more service definitions when explicit configuration is needed
|
||||
# please note that last definitions always *replace* previous ones
|
||||
|
||||
@@ -11,7 +11,7 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||
class ExceptionController extends AbstractController
|
||||
{
|
||||
#[Route("give-me-error-please/exception")]
|
||||
public function makeException(): void {
|
||||
public function makeException() {
|
||||
throw new \InvalidArgumentException("There is exception");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Controller;
|
||||
use App\Entity\Input\QRCode\QRCode;
|
||||
use App\Form\Type\QRCodeType;
|
||||
use App\Service\DTO\QRCodeEntityConverter;
|
||||
use App\Service\QRCodeProviderInterface;
|
||||
use App\Service\QRCodeGeneratorInterface;
|
||||
use App\Service\QRCodeQROptionsProviderInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -17,7 +17,7 @@ class IndexController extends AbstractController {
|
||||
#[Route('/', name: 'homepage')]
|
||||
public function indexAction(
|
||||
Request $request,
|
||||
QRCodeProviderInterface $qrCodeGenerator,
|
||||
QRCodeGeneratorInterface $qrCodeGenerator,
|
||||
): Response
|
||||
{
|
||||
$qrCodeImage = null;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity\Remote\Usetreno;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class QRCodeMoneyType extends AbstractType
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('amount', NumberType::class, ['invalid_message' => 'messages.not_valid_amount'])
|
||||
->add('amount', NumberType::class)
|
||||
->add('currency', ChoiceType::class, [
|
||||
'choices' => array_combine(
|
||||
iterator_to_array($this->currencyLister->getCurrencies()),
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Service;
|
||||
|
||||
use App\Entity\DTO\QRCode\QRCode;
|
||||
|
||||
interface CacheableQRCodeProviderInterface extends QRCodeProviderInterface
|
||||
interface CacheableQRCodeGeneratorInterface extends QRCodeGeneratorInterface
|
||||
{
|
||||
// We can't calculate cache key directly from QRCode
|
||||
public function getCacheKey(QRCode $entity): string;
|
||||
@@ -10,14 +10,14 @@ use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
|
||||
final readonly class CachedQRCodeProvider implements QRCodeProviderInterface
|
||||
final readonly class CachedQRCodeGenerator implements QRCodeGeneratorInterface
|
||||
{
|
||||
private \DateInterval $cacheDuration;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(private CacheableQRCodeProviderInterface $innerGenerator, private CacheInterface $cache, private LoggerInterface $logger, string $cacheDuration)
|
||||
public function __construct(private CacheableQRCodeGeneratorInterface $innerGenerator, private CacheInterface $cache, private LoggerInterface $logger, string $cacheDuration)
|
||||
{
|
||||
$this->cacheDuration = new \DateInterval($cacheDuration);
|
||||
}
|
||||
@@ -6,7 +6,6 @@ use App\Entity\DTO\QRCode\QRCode;
|
||||
use App\Entity\DTO\QRCode\QRCodeMoney;
|
||||
use App\Entity\DTO\QRCode\QRCodePaymentIdentification;
|
||||
use App\Entity\DTO\QRCode\QRCodeQROptions;
|
||||
use Nubium\Exception\ThisShouldNeverHappenException;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
final readonly class QRCodeEntityConverter
|
||||
@@ -21,11 +20,11 @@ final readonly class QRCodeEntityConverter
|
||||
}
|
||||
|
||||
return new QRCode(
|
||||
$code->getIban() ?? throw new ThisShouldNeverHappenException("iban not set"),
|
||||
\DateTimeImmutable::createFromMutable($code->getDueDate() ?? throw new ThisShouldNeverHappenException("due date not set")),
|
||||
$code->getMessage() ?? throw new ThisShouldNeverHappenException("message not set"),
|
||||
$this->convertMoney($code->getMoney() ?? throw new ThisShouldNeverHappenException("money not set")),
|
||||
$this->convertCodeOptions($code->getCodeQROptions() ?? throw new ThisShouldNeverHappenException("codeQROptions not set")),
|
||||
$code->getIban() ?? throw new \InvalidArgumentException("iban not set"),
|
||||
\DateTimeImmutable::createFromMutable($code->getDueDate() ?? throw new \InvalidArgumentException("due date not set")),
|
||||
$code->getMessage() ?? throw new \InvalidArgumentException("message not set"),
|
||||
$this->convertMoney($code->getMoney() ?? throw new \InvalidArgumentException("money not set")),
|
||||
$this->convertCodeOptions($code->getCodeQROptions() ?? throw new \InvalidArgumentException("codeQROptions not set")),
|
||||
$this->convertIdentification($code->getPaymentIdentification())
|
||||
);
|
||||
}
|
||||
@@ -33,8 +32,8 @@ final readonly class QRCodeEntityConverter
|
||||
protected function convertMoney(\App\Entity\Input\QRCode\QRCodeMoney $money): QRCodeMoney
|
||||
{
|
||||
return new QRCodeMoney(
|
||||
$money->getAmount() ?? throw new ThisShouldNeverHappenException("amount not set"),
|
||||
$money->getCurrency() ?? throw new ThisShouldNeverHappenException("currency not set")
|
||||
$money->getAmount() ?? throw new \InvalidArgumentException("amount not set"),
|
||||
$money->getCurrency() ?? throw new \InvalidArgumentException("currency not set")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace App\Service;
|
||||
use App\Entity\DTO\QRCode\QRCode;
|
||||
use App\Service\Exception\QRCodeGeneratorException;
|
||||
|
||||
interface QRCodeProviderInterface
|
||||
interface QRCodeGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* Generates QR code from entity
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service\Remote\Exception;
|
||||
|
||||
class UsetrenoQRCodeRemoteServerErrorException extends UsetrenoQRCodeException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service\Remote;
|
||||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
trait RetryingFailClientTrait
|
||||
{
|
||||
/**
|
||||
* Lepsi zopakovat request kvuli drobnemu vypadku site nebo sluzby (u nedestruktivni operace)
|
||||
* nez hodit klientovi rovnou 500
|
||||
*
|
||||
* @param int $count
|
||||
* @param float $sleep
|
||||
* @param array<string> $catchableExceptions
|
||||
* @param LoggerInterface $logger
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function retryingFailRequest(
|
||||
int $count,
|
||||
float $sleep,
|
||||
array $catchableExceptions,
|
||||
LoggerInterface $logger,
|
||||
callable $callback
|
||||
): mixed {
|
||||
for ($i = 0; ; $i++) {
|
||||
try {
|
||||
return $callback();
|
||||
} catch (Exception $e) {
|
||||
foreach ($catchableExceptions as $exceptionClass) {
|
||||
if ($e instanceof $exceptionClass) {
|
||||
$logger->error("transport: fail request retrying... got catchable exception", [
|
||||
'exception' => $e,
|
||||
'try' => $i
|
||||
]);
|
||||
|
||||
usleep((int) ($sleep * 1_000_000));
|
||||
|
||||
if ($i == $count) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
// phpstan fail
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,7 @@ namespace App\Service\Remote;
|
||||
|
||||
use App\Entity\Remote\Usetreno\AuthRequest;
|
||||
use App\Service\Remote\Exception\AuthorizeException;
|
||||
use Nubium\Exception\ThisShouldNeverHappenException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpClient\Exception\TransportException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
@@ -18,16 +16,12 @@ use Symfony\Contracts\HttpClient\ResponseStreamInterface;
|
||||
|
||||
class UsetrenoHttpClient implements HttpClientInterface
|
||||
{
|
||||
use RetryingFailClientTrait;
|
||||
|
||||
const AUTHORIZE_API = "https://topapi.top-test.cz/chameleon/api/v1/token";
|
||||
|
||||
protected ?string $authorizationToken = null;
|
||||
|
||||
public function __construct(protected HttpClientInterface $innerClient, protected readonly LoggerInterface $logger, protected readonly string $username,
|
||||
protected readonly string $password,
|
||||
protected readonly float $retryWaitSeconds,
|
||||
protected readonly int $retryCount) { }
|
||||
protected readonly string $password) { }
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
@@ -94,8 +88,6 @@ class UsetrenoHttpClient implements HttpClientInterface
|
||||
"AUTHORIZE_API" => static::AUTHORIZE_API
|
||||
]);
|
||||
|
||||
$responseData = $this->retryingFailRequest($this->retryCount, $this->retryWaitSeconds,
|
||||
[AuthorizeException::class, TransportException::class], $this->logger, function() {
|
||||
$rq = $this->innerClient->request(
|
||||
"POST",
|
||||
static::AUTHORIZE_API,
|
||||
@@ -118,13 +110,6 @@ class UsetrenoHttpClient implements HttpClientInterface
|
||||
throw new AuthorizeException("Return code is not 200 OK (got: code: $statusCode)");
|
||||
}
|
||||
|
||||
return $responseData;
|
||||
});
|
||||
|
||||
if (!is_string($responseData)) {
|
||||
throw new ThisShouldNeverHappenException("responseData is not a string");
|
||||
}
|
||||
|
||||
$this->authorizationToken = $this->processAuthorizeResponse($responseData);
|
||||
$this->innerClient = $this->innerClient->withOptions([
|
||||
'headers' => [
|
||||
|
||||
@@ -4,26 +4,19 @@ declare(strict_types=1);
|
||||
namespace App\Service\Remote;
|
||||
|
||||
use App\Entity\DTO\QRCode\QRCode;
|
||||
use App\Service\CacheableQRCodeProviderInterface;
|
||||
use App\Service\CacheableQRCodeGeneratorInterface;
|
||||
use App\Service\Remote\Edge\QRCodeEntityConverter;
|
||||
use App\Service\Remote\Exception\UsetrenoQRCodeException;
|
||||
use App\Service\Remote\Exception\UsetrenoQRCodeRemoteServerErrorException;
|
||||
use Nubium\Exception\ThisShouldNeverHappenException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpClient\Exception\TransportException;
|
||||
|
||||
class UsetrenoQRCodeProvider implements CacheableQRCodeProviderInterface
|
||||
class UsetrenoQRCodeProvider implements CacheableQRCodeGeneratorInterface
|
||||
{
|
||||
use RetryingFailClientTrait;
|
||||
|
||||
const QRCODE_API = 'https://topapi.top-test.cz/chameleon/api/v1/qr-code/create-for-bank-account-payment';
|
||||
const QRCODE_METHOD = 'POST';
|
||||
|
||||
public function __construct(protected readonly LoggerInterface $logger,
|
||||
protected readonly UsetrenoHttpClient $client,
|
||||
protected readonly QRCodeEntityConverter $codeEntityConverter,
|
||||
protected readonly float $retryWaitSeconds,
|
||||
protected readonly int $retryCount) { }
|
||||
protected readonly QRCodeEntityConverter $codeEntityConverter) { }
|
||||
|
||||
public function generateQRCodeFromEntity(QRCode $entity): string
|
||||
{
|
||||
@@ -34,9 +27,6 @@ class UsetrenoQRCodeProvider implements CacheableQRCodeProviderInterface
|
||||
"edgeEntity" => $edgeEntity
|
||||
]);
|
||||
|
||||
$responseData = $this->retryingFailRequest($this->retryCount, $this->retryWaitSeconds,
|
||||
[TransportException::class, UsetrenoQRCodeRemoteServerErrorException::class], $this->logger,
|
||||
function() use ($edgeEntity) {
|
||||
$response = $this->client->request(static::QRCODE_METHOD, static::QRCODE_API, [
|
||||
'json' => $edgeEntity,
|
||||
]);
|
||||
@@ -51,10 +41,6 @@ class UsetrenoQRCodeProvider implements CacheableQRCodeProviderInterface
|
||||
"content" => $responseData,
|
||||
]);
|
||||
|
||||
if ($statusCode > 500) {
|
||||
throw new UsetrenoQRCodeRemoteServerErrorException("Return code is not 200 OK (got: code: $statusCode)");
|
||||
}
|
||||
|
||||
throw new UsetrenoQRCodeException("Return code is not 200 OK (got: code: $statusCode)");
|
||||
}
|
||||
|
||||
@@ -62,13 +48,6 @@ class UsetrenoQRCodeProvider implements CacheableQRCodeProviderInterface
|
||||
"responseContent" => $responseData,
|
||||
]);
|
||||
|
||||
return $responseData;
|
||||
});
|
||||
|
||||
if (!is_string($responseData)) {
|
||||
throw new ThisShouldNeverHappenException("responseData is not a string");
|
||||
}
|
||||
|
||||
return $this->parseBase64String($this->processQRCodeResponseEntity($responseData));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Service;
|
||||
|
||||
use App\Entity\DTO\QRCode\QRCode;
|
||||
|
||||
readonly final class StubQRCodeProvider implements QRCodeProviderInterface
|
||||
readonly final class StubQRCodeGenerator implements QRCodeGeneratorInterface
|
||||
{
|
||||
public function __construct(private string $imagePath) {}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<p>
|
||||
<div class="container">
|
||||
<div style="text-align: center;">
|
||||
<h1>{{ "page not found" | trans }}</h1>
|
||||
<a href="{{ path('homepage') }}">{{ "return to the homepage" | trans }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</p>
|
||||
{% endblock %}
|
||||
@@ -1,13 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<p>
|
||||
<div class="container">
|
||||
<div style="text-align: center;">
|
||||
<h1>{{ "internal server error" | trans }}</h1>
|
||||
{{ "our developers are doing their best to fix it. please try again later." | trans }}
|
||||
<a href="{{ path('homepage') }}">{{ "return to the homepage" | trans }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</p>
|
||||
{% endblock %}
|
||||
@@ -3,7 +3,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Service\QRCodeProviderInterface;
|
||||
use App\Service\QRCodeGeneratorInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
@@ -76,7 +76,7 @@ class IndexControllerTest extends WebTestCase
|
||||
|
||||
private function generateClientForSubmitTest(): KernelBrowser
|
||||
{
|
||||
$mock = $this->createMock(QRCodeProviderInterface::class);
|
||||
$mock = $this->createMock(QRCodeGeneratorInterface::class);
|
||||
$mock->expects($this->any())
|
||||
->method('generateQRCodeFromEntity')
|
||||
->will($this->returnValue('foo'));
|
||||
@@ -85,7 +85,7 @@ class IndexControllerTest extends WebTestCase
|
||||
$client = static::createClient();
|
||||
$client->disableReboot();
|
||||
|
||||
self::getContainer()->set('App\Service\QRCodeProviderInterface', $mock);
|
||||
self::getContainer()->set('App\Service\QRCodeGeneratorInterface', $mock);
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Service\Remote;
|
||||
|
||||
use App\Service\Remote\RetryingFailClientTrait;
|
||||
use App\Tests\Common\LoggerTrait;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class RetryingFailClientTraitTest extends TestCase {
|
||||
use LoggerTrait;
|
||||
|
||||
private int $callCount = 0;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp(); // TODO: Change the autogenerated stub
|
||||
$this->callCount = 0;
|
||||
}
|
||||
|
||||
public function testSuccess() {
|
||||
$trait = new class {
|
||||
use RetryingFailClientTrait {
|
||||
retryingFailRequest as public; // make the method public
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$result = $trait->retryingFailRequest(2, 0, [\RuntimeException::class], $this->getLogger(), function () {
|
||||
$this->callCount = $this->callCount + 1;
|
||||
return 'foo';
|
||||
});
|
||||
|
||||
$this->assertEquals(1, $this->callCount);
|
||||
$this->assertEquals('foo', $result);
|
||||
}
|
||||
public function testRetyingFail() {
|
||||
$trait = new class {
|
||||
use RetryingFailClientTrait {
|
||||
retryingFailRequest as public; // make the method public
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
try {
|
||||
$trait->retryingFailRequest(2, 0, [\RuntimeException::class], $this->getLogger(), function () {
|
||||
$this->callCount = $this->callCount + 1;
|
||||
throw new \RuntimeException("test");
|
||||
});
|
||||
} catch (\RuntimeException) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
$this->assertEquals(3, $this->callCount);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ class UsetrenoHttpClientTest extends TestCase
|
||||
]);
|
||||
$authorizedRequestResponse = clone $authMockResponse;
|
||||
$mockedClient = new MockHttpClient([$authMockResponse, $authorizedRequestResponse]);
|
||||
$client = new UsetrenoHttpClient($mockedClient, $this->getLogger(), "foo", "bar", 0, 0);
|
||||
$client = new UsetrenoHttpClient($mockedClient, $this->getLogger(), "foo", "bar");
|
||||
$client->request("POST", "https://www.root.cz/");
|
||||
$this->assertEquals("https://topapi.top-test.cz/chameleon/api/v1/token", $authMockResponse->getRequestUrl());
|
||||
$headers = $authorizedRequestResponse->getRequestOptions()['headers'];
|
||||
@@ -48,7 +48,7 @@ class UsetrenoHttpClientTest extends TestCase
|
||||
|
||||
$authorizedRequestResponse = clone $authMockResponse;
|
||||
$mockedClient = new MockHttpClient([$authMockResponse, $authorizedRequestResponse]);
|
||||
$client = new UsetrenoHttpClient($mockedClient, $this->getLogger(), "foo", "bar", 0, 0);
|
||||
$client = new UsetrenoHttpClient($mockedClient, $this->getLogger(), "foo", "bar");
|
||||
$client->request("POST", "https://www.root.cz/");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ class UsetrenoQRCodeProviderTest extends TestCase
|
||||
->method('convert')
|
||||
->will($this->returnValue($edgeEntity));
|
||||
|
||||
return new UsetrenoQRCodeProvider($this->getLogger(), $mock, $converterMock, 0, 0);
|
||||
return new UsetrenoQRCodeProvider($this->getLogger(), $mock, $converterMock);
|
||||
}
|
||||
|
||||
protected function createQRCodeEntityPair() {
|
||||
|
||||
@@ -9,7 +9,3 @@ Generate qr code: "Vygenerovat QR kód"
|
||||
Iban: "IBAN"
|
||||
QR code generator: "Generátor bankovních QR kódů"
|
||||
You can generate another QR code here: "Další QR kód si můžete vygenerovat zde"
|
||||
page not found: 'Stránka nenalezena'
|
||||
return to the homepage: 'Zpět na homepage'
|
||||
"our developers are doing their best to fix it. please try again later.": "Naši programátoři dělají maximum aby to opravili. Zkuste to prosím později."
|
||||
internal server error: 'Něco se pokazilo :-('
|
||||
|
||||
Reference in New Issue
Block a user