# Introduction

## ![](/files/-M-RfWdecutzQ0EZemPw)

### Frisby.js - The Easiest REST API Testing Framework Out There

Frisby makes REST API testing easy, fast, and fun. Frisby.js comes loaded with many built-in tools for the most common things you need to test for to ensure your REST API is working as it should, and returning the correct properties, values, and types.

When you need something custom, Frisby.js also provides an easy way to customize and extend assertions to make your job easier, with less repetitive and tedious code.

### A Simple Example

The most basic check of ensuring a URL returns a specific status code:

```
const frisby = require('frisby');

it ('should return a status of 200', function () {
  return frisby
    .get('http://api.example.com')
    .expect('status', 200);
});
```

### Checking a JSON Response Body

A more useful and thorough test might make several assertions on the actual JSON response. Frisby.js makes this easy:

```
const frisby = require('frisby');
const Joi = frisby.Joi; // Frisby exports Joi for convenience on type assersions


it ('should return a status of 200', function () {
  return frisby
    .get('https://jsonfeed.org/feed.json')
    .expect('status', 200)
    .expect('json', 'version', 'https://jsonfeed.org/version/1')
    .expect('json', 'title', 'JSON Feed')
    .expect('jsonTypes', 'items.*', { // Assert *each* object in 'items' array
      'id': Joi.string().required(),
      'url': Joi.string().uri().required(),
      'title': Joi.string().required(),
      'date_published': Joi.date().iso().required(),
    });
});
```

### Gain Confidence In Your API

Check out the [Getting Started](/introduction/installation) page to setup Frisby.js in your project.

Happy testing!


# Frisby.js Overview

## ![](/files/-M-RfWdecutzQ0EZemPw)

### Frisby.js - The Easiest REST API Testing Framework Out There

Frisby makes REST API testing easy, fast, and fun. Frisby.js comes loaded with many built-in tools for the most common things you need to test for to ensure your REST API is working as it should, and returning the correct properties, values, and types.

When you need something custom, Frisby.js also provides an easy way to customize and extend assertions to make your job easier, with less repetitive and tedious code.

### A Simple Example

The most basic check of ensuring a URL returns a specific status code:

```
const frisby = require('frisby');

it ('should return a status of 200', function () {
  return frisby
    .get('http://api.example.com')
    .expect('status', 200);
});
```

### Checking a JSON Response Body

A more useful and thorough test might make several assertions on the actual JSON response. Frisby.js makes this easy:

```
const frisby = require('frisby');
const Joi = frisby.Joi; // Frisby exports Joi for convenience on type assersions


it ('should return a status of 200', function () {
  return frisby
    .get('https://jsonfeed.org/feed.json')
    .expect('status', 200)
    .expect('json', 'version', 'https://jsonfeed.org/version/1')
    .expect('json', 'title', 'JSON Feed')
    .expect('jsonTypes', 'items.*', { // Assert *each* object in 'items' array
      'id': Joi.string().required(),
      'url': Joi.string().uri().required(),
      'title': Joi.string().required(),
      'date_published': Joi.date().iso().required(),
    });
});
```

### Gain Confidence In Your API

Check out the [Getting Started](/introduction/installation) page to setup Frisby.js in your project.

Happy testing!


# Getting Started

## Installation

To get started with Frisby.js, add it to your project as a dev dependency:

```
npm install frisby --save-dev
```

## Writing and Running Tests

