supertest README

The project's README from github.com/forwardemail/supertest. As one markdown file: README.md.

supertest

build status code coverage code style styled with prettier made with lass license

HTTP assertions made easy via superagent. Maintained for Forward Email and Lad.

About

The motivation with this module is to provide a high-level abstraction for testing HTTP, while still allowing you to drop down to the lower-level API provided by superagent.

Getting Started

Install supertest as an npm module and save it to your package.json file as a development dependency:

npm install supertest --save-dev

Once installed it can now be referenced by simply calling require('supertest');

Example

You may pass an http.Server, or a Function to request() - if the server is not already listening for connections then it is bound to an ephemeral port for you so there is no need to keep track of ports.

supertest works with any test framework, here is an example without using any test framework at all:

const request = require('supertest');
const express = require('express');

const app = express();

app.get('/user', function(req, res) {
  res.status(200).json({ name: 'john' });
});

request(app)
  .get('/user')
  .expect('Content-Type', /json/)
  .expect('Content-Length', '15')
  .expect(200)
  .end(function(err, res) {
    if (err) throw err;
  });

To enable http2 protocol, simply append an options to request or request.agent:

const request = require('supertest');
const express = require('express');

const app = express();

app.get('/user', function(req, res) {
  res.status(200).json({ name: 'john' });
});

request(app, { http2: true })
  .get('/user')
  .expect('Content-Type', /json/)
  .expect('Content-Length', '15')
  .expect(200)
  .end(function(err, res) {
    if (err) throw err;
  });

request.agent(app, { http2: true })
  .get('/user')
  .expect('Content-Type', /json/)
  .expect('Content-Length', '15')
  .expect(200)
  .end(function(err, res) {
    if (err) throw err;
  });

Here's an example with mocha, note how you can pass done straight to any of the .expect() calls:

describe('GET /user', function() {
  it('responds with json', function(done) {
    request(app)
      .get('/user')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200, done);
  });
});

You can use auth method to pass HTTP username and password in the same way as in the superagent:

describe('GET /user', function() {
  it('responds with json', function(done) {
    request(app)
      .get('/user')
      .auth('username', 'password')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200, done);
  });
});

One thing to note with the above statement is that superagent now sends any HTTP error (anything other than a 2XX response code) to the callback as the first argument if you do not add a status code expect (i.e. .expect(302)).

If you are using the .end() method .expect() assertions that fail will not throw - they will return the assertion as an error to the .end() callback. In order to fail the test case, you will need to rethrow or pass err to done(), as follows:

describe('POST /users', function() {
  it('responds with json', function(done) {
    request(app)
      .post('/users')
      .send({name: 'john'})
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200)
      .end(function(err, res) {
        if (err) return done(err);
        return done();
      });
  });
});

You can also use promises:

describe('GET /users', function() {
  it('responds with json', function() {
    return request(app)
      .get('/users')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200)
      .then(response => {
         expect(response.body.email).toEqual('[email protected]');
      })
  });
});

Or async/await syntax:

describe('GET /users', function() {
  it('responds with json', async function() {
    const response = await request(app)
      .get('/users')
      .set('Accept', 'application/json')
    expect(response.headers["content-type"]).toMatch(/json/);
    expect(response.status).toEqual(200);
    expect(response.body.email).toEqual('[email protected]');
  });
});

Expectations are run in the order of definition. This characteristic can be used to modify the response body or headers before executing an assertion.

describe('POST /user', function() {
  it('user.name should be an case-insensitive match for "john"', function(done) {
    request(app)
      .post('/user')
      .send('name=john') // x-www-form-urlencoded upload
      .set('Accept', 'application/json')
      .expect(function(res) {
        res.body.id = 'some fixed id';
        res.body.name = res.body.name.toLowerCase();
      })
      .expect(200, {
        id: 'some fixed id',
        name: 'john'
      }, done);
  });
});

Anything you can do with superagent, you can do with supertest - for example multipart file uploads!

request(app)
  .post('/')
  .field('name', 'my awesome avatar')
  .field('complex_object', '{"attribute": "value"}', {contentType: 'application/json'})
  .attach('avatar', 'test/fixtures/avatar.jpg')
  ...

Passing the app or url each time is not necessary, if you're testing the same host you may simply re-assign the request variable with the initialization app or url, a new Test is created per request.VERB() call.

request = request('http://localhost:5555');

request.get('/').expect(200, function(err){
  console.log(err);
});

request.get('/').expect('heya', function(err){
  console.log(err);
});

Here's an example with mocha that shows how to persist a request and its cookies:

const request = require('supertest');
const should = require('should');
const express = require('express');
const cookieParser = require('cookie-parser');

describe('request.agent(app)', function() {
  const app = express();
  app.use(cookieParser());

  app.get('/', function(req, res) {
    res.cookie('cookie', 'hey');
    res.send();
  });

  app.get('/return', function(req, res) {
    if (req.cookies.cookie) res.send(req.cookies.cookie);
    else res.send(':(')
  });

  const agent = request.agent(app);

  it('should save cookies', function(done) {
    agent
    .get('/')
    .expect('set-cookie', 'cookie=hey; Path=/', done);
  });

  it('should send cookies', function(done) {
    agent
    .get('/return')
    .expect('hey', done);
  });
});

