SuperAgent

The superagent test suite documentation generated with the Mocha test framework.

Basic auth

when credentials are present in url

should set Authorization

    request
    .get('http://tobi:learnboost@localhost:3010')
    .end(function(res){
      res.status.should.equal(200);
      done();
    });

req.auth(user, pass)

should set Authorization

    request
    .get('http://localhost:3010')
    .auth('tobi', 'learnboost')
    .end(function(res){
      res.status.should.equal(200);
      done();
    });

request

with an object

should format the url

    request
    .get(url.parse('http://localhost:3000/login'))
    .end(function(res){
      assert(res.ok);
      done();
    })

with a callback

should invoke .end()

    request
    .get('localhost:3000/login', function(res){
      assert(res.status == 200);
      done();
    })

without a schema

should default to http

    request
    .get('localhost:3000/login')
    .end(function(res){
      assert(res.status == 200);
      done();
    })

.end()

should issue a request

    request
    .get('http://localhost:3000/login')
    .end(function(res){
      assert(res.status == 200);
      done();
    });

res.header

should be an object

    request
    .get('http://localhost:3000/login')
    .end(function(res){
      assert('Express' == res.header['x-powered-by']);
      done();
    });

res.charset

should be set when present

    request
    .get('http://localhost:3000/login')
    .end(function(res){
      res.charset.should.equal('utf-8');
      done();
    });

res.statusType

should provide the first digit

    request
    .get('http://localhost:3000/login')
    .end(function(res){
      assert(200 == res.status);
      assert(2 == res.statusType);
      done();
    });

res.type

should provide the mime-type void of params

    request
    .get('http://localhost:3000/login')
    .end(function(res){
      res.type.should.equal('text/html');
      res.charset.should.equal('utf-8');
      done();
    });

req.set(field, val)

should set the header field

    request
    .post('http://localhost:3000/echo')
    .set('X-Foo', 'bar')
    .set('X-Bar', 'baz')
    .end(function(res){
      assert('bar' == res.header['x-foo']);
      assert('baz' == res.header['x-bar']);
      done();
    })

req.set(obj)

should set the header fields

    request
    .post('http://localhost:3000/echo')
    .set({ 'X-Foo': 'bar', 'X-Bar': 'baz' })
    .end(function(res){
      assert('bar' == res.header['x-foo']);
      assert('baz' == res.header['x-bar']);
      done();
    })

req.type(str)

should set the Content-Type

    request
    .post('http://localhost:3000/echo')
    .type('text/x-foo')
    .end(function(res){
      res.header['content-type'].should.equal('text/x-foo');
      done();
    });
should map "json"

    request
    .post('http://localhost:3000/echo')
    .type('json')
    .end(function(res){
      res.should.be.json;
      done();
    });
should map "html"

    request
    .post('http://localhost:3000/echo')
    .type('html')
    .end(function(res){
      res.header['content-type'].should.equal('text/html');
      done();
    });

req.write(str)

should write the given data

    var req = request.post('http://localhost:3000/echo');
    req.write('{"name"').should.be.a('boolean');
    req.write(':"tobi"}').should.be.a('boolean');
    req.end(function(res){
      res.text.should.equal('{"name":"tobi"}');
      done();
    });

req.pipe(stream)

should pipe the response to the given stream

    var stream = new EventEmitter;

    stream.buf = '';
    stream.writable = true;

    stream.write = function(chunk){
      this.buf += chunk;
    };

    stream.end = function(){
      this.buf.should.equal('{"name":"tobi"}');
      done();
    };

    request
    .post('http://localhost:3000/echo')
    .send('{"name":"tobi"}')
    .pipe(stream);

req.send(str)

should write the string

    request
    .post('http://localhost:3000/echo')
    .send('{"name":"tobi"}')
    .end(function(res){
      res.text.should.equal('{"name":"tobi"}');
      done();
    });

req.send(Object)

should default to json

    request
    .post('http://localhost:3000/echo')
    .send({ name: 'tobi' })
    .end(function(res){
      res.should.be.json
      res.text.should.equal('{"name":"tobi"}');
      done();
    });

when called several times

should merge the objects

    request
    .post('http://localhost:3000/echo')
    .send({ name: 'tobi' })
    .send({ age: 1 })
    .end(function(res){
      res.should.be.json
      res.text.should.equal('{"name":"tobi","age":1}');
      done();
    });

exports

should expose .version

    request.version.should.be.a('string');
