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.8k stars 757 forks source link

Supertest fails on Content-Type #187

Closed ilanbiala closed 9 years ago

ilanbiala commented 9 years ago

Supertest says the content-type is text/plain, but when I use Postman or Chrome devtools and check the network tab, it correctly shows the content-type as text/html.

describe('Core controller unit tests:', function() {
    before(function(done) {
        request = request('http://localhost:3001');

        done();
    });

    describe('Loading the homepage', function() {
        it('should return 200 from GET /', function(done) {
            request
                .get('/')
                .expect('Content-Type', /html/)
                .expect(200, done);
        });
    });

    after(function(done) {
        done();
    });
});
ilanbiala commented 9 years ago

Bump.

ilanbiala commented 9 years ago

@gjohnson any thoughts on what's going on?

ilanbiala commented 9 years ago

@gjohnson this still doesn't work for me..I'm positive my content-type is correct, can you take a look at this?

ilanbiala commented 9 years ago

@gjohnson when using an API tester like the Postman Chrome app, I get the content-type as text/html, so what is going on exactly?

trainiac commented 9 years ago

+1 always getting "text/html; charset=utf-8" no matter what I do.

    it('should respond with a 200 if the posted body is valid', function(done) {
        request(app)
            .post('/user/', {
                json: true,
                body: helpers.getUser()
            })
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(function(response) {
                debugger;
                response.res.json.id.should.eql('123');
            })
            .expect(200)
            .end(done);
    });

app.post('/user/', validate({body: helpers.getUserSchema()}), function(req, res) {
   res.set('Content-Type', 'applicaton/json'); 
   res.json({
        id: '1234'
    });
});
isc-rsingh commented 9 years ago

same here

ilanbiala commented 9 years ago

@gjohnson any status on this?

mboughaba commented 9 years ago

@ilanbiala not sure it will help, maybe you should try setting the accept header of your supertest request.

    request(app)
            .get('/')
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200, done);
mikelax commented 9 years ago

@ilanbiala can you attach the sample Postman request and response (with headers) that is working for your example? Is there some server redirect that is happening with the requests as that could change the response types. We use expect Content-Type in almost all our tests and it works for json, html, etc.

mikelax commented 9 years ago

Hi all, I don't think there is anything wrong with supertest, or superagent. Here is a quick test file I wrote that shows things working as they should for a basic express set up.

var request = require('supertest')
  , express = require('express');

var app = express();

app.post('/user/json', function(req, res) {
   res.set('Content-Type', 'application/json');
   res.json({
        id: '1234'
    });
});

app.post('/user/html', function(req, res) {
   res.set('Content-Type', 'text/html');
   res.send('id: 1234');
});

describe('POST /user/json', function(){
    it('should respond with a json 200 response setting Accept header', function(done) {
        request(app)
            .post('/user/json', {
                json: true,
                body: '{"id":"100","name":"Mike"}'
            })
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200)
            .end(done);
    });
    it('should respond with a json 200 not setting Accept header', function(done) {
        request(app)
            .post('/user/json', {
                json: true,
                body: '{"id":"100","name":"Mike"}'
            })
            .expect('Content-Type', /json/)
            .expect(200)
            .end(done);
    });
});

describe('POST /user/html', function(){
    it('should respond with an html 200 response setting Accept header', function(done) {
        request(app)
            .post('/user/html', {
                json: true,
                body: '{"id":"100","name":"Mike"}'
            })
            .set('Accept', 'application/json')
            .expect('Content-Type', /html/)
            .expect(200)
            .end(done);
    });
    it('should respond with an html 200 not setting Accept header', function(done) {
        request(app)
            .post('/user/html', {
                json: true,
                body: '{"id":"100","name":"Mike"}'
            })
            .expect('Content-Type', /html/)
            .expect(200)
            .end(done);
    });
});
colceagus commented 8 years ago

Does supertest match Content-Type: application/json; charset=/whichevercharset/ with .expect('Content-Type', /json/) ?

What should I write to make it do it ?

mikelax commented 8 years ago

@danielmihai yes if you pass a regex as the second argument to .expect it will match in your example.

ie:
.expect('Content-Type', /json/) will match application/json; charset=utf-8

TeemuKoivisto commented 7 years ago

Just FYI for other dummies like me whose tests failed on .expect("Content-Type", /json/)

My mistake was refactoring this bit of code from

res.status(statusCode).send(err); // err is an object

to

res.status(statusCode).send(message); // string from the err object

When the correct way would be

res.status(statusCode).send({ message, });

By default if the data is not inside curly brackets it will be rendered as html, not json. And the reason why I couldn't see it with Postman was because it still sends err-objects while in development environment, not test. Every day I relearn something new...

