diff --git a/.dist.env b/.dist.env new file mode 100644 index 0000000..31ae5a4 --- /dev/null +++ b/.dist.env @@ -0,0 +1,3 @@ +BASE_CONTAINER='' +APACHE_RUN_USER= +APACHE_RUN_GROUP= diff --git a/.docker/.gitignore b/.docker/.gitignore new file mode 100644 index 0000000..676188c --- /dev/null +++ b/.docker/.gitignore @@ -0,0 +1 @@ +supervisor.conf diff --git a/.docker/Dockerfile b/.docker/Dockerfile new file mode 100644 index 0000000..afa0275 --- /dev/null +++ b/.docker/Dockerfile @@ -0,0 +1,27 @@ +ARG BASE_CONTAINER +FROM ${BASE_CONTAINER} + +ARG BASE_CONTAINER +ENV BASE_CONTAINER ${BASE_CONTAINER} + +ARG APACHE_RUN_USER +ENV APACHE_RUN_USER ${APACHE_RUN_USER} + +ARG APACHE_RUN_GROUP +ENV APACHE_RUN_GROUP ${APACHE_RUN_GROUP} + +RUN apt update \ + && apt install -y mc + +RUN composer self-update --2 + +RUN php=$(echo "${BASE_CONTAINER}" | sed -nE 's/.*php-([0-9]+\.[0-9]+).*/\1/p') \ + && echo "xdebug.mode=develop,debug,coverage" >> /etc/php/${php}/mods-available/xdebug.ini + +RUN sed -iE "s/^export APACHE_RUN_USER=.*$/export APACHE_RUN_USER=${APACHE_RUN_USER}/g" /etc/apache2/envvars \ + && sed -iE "s/^export APACHE_RUN_GROUP=.*$/export APACHE_RUN_GROUP=${APACHE_RUN_GROUP}/g" /etc/apache2/envvars + +RUN phpenmod xdebug + +RUN usermod -a -G 1000 www-data +RUN usermod -a -G 1000 mysql diff --git a/.docker/supervisor.conf.dist b/.docker/supervisor.conf.dist new file mode 100644 index 0000000..2fb8386 --- /dev/null +++ b/.docker/supervisor.conf.dist @@ -0,0 +1,26 @@ +[supervisord] +nodaemon=true +[program:apache2] +command = /usr/sbin/apache2ctl -DFOREGROUND +user = root +autostart = false +stdout_events_enabled = true +stderr_events_enabled = true +[program:php-fpm] +command = /usr/sbin/php-fpm7.4 --nodaemonize +user = root +autostart = true +stdout_events_enabled = true +stderr_events_enabled = true +[program:redis] +command = /usr/bin/redis-server +user = root +autostart = false +stdout_events_enabled = true +stderr_events_enabled = true +[program:mysql] +command = /bin/bash -c "service mysql start && sleep 100" +user = root +autostart = false +stdout_events_enabled = true +stderr_events_enabled = true diff --git a/.gitignore b/.gitignore index d5ec54c..c0dc688 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,9 @@ composer.lock vendor/ bin/ .arcconfig +.phpunit.result.cache +dump.rdb + +coverage/ + +.env diff --git a/CHANGELOG.md b/CHANGELOG.md index 82db4c0..5c61a18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## 2.7.0 +### Changed +- Minimal version of PHP is increased to `7.4`. + +### Fixed +- Deprecation error in the RequestException class (occurs in PHP 8+ only) was fixed + +### Development tools +- PHPUnit version is narrowed to `^9.0`. +- Docker wrapper added + ## 2.6.2 ### Fixed - Fixed some deprecation warning temporarily for PHP 8.1. diff --git a/LOCAL_DEPLOYMENT.md b/LOCAL_DEPLOYMENT.md new file mode 100644 index 0000000..e9b2227 --- /dev/null +++ b/LOCAL_DEPLOYMENT.md @@ -0,0 +1,27 @@ +## Local deployment for development and/or running tests + +1. Run: +- cp .docker/supervisor.conf.dist .docker/supervisor.conf +- cp .dist.env .env + +Set environment values inside the `.env`.\ +Also configure `supervisor`'s options if you need. By default no services autostart but that's enough to run tests. +\ +Then: +- docker-compose build +- docker-compose up -d --remove-orphans + +2. Check: +- docker ps | grep lib-rest-client-common\ +You should see an output similar to this:\ +` +1a7b71f2d8f9 lib-rest-client-common-lib "/usr/bin/supervisord" 21 minutes ago Up 21 minutes rest-client-common +` +3. Enter the container:\ +`docker exec -it lib-rest-client-common bash`\ +and run inside:\ +`composer i` + +5. Run tests:\ +`bin/phpunit` +6. Enjoy your work! diff --git a/composer.json b/composer.json index 289dc48..ebe059f 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "name": "paysera/lib-rest-client-common", + "version": "2.7.0", "description": "Base classes/helpers used in REST Clients", "autoload": { "psr-4": { @@ -12,17 +13,25 @@ } }, "require": { - "php": ">=5.5", + "php": ">=7.4", "psr/http-message": "^1.0", "guzzlehttp/guzzle": "^6.0 | ^7.0", "fig/http-message-util": "^1.0", - "guzzlehttp/psr7": "^1.4|^2.0" + "guzzlehttp/psr7": "^1.4|^2.0", + "ext-json": "*" }, "minimum-stability": "stable", "require-dev": { - "phpunit/phpunit": "^4.8|^9.0|^10.0" + "phpunit/phpunit": "^9.0" }, "config": { "bin-dir": "bin" + }, + "archive": { + "exclude": [ + ".docker", + "docker-compose.yml", + "LOCAL_DEPLOYMENT.md" + ] } } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..699d5dd --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3' + +services: + lib: + container_name: rest-client-common + build: + context: . + dockerfile: .docker/Dockerfile + args: + - BASE_CONTAINER=${BASE_CONTAINER} + - APACHE_RUN_USER=${APACHE_RUN_USER} + - APACHE_RUN_GROUP=${APACHE_RUN_GROUP} + volumes: + - ./:/home/app/src + - ./.docker/supervisor.conf:/etc/supervisor/conf.d/supervisor.conf + extra_hosts: + - host.docker.internal:host-gateway diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a579db9..63f9bbf 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,16 +1,20 @@ - + backupGlobals = "false" + backupStaticAttributes = "false" + colors = "true" + convertErrorsToExceptions = "true" + convertNoticesToExceptions = "true" + convertWarningsToExceptions = "true" + convertDeprecationsToExceptions = "true" + processIsolation = "false" + stopOnFailure = "false" + bootstrap = "vendor/autoload.php"> + + + src/ + + tests diff --git a/src/Exception/RequestException.php b/src/Exception/RequestException.php index 19589f5..6119e0a 100644 --- a/src/Exception/RequestException.php +++ b/src/Exception/RequestException.php @@ -32,6 +32,7 @@ public function __construct( ResponseInterface $response, Exception $previous = null ) { + $message = ($message === null ? '' : $message); parent::__construct($message, 0, $previous); $this->request = $request; diff --git a/tests/AuthenticationMiddlewareTest.php b/tests/AuthenticationMiddlewareTest.php index 9671d41..1c05b96 100644 --- a/tests/AuthenticationMiddlewareTest.php +++ b/tests/AuthenticationMiddlewareTest.php @@ -6,6 +6,7 @@ use Fig\Http\Message\StatusCodeInterface; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Psr7\Response; +use Paysera\Component\RestClientCommon\Exception\ClientException; use Paysera\Component\RestClientCommon\Middleware\Authentication\BasicAuthentication; use Paysera\Component\RestClientCommon\Middleware\Authentication\OAuthAuthentication; use Paysera\Component\RestClientCommon\Tests\Client\TestClientFactory; @@ -112,9 +113,6 @@ public function testBasicAuthenticationAdded() $this->assertSame('Basic ' . base64_encode(sprintf('%s:%s', $username, $password)), $auth); } - /** - * @expectedException \Paysera\Component\RestClientCommon\Exception\ClientException - */ public function testUnauthorizedResponse() { TestClientFactory::setHandler( @@ -125,6 +123,18 @@ public function testUnauthorizedResponse() $factory = new TestClientFactory([]); $client = $factory->getTestClient(); - $client->getSomething(); + + try { + $client->getSomething(); + } catch (ClientException $exception) { + $this->assertNull($exception->getError()); + + $this->assertEquals( + "", + $exception->getResponse()->getBody()->getContents() + ); + + $this->assertEquals(401, $exception->getResponse()->getStatusCode()); + } } } diff --git a/tests/Client/TestClient.php b/tests/Client/TestClient.php index 37b935d..ffcea4e 100644 --- a/tests/Client/TestClient.php +++ b/tests/Client/TestClient.php @@ -4,6 +4,7 @@ use Fig\Http\Message\RequestMethodInterface; use Paysera\Component\RestClientCommon\Client\ApiClient; +use Paysera\Component\RestClientCommon\Exception\ClientException; class TestClient { @@ -20,6 +21,7 @@ public function withOptions(array $options) } /** + * @throws ClientException * @return null */ public function getSomething() diff --git a/tests/ClientExceptionTest.php b/tests/ClientExceptionTest.php index 74d3e70..926b114 100644 --- a/tests/ClientExceptionTest.php +++ b/tests/ClientExceptionTest.php @@ -16,7 +16,7 @@ class ClientExceptionTest extends TestCase { private $config; - public function setUp() + public function setUp(): void { $this->config = [ OAuthAuthentication::TYPE => [ @@ -103,7 +103,7 @@ public function testExceptionResponseWhenStreaming() $factory = new TestClientFactory($this->config); $client = $factory->getTestClient(); - $this->setExpectedException(ClientException::class); + $this->expectException(ClientException::class); $client->getSomething(); } diff --git a/tests/ClientWithOptionsTest.php b/tests/ClientWithOptionsTest.php index 38aa584..3d75f6c 100644 --- a/tests/ClientWithOptionsTest.php +++ b/tests/ClientWithOptionsTest.php @@ -24,7 +24,7 @@ public function testExceptionThrownWhenMissingUrlPlaceholders() ]) ); - $this->setExpectedException(ConfigurationException::class); + $this->expectException(ConfigurationException::class); new TestClientFactoryWithBaseUrlParams([]); } diff --git a/tests/Exception/RequestExceptionTest.php b/tests/Exception/RequestExceptionTest.php new file mode 100644 index 0000000..f909f30 --- /dev/null +++ b/tests/Exception/RequestExceptionTest.php @@ -0,0 +1,37 @@ +createMock(RequestInterface::class); + $responseMock = new Response(200, [], 'some body'); + + $errorReporting = error_reporting(); + + error_reporting(-1); + + try { + RequestException::create($requestMock, $responseMock); + + $this->assertTrue(true); + } catch (Deprecated $exception) { + $this->assertEquals( + 'Exception::__construct(): Passing null to parameter #1 ($message) of type string is deprecated', + $exception->getMessage() + ); + $this->fail($exception->getMessage()); + } finally { + error_reporting($errorReporting); + } + } +}