diff --git a/lib/test.js b/lib/test.js index f8300881..7f716535 100644 --- a/lib/test.js +++ b/lib/test.js @@ -275,7 +275,11 @@ class Test extends Request { */// eslint-disable-next-line class-methods-use-this _assertHeader(header, res) { const field = header.name; - const actual = res.header[field.toLowerCase()]; + // Use `res.headers` rather than `res.header`: superagent copies + // content-type parameters onto the response, so a value such as + // `text/csv; header=present` overwrites `res.header` and breaks every + // header assertion. `res.headers` is the untouched header map. + const actual = res.headers[field.toLowerCase()]; const fieldExpected = header.value; if (typeof actual === 'undefined') return new Error('expected "' + field + '" header field'); diff --git a/test/issue-fixes.js b/test/issue-fixes.js index d84904fe..740f10b7 100644 --- a/test/issue-fixes.js +++ b/test/issue-fixes.js @@ -119,4 +119,23 @@ describe('GitHub Issue Fixes', function() { }); }); }); + + describe('Issue #876: "header=" content-type param breaks header matchers', function() { + it('should match other headers when content-type has a "header=" parameter', function(done) { + const csvApp = express(); + csvApp.get('/csv', function(req, res) { + // `header=present` is a valid text/csv parameter (RFC 7111). superagent + // copies content-type params onto the response, clobbering `res.header`. + res.setHeader('Content-Type', 'text/csv; header=present'); + res.setHeader('X-Custom', 'value'); + res.send('a,b,c'); + }); + + supertest(csvApp) + .get('/csv') + .expect('X-Custom', 'value') + .expect(200) + .end(done); + }); + }); });