Skip to content

Commit 007789b

Browse files
authored
Merge pull request #141 from Sammyjo20/feature/v2-handling-simulated-responses
Feature | V2 Allow other simulated responses to take priority
2 parents c35888b + 0d9a22f commit 007789b

File tree

10 files changed

+99
-17
lines changed

10 files changed

+99
-17
lines changed

src/Contracts/MiddlewarePipeline.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@ interface MiddlewarePipeline
1111
/**
1212
* Add a middleware before the request is sent
1313
*
14-
* @param callable $closure
14+
* @param callable $callable
1515
* @param bool $prepend
1616
* @return $this
1717
*/
18-
public function onRequest(callable $closure, bool $prepend = false): static;
18+
public function onRequest(callable $callable, bool $prepend = false): static;
1919

2020
/**
2121
* Add a middleware after the request is sent
2222
*
23-
* @param callable $closure
23+
* @param callable $callable
2424
* @param bool $prepend
2525
* @return $this
2626
*/
27-
public function onResponse(callable $closure, bool $prepend = false): static;
27+
public function onResponse(callable $callable, bool $prepend = false): static;
2828

2929
/**
3030
* Process the request pipeline.

src/Contracts/PendingRequest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,19 @@ public function sendAsync(): PromiseInterface;
232232
* @return mixed
233233
*/
234234
public function createDtoFromResponse(Response $response): mixed;
235+
236+
/**
237+
* Set if the request is going to be sent asynchronously
238+
*
239+
* @param bool $asynchronous
240+
* @return $this
241+
*/
242+
public function setAsynchronous(bool $asynchronous): static;
243+
244+
/**
245+
* Check if the request is asynchronous
246+
*
247+
* @return bool
248+
*/
249+
public function isAsynchronous(): bool;
235250
}