There is another example that is introduced by the file agency.js

Here is an example where 2 cookies are set on the request.

agent(app)
  .get('/api/content')
  .set('Cookie', ['nameOne=valueOne;nameTwo=valueTwo'])
  .send()
  .expect(200)
  .end((err, res) => {
    if (err) {
      return done(err);
    }
    expect(res.text).to.be.equal('hey');
    return done();
  });

API

You may use any superagent methods, including .write(), .pipe() etc and perform assertions in the .end() callback for lower-level needs.

.expect(status[, fn])

Assert response status code.

.expect(status, body[, fn])

Assert response status code and body.

.expect(body[, fn])

Assert response body text with a string, regular expression, or parsed body object.

.expect(field, value[, fn])

Assert header field value with a string or regular expression.

.expect(function(res) {})

Pass a custom assertion function. It'll be given the response object to check. If the check fails, throw an error.

request(app)
  .get('/')
  .expect(hasPreviousAndNextKeys)
  .end(done);

function hasPreviousAndNextKeys(res) {
  if (!('next' in res.body)) throw new Error("missing next key");
  if (!('prev' in res.body)) throw new Error("missing prev key");
}

.end(fn)

Perform the request and invoke fn(err, res).

Cookies

Here is an example of using the set and not cookie assertions:

// setup super-test
const request = require('supertest');
const express = require('express');
const cookies = request.cookies;

// setup express test service
const app = express();

app.get('/users', function(req, res) {
  res.cookie('alpha', 'one', { domain: 'domain.com', path: '/', httpOnly: true });
  res.send(200, { name: 'tobi' });
});

// test request to service
request(app)
  .get('/users')
  .expect('Content-Type', /json/)
  .expect('Content-Length', '15')
  .expect(200)
  // assert 'alpha' cookie is set with domain, path, and httpOnly options
  .expect(cookies.set({ name: 'alpha', options: ['domain', 'path', 'httponly'] }))
  // assert 'bravo' cookie is NOT set
  .expect(cookies.not('set', { name: 'bravo' }))
  .end(function(err, res) {
    if (err) {
      throw err;
    }
  });

It is also possible to chain assertions:

cookies.set({/* ... */}).not('set', {/* ... */})

Functions and methods are chainable.

cookies([secret], [asserts])

Get assertion function for super-test .expect() method.

Arguments

.set(expects, [assert])

Assert that cookie and options are set.

Arguments

.reset(expects, [assert])

Assert that cookie is set and was already set (in request headers).

Arguments

.new(expects, [assert])

Assert that cookie is set and was NOT already set (NOT in request headers).

Arguments

.renew(expects, [assert])

Assert that cookie is set with a strictly greater expires or max-age than the given value.

Arguments

.contain(expects, [assert])

Assert that cookie is set with value and contains options.

Requires cookies(secret) initialization if cookie is signed.

Arguments

.not(method, expects)

Call any cookies assertion method with "assert true" modifier set to false.

Syntactic sugar.

Arguments

Notes

Inspired by api-easy minus vows coupling.

License

MIT

supertest (forwardemail/supertest)

Searching Database…

14.4K ·GitHub
这是什么?Supertest 是一个用于测试 Node.js HTTP 服务器的库,基于 superagent 构建,提供可链式调用的流畅 API。
它是独立的测试运行器,还是能接入我已经在用的运行器?它是你在测试里使用的库,本身不是测试运行器;它可以配合 mocha 等任何测试框架使用,甚至不用任何框架也行。
我怎么把它加到项目里?以 npm 模块的方式安装,并用 --save-dev 将其保存到 package.json 的开发依赖中;然后用 require 引入它,并以你的 http.Server 或一个函数为参数调用 request()。
它底层依赖什么?它基于 superagent 发送 HTTP 请求,内部还用到了 methods 和 cookie-signature;需要 Node.js 14.18.0 或更高版本。
如果用 .end() 时 .expect() 断言失败,我的测试会自动失败吗?不会。传给 .end() 的 .expect() 断言失败时不会抛出异常,而是作为错误返回给回调函数,所以你必须自己重新抛出,或把 err 传给 done(),测试才会失败。
它支持 async/await 和 Promise 吗?支持。除了传统的回调写法,还支持 Promise 链式调用和 async/await 语法。
它能处理 multipart 文件上传吗?可以。supertest 暴露了 superagent 的全部功能,包括通过链式调用实现的 multipart 文件上传。
我能测试 HTTP/2 服务器吗?可以。在 request() 或 request.agent() 后面追加一个选项对象,就能启用 http2 协议。
它支持 cookie 断言吗?支持。它有专门的 cookies() API,提供 .set()、.reset()、.new()、.renew()、.contain()、.not() 等可链式调用的方法,用于断言 cookie 的存在、值和过期时间,也可以通过 secret 检查带签名的 cookie。
哪些项目在维护这个库?它是为 Forward Email、Lad、Spam Scanner、Bree、Cabin 和 Lass 等项目而维护的。
What are similar projects?ava, koa, nock, node-restify, mocha, enzyme, core, hapi
Size
0.9 MB
Stars
14.4K
Age
14y
Commits · 90 Days