Frisby.js uses Jasmine style assertion syntax, and uses [Jest](https://facebook.github.io/jest/) to run tests.

Jest can run sandboxed tests in parallel, which fits the concept of HTTP testing very nicely so your API tests run much faster than other test runners, or using Jasmine directly.

### Install Jest

If you don't have Jest installed in your project yet, install it:

```
npm install --save-dev jest
```

### Create your tests

By default, Jest looks for a folder named `__tests__`. If it does not exist in your project yet, go ahead and create it:

```
mkdir -p __tests__/api
touch __tests__/api/api_spec.js
```

Now open `__tests__/api/api_spec.js` and add the following content:

```
const frisby = require('frisby');

it('should be a teapot', function () {
  return frisby.get('http://httpbin.org/status/418')
    .expect('status', 418);
});
```

### Run your tests from the CLI

To run your tests, open a Terminal or console window, and type `jest` from the root folder of your project:

```
jest
```


# HTTP Request Methods

All of the Frisby.js HTTP methods are based on the `fetch()` API standard. Frisby.js offers pre-defined `get`, `post`, `put`, and `del` for convenience and better readability.

If you need to do something custom like send requests through a proxy, you can also use `fetch` method directly with custom options from the `fetch` spec.

## frisby.get(url)

Issues an HTTP GET request.

```javascript
const frisby = require('frisby');

it ('GET should return a status of 200 OK', function () {
  return frisby
    .get('http://api.example.com/posts')
    .expect('status', 200);
});
```

## frisby.post(url, \[params])

Issues an HTTP POST request, with optional provided parameters.

Assumes JSON and sends the header `Content-Type: application/json` by default.

```javascript
const frisby = require('frisby');

it ('POST should return a status of 201 Created', function () {
  return frisby
    .post('http://api.example.com/posts', {
      title: 'My New Blog Post',
      content: '<p>A cool blog post!</p>'
    })
    .expect('status', 201);
});
```

## frisby.put(url, \[params])

Issues an HTTP PUT request, with optional provided parameters. Semantics are the same as `frisby.post()`.

```javascript
const frisby = require('frisby');

it ('POST should return a status of 200 OK', function () {
  return frisby
    .put('http://api.example.com/posts/1', {
      title: 'My Updated Title',
      content: '<p>Some different content actually</p>'
    })
    .expect('status', 200);
});
```

## frisby.del(url)

Issues an HTTP DELETE request.

```javascript
const frisby = require('frisby');

it ('DELETE should return a status of 204 No Content', function () {
  return frisby
    .del('http://api.example.com/posts/1')
    .expect('status', 204);
});
```

## frisby.fetch(url, \[options])

If you need to do something custom, or if for some reason none of the above helper HTTP methods suit your needs, you can use `fetch` directly, which accepts all the same options and parameters as the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) - Frisby.js just passes them through for your request.

```javascript
const frisby = require('frisby');

it ('fetch with POST should return a status of 201 Created', function () {
  return frisby
    .fetch('http://api.example.com/posts', {
      method: 'POST',
      body: JSON.stringify({
        title: 'My Updated Title',
        content: '<p>Some different content actually</p>'
      })
    })
    .expect('status', 201);
});
```


# globalSetup() / setup()

## globalSetup(options)

Set any global parameters, headers, etc. that need to be sent with each HTTP request that Frisby sends out.

Most people use this for global headers, authentication, cookies, etc.

### Usage Examples

#### Headers

```javascript
const frisby = require('frisby');

// Do setup first
frisby.globalSetup({
  request: {
    headers: {
      'Authorization': 'Basic ' + Buffer.from("username:password").toString('base64'),
      'Content-Type': 'application/json',
    }
  }
});

// Any global setup is automatically applied to every test
it ('uses globalSetup for every test after it is called', function () {
  return frisby
    .get('http://api.example.com')
    .expect('status', 200);
});
```

## setup(options)

The `setup` method is similar to `globalSetup`, but it only affects a single specific test that it is attached to.

**NOTE: The `setup` call MUST COME BEFORE calls to `get`, `post`, `fetch`, etc.**

### Usage Examples

```javascript
const frisby = require('frisby');

// The 'setup' function only affects a single test
it ('runs setup only for a single test', function () {
  return frisby
    .setup({
      request: {
        headers: {
          'Authorization': 'Basic ' + Buffer.from("username:password").toString('base64')
        }
      }
    })
    .get('http://api.example.com')
    .expect('status', 200);
});
```


# Running Assertions

Frisby has many ways of running assertions against the HTTP response. Below are the following methods available by default:

## expect(*handler, \[...args]*)

Frisby comes with many handy built-in expect handlers to help you test the HTTP response of your API.

* `status` - Check HTTP status
* `header` - Check HTTP header key + value
* `json` - Match json structure + values
* `jsonStrict` - Match EXACT json structure + values (extra keys not tested for cause test failures)
* `jsonTypes` - Match json structure + value types
* `jsonTypesStrict` - Match EXACT json structure + value types (extra keys not tested for cause test failures)
* `bodyContains` - Match partial body content (string or regex)

### expect('status', statusCode)

```javascript
it('should be a teapot', function () {
  return frisby.get('https://httpbin.org/status/418')
    .expect('status', 418);
});
```

### expect('header', key \[, value])

```javascript
it('should have a JSON Content-Type header', function () {
  return frisby.get('https://httpbin.org/headers')
    .expect('header', 'Content-Type', 'application/json');
});
```

