koa-lite/test/utils/onfinish.js

265 lines
6.3 KiB
JavaScript

const assert = require('assert');
const http = require('http');
const net = require('net');
const onFinished = require('../../lib/onfinish');
describe('onFinished(res, listener)', () => {
it('should invoke listener given an unknown object', done => {
onFinished({}, done);
});
describe('when the response finishes', () => {
it('should fire the callback', done => {
let server = http.createServer((req, res) => {
onFinished(res, done);
setTimeout(res.end.bind(res), 0);
});
sendGet(server);
});
it('should include the response object', done => {
let server = http.createServer((req, res) => {
onFinished(res, (err, msg) => {
assert.ok(!err);
assert.strictEqual(msg, res);
done();
});
setTimeout(res.end.bind(res), 0);
});
sendGet(server);
});
it('should fire when called after finish', done => {
let server = http.createServer((req, res) => {
onFinished(res, () => {
onFinished(res, done);
});
setTimeout(res.end.bind(res), 0);
});
sendGet(server);
});
});
describe('when using keep-alive', () => {
it('should fire for each response', done => {
let called = false;
let server = http.createServer((req, res) => {
onFinished(res, () => {
if (called) {
socket.end();
server.close();
done(called !== req ? null : new Error('fired twice on same req'));
return;
}
called = req;
writeRequest(socket);
});
res.end();
});
let socket;
server.listen(function(){
socket = net.connect(this.address().port, function(){
writeRequest(this);
});
});
});
});
describe('when requests pipelined', () => {
it('should fire for each request', done => {
let count = 0;
let responses = [];
let server = http.createServer((req, res) => {
responses.push(res);
onFinished(res, err => {
assert.ifError(err);
assert.strictEqual(responses[0], res);
responses.shift();
if (responses.length === 0) {
socket.end();
return;
}
responses[0].end('response b');
});
onFinished(req, err => {
assert.ifError(err);
if (++count !== 2) {
return;
}
assert.strictEqual(responses.length, 2);
responses[0].end('response a');
});
if (responses.length === 1) {
// second request
writeRequest(socket);
}
req.resume();
});
let socket;
server.listen(function(){
let data = '';
socket = net.connect(this.address().port, function(){
writeRequest(this);
});
socket.on('data', chunk => {
data += chunk.toString('binary');
});
socket.on('end', () => {
assert.ok(/response a/.test(data));
assert.ok(/response b/.test(data));
server.close(done);
});
});
});
});
describe('when response errors', () => {
it('should fire with error', done => {
let server = http.createServer((req, res) => {
onFinished(res, err => {
assert.ok(err);
server.close(done);
});
socket.on('error', noop);
socket.write('W');
});
let socket;
server.listen(function(){
socket = net.connect(this.address().port, function(){
writeRequest(this, true);
});
});
});
it('should include the response object', done => {
let server = http.createServer((req, res) => {
onFinished(res, (err, msg) => {
assert.ok(err);
assert.strictEqual(msg, res);
server.close(done);
});
socket.on('error', noop);
socket.write('W');
});
let socket;
server.listen(function(){
socket = net.connect(this.address().port, function(){
writeRequest(this, true);
});
});
});
});
describe('when the response aborts', () => {
it('should execute the callback', done => {
let client;
let server = http.createServer((req, res) => {
onFinished(res, close(server, done));
setTimeout(client.abort.bind(client), 0);
});
server.listen(function(){
let port = this.address().port;
client = http.get('http://127.0.0.1:' + port);
client.on('error', noop);
});
});
});
describe('when calling many times on same response', () => {
it('should not print warnings', done => {
let server = http.createServer((req, res) => {
let stderr = captureStderr(() => {
for (let i = 0; i < 400; i++) {
onFinished(res, noop);
}
});
onFinished(res, done);
assert.strictEqual(stderr, '');
res.end();
});
server.listen(function(){
let port = this.address().port;
http.get('http://127.0.0.1:' + port, res => {
res.resume();
res.on('end', server.close.bind(server));
});
});
});
});
});
/**********************************************************
* Removed request tests as those are not needed by our app
***********************************************************/
function captureStderr(fn){
let chunks = [];
let write = process.stderr.write;
process.stderr.write = function write(chunk, encoding){
chunks.push(new Buffer(chunk, encoding));
};
try {
fn();
} finally {
process.stderr.write = write;
}
return Buffer.concat(chunks).toString('utf8');
}
function close(server, callback){
return function(error){
server.close(err => {
callback(error || err);
});
};
}
function noop(){}
function sendGet(server){
server.listen(function onListening(){
let port = this.address().port;
http.get('http://127.0.0.1:' + port, res => {
res.resume();
res.on('end', server.close.bind(server));
});
});
}
function writeRequest(socket, chunked){
socket.write('GET / HTTP/1.1\r\n');
socket.write('Host: localhost\r\n');
socket.write('Connection: keep-alive\r\n');
if (chunked) {
socket.write('Transfer-Encoding: chunked\r\n');
}
socket.write('\r\n');
}