Many times I write these blog posts as a reminder to myself of how to do something when I seemingly ‘forget’ how. This blog post is know different. I’ve recently been struggling with correctly sending headers with PestPHP. I hope this blog post serves both as new knowledge for some, a problem solved for others and a reminder to those who need it!
A common theme amongst API Development is the necessity to send through headers. Whether this is a custom header you have declared in your API, or simply an Authorization
header. Either way, when using a testing framework such as Pest, knowing how to correctly send headers with your request is important.
Using withHeaders(), or not…!
For most standard API Requests, when you are reaching out to an external service, you would generally reach out for the ->withHeaders([])
function chained onto your request, which most of the time, is perfect. You add your array of headers to send along with the request, and all being well you get your response.
<?php
$request = Http::get('https://example.com/something')->withHeaders([
'accept' => 'application/json',
'authorization' => 'Bearer: someToken'
]);1
The same isn’t exactly true with Pest. With Pest, when using function based requests, you need to pass headers in a slightly different way, and it can vary based on the function method you are using. Below is a list of the 4 main methods used.
<?php
use function Pest\Laravel\get;
use function Pest\Laravel\put;
use function Pest\Laravel\post;
use function Pest\Laravel\delete;
// Post Signature
get('url', headers:[])
put('url', data:[], headers:[]);
post('url', data:[] headers:[]);
delete('url', data:[], headers:[])
As you can see, instead of using ->withHeaders([])
, the headers are accepted as an array of values in the third argument for put
, post
and delete
but the second argument for get
Working Example
What does this look like with actual data you may ask? Below is a test from my current project I am working on, with an API Request. You will notice that ->withHeaders([])
is not used anywhere.
<?php
use function Pest\Laravel\actingAs;
use function Pest\Laravel\get;
use function Pest\Laravel\post;
use function Pest\Laravel\seed;
use ....
// Example Get Request where the headers are the
// second argument of the get function
test('cannot see customer from another team', function () {
$customer = Customer::where('team_id', '!=', $this->user->team_id)->first();
$response = get('/api/customers/' . $customer->id, [
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json',
]);
$response->assertStatus(404);
});
// Example Post Request where the headers are the
// third agument of the post function
test('can create a customer via the API', function () {
$response = post('/api/customers', [
'first_name' => 'Test',
'last_name' => 'Customer',
'email' => 'davidbirkin1988@example.com',
'phone' => '0123456789',
], [
'Authorization' => 'Bearer ' . $this->token,
'Accept' => 'application/json',
]);
$response->assertStatus(201);
$data = $response->json()['data'];
expect($data['first_name'])->toBe('Test')
->and($data['last_name'])->toBe('Customer')
->and($data['email'])->toBe('davidbirkin1988@example.com')
->and($data['phone'])->toBe('0123456789');
});
Closing Words
It took me a while to work out how to correctly send headers with PestPHP. It was necessary for me to do this as I am using a custom middleware to ensure headers are set, otherwise returning the necessary message with status code.
I hope this helps you out and resolves any issues you may be experiencing with Pest and HTTP Headers.
Thanks for reading!