Skip to content

Commit

Permalink
Merge pull request #4 from pascalbaljet/main
Browse files Browse the repository at this point in the history
Improve test suite
  • Loading branch information
onlime authored Mar 14, 2024
2 parents 880dec3 + 7fbada6 commit d5697e2
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 56 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: CI

on: [push]

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
php: [8.3, 8.2, 8.1]
laravel: [11.*, 10.*]
stability: [prefer-lowest, prefer-stable]
include:
- laravel: 11.*
testbench: 9.*
- laravel: 10.*
testbench: 8.*
exclude:
- laravel: 11.*
php: 8.1

name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
coverage: xdebug

- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
composer update --${{ matrix.stability }} --prefer-dist --no-interaction
- name: Execute tests
run: |
vendor/bin/pest
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
],
"require": {
"php": "^8.1",
"guzzlehttp/guzzle": "^7.6",
"illuminate/http": "^10.0|^11.0",
"illuminate/http": "^10.32|^11.0",
"illuminate/support": "^10.0|^11.0",
"monolog/monolog": "^3.0"
},
Expand All @@ -39,8 +38,9 @@
"pestphp/pest": "^2.33",
"pestphp/pest-plugin-arch": "^2.0",
"pestphp/pest-plugin-laravel": "^2.0",
"saloonphp/laravel-http-sender": "^2.0",
"saloonphp/laravel-plugin": "^3.0"
"saloonphp/laravel-http-sender": "^2.0|^3.0",
"saloonphp/laravel-plugin": "^3.0",
"spatie/invade": "^2.0"
},
"suggest": {
"saloonphp/laravel-plugin": "To support logging of Saloon events (^3.0)"
Expand Down Expand Up @@ -75,4 +75,4 @@
},
"minimum-stability": "stable",
"prefer-stable": true
}
}
5 changes: 3 additions & 2 deletions src/Mixins/PendingRequestMixin.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ public function log()
if (! is_null($name)) {
$logger = $logger->withName($name);
}
foreach ($messageFormats as $format) {
foreach ($messageFormats as $key => $format) {
// We'll use unshift instead of push, to add the middleware to the bottom of the stack, not the top
$stack->unshift(
Middleware::log($logger, new MessageFormatter($format))
Middleware::log($logger, new MessageFormatter($format)),
'http-client-global-logger-'.$key
);
}

Expand Down
47 changes: 0 additions & 47 deletions src/Providers/EventServiceProvider.php

This file was deleted.

22 changes: 20 additions & 2 deletions src/Providers/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@

namespace Onlime\LaravelHttpClientGlobalLogger\Providers;

use Illuminate\Http\Client\Events\RequestSending;
use Illuminate\Http\Client\Events\ResponseReceived;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
use Monolog\Handler\StreamHandler;
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogRequestSending;
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogResponseReceived;
use Onlime\LaravelHttpClientGlobalLogger\Mixins\PendingRequestMixin;
use Saloon\Laravel\Events\SendingSaloonRequest;
use Saloon\Laravel\Events\SentSaloonRequest;

class ServiceProvider extends BaseServiceProvider
{
Expand All @@ -18,15 +25,26 @@ public function register()

if (config('http-client-global-logger.enabled') &&
! config('http-client-global-logger.mixin')) {
$this->app->register(EventServiceProvider::class);
$this->registerEventListeners();
}
}

private function registerEventListeners(): void
{
// Laravel HTTP Client
Event::listen(RequestSending::class, LogRequestSending::class);
Event::listen(ResponseReceived::class, LogResponseReceived::class);

// Saloon
Event::listen(SendingSaloonRequest::class, LogRequestSending::class);
Event::listen(SentSaloonRequest::class, LogResponseReceived::class);
}

public function boot()
{
$this->publishes([
$this->configFileLocation() => config_path('http-client-global-logger.php'),
], 'config');
], 'http-client-global-logger');