src/Helpers/MiddlewarePipeline.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ public function __construct()
3737
/**
3838
* Add a middleware before the request is sent
3939
*
40-
* @param callable $closure
40+
* @param callable $callable
4141
* @param bool $prepend
4242
* @return $this
4343
*/
44-
public function onRequest(callable $closure, bool $prepend = false): static
44+
public function onRequest(callable $callable, bool $prepend = false): static
4545
{
46-
$this->requestPipeline = $this->requestPipeline->pipe(function (PendingRequest $pendingRequest) use ($closure) {
47-
$result = $closure($pendingRequest);
46+
$this->requestPipeline = $this->requestPipeline->pipe(function (PendingRequest $pendingRequest) use ($callable) {
47+
$result = $callable($pendingRequest);
4848

4949
if ($result instanceof PendingRequest) {
5050
return $result;
@@ -63,14 +63,14 @@ public function onRequest(callable $closure, bool $prepend = false): static
6363
/**
6464
* Add a middleware after the request is sent
6565
*
66-
* @param callable $closure
66+
* @param callable $callable
6767
* @param bool $prepend
6868
* @return $this
6969
*/
70-
public function onResponse(callable $closure, bool $prepend = false): static
70+
public function onResponse(callable $callable, bool $prepend = false): static
7171
{
72-
$this->responsePipeline = $this->responsePipeline->pipe(function (Response $response) use ($closure) {
73-
$result = $closure($response);
72+
$this->responsePipeline = $this->responsePipeline->pipe(function (Response $response) use ($callable) {
73+
$result = $callable($response);
7474

7575
return $result instanceof Response ? $result : $response;
7676
}, $prepend);

src/Http/Dispatcher.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ class Dispatcher implements DispatcherContract
1616
* Constructor
1717
*
1818
* @param PendingRequest $pendingRequest
19-
* @param bool $asynchronous
2019
*/
21-
public function __construct(protected PendingRequest $pendingRequest, protected bool $asynchronous = false)
20+
public function __construct(protected PendingRequest $pendingRequest)
2221
{
2322
//
2423
}
@@ -37,7 +36,7 @@ public function execute(): Response|PromiseInterface
3736
// to create the SimulatedResponse and return that. Otherwise, we
3837
// will send a real request to the sender.
3938

40-
$response = $this->getSender()->sendRequest($pendingRequest, $this->asynchronous);
39+
$response = $this->getSender()->sendRequest($pendingRequest, $pendingRequest->isAsynchronous());
4140

4241
// Next we will need to run the response pipeline. If the response
4342
// is a Response we can run it directly, but if it is

src/Http/Middleware/DetermineMockResponse.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ public function __invoke(PendingRequest $pendingRequest): PendingRequest|MockRes
2525
return $pendingRequest;
2626
}
2727

28+
if ($pendingRequest->hasSimulatedResponsePayload()) {
29+
return $pendingRequest;
30+
}
31+
2832
$mockClient = $pendingRequest->getMockClient();
2933

3034
// When we guess the next response from the MockClient it will

src/Http/PendingRequest.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ class PendingRequest implements PendingRequestContract
8787
*/
8888
protected ?SimulatedResponsePayload $simulatedResponsePayload = null;
8989

90+
/**
91+
* Determine if the pending request is asynchronous
92+
*
93+
* @var bool
94+
*/
95+
protected bool $asynchronous = false;
96+
9097
/**
9198
* Build up the request payload.
9299
*
@@ -436,6 +443,8 @@ protected function resolveResponseClass(): string
436443
*/
437444
public function send(): ResponseContract
438445
{
446+
$this->setAsynchronous(false);
447+
439448
return (new Dispatcher($this))->execute();
440449
}
441450

@@ -446,7 +455,9 @@ public function send(): ResponseContract
446455
*/
447456
public function sendAsync(): PromiseInterface
448457
{
449-
return (new Dispatcher($this, true))->execute();
458+
$this->setAsynchronous(true);
459+
460+
return (new Dispatcher($this))->execute();
450461
}
451462

452463
/**
@@ -459,4 +470,27 @@ public function createDtoFromResponse(ResponseContract $response): mixed
459470
{
460471
return $this->request->createDtoFromResponse($response) ?? $this->connector->createDtoFromResponse($response);
461472
}
473+
474+
/**
475+
* Set if the request is going to be sent asynchronously
476+
*
477+
* @param bool $asynchronous
478+
* @return PendingRequestContract
479+
*/
480+
public function setAsynchronous(bool $asynchronous): static
481+
{
482+
$this->asynchronous = $asynchronous;
483+
484+
return $this;
485+
}
486+
487+
/**
488+
* Check if the request is asynchronous
489+
*
490+
* @return bool
491+
*/
492+
public function isAsynchronous(): bool
493+
{
494+
return $this->asynchronous;
495+
}
462496
}

src/Http/Pool.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,10 @@ public function getRequests(): Generator
141141
* Send the pool and create a Promise
142142
*
143143
* @return \GuzzleHttp\Promise\PromiseInterface
144+
* @throws \ReflectionException
144145
* @throws \Saloon\Exceptions\InvalidPoolItemException
145-
* @throws \Saloon\Exceptions\SaloonException
146+
* @throws \Saloon\Exceptions\InvalidResponseClassException
147+
* @throws \Saloon\Exceptions\PendingRequestException
146148
*/
147149
public function send(): PromiseInterface
148150
{

tests/Feature/AsyncRequestTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
$data = $response->json();
2727

28+
expect($response->getPendingRequest()->isAsynchronous())->toBeTrue();
2829
expect($response->isMocked())->toBeFalse();
2930
expect($response->status())->toEqual(200);
3031

tests/Feature/RequestTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
$data = $response->json();
1818

19+
expect($response->getPendingRequest()->isAsynchronous())->toBeFalse();
1920
expect($response)->toBeInstanceOf(Response::class);
2021
expect($response->isMocked())->toBeFalse();
2122
expect($response->status())->toEqual(200);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Saloon\Http\Faking\MockClient;
6+
use Saloon\Http\Faking\MockResponse;
7+
use Saloon\Tests\Fixtures\Requests\UserRequest;
8+
use Saloon\Http\Faking\SimulatedResponsePayload;
9+
use Saloon\Tests\Fixtures\Connectors\TestConnector;
10+
11+
test('if a simulated response payload was provided before mock response it will take priority', function () {
12+
$mockClient = new MockClient([
13+
new MockResponse(['name' => 'Sam'], 200, ['X-Greeting' => 'Howdy']),
14+
]);
15+
16+
$fakeResponse = new SimulatedResponsePayload(['name' => 'Gareth'], 201, ['X-Greeting' => 'Hello']);
17+
18+
$request = new UserRequest;
19+
$request->middleware()->onRequest(fn () => $fakeResponse);
20+
21+
$response = TestConnector::make()->send($request, $mockClient);
22+
23+
expect($response->json())->toEqual(['name' => 'Gareth']);
24+
expect($response->status())->toEqual(201);
25+
expect($response->header('X-Greeting'))->toEqual('Hello');
26+
});

0 commit comments

Comments
 (0)