PHPackages                             digitonic/api-test-suite - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. digitonic/api-test-suite

ActiveLibrary[Testing &amp; Quality](/categories/testing)

digitonic/api-test-suite
========================

A Laravel API CRUD testing framework

4.0.2(1y ago)22.7k2MITPHPPHP ^7.1|^8.0|^8.1CI failing

Since Mar 27Pushed 1y ago4 watchersCompare

[ Source](https://github.com/digitonic/api-test-suite)[ Packagist](https://packagist.org/packages/digitonic/api-test-suite)[ Docs](https://github.com/digitonic/api-test-suite)[ RSS](/packages/digitonic-api-test-suite/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (10)Dependencies (4)Versions (27)Used By (0)

Digitonic API Test Suite
========================

[](#digitonic-api-test-suite)

[![Latest Version on Packagist](https://camo.githubusercontent.com/93ff3afa5aae71e0164791832176d0da34772c20fd0914c512f4d4e3c9127334/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f64696769746f6e69632f6170692d746573742d73756974652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/digitonic/api-test-suite)[![Build Status](https://camo.githubusercontent.com/728bcd3e7021a5e80c1e61348dc10e19c7a2003d63ed2e01f831af4ee1ccb108/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f64696769746f6e69632f6170692d746573742d73756974652f6261646765732f6275696c642e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/digitonic/api-test-suite/build-status/master)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/cb3fd0ceb1d04f977db2a38ddc5bb9a3338f9982efbdd7f90a2e1146a0f70815/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f64696769746f6e69632f6170692d746573742d73756974652f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/digitonic/api-test-suite/?branch=master)[![Total Downloads](https://camo.githubusercontent.com/c4466c68d07f4a5a5c3d8271f809ead73ab67242718b802b5a23dc63071f7b63/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f64696769746f6e69632f6170692d746573742d73756974652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/digitonic/api-test-suite)

A set of testing tools designed around the confirmation that each of your API endpoints is setup to conform to a configured standard.

Installation
------------

[](#installation)

You can install the package via composer:

```
$ composer require digitonic/api-test-suite
```

#### Install Config &amp; Templates

[](#install-config--templates)

```
$ php artisan digitonic:api-test-suite:install
```

Usage
-----

[](#usage)

### General structure

[](#general-structure)

The main class you will want to extend to enable the test framework functionality is CRUDTestCase. This is the main entry point for the test suite automated assertions via the `runBaseApiTestSuite()`method. This class also provides a default `setUp()` method creating users. The CRUDTestCase class extends the base Laravel TestCase from your app, so it will take into account everything you change in there too, e.g. Migrations runs, setUp, or tearDown methods;

### Configuration file

[](#configuration-file)

This file is generated in `config/digitonic` when you run the installer command: `php artisan digitonic:api-test-suite:install` or `php artisan d:a:i` for short. It contains the following options:

###### `api_user_class`

[](#api_user_class)

This is the class that is used for your base user. *e.g.: App\\Models\\User::class*

###### `required_response_headers`

[](#required_response_headers)

An array of header-header value pairs to be returned by all your API routes. If any value goes, you can set the value of your header to null. This can be overwritten at the endpoint level by overwriting the `checkRequiredResponseHeaders` method of the AssertsOuput trait in your Test class.

###### `default_headers`

[](#default_headers)

The default headers that will be passed to all your api calls. Keys should be capitalised, and prefixed with HTTP, guzzle style. *e.g.: \['HTTP\_ACCEPT' =&gt; 'application/json'\]*

###### `entities_per_page`

[](#entities_per_page)

Indicate here the maximum number of entities your responses should have on index requests. This is used for pagination testing.

###### `identifier_field`

[](#identifier_field)

A closure that returns a string determining the name of the ID field. You have access to the same context as your test here. *e.g.: function () {return 'uuid';} for a use of uuids across all entities*

###### `identifier_faker`

[](#identifier_faker)

A closure to fake an identifier. Mainly used for NOT\_FOUND status code testing. *e.g.: function () {return \\App\\Concerns\\HasUuid::generateUuid();}*

###### `templates`

[](#templates)

An array which contain a `base_path` key, with a string value indicating the path to the templates for pagination and error responses . *e.g.: \['base\_path' =&gt; base\_path('tests/templates/')\]*

###### `creation_rules`

[](#creation_rules)

***Probably the most useful configuration option***. It allows to create ad hoc creation rules for your payloads. It should be an array with creation rules names used in your tests as keys, and closures returning an appropriate value as values. *e.g.: `['tomorrow' => function () {return Carbon::parse('+1day')->format('Y-m-d H:i:s');}]` allows you to generate the date of tomorrow in your payloads. We'll come back to it when we'll see the `creationRules()` method*

### `setUp()` method

[](#setup-method)

This methods generates:

- an `identifierGenerator` field usable anywhere in your tests, based on your `identifier_faker` configuration (see above).
- A new `entities` field defaulting to an empty Laravel Collection.
- A `user` field which will be the rightful user of your resources in your API. This relies on you creating a `crud` factory state for your `api_user_class` in your factories folder. This should set up the user default fields, and it's relation to a team/organization.
- An `otherUser` field which is created using the same factory, which represent a user that shouldn't have access to the resource being accessed. Make sure that your factory `crud` state creates a different team each time it is called.

All these fields are available anywhere in your test class.

### `runBaseApiTestSuite()` method

[](#runbaseapitestsuite-method)

This method is where the magic happen. Most classical CRUD endpoints will be able to use that method out of the box, but some more complexe endpoints might need to override it to get the context for the test suite right. If that was to be the case, all the CRUDTestCase methods are still available to help you build your test.

This method runs the following assertions in order:

- `Unauthorized` status code and error format when not providing an authorization token.
- `Not Found` status code and error format when providing a non existent identifier for your resource.
- `Unprocessable entity` status code and error format when forgetting required fields.
- `Forbidden` status code and error format when trying to access a resource you don't have permissions to access.
- `Bad Request` status code and error format if a required header is missing (we need that to ensure that the `Accept: application/json` is systematically set, which is the guarantee of integrity of the output of your API, otherwise you may have web redirects happening on Unauthorized requests, for example). This can also be used to enforce any other HTTP header to be present. It will test the value for that header, if it is provided.
- `Created` status code, and response data format, including provided links and timestamps, and the id replacement value if specified (e.g., `uuid` instead of `id`). If the resource shouldn't be duplicated, it will also make sure it is created only once (or twice, if it can be duplicated).
- `Accepted` status code, and response data format, including provided links and timestamps (`updated_at` has to be updated), and the id replacement value if specified (e.g., `uuid` instead of `id`).
- `OK` status code, and response data format, including provided links and timestamps, and the id replacement value if specified (e.g., `uuid` instead of `id`) for ListAll and Retrieve endpoints. In the case of a ListAll endpoint, pagination will also be tested for maximum numbers per page, and format, if the test is set to do so.
- `No Content` status code, and an empty response body for Delete endpoints.

Which assertion will be run is determined by the `DeterminesAssertions` Trait in the `CRUDTestCase` class. The method is based on the metadata you provide about your endpoint through the implementation of the CRUDTestCase abstract methods. I encourage you to read that file if you find unexpected assertions being run, and to override them if necessary.

Test interface implementation
-----------------------------

[](#test-interface-implementation)

To help you, the package provides you with a a few Traits that you can use to set the defaults for Create, Retrieve, Update, ListAll, and Delete actions (`TestsCreateAction`,`TestsRetrieveAction`,`TestsUpdateAction`,`TestsListAllAction`, and `TestsDeleteAction` respectively). These provides with sensible defaults for the `httpAction()`, `statusCodes()`, `shouldAssertPaginate()`, `requiredHeaders()`, `creationHeaders()`, `requiredFields()` and `cannotBeDuplicated()` methods below. These can be overwritten in your test class if needed.

### Resource metadata

[](#resource-metadata)

###### `resourceClass()`

[](#resourceclass)

Return the class name for the entity at hands.

###### `createResource()`

[](#createresource)

This method should return a string (the name of your create endpoint route, e.g. `campaigns.api.store`) if you choose to use your API Create endpoint to create the test's resources. In that case, expect other related endpoints tests to fail if you break the Create Endpoint. Otherwise, you can provide a closure setting up the database in the required state for your test, and returning the target entity, the way your Create endpoint would do (as an object though, not an array or json).

###### `creationRules()`

[](#creationrules)

This should return an associative array of form fields. Each should use a rule that is either available from the api test suite, or a custom rule that you have declared in your api-test-suite.php configuration file. The rules available by default can be seen in this [file](https://github.com/digitonic/api-test-suite/blob/master/src/DataGeneration/Factories/RuleFactory.php).

###### `viewableByOwnerOnly()`

[](#viewablebyowneronly)

This should return true if the resource you are creating is only available by the owner of the resource, or false otherwise.

###### `cannotBeDuplicated()`

[](#cannotbeduplicated)

This should return true if the resource can be duplicated on several Create endpoints calls with the same payload, or false if not.

\##Request metadata

###### `httpAction()`

[](#httpaction)

Should return one of these values as a string, according to the method your endpoint allows: get, post, put, or delete.

###### `requiredFields()`

[](#requiredfields)

This should return a non associative array of required fields for your request. Most useful for Create endpoints. *e.g.: \['code', 'sender', 'send\_at', 'is\_live'\]*

###### `requiredHeaders()`

[](#requiredheaders)

These are the headers you want to enforce the presence of in your request. It defaults to the default Headers from your configuration file if you're using the helper traits. *e.g.: \['HTTP\_ACCEPT' =&gt; 'application/json'\]*

###### `creationHeaders()`

[](#creationheaders)

If you choose to use the API to create your resources (see `createResource()` method below), this should match the requiredHeaders() return value for your Create endpoint. *e.g.: \['HTTP\_ACCEPT' =&gt; 'application/json'\]*

### Response metadata

[](#response-metadata)

###### `statusCodes()`

[](#statuscodes)

***This method determines what status codes should be returned by your endpoint, that is the different scenarios to be tested for success and errors. As such, it is very important to understans***This method shold return an array of statusCodes from the list above in the `runBaseApiTestSuite()` method section. However the default from the helper traits are most often that not the ones you're after. *e.g.: \[Response::HTTP\_CREATED,Response::HTTP\_UNPROCESSABLE\_ENTITY,Response::HTTP\_UNAUTHORIZED\]*

###### `expectedResourceData(array $data)`

[](#expectedresourcedataarray-data)

This method is a way to declare the expected value. Most of the time, it will be the payload, plus or minus some fields. You can add these from the $data array, if there is no way for you to know in advance what value will be returned (for timestamps for example).

###### `expectsTimestamps()`

[](#expectstimestamps)

Return true if the API returns the created\_at, and updated\_at timestamps, false otherwise.

###### `expectedLinks()`

[](#expectedlinks)

Return an array of links related to your entity that your API returns. *e.g. \['self' =&gt; 'campaigns.api.show'\]*. This hasn't been used so far for any other type of link.

###### `fieldsReplacement()`

[](#fieldsreplacement)

Return an array with the keys being the current entity's fields that should not be public, and therefore replace by the value of the pair. *e.g., \['id' =&gt; 'uuid'\] to check that hte id is not present, and that the uuid is, in the returned API data for your entity.*

###### `shouldAssertPaginate()`

[](#shouldassertpaginate)

This should return true if the endpoint should be paginated, false otherwise. Usually useful for ListAll endpoints.

###### `checkRequiredResponseHeaders()`

[](#checkrequiredresponseheaders)

Return a list of headers and values which have to be included in the response from the server for the endpoint at hand. If any value goes, you can set the value of your header to null.

Helper methods and fields
-------------------------

[](#helper-methods-and-fields)

You can obviously use any of the subroutines used in the runBaseApiTestSuite in order to write a more flexible, custom test suite for your endpoint.

Useful methods provided by the CRUDTestCase class are the following:

- `getCurrentIdentifier()` returns the identifier (according to your configuration file) of the entity being tested.
- `doAuthenticatedRequest($data, array $params = [], $headers = [])` does the configured request for your endpoint, allows you to pass a $data array for your payload, and custom $params (used to build the target url, e.g. `campaignUuid`) and headers (these will override the default headers set in your configuration. If $headers is not set or is empty, they will use the default ones); It also sets the actingAs on the test to be $this-&gt;user.
- `doRequest($data, array $params = [], $headers = [])` is the same as the above, but without setting the actingAs to $this-&gt;user
- `getResponseData(TestResponse $response)` allows you to easily extract the `data` attribute from your response.
- `generateEntities($numberOfEntities, $httpAction, $baseUser, $otherUser)` will create the number of entities of the `resourceClass()`, for the $baseUser provided. In addition, the $otherUser will be used to create another entity, not belonging to the $baseUser if the $httpAction is 'get' and $this-&gt;viewableByOwnerOnly() returns true, in order to test that it can't be seen by the $baseUser.
- `generatePayload($user)` returns a payload for the $user provided, that follows the rules returned by $this-&gt;creationRules().
- `generateEntityOverApi(array $payload, $user)` creates the entity at hand for the payload and user provided. This needs the createResource method to return an endpoint name.
- `generateUpdateData($payload, $user)` generate an update payload from the creation payload that is passed to it.
- `identifier()` is the identifier key in the current context. This can be quite handy when trying to build a custom test, if you have problems creating the `identifier_field` closure in the api-test-suite config.
- `generateSingleEntity($user, $payload = null)` returns an entity of the type at hand. If you don't pass a specific payload, it will use the above `generatePayload($user)` to create one.

Pagination and Error Templates
------------------------------

[](#pagination-and-error-templates)

Use the config file's `templates` field to indicate where your templates are for your automated test suite. By default they will be in `tests/templates`. Defaults are provided on running the installer command, to get you started.

###### pagination

[](#pagination)

The pagination template has currently no default. If you keep it as is, this won't be used.

###### errors

[](#errors)

The error templates should be named after the statusCodes you are expecting (you then should have the following files: `400.blade.php, 401.blade.php, 403.blade.php, 404.blade.php and 422.blade.php`). For your convenience, templates allow the use of regular expressions, and the 422 template is being passed 2 variables: 'fieldName' (the required key under scrutiny being tested from your `requiredFields()`, and 'formattedFieldName' which is the same field in snake\_case.

### Testing

[](#testing)

```
composer test
```

### Changelog

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

### Security

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Yannick Glade](https://github.com/MrTammer)
- [Chris Crawford](https://github.com/ChrisCrawford1)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance36

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity79

Established project with proven stability

 Bus Factor1

Top contributor holds 97.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~84 days

Recently: every ~201 days

Total

25

Last Release

585d ago

Major Versions

0.0.10 → 1.0.02019-07-23

1.1.2 → 2.0.02019-10-16

2.1.0 → 3.0.02022-07-25

3.0.1 → 4.0.02024-09-29

PHP version history (4 changes)0.0.1PHP &gt;=7.0

2.0.0PHP ^7.1

2.1.0PHP ^7.1|^8.0

3.0.0PHP ^7.1|^8.0|^8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1104549?v=4)[Steven Richardson](/maintainers/richdynamix)[@richdynamix](https://github.com/richdynamix)

---

Top Contributors

[![MrTammer](https://avatars.githubusercontent.com/u/15137960?v=4)](https://github.com/MrTammer "MrTammer (33 commits)")[![ChrisCrawford1](https://avatars.githubusercontent.com/u/44769623?v=4)](https://github.com/ChrisCrawford1 "ChrisCrawford1 (1 commits)")

---

Tags

digitonicapi-test-suite

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/digitonic-api-test-suite/health.svg)

```
[![Health](https://phpackages.com/badges/digitonic-api-test-suite/health.svg)](https://phpackages.com/packages/digitonic-api-test-suite)
```

###  Alternatives

[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k43.5M5.2k](/packages/larastan-larastan)[timacdonald/log-fake

A drop in fake logger for testing with the Laravel framework.

4235.9M56](/packages/timacdonald-log-fake)[jasonmccreary/laravel-test-assertions

A set of helpful assertions when testing Laravel applications.

3513.9M32](/packages/jasonmccreary-laravel-test-assertions)[illuminate/testing

The Illuminate Testing package.

3315.6M113](/packages/illuminate-testing)[christophrumpel/missing-livewire-assertions

This package adds missing livewire test assertions.

149336.0k9](/packages/christophrumpel-missing-livewire-assertions)[calebdw/larastan-livewire

A Larastan / PHPStan extension for Livewire.

43482.4k3](/packages/calebdw-larastan-livewire)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
