From 81c0ec66c049a0510b3ec0a621be5c5ad7f6407a Mon Sep 17 00:00:00 2001 From: Jasper Zonneveld Date: Thu, 22 Aug 2019 17:34:09 +0200 Subject: [PATCH] Use PSR-17 and PSR-18 interfaces --- CHANGELOG.md | 10 ++ README.MD | 54 ++++----- composer.json | 13 ++- src/Client.php | 165 +++++++++++++++------------- src/DocumentClient.php | 2 +- src/Interfaces/ClientInterface.php | 12 +- src/Providers/ServiceProvider.php | 42 +++---- tests/ClientTest.php | 171 ++++++++++++----------------- 8 files changed, 220 insertions(+), 249 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 549bfb4..ebd5cf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Changed + +* Switched from [PHP-HTTP](http://php-http.org/) to [PSR-18](https://www.php-fig.org/psr/psr-18/), its successor. +* The `\Swis\JsonApi\Client\Client` now uses [php-http/discovery](https://github.com/php-http/discovery) itself instead of the service provider. This should make usage without Laravel easier. +* Removed the `$baseUri` parameter from `\Swis\JsonApi\Client\Client::__construct()`, use `\Swis\JsonApi\Client\Client::setBaseUri()` instead. + +### Removed + +* Removed `\Swis\JsonApi\Client\Providers\ServiceProvider::getHttpClient()` and `\Swis\JsonApi\Client\Providers\ServiceProvider::getMessageFactory()` as the client now discovers these classes itself. Custom HTTP clients must now be registered within your own service provider using a custom container binding. + ### Fixed * Self and related links can not be `null` [#59](https://github.com/swisnl/json-api-client/pull/59). diff --git a/README.MD b/README.MD index 7b4a56c..4c1e905 100644 --- a/README.MD +++ b/README.MD @@ -19,12 +19,12 @@ A PHP package for mapping remote [JSON:API](http://jsonapi.org/) resources to El composer require swisnl/json-api-client ``` -N.B. Make sure you have installed a HTTP Client before you install this package or install one at the same time e.g. `composer require swisnl/json-api-client php-http/guzzle6-adapter`. +N.B. Make sure you have installed a PSR-18 HTTP Client before you install this package or install one at the same time e.g. `composer require swisnl/json-api-client php-http/guzzle6-adapter`. ### HTTP Client -We are decoupled from any HTTP messaging client with the help of [PHP-HTTP](http://docs.php-http.org/en/latest/httplug/users.html). -This requires another package providing [php-http/client-implementation](https://packagist.org/providers/php-http/client-implementation). +We are decoupled from any HTTP messaging client with the help of [PSR-18 HTTP Client](https://www.php-fig.org/psr/psr-18/). +This requires an extra package providing [psr/http-client-implementation](https://packagist.org/providers/psr/http-client-implementation). To use Guzzle 6, for example, simply require `php-http/guzzle6-adapter`: ``` bash @@ -498,25 +498,31 @@ The service provider registers the `TypeMapper` as a singleton so your entire ap ### Bind Clients The service provider registers the `Client` and `DocumentClient` to your application. -By default it uses [php-http/discovery](https://github.com/php-http/discovery) to find a HTTP client and message factory. -You can specify your own message factory by overwriting the `getMessageFactory()` method and your own HTTP client by overwriting the `getHttpClient()` method. -The first should return a message factory and the latter should return a HTTP client, both implementing HTTPlug. -These methods are the perfect place to add extra options to your HTTP client or register a mock HTTP client for your tests: +By default the `Client` uses [php-http/discovery](https://github.com/php-http/discovery) to find an available HTTP client, request factory and stream factory so you don't have to setup those yourself. +You can specify your own HTTP client, request factory or stream factory by customizing the container binding. +This is a perfect way to add extra options to your HTTP client or register a mock HTTP client for your tests: ``` php -protected function getHttpClient(): HttpClient +class ServiceProvider extends \Illuminate\Support\ServiceProvider { - if (app()->environment('testing')) { - return new \Swis\Http\Fixture\Client( - new \Swis\Http\Fixture\ResponseBuilder('/path/to/fixtures'); - ); + protected function register() + { + $this->app->bind(\Swis\JsonApi\Client\Client::class, function ($app) { + if ($app->environment('testing')) { + $httpClient = new \Swis\Http\Fixture\Client( + new \Swis\Http\Fixture\ResponseBuilder('/path/to/fixtures'); + ); + } else { + $httpClient = \Http\Adapter\Guzzle6\Client::createWithConfig( + [ + 'timeout' => 2, + ] + ); + } + + return new \Swis\JsonApi\Client\Client($httpClient); + }); } - - return \Http\Adapter\Guzzle6\Client::createWithConfig( - [ - 'timeout' => 2, - ] - ); } ``` @@ -524,18 +530,6 @@ N.B. This example uses our [swisnl/php-http-fixture-client](https://github.com/s This package allows you to easily mock requests with static fixtures. Definitely worth a try! -If you register your own service provider and use package auto discover, don't forget to exclude this package in your `package.json`: - -``` json -"extra": { - "laravel": { - "dont-discover": [ - "swisnl/json-api-client" - ] - } -}, -``` - ## Advanced usage diff --git a/composer.json b/composer.json index 5191b5b..e63a1f3 100644 --- a/composer.json +++ b/composer.json @@ -7,15 +7,20 @@ "ext-json": "*", "illuminate/support": "5.5.*|5.6.*|5.7.*|5.8.*", "jenssegers/model": "^1.1", - "php-http/client-implementation": "^1.0", - "php-http/discovery": "^1.0" + "nyholm/psr7": "^1.2", + "php-http/discovery": "^1.0", + "psr/http-client": "^1.0", + "psr/http-client-implementation": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-factory-implementation": "^1.0", + "psr/http-message": "^1.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.0", "graham-campbell/testbench": "^5.1", "phpunit/phpunit": "^6.1|^7.0|^8.0", - "php-http/guzzle6-adapter": "^1.1", - "php-http/mock-client": "^1.1" + "php-http/guzzle6-adapter": "^2.0", + "php-http/mock-client": "^1.2" }, "suggest": { "swisnl/php-http-fixture-client": "Allows for easily mocking API calls with fixtures in your tests" diff --git a/src/Client.php b/src/Client.php index e475783..244592c 100644 --- a/src/Client.php +++ b/src/Client.php @@ -2,68 +2,59 @@ namespace Swis\JsonApi\Client; -use Http\Client\Exception\HttpException; -use Http\Client\HttpClient; -use Http\Message\MessageFactory; +use Http\Discovery\Psr17FactoryDiscovery; +use Http\Discovery\Psr18ClientDiscovery; +use Psr\Http\Client\ClientInterface as HttpClientInterface; +use Psr\Http\Message\RequestFactoryInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Psr\Http\Message\StreamInterface; use Swis\JsonApi\Client\Interfaces\ClientInterface; class Client implements ClientInterface { /** - * @var string - */ - const METHOD_DELETE = 'DELETE'; - - /** - * @var string - */ - const METHOD_GET = 'GET'; - - /** - * @var string + * @var \Psr\Http\Client\ClientInterface */ - const METHOD_PATCH = 'PATCH'; + private $client; /** - * @var string + * @var \Psr\Http\Message\RequestFactoryInterface */ - const METHOD_POST = 'POST'; + private $requestFactory; /** - * @var \Http\Client\HttpClient + * @var \Psr\Http\Message\StreamFactoryInterface */ - private $client; + private $streamFactory; /** * @var string */ - private $baseUri; + private $baseUri = ''; /** - * @var MessageFactory + * @var array */ - private $messageFactory; - - protected $defaultHeaders = [ + private $defaultHeaders = [ 'Accept' => 'application/vnd.api+json', 'Content-Type' => 'application/vnd.api+json', ]; /** - * @param \Http\Client\HttpClient $client - * @param string $baseUri - * @param MessageFactory $messageFactory + * @param \Psr\Http\Client\ClientInterface|null $client + * @param \Psr\Http\Message\RequestFactoryInterface|null $requestFactory + * @param \Psr\Http\Message\StreamFactoryInterface|null $streamFactory */ public function __construct( - HttpClient $client, - string $baseUri, - MessageFactory $messageFactory + HttpClientInterface $client = null, + RequestFactoryInterface $requestFactory = null, + StreamFactoryInterface $streamFactory = null ) { - $this->client = $client; - $this->baseUri = $baseUri; - $this->messageFactory = $messageFactory; + $this->client = $client ?: Psr18ClientDiscovery::find(); + $this->requestFactory = $requestFactory ?: Psr17FactoryDiscovery::findRequestFactory(); + $this->streamFactory = $streamFactory ?: Psr17FactoryDiscovery::findStreamFactory(); } /** @@ -77,97 +68,124 @@ public function getBaseUri(): string /** * @param string $baseUri */ - public function setBaseUri(string $baseUri) + public function setBaseUri(string $baseUri): void { $this->baseUri = $baseUri; } + /** + * @return array + */ + public function getDefaultHeaders(): array + { + return $this->defaultHeaders; + } + + /** + * @param array $defaultHeaders + */ + public function setDefaultHeaders(array $defaultHeaders): void + { + $this->defaultHeaders = $defaultHeaders; + } + /** * @param string $endpoint * @param array $headers * - * @throws \Http\Client\Exception + * @throws \Psr\Http\Client\ClientExceptionInterface * * @return \Psr\Http\Message\ResponseInterface */ public function get(string $endpoint, array $headers = []): ResponseInterface { - return $this->request(static::METHOD_GET, $endpoint, null, $headers); + return $this->request('GET', $endpoint, null, $headers); } /** - * @param string $endpoint - * @param resource|string|int|float|bool|\Psr\Http\Message\StreamInterface|callable|null $body - * @param array $headers + * @param string $endpoint + * @param string|resource|\Psr\Http\Message\StreamInterface|null $body + * @param array $headers * - * @throws \Http\Client\Exception + * @throws \Psr\Http\Client\ClientExceptionInterface * * @return \Psr\Http\Message\ResponseInterface */ public function post(string $endpoint, $body, array $headers = []): ResponseInterface { - return $this->request(static::METHOD_POST, $endpoint, $body, $headers); + return $this->request('POST', $endpoint, $body, $headers); } /** - * @param string $endpoint - * @param resource|string|int|float|bool|\Psr\Http\Message\StreamInterface|callable|null $body - * @param array $headers + * @param string $endpoint + * @param string|resource|\Psr\Http\Message\StreamInterface|null $body + * @param array $headers * - * @throws \Http\Client\Exception + * @throws \Psr\Http\Client\ClientExceptionInterface * * @return \Psr\Http\Message\ResponseInterface */ public function patch(string $endpoint, $body, array $headers = []): ResponseInterface { - return $this->request(static::METHOD_PATCH, $endpoint, $body, $headers); + return $this->request('PATCH', $endpoint, $body, $headers); } /** * @param string $endpoint * @param array $headers * - * @throws \Http\Client\Exception + * @throws \Psr\Http\Client\ClientExceptionInterface * * @return \Psr\Http\Message\ResponseInterface */ public function delete(string $endpoint, array $headers = []): ResponseInterface { - return $this->request(static::METHOD_DELETE, $endpoint, null, $headers); + return $this->request('DELETE', $endpoint, null, $headers); } /** - * @param string $method - * @param string $endpoint - * @param resource|string|int|float|bool|\Psr\Http\Message\StreamInterface|callable|null $body - * @param array $headers + * @param string $method + * @param string $endpoint + * @param string|resource|\Psr\Http\Message\StreamInterface|null $body + * @param array $headers * - * @throws \Http\Client\Exception + * @throws \Psr\Http\Client\ClientExceptionInterface * * @return \Psr\Http\Message\ResponseInterface */ public function request(string $method, string $endpoint, $body = null, array $headers = []): ResponseInterface { - $request = $this->buildRequest($method, $endpoint, $body, $headers); - - try { - return $this->client->sendRequest($request); - } catch (HttpException $e) { - return $e->getResponse(); - } + return $this->client->sendRequest($this->buildRequest($method, $endpoint, $body, $headers)); } /** - * @param string $method - * @param string $endpoint - * @param resource|string|int|float|bool|\Psr\Http\Message\StreamInterface|callable|null $body - * @param array $headers + * @param string $method + * @param string $endpoint + * @param string|resource|\Psr\Http\Message\StreamInterface|null $body + * @param array $headers * * @return \Psr\Http\Message\RequestInterface */ protected function buildRequest(string $method, string $endpoint, $body = null, array $headers = []): RequestInterface { - return $this->messageFactory->createRequest($method, $this->getEndpoint($endpoint), $this->mergeHeaders($headers), $body); + $request = $this->requestFactory->createRequest($method, $this->getEndpoint($endpoint)); + + if ($body !== null) { + if (is_resource($body)) { + $body = $this->streamFactory->createStreamFromResource($body); + } + if (!($body instanceof StreamInterface)) { + $body = $this->streamFactory->createStream($body); + } + + $request = $request->withBody($body); + } + + foreach ($this->mergeHeaders($headers) as $name => $value) { + $request = $request->withHeader($name, $value); + } + + return $request; } /** @@ -180,18 +198,13 @@ protected function getEndpoint(string $endpoint): string return $this->baseUri.$endpoint; } - protected function mergeHeaders(array $headers = []): array + /** + * @param array $headers + * + * @return array + */ + protected function mergeHeaders(array $headers): array { return array_merge($this->defaultHeaders, $headers); } - - public function getDefaultHeaders(): array - { - return $this->defaultHeaders; - } - - public function setDefaultHeaders(array $defaultHeaders) - { - $this->defaultHeaders = $defaultHeaders; - } } diff --git a/src/DocumentClient.php b/src/DocumentClient.php index c4ff442..9e16f4c 100644 --- a/src/DocumentClient.php +++ b/src/DocumentClient.php @@ -42,7 +42,7 @@ public function getBaseUri(): string /** * @param string $baseUri */ - public function setBaseUri(string $baseUri) + public function setBaseUri(string $baseUri): void { $this->client->setBaseUri($baseUri); } diff --git a/src/Interfaces/ClientInterface.php b/src/Interfaces/ClientInterface.php index 2029d26..1c1dff6 100644 --- a/src/Interfaces/ClientInterface.php +++ b/src/Interfaces/ClientInterface.php @@ -15,18 +15,18 @@ interface ClientInterface public function get(string $endpoint, array $headers = []): ResponseInterface; /** - * @param string $endpoint - * @param resource|string|int|float|bool|\Psr\Http\Message\StreamInterface|callable|null $body - * @param array $headers + * @param string $endpoint + * @param string|resource|\Psr\Http\Message\StreamInterface|null $body + * @param array $headers * * @return \Psr\Http\Message\ResponseInterface */ public function patch(string $endpoint, $body, array $headers = []): ResponseInterface; /** - * @param string $endpoint - * @param resource|string|int|float|bool|\Psr\Http\Message\StreamInterface|callable|null $body - * @param array $headers + * @param string $endpoint + * @param string|resource|\Psr\Http\Message\StreamInterface|null $body + * @param array $headers * * @return \Psr\Http\Message\ResponseInterface */ diff --git a/src/Providers/ServiceProvider.php b/src/Providers/ServiceProvider.php index 3e0a91a..ebd6bde 100644 --- a/src/Providers/ServiceProvider.php +++ b/src/Providers/ServiceProvider.php @@ -2,10 +2,6 @@ namespace Swis\JsonApi\Client\Providers; -use Http\Client\HttpClient; -use Http\Discovery\HttpClientDiscovery; -use Http\Discovery\MessageFactoryDiscovery; -use Http\Message\MessageFactory; use Illuminate\Support\ServiceProvider as BaseServiceProvider; use Swis\JsonApi\Client\Client; use Swis\JsonApi\Client\DocumentClient; @@ -20,13 +16,6 @@ class ServiceProvider extends BaseServiceProvider { - public function boot() - { - $this->publishes([ - dirname(__DIR__, 2).'/config/' => config_path(), - ], 'config'); - } - public function register() { $this->mergeConfigFrom( @@ -39,6 +28,13 @@ public function register() $this->registerClients(); } + public function boot() + { + $this->publishes([ + dirname(__DIR__, 2).'/config/' => config_path(), + ], 'config'); + } + protected function registerSharedTypeMapper() { $this->app->singleton(TypeMapperInterface::class, TypeMapper::class); @@ -52,28 +48,16 @@ protected function registerParsers() protected function registerClients() { - $this->app->bind( - Client::class, - function () { - return new Client( - $this->getHttpClient(), - config('jsonapi.base_uri'), - $this->getMessageFactory() - ); + $this->app->extend( + ClientInterface::class, + static function (ClientInterface $client) { + $client->setBaseUri(config('jsonapi.base_uri')); + + return $client; } ); $this->app->bind(ClientInterface::class, Client::class); $this->app->bind(DocumentClientInterface::class, DocumentClient::class); } - - protected function getHttpClient(): HttpClient - { - return HttpClientDiscovery::find(); - } - - protected function getMessageFactory(): MessageFactory - { - return MessageFactoryDiscovery::find(); - } } diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 78205af..93e06e8 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -2,9 +2,8 @@ namespace Swis\JsonApi\Client\Tests; -use Http\Client\Common\Exception\LoopException; -use Http\Client\Exception\HttpException; -use Http\Discovery\MessageFactoryDiscovery; +use function GuzzleHttp\Psr7\stream_for; +use Http\Mock\Client as HttpMockClient; use Psr\Http\Message\ResponseInterface; use Swis\JsonApi\Client\Client; @@ -13,17 +12,11 @@ class ClientTest extends AbstractTest /** * @test */ - public function the_base_url_can_be_changed_after_instantiation() + public function it_can_get_and_set_the_base_url() { - $httpClient = new \Http\Mock\Client(); + $client = new Client(); - $client = new Client( - $httpClient, - 'http://www.test.com', - MessageFactoryDiscovery::find() - ); - - $this->assertEquals('http://www.test.com', $client->getBaseUri()); + $this->assertEquals('', $client->getBaseUri()); $client->setBaseUri('http://www.test-changed.com'); $this->assertEquals('http://www.test-changed.com', $client->getBaseUri()); } @@ -31,15 +24,9 @@ public function the_base_url_can_be_changed_after_instantiation() /** * @test */ - public function the_default_headers_can_be_changed_after_instantiation() + public function it_can_get_and_set_the_default_headers() { - $httpClient = new \Http\Mock\Client(); - - $client = new Client( - $httpClient, - 'http://www.test.com', - MessageFactoryDiscovery::find() - ); + $client = new Client(); $this->assertEquals( [ @@ -70,26 +57,20 @@ public function the_default_headers_can_be_changed_after_instantiation() */ public function it_builds_a_get_request() { - $baseUri = 'http://www.test.com'; - $endpoint = '/test/1'; + $httpClient = new HttpMockClient(); + $client = new Client($httpClient); - $httpClient = new \Http\Mock\Client(); + $endpoint = '/test/1'; - $client = new Client( - $httpClient, - $baseUri, - MessageFactoryDiscovery::find() - ); $response = $client->get($endpoint, ['X-Foo' => 'bar']); $this->assertInstanceOf(ResponseInterface::class, $response); $this->assertEquals('GET', $httpClient->getLastRequest()->getMethod()); - $this->assertEquals($baseUri.$endpoint, $httpClient->getLastRequest()->getUri()); + $this->assertEquals($endpoint, $httpClient->getLastRequest()->getUri()); $this->assertEquals( [ 'Accept' => ['application/vnd.api+json'], 'Content-Type' => ['application/vnd.api+json'], 'X-Foo' => ['bar'], - 'Host' => ['www.test.com'], ], $httpClient->getLastRequest()->getHeaders() ); @@ -100,26 +81,20 @@ public function it_builds_a_get_request() */ public function it_builds_a_delete_request() { - $baseUri = 'http://www.test.com'; - $endpoint = '/test/1'; + $httpClient = new HttpMockClient(); + $client = new Client($httpClient); - $httpClient = new \Http\Mock\Client(); + $endpoint = '/test/1'; - $client = new Client( - $httpClient, - $baseUri, - MessageFactoryDiscovery::find() - ); $response = $client->delete($endpoint, ['X-Foo' => 'bar']); $this->assertInstanceOf(ResponseInterface::class, $response); $this->assertEquals('DELETE', $httpClient->getLastRequest()->getMethod()); - $this->assertEquals($baseUri.$endpoint, $httpClient->getLastRequest()->getUri()); + $this->assertEquals($endpoint, $httpClient->getLastRequest()->getUri()); $this->assertEquals( [ 'Accept' => ['application/vnd.api+json'], 'Content-Type' => ['application/vnd.api+json'], 'X-Foo' => ['bar'], - 'Host' => ['www.test.com'], ], $httpClient->getLastRequest()->getHeaders() ); @@ -130,27 +105,21 @@ public function it_builds_a_delete_request() */ public function it_builds_a_patch_request() { - $baseUri = 'http://www.test.com'; - $endpoint = '/test/1'; + $httpClient = new HttpMockClient(); + $client = new Client($httpClient); - $httpClient = new \Http\Mock\Client(); + $endpoint = '/test/1'; - $client = new Client( - $httpClient, - $baseUri, - MessageFactoryDiscovery::find() - ); $response = $client->patch($endpoint, 'testvar=testvalue', ['Content-Type' => 'application/pdf', 'X-Foo' => 'bar']); $this->assertInstanceOf(ResponseInterface::class, $response); $this->assertEquals('PATCH', $httpClient->getLastRequest()->getMethod()); - $this->assertEquals('testvar=testvalue', $httpClient->getLastRequest()->getBody()->getContents()); - $this->assertEquals($baseUri.$endpoint, $httpClient->getLastRequest()->getUri()); + $this->assertEquals('testvar=testvalue', (string)$httpClient->getLastRequest()->getBody()); + $this->assertEquals($endpoint, $httpClient->getLastRequest()->getUri()); $this->assertEquals( [ 'Accept' => ['application/vnd.api+json'], 'Content-Type' => ['application/pdf'], 'X-Foo' => ['bar'], - 'Host' => ['www.test.com'], ], $httpClient->getLastRequest()->getHeaders() ); @@ -161,27 +130,21 @@ public function it_builds_a_patch_request() */ public function it_builds_a_post_request() { - $baseUri = 'http://www.test.com'; - $endpoint = '/test/1'; + $httpClient = new HttpMockClient(); + $client = new Client($httpClient); - $httpClient = new \Http\Mock\Client(); + $endpoint = '/test/1'; - $client = new Client( - $httpClient, - $baseUri, - MessageFactoryDiscovery::find() - ); $response = $client->post($endpoint, 'testvar=testvalue', ['Content-Type' => 'application/pdf', 'X-Foo' => 'bar']); $this->assertInstanceOf(ResponseInterface::class, $response); $this->assertEquals('POST', $httpClient->getLastRequest()->getMethod()); - $this->assertEquals('testvar=testvalue', $httpClient->getLastRequest()->getBody()->getContents()); - $this->assertEquals($baseUri.$endpoint, $httpClient->getLastRequest()->getUri()); + $this->assertEquals('testvar=testvalue', (string)$httpClient->getLastRequest()->getBody()); + $this->assertEquals($endpoint, $httpClient->getLastRequest()->getUri()); $this->assertEquals( [ 'Accept' => ['application/vnd.api+json'], 'Content-Type' => ['application/pdf'], 'X-Foo' => ['bar'], - 'Host' => ['www.test.com'], ], $httpClient->getLastRequest()->getHeaders() ); @@ -192,26 +155,20 @@ public function it_builds_a_post_request() */ public function it_builds_other_requests() { - $baseUri = 'http://www.test.com'; - $endpoint = '/test/1'; + $httpClient = new HttpMockClient(); + $client = new Client($httpClient); - $httpClient = new \Http\Mock\Client(); + $endpoint = '/test/1'; - $client = new Client( - $httpClient, - $baseUri, - MessageFactoryDiscovery::find() - ); $response = $client->request('OPTIONS', $endpoint, null, ['Content-Type' => 'application/pdf', 'X-Foo' => 'bar']); $this->assertInstanceOf(ResponseInterface::class, $response); $this->assertEquals('OPTIONS', $httpClient->getLastRequest()->getMethod()); - $this->assertEquals($baseUri.$endpoint, $httpClient->getLastRequest()->getUri()); + $this->assertEquals($endpoint, $httpClient->getLastRequest()->getUri()); $this->assertEquals( [ 'Accept' => ['application/vnd.api+json'], 'Content-Type' => ['application/pdf'], 'X-Foo' => ['bar'], - 'Host' => ['www.test.com'], ], $httpClient->getLastRequest()->getHeaders() ); @@ -220,53 +177,61 @@ public function it_builds_other_requests() /** * @test */ - public function it_passes_http_exceptions() + public function it_builds_requests_with_a_string_as_body() { - $baseUri = 'http://www.test.com'; - $endpoint = '/test/1'; + $httpClient = new HttpMockClient(); + $client = new Client($httpClient); - $httpClient = new \Http\Mock\Client(); + $body = 'testvar=testvalue'; - $request = $this->createMock(\Psr\Http\Message\RequestInterface::class); - $response = $this->createMock(\Psr\Http\Message\ResponseInterface::class); - - $exception = HttpException::create($request, $response); - $httpClient->setDefaultException($exception); + $response = $client->request('POST', '/test/1', $body); + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertEquals('testvar=testvalue', (string)$httpClient->getLastRequest()->getBody()); + } - $client = new Client( - $httpClient, - $baseUri, - MessageFactoryDiscovery::find() - ); + /** + * @test + */ + public function it_builds_requests_with_a_resource_as_body() + { + $httpClient = new HttpMockClient(); + $client = new Client($httpClient); - $httpResponse = $client->get($endpoint); + $body = fopen('php://temp', 'r+'); + fwrite($body, 'testvar=testvalue'); - $this->assertSame($response, $httpResponse); + $response = $client->request('POST', '/test/1', $body); + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertEquals('testvar=testvalue', (string)$httpClient->getLastRequest()->getBody()); } /** * @test */ - public function it_throws_non_http_exceptions() + public function it_builds_requests_with_a_stream_as_body() { - $baseUri = 'http://www.test.com'; - $endpoint = '/test/1'; + $httpClient = new HttpMockClient(); + $client = new Client($httpClient); - $httpClient = new \Http\Mock\Client(); + $body = stream_for('testvar=testvalue'); - $request = $this->createMock(\Psr\Http\Message\RequestInterface::class); - - $exception = new LoopException('Whoops, detected a loop!', $request); - $httpClient->setDefaultException($exception); + $response = $client->request('POST', '/test/1', $body); + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertEquals('testvar=testvalue', (string)$httpClient->getLastRequest()->getBody()); + } - $client = new Client( - $httpClient, - $baseUri, - MessageFactoryDiscovery::find() - ); + /** + * @test + */ + public function it_builds_requests_without_a_body() + { + $httpClient = new HttpMockClient(); + $client = new Client($httpClient); - $this->expectException(LoopException::class); + $body = null; - $client->get($endpoint); + $response = $client->request('POST', '/test/1', $body); + $this->assertInstanceOf(ResponseInterface::class, $response); + $this->assertEquals('', (string)$httpClient->getLastRequest()->getBody()); } }