Skip to content

Instantly share code, notes, and snippets.

@Sammyjo20
Last active July 11, 2022 21:25
Show Gist options
  • Save Sammyjo20/56928414d4d512f8c3d84bcf097c312d to your computer and use it in GitHub Desktop.
Save Sammyjo20/56928414d4d512f8c3d84bcf097c312d to your computer and use it in GitHub Desktop.
Record a Saloon Response to create a fixture
<?php
/**
* Record a request and respond with a fixture.
*
* @throws \Sammyjo20\Saloon\Exceptions\SaloonInvalidMockResponseCaptureMethodException
* @throws ReflectionException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \Sammyjo20\Saloon\Exceptions\SaloonException
* @throws JsonException
*/
function recordSend(TMDB $sdk, SaloonRequest $request, string $customKey = null): SaloonResponse
{
$fixtureName = $customKey ?? (new ReflectionClass($request))->getShortName();
$path = __DIR__ . '/Fixtures/' . $fixtureName . '.json';
try {
$fixture = file_get_contents($path);
} catch (Throwable $ex) {
$fixture = null;
}
// If we have found a fixture, we will attempt to decode it and convert it into a MockResponse.
if (isset($fixture)) {
$fixture = json_decode($fixture, true, 512, JSON_THROW_ON_ERROR);
$mockResponse = unserialize($fixture['mockResponse'], ['allowed_classes' => [MockResponse::class]]);
$mockClient = new MockClient([$mockResponse]);
return $sdk->send($request, $mockClient);
}
// However if the fixture does not exist, we will register a response interceptor which will
// store the fixture if the request is successful, ready for the next request.
$sdk->addResponseInterceptor(function (SaloonRequest $request, TMDBResponse $response) use ($path) {
if ($response->failed()) {
return $response;
}
$mockResponse = new MockResponse($response->body(), $response->status(), $response->headers());
$data = ['mockResponse' => serialize($mockResponse)];
file_put_contents($path, json_encode($data));
return $response;
});
return $sdk->send($request);
}
@Sammyjo20
Copy link
Author

Sammyjo20 commented Jul 11, 2022

Here's the usage:

test('you can retrieve the most popular movies', function () {
    $api = new TMDB(token());

    $response = recordSend($api, new GetPopularMovies);

    expect($response)->toBeInstanceOf(TMDBResponse::class);
    expect($response->successful())->toBeTrue();
});

On the first request, it will make the real request and record it as a JSON file, and then on subsequent requests - it will use the fixture that it recorded previously. I was thinking that using the request's name is a bit generic, perhaps we could use a combination of the request name as well as query parameters provided.

@Sammyjo20
Copy link
Author

Update: I allow you to pass in a third argument as a custom key, so if you have a test that does something different with a specific request name, you can customise the key here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment