Skip to content

Commit d5697e2

Browse files
authored
Merge pull request #4 from pascalbaljet/main
Improve test suite
2 parents 880dec3 + 7fbada6 commit d5697e2

File tree

8 files changed

+286
-56
lines changed

8 files changed

+286
-56
lines changed

.github/workflows/ci.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: CI
2+
3+
on: [push]
4+
5+
jobs:
6+
test:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
fail-fast: true
10+
matrix:
11+
php: [8.3, 8.2, 8.1]
12+
laravel: [11.*, 10.*]
13+
stability: [prefer-lowest, prefer-stable]
14+
include:
15+
- laravel: 11.*
16+
testbench: 9.*
17+
- laravel: 10.*
18+
testbench: 8.*
19+
exclude:
20+
- laravel: 11.*
21+
php: 8.1
22+
23+
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
24+
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v4
28+
29+
- name: Setup PHP
30+
uses: shivammathur/setup-php@v2
31+
with:
32+
php-version: ${{ matrix.php }}
33+
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
34+
coverage: xdebug
35+
36+
- name: Install dependencies
37+
run: |
38+
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
39+
composer update --${{ matrix.stability }} --prefer-dist --no-interaction
40+
41+
- name: Execute tests
42+
run: |
43+
vendor/bin/pest

composer.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@
2727
],
2828
"require": {
2929
"php": "^8.1",
30-
"guzzlehttp/guzzle": "^7.6",
31-
"illuminate/http": "^10.0|^11.0",
30+
"illuminate/http": "^10.32|^11.0",
3231
"illuminate/support": "^10.0|^11.0",
3332
"monolog/monolog": "^3.0"
3433
},
@@ -39,8 +38,9 @@
3938
"pestphp/pest": "^2.33",
4039
"pestphp/pest-plugin-arch": "^2.0",
4140
"pestphp/pest-plugin-laravel": "^2.0",
42-
"saloonphp/laravel-http-sender": "^2.0",
43-
"saloonphp/laravel-plugin": "^3.0"
41+
"saloonphp/laravel-http-sender": "^2.0|^3.0",
42+
"saloonphp/laravel-plugin": "^3.0",
43+
"spatie/invade": "^2.0"
4444
},
4545
"suggest": {
4646
"saloonphp/laravel-plugin": "To support logging of Saloon events (^3.0)"
@@ -75,4 +75,4 @@
7575
},
7676
"minimum-stability": "stable",
7777
"prefer-stable": true
78-
}
78+
}

src/Mixins/PendingRequestMixin.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ public function log()
3333
if (! is_null($name)) {
3434
$logger = $logger->withName($name);
3535
}
36-
foreach ($messageFormats as $format) {
36+
foreach ($messageFormats as $key => $format) {
3737
// We'll use unshift instead of push, to add the middleware to the bottom of the stack, not the top
3838
$stack->unshift(
39-
Middleware::log($logger, new MessageFormatter($format))
39+
Middleware::log($logger, new MessageFormatter($format)),
40+
'http-client-global-logger-'.$key
4041
);
4142
}
4243

src/Providers/EventServiceProvider.php

Lines changed: 0 additions & 47 deletions
This file was deleted.

src/Providers/ServiceProvider.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@
22

33
namespace Onlime\LaravelHttpClientGlobalLogger\Providers;
44

5+
use Illuminate\Http\Client\Events\RequestSending;
6+
use Illuminate\Http\Client\Events\ResponseReceived;
57
use Illuminate\Http\Client\PendingRequest;
8+
use Illuminate\Support\Facades\Event;
69
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
710
use Monolog\Handler\StreamHandler;
11+
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogRequestSending;
12+
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogResponseReceived;
813
use Onlime\LaravelHttpClientGlobalLogger\Mixins\PendingRequestMixin;
14+
use Saloon\Laravel\Events\SendingSaloonRequest;
15+
use Saloon\Laravel\Events\SentSaloonRequest;
916

1017
class ServiceProvider extends BaseServiceProvider
1118
{
@@ -18,15 +25,26 @@ public function register()
1825

1926
if (config('http-client-global-logger.enabled') &&
2027
! config('http-client-global-logger.mixin')) {
21-
$this->app->register(EventServiceProvider::class);
28+
$this->registerEventListeners();
2229
}
2330
}
2431

32+
private function registerEventListeners(): void
33+
{
34+
// Laravel HTTP Client
35+
Event::listen(RequestSending::class, LogRequestSending::class);
36+
Event::listen(ResponseReceived::class, LogResponseReceived::class);
37+
38+
// Saloon
39+
Event::listen(SendingSaloonRequest::class, LogRequestSending::class);
40+
Event::listen(SentSaloonRequest::class, LogResponseReceived::class);
41+
}
42+
2543
public function boot()
2644
{
2745
$this->publishes([
2846
$this->configFileLocation() => config_path('http-client-global-logger.php'),
29-
], 'config');
47+
], 'http-client-global-logger');
3048