should expose Part

    request.Part.should.be.a('function');
should expose .protocols

    Object.keys(request.protocols)
      .should.eql(['http:', 'https:']);
should expose .serialize

    Object.keys(request.serialize)
      .should.eql(['application/x-www-form-urlencoded', 'application/json']);
should expose .parse

    Object.keys(request.parse)
      .should.eql(['application/x-www-form-urlencoded', 'application/json']);

flags

with 4xx response

should set res.error and res.clientError

    request
    .get('http://localhost:3004/notfound')
    .end(function(res){
      assert(!res.ok, 'response should not be ok');
      assert(res.error, 'response should be an error');
      assert(res.clientError, 'response should be a client error');
      assert(!res.serverError, 'response should not be a server error');
      done();
    });

with 5xx response

should set res.error and res.serverError

    request
    .get('http://localhost:3004/error')
    .end(function(res){
      assert(!res.ok, 'response should not be ok');
      assert(!res.notFound, 'response should not be notFound');
      assert(res.error, 'response should be an error');
      assert(!res.clientError, 'response should not be a client error');
      assert(res.serverError, 'response should be a server error');
      done();
    });

with 404 Not Found

should res.notFound

    request
    .get('http://localhost:3004/notfound')
    .end(function(res){
      assert(res.notFound, 'response should be .notFound');
      done();
    });

with 400 Bad Request

should set req.badRequest

    request
    .get('http://localhost:3004/bad-request')
    .end(function(res){
      assert(res.badRequest, 'response should be .badRequest');
      done();
    });

with 401 Bad Request

should set res.unauthorized

    request
    .get('http://localhost:3004/unauthorized')
    .end(function(res){
      assert(res.unauthorized, 'response should be .unauthorized');
      done();
    });

with 406 Not Acceptable

should set res.notAcceptable

    request
    .get('http://localhost:3004/not-acceptable')
    .end(function(res){
      assert(res.notAcceptable, 'response should be .notAcceptable');
      done();
    });

with 204 No Content

should set res.noContent

    request
    .get('http://localhost:3004/no-content')
    .end(function(res){
      assert(res.noContent, 'response should be .noContent');
      done();
    });

req.send(Object) as "form"

with req.type() set to form

should send x-www-form-urlencoded data

    request
    .post('http://localhost:3000/echo')
    .type('form')
    .send({ name: 'tobi' })
    .end(function(res){
      res.header['content-type'].should.equal('application/x-www-form-urlencoded');
      res.text.should.equal('name=tobi');
      done();
    });

when called several times

should merge the objects

    request
    .post('http://localhost:3002/echo')
    .type('form')
    .send({ name: { first: 'tobi', last: 'holowaychuk' } })
    .send({ age: '1' })
    .end(function(res){
      res.header['content-type'].should.equal('application/x-www-form-urlencoded');
      res.text.should.equal('name[first]=tobi&name[last]=holowaychuk&age=1');
      done();
    });

res.body

application/x-www-form-urlencoded

should parse the body

    request
    .get('http://localhost:3002/form-data')
    .end(function(res){
      res.text.should.equal('pet[name]=manny');
      res.body.should.eql({ pet: { name: 'manny' }});
      done();
    });

request multipart/form-data

req.body

should be populated with fields

    request.get('http://localhost:3007/', function(res){
      res.status.should.equal(200);
      res.body.should.eql({ name: 'tobi' });
      res.files.image.name.should.equal('something.png');
      res.files.image.type.should.equal('image/png');
      assert(null == res.text, 'res.text should be empty for multipart');
      done();
    });

zlib

should deflate the content

    request
      .get('http://localhost:3080')
      .end(function(res){
        res.should.have.status(200);
        res.text.should.equal(subject);
        res.headers['content-length'].should.be.below(subject.length);
        done();
      });

req.send(Object) as "json"

should default to json

    request
    .post('http://localhost:3001/echo')
    .send({ name: 'tobi' })
    .end(function(res){
      res.should.be.json
      res.text.should.equal('{"name":"tobi"}');
      done();
    });
should work with arrays

    request
    .post('http://localhost:3001/echo')
    .send([1,2,3])
    .end(function(res){
      res.should.be.json
      res.text.should.equal('[1,2,3]');
      done();
    });

when called several times

should merge the objects

    request
    .post('http://localhost:3001/echo')
    .send({ name: 'tobi' })
    .send({ age: 1 })
    .end(function(res){
      res.should.be.json
      res.text.should.equal('{"name":"tobi","age":1}');
      done();
    });

