I am trying to write a test that checks whether an API route outputs a ZIP file with the correct contents.
I am using mocha and supertest for testing, and I would like to actually read the output stream/buffer, read the zip file contents and see if the contents are correct.
Any ideas how should I do it? When I try to read res.body, it's just an empty object.
  request(app)
    .get( "/api/v1/orders/download?id[]=1&id=2" )
    .set( "Authorization", authData )
    .expect( 200 )
    .expect( 'Content-Type', /application\/zip/ )
    .end( function (err, res) {
      if (err) return done( err );
      console.log( 'body:', res.body )
      // Write the temp HTML file to filesystem using utf-8 encoding
      var zip = new AdmZip( res.body );
      var zipEntries = zip.getEntries();
      console.log( 'zipentries:', zipEntries );
      zipEntries.forEach(function(zipEntry) {
        console.log(zipEntry.toString()); // outputs zip entries information
      });
      done();
    });
                Expanding on @Beau's answer, the following can be used to get any binary response content as a Buffer which you can examine further in request.end():
function binaryParser(res, callback) {
    res.setEncoding('binary');
    res.data = '';
    res.on('data', function (chunk) {
        res.data += chunk;
    });
    res.on('end', function () {
        callback(null, new Buffer(res.data, 'binary'));
    });
}
// example mocha test
it('my test', function(done) {
    request(app)
        .get('/path/to/image.png')
        .expect(200)
        .expect('Content-Type', 'image.png')
        .buffer()
        .parse(binaryParser)
        .end(function(err, res) {
            if (err) return done(err);
            // binary response data is in res.body as a buffer
            assert.ok(Buffer.isBuffer(res.body));
            console.log("res=", res.body);
            done();
        });
});
                        I think you'll want to create your own parser for application/zip and use that to get at the actual response data; the JSON parser is here, for example. Once you've got that you can use it by passing it to request.parse; so your test would become:
request(app)
  .get( "/api/v1/orders/download?id[]=1&id=2" )
  .set( "Authorization", authData )
  .expect( 200 )
  .expect( 'Content-Type', /application\/zip/ )
  .parse( function (res, fn) {
    res.data = '';
    res.on( 'data', function (chunk) { res.data += chunk; } );
    res.on( 'end', function () {
      try {
        fn( null, new AdmZip( res.data ) );
      } catch ( err ) {
        fn( err );
      }
    });
  })
  .end( function (err, res) {
    if (err) return done( err );
    console.log( 'body:', res.body )
    // Write the temp HTML file to filesystem using utf-8 encoding
    var zipEntries = res.body.getEntries();
    console.log( 'zipentries:', zipEntries );
    zipEntries.forEach(function(zipEntry) {
      console.log(zipEntry.toString()); // outputs zip entries information
    });
    done();
  });
To find the answer to this I mostly relied on inspecting the superagent test suite. :)
As descirbed in Testing binary response with supertest setting .responseType('blob') on the request will cause req.body to be a Buffer.
https://visionmedia.github.io/superagent/#binary
it('test', async () => {
  await request(app)
    .get('/api/some-zip')
    .responseType('blob')
    .expect(200)
    .expect('Content-Type', /application\/zip/)
    .expect(( res) => {
      const zipEntries = new AdmZip(res.body).getEntries().map(e => e.entryName);
      expect(zipEntries).toEqual(expect.arrayContaining(['zipfile1.pdf', 'zipfile2.pdf']));
  });
});
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With