ladjs / supertest

🕷 Super-agent driven library for testing node.js HTTP servers using a fluent API. Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.
MIT License
13.83k stars 759 forks source link

supertest pipe and end #241

Closed ganna-shmatova closed 5 years ago

ganna-shmatova commented 9 years ago
var ws = fs.createWriteStream('./test/dir/test_download.txt');
ws.on('error', function(err){
    console.log(err);
});
ws.on('close', function(){
    console.log('done download');
});
request.get('/download').expect(200)
    .send({'file': './test/nonbinary.txt'})
    .pipe(ws);
    //.end(assert('download'));

cannot call end() after piping. If you try to end() after pipe(), writestream prematurely ends & never finishes writing the file (so file is empty) & writestream tries to write again & it throws a 'writing after end' error.

the readme says one can use pipe() with supertest. What was the test case used to determine that?

drauschenbach commented 8 years ago

Confirming that this is a problem. I see no way of uploading a non-multipart application/octet-stream in a PUT or POST request.

shaunc commented 7 years ago

I had a related problem... seems to be possible to upload (at least) using the promise interface. However, the "onend()" of the stream doesn't chain a callback to Test.end().

var csvStream = csv.createWriteStream();
var req = request.post("/sheets/" + sheet3.id + "/load").type("csv");
csvStream.pipe(req);

rows.forEach(function(row) {
  csvStream.write(row);
});
return new Promise(function(res) {
  csvStream.end(res);
}).then(function() {
 return req;
});

Intercepting the call to Test.end, it is called from stream.end() without a callback:

  at Test.end (/Volumes/Macintosh_HD/Users/shauncutts/src/xquery-rest/node_modules/supertest/lib/test.js:125:7)
  at CsvTransformStream.onend (_stream_readable.js:511:10)
  at CsvTransformStream.g (events.js:292:16)
  at emitNone (events.js:91:20)
  at CsvTransformStream.emit (events.js:185:7)
  at endReadableNT (_stream_readable.js:974:12)
  at _combinedTickCallback (internal/process/next_tick.js:74:11)
  at process._tickDomainCallback (internal/process/next_tick.js:122:9)

resulting in an error when assert tries to chain to the callback. This error also doesn't seem to be caught in the promise chain correctly.

dkadrios commented 7 years ago

Turns out writeable streams have a 'finish' event.

This is working for me:


after((done) => {
    request(server)
        .get('/coverage/download')
        .pipe(fs.createWriteStream('./coverage.zip'))
        .on('finish', done);
});
isaachinman commented 6 years ago

@dkadrios Any idea how to do this in reverse, eg using .pipe for a POST upload request?