3149
$channel = config('http-client-global-logger.channel');
3250
if (! array_key_exists($channel, config('logging.channels'))) {

tests/EventHelperTest.php

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
use GuzzleHttp\Psr7\Request as Psr7Request;
4+
use GuzzleHttp\Psr7\Response as Psr7Response;
5+
use Illuminate\Http\Client\Events\RequestSending;
6+
use Illuminate\Http\Client\Events\ResponseReceived;
7+
use Illuminate\Http\Client\Request as ClientRequest;
8+
use Illuminate\Http\Client\Response as ClientResponse;
9+
use Onlime\LaravelHttpClientGlobalLogger\EventHelper;
10+
use Saloon\Enums\Method;
11+
use Saloon\Http\Connector;
12+
use Saloon\Http\PendingRequest;
13+
use Saloon\Http\Request;
14+
use Saloon\Http\Response;
15+
use Saloon\Laravel\Events\SendingSaloonRequest;
16+
use Saloon\Laravel\Events\SentSaloonRequest;
17+
18+
function psr7Request(): Psr7Request
19+
{
20+
return new Psr7Request('GET', 'http://localhost/test');
21+
}
22+
23+
function psr7Response(): Psr7Response
24+
{
25+
return new Psr7Response(200, ['X-Foo' => 'Bar']);
26+
}
27+
28+
function laravelHttpRequest(): ClientRequest
29+
{
30+
return new ClientRequest(psr7Request());
31+
}
32+
33+
function laravelHttpResponse(): ClientResponse
34+
{
35+
return new ClientResponse(psr7Response());
36+
}
37+
38+
it('resolves the psr request from Laravel\'s RequestSending event', function () {
39+
$psrRequest = EventHelper::getPsrRequest(new RequestSending(laravelHttpRequest()));
40+
41+
expect($psrRequest)->toBeInstanceOf(Psr7Request::class)
42+
->and($psrRequest->getMethod())->toBe('GET')
43+
->and($psrRequest->getUri()->__toString())->toBe('http://localhost/test');
44+
});
45+
46+
it('resolves the psr request from Laravel\'s ResponseReceived event', function () {
47+
$psrRequest = EventHelper::getPsrRequest(new ResponseReceived(laravelHttpRequest(), laravelHttpResponse()));
48+
49+
expect($psrRequest)->toBeInstanceOf(Psr7Request::class)
50+
->and($psrRequest->getMethod())->toBe('GET')
51+
->and($psrRequest->getUri()->__toString())->toBe('http://localhost/test');
52+
});
53+
54+
it('resolves the psr response from Laravel\'s ResponseReceived event', function () {
55+
$psrResponse = EventHelper::getPsrResponse(new ResponseReceived(laravelHttpRequest(), laravelHttpResponse()));
56+
57+
expect($psrResponse)->toBeInstanceOf(Psr7Response::class)
58+
->and($psrResponse->getStatusCode())->toBe(200)
59+
->and($psrResponse->getHeaderLine('X-Foo'))->toBe('Bar');
60+
});
61+
62+
function saloonPendingRequest(): PendingRequest
63+
{
64+
return new PendingRequest(
65+
new class extends Connector
66+
{
67+
public function resolveBaseUrl(): string
68+
{
69+
return 'http://localhost';
70+
}
71+
},
72+
new class extends Request
73+
{
74+
protected Method $method = Method::GET;
75+
76+
public function resolveEndpoint(): string
77+
{
78+
return '/test';
79+
}
80+
}
81+
);
82+
}
83+
84+
function saloonResponse(PendingRequest $pendingRequest): Response
85+
{
86+
return new Response(psr7Response(), $pendingRequest, $pendingRequest->createPsrRequest());
87+
}
88+
89+
it('resolves the psr request from Saloon\'s SendingSaloonRequest event', function () {
90+
$psrRequest = EventHelper::getPsrRequest(new SendingSaloonRequest(saloonPendingRequest()));
91+
92+
expect($psrRequest)->toBeInstanceOf(Psr7Request::class)
93+
->and($psrRequest->getMethod())->toBe('GET')
94+
->and($psrRequest->getUri()->__toString())->toBe('http://localhost/test');
95+
});
96+
97+
it('resolves the psr request from Saloon\'s SentSaloonRequest event', function () {
98+
$pendingRequest = saloonPendingRequest();
99+
$psrRequest = EventHelper::getPsrRequest(new SentSaloonRequest($pendingRequest, saloonResponse($pendingRequest)));
100+
101+
expect($psrRequest)->toBeInstanceOf(Psr7Request::class)
102+
->and($psrRequest->getMethod())->toBe('GET')
103+
->and($psrRequest->getUri()->__toString())->toBe('http://localhost/test');
104+
});
105+
106+
it('resolves the psr response from Saloon\'s SentSaloonRequest event', function () {
107+
$pendingRequest = saloonPendingRequest();
108+
$psrResponse = EventHelper::getPsrResponse(new SentSaloonRequest($pendingRequest, saloonResponse($pendingRequest)));
109+
110+
expect($psrResponse)->toBeInstanceOf(Psr7Response::class)
111+
->and($psrResponse->getStatusCode())->toBe(200)
112+
->and($psrResponse->getHeaderLine('X-Foo'))->toBe('Bar');
113+
});

tests/PendingRequestMixinTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
use GuzzleHttp\HandlerStack;
4+
use Illuminate\Http\Client\PendingRequest;
5+
use Illuminate\Support\Arr;
6+
use Illuminate\Support\Facades\Http;
7+
use Onlime\LaravelHttpClientGlobalLogger\Mixins\PendingRequestMixin;
8+
9+
it('rebuilds the guzzle handler stack to include the logger middleware at the bottom of the stack', function () {
10+
PendingRequest::mixin(new PendingRequestMixin);
11+
12+
$pendingRequest = Http::withHeaders(['X-Test' => 'true'])->log();
13+
14+
/** @var HandlerStack $handler */
15+
$handler = $pendingRequest->getOptions()['handler'];
16+
17+
// We need to invade the HandlerStack to access the stack property or findByName method
18+
expect($handler)->toBeInstanceOf(HandlerStack::class)
19+
->and(invade($handler)->findByName('http-client-global-logger-0'))->toBeInt()
20+
->and(invade($handler)->findByName('http-client-global-logger-1'))->toBeInt()
21+
->and(fn () => invade($handler)->findByName('http-client-global-logger-2'))
22+
->toThrow(\InvalidArgumentException::class);
23+
});

tests/ServiceProviderTest.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
use Illuminate\Http\Client\Events\RequestSending;
4+
use Illuminate\Http\Client\Events\ResponseReceived;
5+
use Illuminate\Http\Client\PendingRequest;
6+
use Illuminate\Support\Facades\Event;
7+
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogRequestSending;
8+
use Onlime\LaravelHttpClientGlobalLogger\Listeners\LogResponseReceived;
9+
use Onlime\LaravelHttpClientGlobalLogger\Providers\ServiceProvider;
10+
use Saloon\Laravel\Events\SendingSaloonRequest;
11+
use Saloon\Laravel\Events\SentSaloonRequest;
12+
13+
it('registers event listeners', function (string $eventName, string $listenerName) {
14+
config([
15+
'http-client-global-logger.enabled' => true,
16+
'http-client-global-logger.mixin' => false,
17+
]);
18+
19+
(new ServiceProvider(app()))->register();
20+
21+
$listeners = Event::getRawListeners()[$eventName] ?? [];
22+
23+
expect($listeners)->not->toBeEmpty()
24+
->and($listeners)->toContain($listenerName);
25+
})->with([
26+
[RequestSending::class, LogRequestSending::class],
27+
[ResponseReceived::class, LogResponseReceived::class],
28+
[SendingSaloonRequest::class, LogRequestSending::class],
29+
[SentSaloonRequest::class, LogResponseReceived::class],
30+
]);
31+
32+
it('merges the default config', function () {
33+
$config = config('http-client-global-logger');
34+
35+
expect($config)->toBeArray();
36+
37+
foreach ([
38+
'enabled',
39+
'mixin',
40+
'channel',
41+
'logfile',
42+
'format',
43+
'obfuscate',
44+
'trim_response_body',
45+
] as $key) {
46+
expect($config)->toHaveKey($key);
47+
}
48+
});
49+
50+
it('can publish the config file', function () {
51+
@unlink(config_path('http-client-global-logger.php'));
52+
53+
$this->artisan('vendor:publish', ['--tag' => 'http-client-global-logger']);
54+
55+
$this->assertFileExists(config_path('http-client-global-logger.php'));
56+
});
57+
58+
it('configures the log channel', function () {
59+
$defaultChannel = config('http-client-global-logger.channel');
60+
61+
$config = config('logging.channels.'.$defaultChannel);
62+
63+
expect($config)->toBeArray();
64+
});
65+
66+
it('can register the mixin on the PendingRequest class', function (bool $mixin) {
67+
PendingRequest::flushMacros();
68+
69+
config([
70+
'http-client-global-logger.mixin' => $mixin,
71+
]);
72+
73+
(new ServiceProvider(app()))->boot();
74+
75+
expect(PendingRequest::hasMacro('log'))->toBe($mixin);
76+
})->with([
77+
true,
78+
false,
79+
]);

0 commit comments

Comments
 (0)