Skip to content

Commit

Permalink
When simulating close, ensure res emits close. (#139)
Browse files Browse the repository at this point in the history
  • Loading branch information
devinivy authored Jan 23, 2021
1 parent 1ba702c commit ad84924
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 8 deletions.
9 changes: 9 additions & 0 deletions lib/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ exports = module.exports = internals.Response = class extends Http.ServerRespons
this._shot = { headers: null, trailers: {}, payloadChunks: [] };
this.assignSocket(internals.nullSocket());

if (req._shot.simulate.close) {
// Ensure premature, manual close is forwarded to res.
// In HttpServer the socket closing actually triggers close on both req and res.
req.once('close', () => {

process.nextTick(() => this.emit('close'));
});
}

this.once('finish', () => {

const res = internals.payload(this);
Expand Down
19 changes: 11 additions & 8 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ const Code = require('@hapi/code');
const internals = {};


internals.trackStreamLifetime = function (stream, list) {
internals.trackStreamLifetime = function (stream, list, tag) {

const events = ['close', 'error', 'end', 'finish'];
for (const event of events) {
stream.on(event, () => list.push(event));
stream.on(event, () => list.push(tag ? `${event} (${tag})` : event));
}
};

Expand Down Expand Up @@ -680,13 +680,14 @@ describe('_read()', () => {
res.end('close');
});

internals.trackStreamLifetime(req, events);
internals.trackStreamLifetime(req, events, 'req');
internals.trackStreamLifetime(res, events, 'res');
};

const body = 'something special just for you';
const res = await Shot.inject(dispatch, { method: 'get', url: '/', payload: body, simulate: { error: true, close: true } });
expect(res.payload).to.equal('close');
expect(events).to.equal(['error', 'close']);
expect(events).to.equal(['error (req)', 'finish (res)', 'close (req)', 'close (res)']);
});

it('simulates no end without payload', async () => {
Expand Down Expand Up @@ -734,13 +735,14 @@ describe('_read()', () => {
res.end('close');
});

internals.trackStreamLifetime(req, events);
internals.trackStreamLifetime(req, events, 'req');
internals.trackStreamLifetime(res, events, 'res');
};

const body = 'something special just for you';
const res = await Shot.inject(dispatch, { method: 'get', url: '/', payload: body, simulate: { close: true, end: true } });
expect(res.payload).to.equal('close');
expect(events).to.equal(['end', 'close']);
expect(events).to.equal(['end (req)', 'finish (res)', 'close (req)', 'close (res)']);
});

it('simulates close (end = false)', async () => {
Expand All @@ -760,13 +762,14 @@ describe('_read()', () => {
res.end('close');
});

internals.trackStreamLifetime(req, events);
internals.trackStreamLifetime(req, events, 'req');
internals.trackStreamLifetime(res, events, 'res');
};

const body = 'something special just for you';
const res = await Shot.inject(dispatch, { method: 'get', url: '/', payload: body, simulate: { close: true, end: false } });
expect(res.payload).to.equal('close');
expect(events).to.equal(['close']);
expect(events).to.equal(['finish (res)', 'close (req)', 'close (res)']);
});

it('errors for invalid input options', async () => {
Expand Down

0 comments on commit ad84924

Please sign in to comment.