### expect('json' *\[, path]*, data)

```javascript
it('should have a "Host" header with a value of "httpbin.org"', function () {
  return frisby.get('https://httpbin.org/headers')
    .expect('json', 'headers', {
      Host: 'httpbin.org'
    });
});
```

A more complex example:

```javascript
it ('should return a list of feed items', function () {
  return frisby
    .get('https://jsonfeed.org/feed.json')
    .expect('status', 200)
    .expect('json', 'version', 'https://jsonfeed.org/version/1')
    .expect('json', 'title', 'JSON Feed')
    .expect('jsonTypes', 'items.*', { // Assert *each* object in 'items' array
      'id': Joi.string().required(),
      'url': Joi.string().uri().required(),
      'title': Joi.string().required(),
      'date_published': Joi.date().iso().required(),
    });
});
```

### expect('jsonTypes' *\[, path]*, data)

```javascript
it('should return all headers as strings', function () {
  return frisby.get('https://httpbin.org/headers')
    // Using a wildcard in the path '*' check EACH value
    .expect('jsonTypes', 'headers.*', frisby.Joi.string());
});
```

## expectNot(*handler, \[...args]*)

Runs an inverse assertion that passes when there is an error thrown. Uses all the same types and arguments as `expect()`.

```javascript
it('should not return an error', function () {
  return frisby.get('https://httpbin.org/headers')
    // Should not return an error
    .expectNot('json', { result: 'error' });
});
```


# Nested Tests

Sometimes you have some HTTP calls that are dependent on others, like creating a new item and then checking to ensure that it exists and is returned from the API.

Here is a more complex test example with nested dependent Frisby tests with Frisby's Promise-style \`then\` method.

```javascript
const frisby = require('frisby');
const Joi = frisby.Joi; // Frisby exposes Joi for convenience

describe('Posts', function () {
  it('should return all posts and first post should have comments', function () {
    return frisby.get('http://jsonplaceholder.typicode.com/posts')
      .expect('status', 200)
      .expect('jsonTypes', '*', {
        userId: Joi.number(),
        id: Joi.number(),
        title: Joi.string(),
        body: Joi.string()
      })
      .then(function (res) { // res = FrisbyResponse object
        let postId = res.json[0].id;

        // Get first post's comments
        // RETURN the FrisbySpec object so function waits on it to finish - just like a Promise chain
        return frisby.get('http://jsonplaceholder.typicode.com/posts/' + postId + '/comments')
          .expect('status', 200)
          .expect('json', '*', {
            postId: postId
          })
          .expect('jsonTypes', '*', {
            postId: Joi.number(),
            id: Joi.number(),
            name: Joi.string(),
            email: Joi.string().email(),
            body: Joi.string()
          });
      });
  });
});
```

\`\`\`


# Inspectors

If you need to get more information about the HTTP request, response, body, JSON, etc. Frisby has several built-in helpers that log information to the console for you to see.

## frisby.inspectJSON()

Prints formatted and spaced JSON to the console.

```javascript
const frisby = require('frisby');

it ('GET should return a status of 200 OK', function (done) {
  frisby
    .get('http://api.example.com/ping')
    .inspectJSON()
    .done(done);
});
```

Output:

```
{
  "ping": "pong"
}
```

## frisby.inspectResponse()

Inspect HTTP response object (full fetch() request object dumped).

## frisby.inspectRequest()

Inspect HTTP request object (full fetch() request object dumped).

## frisby.inspectRequestHeaders()

Inspect HTTP request headers.

## frisby.inspectBody()

Inspect raw, unparsed HTTP response body text. Useful for debugging why an API is not returning valid JSON, etc.

## frisby.inspectStatus()

Inspect HTTP response status code.

## frisby.inspectHeaders()

Inspect HTTP response headers.


# File Uploads

Since Frisby.js is based on the Fetch API, file uploads are a cinch with the built-in FormData object (see [Using FormData Objects on MDN](https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects) if you are not familiar with them).

You can get a new FormData object from Frisby:

```
let formData = frisby.formData();
```

A full usage example might look like this:

```
const csvPath = path.resolve(__dirname, './file.csv');
let content = fs.createReadStream(csvPath);
let formData = frisby.formData();

formData.append('file', content);

return frisby
  .post('http://api.example.com/files', { body: formData })
  .inspectRequestHeaders()
  .expect('status', 200)
```