res.body

application/json

should parse the body

    request
    .get('http://localhost:3001/json')
    .end(function(res){
      res.text.should.equal('{"name":"manny"}');
      res.body.should.eql({ name: 'manny' });
      done();
    });

Request

should default res.files to {}

    var req = request.post('http://localhost:3005/echo');

    req.end(function(res){
      res.files.should.eql({});
      res.body.should.eql({});
      done();
    });

#part()

should return a new Part

    var req = request.post('http://localhost:3005');
    req.part().constructor.name.should.equal('Part');
    req.part().constructor.name.should.equal('Part');
    req.part().should.not.equal(req.part());

#field(name, value)

should set a multipart field value

    var req = request.post('http://localhost:3005/echo');

    req.field('user[name]', 'tobi');
    req.field('user[age]', '2');
    req.field('user[species]', 'ferret');

    req.end(function(res){
      res.body['user[name]'].should.equal('tobi');
      res.body['user[age]'].should.equal('2');
      res.body['user[species]'].should.equal('ferret');
      done();
    });
should work with file attachments

    var req = request.post('http://localhost:3005/echo');

    req.field('name', 'Tobi');
    req.attach('test/node/fixtures/user.html', 'document');
    req.field('species', 'ferret');

    req.end(function(res){
      res.body.name.should.equal('Tobi');
      res.body.species.should.equal('ferret');

      var html = res.files.document;
      html.name.should.equal('document');
      html.type.should.equal('text/html');
      read(html.path).should.equal('<h1>name</h1>');
      done();
    })

#attach(file)

should attach a file

    var req = request.post('http://localhost:3005/echo');

    req.attach('test/node/fixtures/user.html');
    req.attach('test/node/fixtures/user.json');
    req.attach('test/node/fixtures/user.txt');

    req.end(function(res){
      var html = res.files['user.html'];
      var json = res.files['user.json'];
      var text = res.files['user.txt'];

      html.name.should.equal('user.html');
      html.type.should.equal('text/html');
      read(html.path).should.equal('<h1>name</h1>');

      json.name.should.equal('user.json');
      json.type.should.equal('application/json');
      read(json.path).should.equal('{"name":"tobi"}');

      text.name.should.equal('user.txt');
      text.type.should.equal('text/plain');
      read(text.path).should.equal('Tobi');

      done();
    })

when a file does not exist

should emit an error

    var req = request.post('http://localhost:3005/echo');

    req.attach('foo');
    req.attach('bar');
    req.attach('baz');

    req.on('error', function(err){
      err.message.should.include('ENOENT, no such file');
      err.path.should.equal('foo');
      done();
    });

    req.end(function(res){
      assert(0, 'end() was called');
    });

#attach(file, filename)

should use the custom filename

    request
    .post(':3005/echo')
    .attach('test/node/fixtures/user.html', 'document')
    .end(function(res){
      var html = res.files.document;
      html.name.should.equal('document');
      html.type.should.equal('text/html');
      read(html.path).should.equal('<h1>name</h1>');
      done();
    })

Part

with a single part

should construct a multipart request

    var req = request.post('http://localhost:3005/echo');

    req
      .part()
      .set('Content-Disposition', 'attachment; name="image"; filename="image.png"')
      .set('Content-Type', 'image/png')
      .write('some image data');

    req.end(function(res){
      var ct = res.header['content-type'];
      ct.should.include('multipart/form-data; boundary=');
      res.body.should.eql({});
      res.files.image.name.should.equal('image.png');
      res.files.image.type.should.equal('image/png');
      done();
    });

with several parts

should construct a multipart request


        var req = request.post('http://localhost:3005/echo');

        req.part()
          .set('Content-Type', 'image/png')
          .set('Content-Disposition', 'attachment; filename="myimage.png"')
          .write('some image data');

        var part = req.part()
          .set('Content-Type', 'image/png')
          .set('Content-Disposition', 'attachment; filename="another.png"')

        part.write('random');
        part.write('thing');
        part.write('here');

        req.part()
          .set('Content-Disposition', 'form-data; name="name"')
          .set('Content-Type', 'text/plain')
          .write('tobi');

        req.end(function(res){
          res.body.name.should.equal('tobi');
          Object.keys(res.files).should.eql(['myimage.png', 'another.png']);
        done();
        });

with a Content-Type specified

