Testing
The toolkit provides enhanced response assertions designed for JSON:API responses. They let you write expressive, chainable tests with both Pest and PHPUnit.
Setup
Add the CreatesTestResponse trait to your tests/Pest.php:
uses(
Tests\TestCase::class,
BlueBeetle\ApiToolkit\Testing\CreatesTestResponse::class,
)->in('Feature');
This overrides createTestResponse() so all HTTP test responses (getJson, postJson, etc.) return the toolkit's TestResponse with JSON:API-specific assertions.
Response Assertions
Resource Type and ID
$response = $this->getJson('/api/products/1');
$response->assertOk();
$response->assertResourceType('products');
$response->assertResourceId('1');
Attributes
$response->attributes()
->assertSame('name', 'Widget Pro')
->assertSame('price', 29.99)
->assertNotNull('created_at');
Collection Data
$response = $this->getJson('/api/products');
$response->data()->assertCount(10);
$response->data()->item(0)->assertSame('type', 'products');
$response->data()->item(0)->attributes()->assertSame('name', 'Widget Pro');
Included Resources
$response = $this->getJson('/api/products/1?include=category');
$response->included()
->assertNotEmpty()
->item(0)
->assertSame('type', 'categories');
Meta
$response->meta()
->assertSame('currentPage', 1)
->assertSame('total', 50);
Error Assertions
Basic Error
$response = $this->getJson('/api/products/999');
$response->assertNotFound();
$response->assertErrorTitle('Not Found');
$response->assertErrorDetail('Product not found');
Validation Errors
$response = $this->postJson('/api/products', []);
$response->assertStatus(422);
$response->assertValidationError('name', 'The name field is required.');
Error Code and Detail
$response->assertErrorCode('INSUFFICIENT_FUNDS');
$response->assertErrorDetailContains('balance');
Chainable Data Navigation
The TestDataResponse class lets you navigate into nested structures:
$response->data() // -> data
->item(0) // -> data[0]
->attributes() // -> data[0].attributes
->assertSame('name', 'Widget');
$response->data()
->item(0)
->relationships() // -> data[0].relationships
->assertHasKey('category');
$response->data()
->item(0)
->meta() // -> data[0].meta
->assertHasKey('stock_level');
Available Assertions
| Method | Description |
|---|---|
assertSame(key, value) | Strict equality |
assertNotSame(key, value) | Strict inequality |
assertTrue(key) | Value is true |
assertFalse(key) | Value is false |
assertNull(key) | Value is null |
assertNotNull(key) | Value is not null |
assertHasKey(key) | Key exists |
assertMissingKey(key) | Key does not exist |
assertCount(int) | Array has N items |
assertEmpty() | Array is empty |
assertNotEmpty() | Array is not empty |
TestResponse Assertions
| Method | Description |
|---|---|
assertResourceType(type) | Assert data.type matches |
assertResourceId(id) | Assert data.id matches |
assertErrorTitle(title) | Assert first error title |
assertErrorDetail(detail) | Assert first error detail |
assertErrorDetailContains(needle) | Assert first error detail contains string |
assertErrorCode(code) | Assert first error code |
assertValidationError(field, message) | Assert validation error for field with message |
Navigation Methods
| Method | Returns | Description |
|---|---|---|
data() | TestDataResponse | Access data key |
attributes() | TestDataResponse | Shortcut for data.attributes |
errors() | TestDataResponse | Access errors array |
included() | TestDataResponse | Access included array |
meta() | TestDataResponse | Access meta object |
item(index) | TestDataResponse | Scope to array item by index |
relationships() | TestDataResponse | Scope to relationships key |
links() | TestDataResponse | Scope to links key |