# Test Requests

# Introduction

This chapter documents the test helpers that are available via the jsonApi() method that the MakesJsonApiRequests trait adds to your test class. These test helpers are designed to help you fluently create test JSON:API requests.

# Expected Resource Type

When calling the jsonApi method, it is important to provide the resource type that you expect in the response. This allows you to then pass models to our test assertions, as the assertions will use the expected resource type when checking if the models are in the response JSON.

The expected resource type can be set using the expects method. For example:

$response = $this->jsonApi()->expects('posts')->get('/api/v1/posts');

If you prefer, you can also provide the expected resource type to the jsonApi method:

$response = $this->jsonApi('posts')->get('/api/v1/posts');

# Query Parameters

The following methods allow you to set query parameters when creating test JSON:API requests:

# Query

The query method allows you to set multiple query parameters in a single method:

$response = $this->jsonApi()->expects('posts')->query([
    'include' => 'author,tags',
    'page' => ['number' => 1, 'size' => 10],
])->get('/api/v1/posts');

This is equivalent to the following request:

GET /api/v1/posts?include=author,tags&page[number]=1&page[size]=10 HTTP/1.1
Accept: application/vnd.api+json

# Include Paths

The includePaths method allows you to fluently set the include query parameter:

$response = $this
    ->jsonApi()
    ->expects('posts')
    ->includePaths('author', 'tags')
    ->get('/api/v1/posts');

This is equivalent to the following request:

GET /api/v1/posts?include=author,tags HTTP/1.1
Accept: application/vnd.api+json

# Sparse Fields

The sparseFields method allows you to fluently set the fields query parameter for a specific resource type. For example:

$response = $this
    ->jsonApi()
    ->expects('posts')
    ->sparseFields('posts', ['title', 'slug', 'author'])
    ->sparseFields('users', ['name'])
    ->get('/api/v1/posts');

This is equivalent to the following request:

GET /api/v1/posts?fields[posts]=title,slug,author&fields[users]=name HTTP/1.1
Accept: application/vnd.api+json

# Filter

The filter method allows you to fluently set the filter query parameter:

$response = $this
    ->jsonApi()
    ->expects('posts')
    ->filter(['published' => 'true'])
    ->get('/api/v1/posts');

This is equivalent to the following request:

GET /api/v1/posts?filter[published]=true HTTP/1.1
Accept: application/vnd.api+json

If you provide models as filter values, these will be converted to their route keys. For example:

$posts = Post::factory()->count(3)->create();

$response = $this
    ->jsonApi()
    ->expects('posts')
    ->filter(['id' => $posts])
    ->get('/api/v1/posts');

# Sort

The sort method allows you to fluently set the sort query parameter:

$response = $this
    ->jsonApi()
    ->expects('posts')
    ->sort('-publishedAt', 'title')
    ->get('/api/v1/posts');

This is equivalent to the following request:

GET /api/v1/posts?sort=-publishedAt,title HTTP/1.1
Accept: application/vnd.api+json

TIP

You should pair the sort method with our ordered assertions - for example, assertFetchedManyInOrder.

# Page

The page method allows you to fluently set the page query parameter:

$response = $this
    ->jsonApi()
    ->expects('posts')
    ->page(['number' => 1, size => 10])
    ->get('/api/v1/posts');

This is equivalent to the following request:

GET /api/v1/posts?page[number]=1&page[size]=10 HTTP/1.1
Accept: application/vnd.api+json

If you provide models as page values, these will be converted to their route keys. For example:

$posts = Post::factory()->count(3)->create();

$response = $this
    ->jsonApi()
    ->expects('posts')
    ->page(['after' => $posts[0]])
    ->get('/api/v1/posts');

# Request Body and Headers

The following methods allow you to set request body content when creating test JSON:API requests:

# withData

The withData method allows you to set the request content to a JSON document, that contains the provided value as the data member.

For example:

$response = $this->jsonApi()->withData([
    'type' => 'posts',
    'attributes' => [
        'content' => '...',
        'title' => 'Hello World!',
        'slug' => 'hello-world',
    ],
])->post('/api/v1/posts');

Is equivalent to the following request:

POST /api/v1/posts HTTP/1.1
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
  "data": {
    "type": "posts",
    "attributes": {
      "content": "...",
      "title": "Hello World!",
      "slug": "hello-world"
    }
  }
}

# withJson

The withJson method allows you to set the entire JSON body content. For example:

$response = $this->jsonApi()->withJson([
    'meta' => [
        'foo' => 'bar',
    ],
])->post('/api/v1/posts');

Is equivalent to the following request:

POST /api/v1/posts HTTP/1.1
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
  "meta": {
    "foo": "bar"
  }
}

# withPayload

The withPayload method should be used when you are sending request content that is not JSON:API content. This should be used in combination with any of the helper methods that allow you to set an alternative content type.

For example:

$response = $this->jsonApi()->asFormUrlEncoded()->withPayload([
    'foo' => 'bar',
    'baz' => 'bat',
])->post('/api/v1/posts');

Is equivalent to the following request:

POST /api/v1/posts HTTP/1.1
Accept: application/vnd.api+json
Content-Type: application/x-www-form-urlencoded

foo=bar&baz=bat

# contentType

The contentType method allows you to set an alternative Content-Type header. This is useful when testing requests that send non-JSON:API content, but expect a JSON:API response.

Typically you would pair this with the withPayload method to set the non-JSON:API request body.

For example:

$response = $this
    ->jsonApi()
    ->contentType('application/x-www-form-urlencoded')
    ->withPayload(['foo' => 'bar', 'baz' => 'bat'])
    ->post('/api/v1/posts');

Is equivalent to the following request:

POST /api/v1/posts HTTP/1.1
Accept: application/vnd.api+json
Content-Type: application/x-www-form-urlencoded

foo=bar&baz=bat

# asFormUrlEncoded

The asFormUrlEncoded method is a short-hand for setting the Content-Type header to application/x-www-form-urlencoded.

# asMultiPartFormData

The asMultiPartFormData method is a short-hand for setting the Content-Type header to multipart/form-data.

# withHeaders and withHeader

The withHeaders method allows you to fluently set multiple headers when constructing your test request. The withHeader method sets a single header.

For example:

$response = $this->jsonApi()->expects('posts')->withHeaders([
  'X-Foo' => 'Bar',
  'X-Baz' => 'Bat',
])->get('/api/v1/posts');

// is equivalent to:

$response = $this
    ->jsonApi()
    ->expects('posts')
    ->withHeader('X-Foo', 'Bar')
    ->withHeader('X-Baz', 'Bat')
    ->get('/api/v1/posts');

# HTTP Verbs

Methods exist for the following HTTP verbs:

  • get
  • post
  • patch
  • put
  • delete

All these methods expect the first argument to be a string URI, and the second argument is an optional array of headers.

This makes these methods different from the Laravel equivalents, which accept an array of data for verbs such as post. You should instead use our fluent Request Body helpers to set the request content before calling the HTTP verb method.

Last Updated: 1/30/2022, 2:20:50 PM