should append the boundary

    var req = request
      .post('http://localhost:3005/echo')
      .type('multipart/form-data');

    req
      .part()
      .set('Content-Type', 'text/plain')
      .set('Content-Disposition', 'form-data; name="name"')
      .write('Tobi');

    req.end(function(res){
      res.header['content-type'].should.include('boundary=');
      res.body.name.should.equal('Tobi');
      done();
    });

#name(str)

should set Content-Disposition to form-data and name param

    var req = request
      .post('http://localhost:3005/echo');

    req
      .part()
      .name('user[name]')
      .write('Tobi');

    req.end(function(res){
      res.body['user[name]'].should.equal('Tobi');
      done();
    });

#filename(str)

should set Content-Disposition and Content-Type

    var req = request
      .post('http://localhost:3005/echo')
      .type('multipart/form-data');

    req
      .part()
      .filename('path/to/my.txt')
      .write('Tobi');

    req.end(function(res){
      var file = res.files['my.txt'];
      file.name.should.equal('my.txt');
      file.type.should.equal('text/plain');
      done();
    });

request

act as a writable stream

should format the url

    var req = request.post('http://localhost:3020')
      , stream = fs.createReadStream('test/node/fixtures/user.json');

    req.type('json');

    req.on('response', function(res){
      res.body.should.eql({ name: 'tobi' });
      done();
    });

    stream.pipe(req);

req.send(Object)

on a GET request

should construct the query-string

    request
    .get('http://localhost:3006/')
    .send({ name: 'tobi' })
    .send({ order: 'asc' })
    .send({ limit: ['1', '2'] })
    .end(function(res){
      res.body.should.eql({ name: 'tobi', order: 'asc', limit: ['1', '2'] });
      done();
    });
should append to the original query-string

    request
    .get('http://localhost:3006/?name=tobi')
    .send({ order: 'asc' })
    .end(function(res) {
      res.body.should.eql({ name: 'tobi', order: 'asc' });
      done();
    });
should retain the original query-string

    request
    .get('http://localhost:3006/?name=tobi')
    .end(function(res) {
      res.body.should.eql({ name: 'tobi' });
      done();
    });

req.query(Object)

should construct the query-string

    request
    .del('http://localhost:3006/')
    .query({ name: 'tobi' })
    .query({ order: 'asc' })
    .query({ limit: ['1', '2'] })
    .end(function(res){
      res.body.should.eql({ name: 'tobi', order: 'asc', limit: ['1', '2'] });
      done();
    });
should append to the original query-string

    request
    .del('http://localhost:3006/?name=tobi')
    .query({ order: 'asc' })
    .end(function(res) {
      res.body.should.eql({ name: 'tobi', order: 'asc' });
      done();
    });
should retain the original query-string

    request
    .del('http://localhost:3006/?name=tobi')
    .end(function(res) {
      res.body.should.eql({ name: 'tobi' });
      done();
    });

request

on redirect

should follow Location

    var redirects = [];

    request
    .get('http://localhost:3003/')
    .on('redirect', function(res){
      redirects.push(res.headers.location);
    })
    .end(function(res){
      var arr = [];
      arr.push('http://localhost:3003/movies');
      arr.push('http://localhost:3003/movies/all');
      arr.push('http://localhost:3003/movies/all/0');
      redirects.should.eql(arr);
      res.text.should.equal('first movie page');
      done();
    });

req.redirects(n)

should alter the default number of redirects to follow

    var redirects = [];

    request
    .get('http://localhost:3003/')
    .redirects(2)
    .on('redirect', function(res){
      redirects.push(res.headers.location);
    })
    .end(function(res){
      var arr = [];
      assert(res.redirect, 'res.redirect');
      arr.push('http://localhost:3003/movies');
      arr.push('http://localhost:3003/movies/all');
      redirects.should.eql(arr);
      res.text.should.match(/Moved Temporarily/);
      done();
    });

utils.uid(len)

should generate a unique id

    utils.uid(10).should.have.length(10);
    utils.uid(30).should.have.length(30);
    utils.uid(30).should.not.equal(utils.uid(30));

utils.type(str)

should return the mime type

    utils.type('application/json; charset=utf-8')
      .should.equal('application/json');

    utils.type('application/json')
      .should.equal('application/json');

utils.params(str)

should return the field parameters

    var str = 'application/json; charset=utf-8; foo  = bar';
    var obj = utils.params(str);
    obj.charset.should.equal('utf-8');
    obj.foo.should.equal('bar');

    var str = 'application/json';
    utils.params(str).should.eql({});