cbt2016 commented 7 years ago
`request(app)
          .get('/')
          .expect('Content-Type','text/html; charset=utf-8')
          .end(done);

    });
`

will work perfectly whereas

`request(app)
          .get('/')
          .expect('Content-Type','text/html')
          .end(done);

    });` 

won't work because the http header received adds an encoding of utf-8

colceagus commented 7 years ago

You could use a regexp to match your expected content type. /text\/html/ would pass your test.

On Tue, Mar 28, 2017 at 2:18 PM, Simo notifications@github.com wrote:

`request(app) .get('/') .expect('Content-Type','text/html; charset=utf-8') .end(done);

});

while work perfectly whereasrequest(app) .get('/') .expect('Content-Type','text/html') .end(done);

});`

won't work because the http header received adds an encoding of utf-8

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/visionmedia/supertest/issues/187#issuecomment-289738784, or mute the thread https://github.com/notifications/unsubscribe-auth/ABzKA4SGG70kSVqw3EBhJRtGNTpkvr37ks5rqOyVgaJpZM4DFFa6 .

ghost commented 6 years ago

it is work to return as a json~

describe('Loading the homepage', function() {  
      it('should return 200 from GET /', function(done) {  
            request  
            .get('/')  
            .set('Content-Type', 'application/json')  
            .expect(200, done);  
       });  
});
akotranza commented 6 years ago

Had this error in an older project using https://www.npmjs.com/package/express-force-https ... not a very popular package, but it will cause Express to always return 302 with html/text when using Supertest. With the tests expecting Content-Type of /json/ of course. Easy fix was to not use this package in test env. Commenting here in the off chance it saves someone else several hours of googling and debugging.

Tragopoulos commented 5 years ago

As the issue is closed I suppose that I'm doing something wrong here and some help would be appreciated.

const express = require('express');

var app = express();

app.get('/', (req, res) => {
    res.status(404).send({
        error: 'Page not found.',
        name: 'Todo App v1.0'
    });
});

app.listen(3000);
module.exports.app = app;
const request = require('supertest');
const expect = require

var app = require('./server').app;

describe('Server', () => {
    describe('GET /', () => {
        it('Should return hello world response', (done) => {
            request(app)
                .get('/')
                .expect(404)
                .expect((res) => {
                    expect(res.body).toInclude({
                        error: "Page not found."
                    });
                })
                .end(done);
        });
    });
});

My error message is the same

  1) Server
       GET /
         Should return hello world response:
     TypeError [ERR_INVALID_ARG_TYPE]: The "id" argument must be of type string. Received type object
      at validateString (internal/validators.js:125:11)
      at Module.require (internal/modules/cjs/loader.js:652:3)
      at require (internal/modules/cjs/helpers.js:22:18)
      at request.get.expect.expect (server/server.test.js:13:21)
      at Test._assertFunction (node_modules/supertest/lib/test.js:283:11)
      at Test.assert (node_modules/supertest/lib/test.js:173:18)
      at Server.localAssert (node_modules/supertest/lib/test.js:131:12)
      at emitCloseNT (net.js:1599:8)
      at process.internalTickCallback (internal/process/next_tick.js:72:19)
Jetlum commented 3 years ago

Had the same problem. Just need a little bit of code refactoring.

What solved the problem for me was: Test didn't pass: notesRouter.get('/', (request, response) => { response.send('<h1>Hello World!</h1>') })

Test passed: notesRouter.get('/', (request, response) => { const message = '<h1>Hello World</h1>' response.json({message}) })

Felexonyango commented 2 years ago

Same error any help please

describe("GET api/job/:id",()=>{

it("should return  post by id",(done)=>{

  const id=2
  app.get(`/api/jobs/${id}`)
   .end((err, res) => {

  res.should.have.a('object')
  res.should.be.json

  done();
  })

}) })

1) JOB GET api/job/:id should return post by id: Uncaught AssertionError: expected 'text/html; charset=utf-8' to include 'application/json' at /home/felex/DevCon/test/jobs.test.js:74:21 at Test.Request.callback (node_modules/superagent/lib/node/index.js:716:12) at IncomingMessage. (node_modules/superagent/lib/node/index.js:916:18) at IncomingMessage.emit (node:events:539:35) at endReadableNT (node:internal/streams/readable:1345:12) at processTicksAndRejections (node:internal/process/task_queues:83:21)

Felexonyango commented 2 years ago

I'm getting error on testing .Any help please

krzywiecki commented 2 years ago

Thanks @mikelax!

.post('/campaignunits/1/tvschedule', {
    json: true,
    body: '{ data: "test" }'
})
.set('Accept', 'application/json')

works without any errors.