AdonisJS 5.0 is here! Learn More

HTTP Tests

In this guide, we learn how to write HTTP tests against an API server.

If you are new to testing with AdonisJs, or just testing in general, consider reading the Getting Started guide before continuing further.

Basic Example

Let’s start with a basic example to test a HTTP endpoint returns a list of posts in JSON format.

The following example assumes you’ve created a Post model with related database table, and defined a GET /posts route that returns all Post models.

First, make a new functional test (since we’ll test the API like an end-user):

> adonis make:test Post
make:test Menu
> Select the type of test to create
  Unit test
❯ Functional test
Output
create: test/functional/post.spec.js

Next, open the test file and paste in the following code:

test/functional/post.spec.js
const { test, trait } = use('Test/Suite')('Post')
const Post = use('App/Models/Post')

trait('Test/ApiClient')

test('get list of posts', async ({ client }) => {
  await Post.create({
    title: 'Adonis 101',
    body: 'Blog post content'
  })

  const response = await client.get('/posts').end()

  response.assertStatus(200)
  response.assertJSONSubset([{
    title: 'Adonis 101',
    body: 'Blog post content'
  }])
})

Examining our test file…

  1. We register the Test/ApiClient trait, providing us an HTTP client to make requests with

  2. We create a dummy Post instance

  3. We request the /posts URL and capture the response

  4. We run assertions against the response to ensure the HTTP status is 200 and at least one returned post has the same title and body as our dummy Post instance

Finally, run all your functional tests via the following command:

> adonis test functional
Output
  Post
    ✓ get list of posts (286ms)

   PASSED

  total       : 1
  passed      : 1
  time        : 289ms
Your first HTTP test PASSED. Congratulations! 🎉

Client Methods

The following methods can be called when making HTTP requests.

get(url)

Make an HTTP GET request to a given url:

client.get('posts')
The post, patch, put, delete, and head methods can also be used to make HTTP requests.

header(key, value)

Set a header key/value pair when making the HTTP request:

client
  .get('posts')
  .header('accept', 'application/json')

send(body)

Send request body when making the HTTP request:

client
  .post('posts')
  .send({
    title: 'Adonis 101',
    body: 'Post content'
  })

query(queryObject)

Set query string parameters:

client
  .get('posts')
  .query({ order: 'desc', page: 1 }) // ?order=desc&page=1

type(type)

Set the request content type:

client
  .get('posts')
  .type('json')

accept(type)

Set the data type you want to accept from the server:

client
  .get('posts')
  .accept('json')

cookie(key, value)

Set request cookies:

client
  .get('posts')
  .cookie('name', 'virk')
As all cookies are encrypted in AdonisJs, this method makes sure to encrypt the values properly so that AdonisJs server can parse them.

plainCookie(key, value)

Set a cookie which doesn’t get encrypted:

client
  .get('posts')
  .plainCookie('name', 'virk')

end

End the HTTP request chain, execute the request and return the response:

const response = await client.get('posts').end()
You must call end to execute HTTP client requests.

Multipart Requests

To make multipart requests and send files with the request body:

await client
  .post('posts')
  .field('title', 'Adonis 101')
  .attach('cover_image', Helpers.tmpPath('cover-image.jpg'))
  .end()

You can also set HTML form style field names to send an array of data:

await client
  .post('user')
  .field('user[name]', 'Virk')
  .field('user[email]', '[email protected]')
  .end()

Sessions

When writing tests, you may want to set sessions beforehand.

This can be done by using the Session/Client trait:

const { test, trait } = use('Test/Suite')('Post')

trait('Test/ApiClient')
trait('Session/Client')

test('get list of posts', async ({ client }) => {
  const response = await client
    .get('posts')
    .session('adonis-auth', 1)
    .end()
})
The AdonisJs Session Provider must be installed before you can take advantage of the Session/Client trait.

Authentication

You can authenticate users beforehand by using the Auth/Client trait:

const { test, trait } = use('Test/Suite')('Post')

trait('Test/ApiClient')
trait('Auth/Client')
trait('Session/Client')

test('get list of posts', async ({ client }) => {
  const user = await User.find(1)

  const response = await client
    .get('posts')
    .loginVia(user)
    .end()
})

To authenticate with a custom scheme:

client
  .get('posts')
  .loginVia(user, 'jwt')

For basic auth, pass the user’s username and the password:

client
  .get('posts')
  .loginVia(username, password, 'basic')

Assertions

The following assertions can be called on HTTP client responses.

assertStatus

Assert the response status:

response.assertStatus(200)

assertJSON

Assert the response body should deepEqual the expected value:

response.assertJSON({
})

assertJSONSubset

Assert a subset of JSON:

response.assertJSONSubset({
  title: 'Adonis 101',
  body: 'Some content'
})
This assertion tests a subset of objects, which is helpful when values inside an object are not determinable (e.g. timestamps).

assertText

Assert plain text returned by the server:

response.assertText('Hello world')

assertError

Assert the response error:

response.assertError([
  {
    message: 'username is required',
    field: 'username',
    validation: 'required'
  }
])

assertCookie

Assert the server set a cookie with value:

response.assertCookie('key', 'value')

assertPlainCookie

Assert a plain cookie value:

response.assertPlainCookie('key', 'value')

assertCookieExists

Assert the server set a cookie with the given name:

response.assertCookieExists('key')

assertPlainCookieExists

Assert a plain cookie exists:

response.assertPlainCookieExists('key')

assertHeader

Assert the server sent a header:

response.assertHeader('content-type', 'application/json')

assertRedirect

Assert the request was redirected to a given URL:

response.assertRedirect('/there')