OpenAPI Laravel
When designing an API for other people to use, having excellent documentation is critical. Your users can’t explore your code to figure out what is happening, they only know what your docs say; if your docs aren’t accurate they will be tearing their hair out.
So how do we ensure our API and our documentation match up, and - perhaps a bigger challenge - how do we make sure we keep our documentation up to date with our code?
The answer is to use an OpenAPI Specification file, then to test your code against and generate your documentation from it.
That way any change in the code must be reflected in the specification, and any change in the specification is reflected in your documentation. Leading to a happier time for project managers, developers and your members too.
Laravel Tests using a OpenAPI Specification
While implementing an API for a membership platform recently I realised that one of the testing tools we used was lacking real-world examples to help new users start using it.
It’s a brilliant tool called osteel/openapi-httpfoundation-testing which allows you to validate HTTP requests in your automated test suite against an OpenAPI Specification.
Always looking for ways to leave the internet better than we found it, I set out to create some examples and write this post to help others get started.
Testing your Laravel API against your OpenAPI Specification
The OpenAPI HttpFoundation Testing library we’re using works with Symfony Http Foundation objects. At Steadfast Collective we love Laravel, which is built on Symfony and these test examples are based on using phpunit in Laravel.
If you’re using any kind of HttpFoundation objects, you can adapt these tests for your test suite.
Simple Example
Here’s an simple example of using the validator:
/**
* Check that our API response returns the name of a pet.
*/
public function test_it_can_read_pet_name(): void
{
// Make our request as usual
$response = $this->getJson('/api/pet-name');
// Create the validator, and check that both our request and response
// match the OpenAPI Specification:
$apiValidator = ValidatorBuilder::fromYamlFile(
base_path('resources/api-docs/example-api.yaml')
)->getValidator();
$apiValidator->get($response->baseRequest, '/api/pet-name');
$apiValidator->get($response->baseResponse, '/api/pet-name');
// Perform any other validations we wish
$response->assertStatus(200);
}
See the full example in our OpenAPI in Laravel Demo file: ManualValidationTest.php
Automatic Example
Valdiating your tests against your specification file is one thing, but there is a lot of boilerplate code and you only test the methods you remember to test.
A better approach is to test everything by default, and that is where our HasValidatingJsonMethods trait comes in.
Simply add it to your TestCase and every JSON request in your tests is compared against your specification file.
The test above becomes:
/**
* Check that our API response returns the name of a pet.
*/
public function test_it_can_read_pet_name(): void
{
// Make our request as usual
$response = $this->getJson('/api/pet-name');
// Perform any other validations we wish
$response->assertStatus(200);
}
See the full example in our OpenAPI in Laravel Demo file: AutomaticValidationTest.php and the trait which does the magic: HasValidatingJsonMethods.php
Generating API Documentation
However brilliant your API is without good documentation nobody will know how to use it.
Our test suites give us confidence that our OpenAPI Specification is accurate - and with a good OAS file you can generate great docs really easily.
We use an open source tool called Redocly to both valdiate our OAS (as part of our CI pipeline) and to build the front-end assets for our users to usee.
Simply setup two scripts in your package.json to make linting and building your API Docs a breeze:
{
"scripts": {
"build-api-docs": "redocly build-docs resources/api-docs/example-api.yaml -o public/build/api-docs.html",
"lint-api-docs": "redocly lint resources/api-docs/example-api.yaml"
},
}
See the full example in our OpenAPI in Laravel Demo
More Articles
Eloquent explained: what it is and why it matters
Eloquent in plain English. What Laravel's ORM actually does, why your developers love it, and the questions to ask in your next project meeting.
Statamic vs WordPress: Why Pick Statamic
Wondering whether to pick Statamic or WordPress for your next build? Here's the honest case for Statamic from an agency that works with both.
Stripe Connect for a Membership Platform: A Leadership Guide
Why Stripe Connect is the right payments foundation for a membership platform, and how to make the case to your leadership team.