$channel = config('http-client-global-logger.channel');
if (! array_key_exists($channel, config('logging.channels'))) {
Expand Down
113 changes: 113 additions & 0 deletions tests/EventHelperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

use GuzzleHttp\Psr7\Request as Psr7Request;
use GuzzleHttp\Psr7\Response as Psr7Response;
use Illuminate\Http\Client\Events\RequestSending;
use Illuminate\Http\Client\Events\ResponseReceived;
use Illuminate\Http\Client\Request as ClientRequest;
use Illuminate\Http\Client\Response as ClientResponse;
use Onlime\LaravelHttpClientGlobalLogger\EventHelper;
use Saloon\Enums\Method;
use Saloon\Http\Connector;
use Saloon\Http\PendingRequest;
use Saloon\Http\Request;
use Saloon\Http\Response;
use Saloon\Laravel\Events\SendingSaloonRequest;
use Saloon\Laravel\Events\SentSaloonRequest;

function psr7Request(): Psr7Request
{
return new Psr7Request('GET', 'http://localhost/test');
}

function psr7Response(): Psr7Response
{
return new Psr7Response(200, ['X-Foo' => 'Bar']);
}

function laravelHttpRequest(): ClientRequest
{
return new ClientRequest(psr7Request());
}

function laravelHttpResponse(): ClientResponse
{
return new ClientResponse(psr7Response());
}

it('resolves the psr request from Laravel\'s RequestSending event', function () {
$psrRequest = EventHelper::getPsrRequest(new RequestSending(laravelHttpRequest()));

expect($psrRequest)->toBeInstanceOf(Psr7Request::class)
->and($psrRequest->getMethod())->toBe('GET')
->and($psrRequest->getUri()->__toString())->toBe('http://localhost/test');
});

it('resolves the psr request from Laravel\'s ResponseReceived event', function () {
$psrRequest = EventHelper::getPsrRequest(new ResponseReceived(laravelHttpRequest(), laravelHttpResponse()));

expect($psrRequest)->toBeInstanceOf(Psr7Request::class)
->and($psrRequest->getMethod())->toBe('GET')
->and($psrRequest->getUri()->__toString())->toBe('http://localhost/test');
});

it('resolves the psr response from Laravel\'s ResponseReceived event', function () {
$psrResponse = EventHelper::getPsrResponse(new ResponseReceived(laravelHttpRequest(), laravelHttpResponse()));

expect($psrResponse)->toBeInstanceOf(Psr7Response::class)
->and($psrResponse->getStatusCode())->toBe(200)
->and($psrResponse->getHeaderLine('X-Foo'))->toBe('Bar');
});

function saloonPendingRequest(): PendingRequest
{
return new PendingRequest(
new class extends Connector
{
public function resolveBaseUrl(): string
{
return 'http://localhost';
}
},
new class extends Request
{
protected Method $method = Method::GET;

public function resolveEndpoint(): string
{
return '/test';
}
}
);
}

function saloonResponse(PendingRequest $pendingRequest): Response
{
return new Response(psr7Response(), $pendingRequest, $pendingRequest->createPsrRequest());
}

it('resolves the psr request from Saloon\'s SendingSaloonRequest event', function () {
$psrRequest = EventHelper::getPsrRequest(new SendingSaloonRequest(saloonPendingRequest()));

expect($psrRequest)->toBeInstanceOf(Psr7Request::class)
->and($psrRequest->getMethod())->toBe('GET')
->and($psrRequest->getUri()->__toString())->toBe('http://localhost/test');
});

it('resolves the psr request from Saloon\'s SentSaloonRequest event', function () {
$pendingRequest = saloonPendingRequest();
$psrRequest = EventHelper::getPsrRequest(new SentSaloonRequest($pendingRequest, saloonResponse($pendingRequest)));

expect($psrRequest)->toBeInstanceOf(Psr7Request::class)
->and($psrRequest->getMethod())->toBe('GET')
->and($psrRequest->getUri()->__toString())->toBe('http://localhost/test');
});

it('resolves the psr response from Saloon\'s SentSaloonRequest event', function () {
$pendingRequest = saloonPendingRequest();
$psrResponse = EventHelper::getPsrResponse(new SentSaloonRequest($pendingRequest, saloonResponse($pendingRequest)));

expect($psrResponse)->toBeInstanceOf(Psr7Response::class)
->and($psrResponse->getStatusCode())->toBe(200)
->and($psrResponse->getHeaderLine('X-Foo'))->toBe('Bar');
});
23 changes: 23 additions & 0 deletions tests/PendingRequestMixinTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

use GuzzleHttp\HandlerStack;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Onlime\LaravelHttpClientGlobalLogger\Mixins\PendingRequestMixin;

it('rebuilds the guzzle handler stack to include the logger middleware at the bottom of the stack', function () {
PendingRequest::mixin(new PendingRequestMixin);

$pendingRequest = Http::withHeaders(['X-Test' => 'true'])->log();

/** @var HandlerStack $handler */
$handler = $pendingRequest->getOptions()['handler'];

// We need to invade the HandlerStack to access the stack property or findByName method
expect($handler)->toBeInstanceOf(HandlerStack::class)
->and(invade($handler)->findByName('http-client-global-logger-0'))->toBeInt()
->and(invade($handler)->findByName('http-client-global-logger-1'))->toBeInt()
->and(fn () => invade($handler)->findByName('http-client-global-logger-2'))
->toThrow(\InvalidArgumentException::class);
});
79 changes: 79 additions & 0 deletions tests/ServiceProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

use Illuminate\Http\Client\Events\RequestSending;
use Illuminate\Http\Client\Events\ResponseReceived;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Event;
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogRequestSending;
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogResponseReceived;
use Onlime\LaravelHttpClientGlobalLogger\Providers\ServiceProvider;
use Saloon\Laravel\Events\SendingSaloonRequest;
use Saloon\Laravel\Events\SentSaloonRequest;

it('registers event listeners', function (string $eventName, string $listenerName) {
config([
'http-client-global-logger.enabled' => true,
'http-client-global-logger.mixin' => false,
]);

(new ServiceProvider(app()))->register();

$listeners = Event::getRawListeners()[$eventName] ?? [];

expect($listeners)->not->toBeEmpty()
->and($listeners)->toContain($listenerName);
})->with([
[RequestSending::class, LogRequestSending::class],
[ResponseReceived::class, LogResponseReceived::class],
[SendingSaloonRequest::class, LogRequestSending::class],
[SentSaloonRequest::class, LogResponseReceived::class],
]);

it('merges the default config', function () {
$config = config('http-client-global-logger');

expect($config)->toBeArray();

foreach ([
'enabled',
'mixin',
'channel',
'logfile',
'format',
'obfuscate',
'trim_response_body',
] as $key) {
expect($config)->toHaveKey($key);
}
});

it('can publish the config file', function () {
@unlink(config_path('http-client-global-logger.php'));

$this->artisan('vendor:publish', ['--tag' => 'http-client-global-logger']);

$this->assertFileExists(config_path('http-client-global-logger.php'));
});

it('configures the log channel', function () {
$defaultChannel = config('http-client-global-logger.channel');

$config = config('logging.channels.'.$defaultChannel);

expect($config)->toBeArray();
});

it('can register the mixin on the PendingRequest class', function (bool $mixin) {
PendingRequest::flushMacros();

config([
'http-client-global-logger.mixin' => $mixin,
]);

(new ServiceProvider(app()))->boot();

expect(PendingRequest::hasMacro('log'))->toBe($mixin);
})->with([
true,
false,
]);

0 comments on commit d5697e2

Please sign in to comment.