Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot read property 'status' of undefined #352

Closed
jakubknejzlik opened this issue Jun 28, 2016 · 40 comments
Closed

Cannot read property 'status' of undefined #352

jakubknejzlik opened this issue Jun 28, 2016 · 40 comments
Labels
too-old Item to old

Comments

@jakubknejzlik
Copy link

When sending test request with expected status code and getting response with invalid content type (eg. header says application/json, but server sends xml/html), the Test.prototype._assertStatus fails while getting status from res (which is undefined).

@mikelax
Copy link
Contributor

mikelax commented Jul 5, 2016

thanks @jakubknejzlik can you please post a small test snippet showing the problem?

@isaac-peka
Copy link

isaac-peka commented Jul 6, 2016

I'm also experiencing this problem when using multiple callbacks in a single route - status is undefined on the response object. I haven't had a chance to test how this behaves with single callback routes, but here's a quick example for the multiple callback issue:

function callback1(req, res, next) {
  if (!res.status) {
    throw new Error("res.status is undefined");
  } else {
    next();
  }
}

function callback2(req, res, next) {
  res.json({ success: true });
}

app.get('/test', callback1, callback2);

Then $ curl http://localhost:3000/test will return { success: true }.

The following test fails for me due to the throw above, I use Jest but this could easily be changed to use mocha:

 it("shouldn't throw an error", (done) => {
    supertest(app)
      .get('/test')
      .expect(200)
      .end((err, res) => err ? done.fail(err) : done());
 });

I'm using supertest v1.2.0 and express v4.14.0.

@jeffijoe
Copy link

In my case I was using then to end the request instead of end, and supertest adds logic to wait for the server to actually be listening for end which was not executing for then. In my before I just ensure that tests wont run until the server is listening.

It might be a good idea to add the waiting logic in a then on Test?

@Starefossen
Copy link

This is how I solved it using Promises from Supertest@2.0.0:

it('should return 404 Not Found for missing resources', function() {
  return req.get('/this/is/not/found')
    .expect(404)
    .expect(function(res) {
      assert.equal(res.body.message, 'Resource Not Found');
    });
});

@Vanuan
Copy link

Vanuan commented Aug 23, 2016

Here's a traceback:


     TypeError: Cannot read property 'status' of undefined
      at Test._assertStatus (node_modules/supertest/lib/test.js:229:10)
      at Test._assertFunction (node_modules/supertest/lib/test.js:247:11)
      at Test.assert (node_modules/supertest/lib/test.js:148:18)
      at Server.assert (node_modules/supertest/lib/test.js:127:12)
      at net.js:1277:10    


@Vanuan
Copy link

Vanuan commented Aug 23, 2016

Similarly,

     TypeError: Cannot read property 'header' of undefined
      at Test._assertHeader (node_modules/supertest/lib/test.js:208:19)
      at Test._assertFunction (node_modules/supertest/lib/test.js:247:11)
      at Test.assert (node_modules/supertest/lib/test.js:148:18)
      at Server.assert (node_modules/supertest/lib/test.js:127:12)
      at net.js:1277:10    


@Vanuan
Copy link

Vanuan commented Aug 23, 2016

Looks like #348 is a fix

@Vanuan
Copy link

Vanuan commented Aug 24, 2016

This happens when I use res.sendFile.

@santanu-biswas
Copy link
Contributor

Submitted #348 almost three months back and it should take care of this bug. However, it seems that the repository is not active and nobody is accepting PRs!

@danday74
Copy link

danday74 commented Oct 4, 2016

I got this error when testing over a secure connection. I fixed it by adding NODE_TLS_REJECT_UNAUTHORIZED=0 as an env var on the test run.

For those wondering why this happens, it can happen because '127.0.0.1' is not listed as a valid IP in your certificate.
The underlying error is ...
Hostname/IP doesn't match certificate's altnames: "IP: 127.0.0.1 is not in the cert's list: "
However, you will not see this error message - Just the spurious and much disliked ...

Cannot read property 'status' of undefined

Hope this helps someone. God bless.

@cwdcwd
Copy link

cwdcwd commented Dec 14, 2016

FWIW. I run into this very error when I run under node 6.9.2 (LTS) but don't see it when I switch to 4.0.0. Is this an ES6 related issue?

     TypeError: Cannot read property 'status' of undefined
      at Test._assertStatus (node_modules/supertest/lib/test.js:263:10)
      at Test._assertFunction (node_modules/supertest/lib/test.js:281:11)
      at Test.assert (node_modules/supertest/lib/test.js:171:18)
      at Server.assert (node_modules/supertest/lib/test.js:131:12)
      at emitCloseNT (net.js:1555:8)
      at _combinedTickCallback (internal/process/next_tick.js:71:11)
      at process._tickDomainCallback (internal/process/next_tick.js:122:9)

@cwdcwd
Copy link

cwdcwd commented Dec 14, 2016

tracing through my particular issue, res is undefined and I'm seeing and HPE_UNEXPECTED_CONTENT_LENGTH error. That led me to this which seems to imply it's an issue w/ request & node.js versioning.

@cwdcwd
Copy link

cwdcwd commented Dec 14, 2016

upgrading all my dependencies, including request seems to have resolved this for me. here's a snippet of all my deps:

{
        "async": "^2.1.4",
        "aws-sdk": "2.7.13",
        "bluebird": "3.4.6",
        "body-parser": "^1.15.2",
        "config": "^1.24.0",
        "express": "^4.14.0",
        "express-http-proxy": "^0.10.1",
        "http-auth": "^3.1.1",
        "kue": "^0.11.5",
        "lodash": "4.17.2",
        "morgan": "^1.7.0",
        "request": "^2.79.0",
        "throng": "^4.0.0",
        "underscore": "^1.8.3",
        "url": "^0.11.0",
        "winston": "^2.3.0"
    }

@turakvlad
Copy link

turakvlad commented Dec 15, 2016

I have the same issue with node 7.2.1:

     TypeError: Cannot read property 'status' of undefined
      at Test._assertStatus (node_modules/supertest/lib/test.js:263:10)
      at Test._assertFunction (node_modules/supertest/lib/test.js:281:11)
      at Test.assert (node_modules/supertest/lib/test.js:171:18)
      at assert (node_modules/supertest/lib/test.js:131:12)
      at node_modules/supertest/lib/test.js:128:5
      at Test.Request.callback (node_modules/superagent/lib/node/index.js:615:12)
      at ClientRequest.<anonymous> (node_modules/superagent/lib/node/index.js:567:10)
      at Socket.socketErrorListener (_http_client.js:309:9)
      at onwriteError (_stream_writable.js:346:10)
      at onwrite (_stream_writable.js:364:5)
      at WritableState.onwrite (_stream_writable.js:90:5)
      at fireErrorCallbacks (net.js:471:13)
      at Socket._destroy (net.js:512:3)
      at WriteWrap.afterWrite (net.js:806:10)

It fails sometimes. About 1 to 10 times. My test looks pretty straight forward:

it('should fail because the token has already been used', function (done) {
            request(server)
                .post(`${apiPath}/${token}/actions/create`)
                .attach('upload', filePath)
                .expect(400)
                .end((err, res) => {
                    if (err) return done(err);
                    expect(res.body.success).to.be.false;
                    done();
                })
        });

My deps:

  "dependencies": {
    "cron": "^1.1.1",
    "debug": "~2.2.0",
    "dotenv": "^2.0.0",
    "express": "^4.14.0",
    "extract-zip": "^1.5.0",
    "formidable": "^1.0.17",
    "jsonfile": "^2.4.0",
    "mysql": "^2.11.1",
    "promise": "^7.1.1",
    "request": "^2.79.0",
    "shelljs": "^0.7.5"
  },
  "devDependencies": {
    "babel-cli": "^6.18.0",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-stage-2": "^6.18.0",
    "babel-register": "^6.18.0",
    "chai": "^3.5.0",
    "mocha": "^3.2.0",
    "supertest": "^2.0.1"
  }

@elasticsearcher
Copy link

@Starefossen It does indeed work when using promises, thanks!

@ttbarnes
Copy link

ttbarnes commented Dec 24, 2016

Will there be a fix for this soon? Does anyone have a workaround for this?

This only seems to happen with POST and PUT requests, for me at least.

I've tried upgrading relevant packages (express, bluebird, http-status, mocha, node, supertest), using promises as suggested above, downgrading to node v5/v4, getting latest mac OS and xcode - still getting the same supertest error:

Unhandled rejection TypeError: Cannot read property 'status' of undefined

Here is one example that fails - this used to work, I don't understand why this is no longer working.

it('should work', (done) => {
    request(app)
      .post('/api/create')
      .set('Authorization', JWT_VALID)
      .send(CREATE_OBJ)
      // .expect(httpStatus.OK)
      .expect(200)
      .then((res) => {
        expect(res.body).to.be.an('object');
        done();
      });
  });
});

This is completely blocking me atm. Maybe superagent is the way to go.

@ttbarnes
Copy link

This seems random and doesn't make any sense to me.

Supertest was working perfectly. I made some very unrelated code changes (eg just a small change to a schema object) and now supertest Cannot read property 'status' of undefined.

If I revert the unrelated code change, I get the same error.

Wtf?

I am unable to run tests at all now because of this.

@jakubknejzlik
Copy link
Author

@ttbarnes just quick question...does it do the similar when using promises? Eg:

it('should work', () => {
    return request(app)
      .post('/api/create')
      .set('Authorization', JWT_VALID)
      .send(CREATE_OBJ)
      // .expect(httpStatus.OK)
      .expect(200)
      .then((res) => {
        expect(res.body).to.be.an('object');
      });
  });
});

@ttbarnes
Copy link

@jakubknejzlik by adding the 'return' in the app request, It's not getting to the promise, and just getting a unit test timeout error. eg:

it('should work', () => {
    return request(app)
      .get('/api/profile/private')
      .set('Authorization', JWT_VALID)
      .expect(200)
      .then((res) => {
        console.log(res);
        expect(res.body).to.be.an('object');
      });
  });
});

If I remove the 'return' from the initial app request, I get Cannot read property 'status' of undefined, eg:

it('should work', () => {
  request(app)
  ...
  // same as above
}):

@jakubknejzlik
Copy link
Author

@ttbarnes well that's strange. The latter one should give you timeout not the first one.

@JeffML
Copy link

JeffML commented Jan 23, 2017

Getting this error, but only on some servers. Code:

basicTest.js
`
var chai = require('chai');
var should = chai.should();

var server = process.env.SERVER_UNDER_TEST;
var serverName = server.split('//')[1];

describe("Basic-test", () => {
var request = require('supertest')(server);

it("request initialized", done => {
    request.should.be.ok;
    done();
});

it("can get /test page", done => {
    var req = request.get('/test');

    req
        .expect(200)
        .expect('Content-Type', /text\/plain/)
        .end((err, res) => {
            should.not.exist(err);
            should.exist(res.headers.date)
            should.not.exist(res.headers.cookies);
            res.text.should.contain(serverName);
            res.text.should.contain('cookies are undefined');
            done();
        })
});

});`

Unfortunately, the errors occur on two out of three of our internal servers:

It looks like the problem may be due to gzip compression; test server returns:
HTTP/1.1 200 OK Date: Mon, 23 Jan 2017 20:44:43 GMT X-Powered-By: Express Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/plain; charset=UTF-8

dev server returns:
HTTP/1.1 200 OK Date: Mon, 23 Jan 2017 20:47:28 GMT X-Powered-By: Express Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS Vary: Accept-Encoding,User-Agent Content-Encoding: gzip Content-Length: 389 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/plain; charset=UTF-8

@ianstormtaylor
Copy link

Just ran into this as well, very frustrating, and it was already using the promises API, so @Starefossen's fix didn't help. Weirdly, I could request any route other than my site's / index route and that would work, but the index route threw this error.

@basslagter
Copy link

Updating body-parser (https://www.npmjs.com/package/body-parser) to 1.16.0 (in my case) did the trick for me.

@ttbarnes
Copy link

ttbarnes commented Feb 11, 2017

Tried updating various dependencies including body-parser - same issue for me. 👎

@radostnomne
Copy link

I have the same issue while run HTTPS local server. The problem disappear with HTTP server.

@danday74
Copy link

@radostnomne see my HTTPS fix above

@atomantic
Copy link

I've got the same issue, inconsistently, only for requests on the root path (all other tests pass).

Node 6.11.2
supertest 3.0.0

@hilongjw
Copy link

same issue in gitlab ci

node: 7.10.0
supertest": "^3.0.0"

@michaelquery
Copy link

Not sure if this is entirely relevant, but we have experienced this issue. The problem in our case was that there were errors generated inside Axios.request in preparing data for send. An error was thrown and caught by Axios, but in our interceptors, we were expecting a status to be available on error.response.

Since errors were thrown before the response was created, the error object, as delivered to the interceptor handler, did not have a "response" so an error was thrown when referencing error.repsonse.status

A scheme that would allow Axios to only catch errors related to the requests and pass others up the chain.

@Jeff-Li-Realster
Copy link

Same issue here

"node": "8.5.0",
"supertest": "^3.0.0"

@MartijnR
Copy link

MartijnR commented Oct 3, 2017

for me only the 4xx response tests started failing with this error due to some npm dependency update.

Update: For me this was caused by the response content-type not matching the actual content-type of the error response body (a JSON parse error occurs). This regression occurred due to a change somewhere in the app which set Content-type to "application/json; charset=utf-8" instead of the old "application/json".

@01binary
Copy link

01binary commented Oct 17, 2017

Just got this error, and my problem is that I forgot the slash in get path:
supertest(server).get('favicon.ico')
gets me...

TypeError: Cannot read property 'status' of undefined
at Test.Object.<anonymous>.Test._assertStatus (node_modules/supertest/lib/test.js:268:10)
      at Test.Object.<anonymous>.Test._assertFunction (node_modules/supertest/lib/test.js:286:11)
      at Test.Object.<anonymous>.Test.assert (node_modules/supertest/lib/test.js:175:18)
      at Server.assert (node_modules/supertest/lib/test.js:132:12)

putting the slash in,
supertest(server).get('/favicon.ico')
...the test works as expected.

I traced the issue down to logic that applies assertions. It's supposed to early-exit with an error if there was an error, but something causes it to run the assertions anyway and it fails because response is undefined when there's an error:

callback that performs assertions gets resError { Error: connect ECONNREFUSED 127.0.0.1:80
          at Object._errnoException (util.js:1041:11)
          at _exceptionWithHostPort (util.js:1064:20)
          at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1153:14)
        code: 'ECONNREFUSED',
        errno: 'ECONNREFUSED',
        syscall: 'connect',
        address: '127.0.0.1',
        port: 80,
        response: undefined } res undefined

Maybe it fails because the un-intended effect of forgetting the slash means that it will try to connect to "http://favicon.ico" which isn't a server?

Either way it needs some logic hardened in Test.assert (or whatever runs through the array of assertions and applies them) and a friendly error message saying it Couldn't connect to http://favicon.ico:80 to run the tests instead of throwing some IP number out - there is no way to know what that means without reading the whole library.

@ttbarnes
Copy link

interesting @01binary , i'm quite certain that I was getting the same error regardless of the slash.

@Andreimereuta
Copy link

Like @danday74 said this issue is present when using HTTPS without NODE_TLS_REJECT_UNAUTHORIZED=0.

@bkeepers
Copy link

#446 should help reveal the underlying error here.

@vnen
Copy link

vnen commented Mar 8, 2018

I'm getting this when the response body has a malformed JSON. It's good that the test fails, but it's for the wrong reasons and also with a cryptic message. Would it be possible to not try to parse the body unless I'm reading from it? At least don't give a catastrophic failure just because the response body can't be parsed.

@camlegleiter
Copy link

I also see this if I make a request against a site that doesn't exist:

it('errors if the domain does not exist', () =>
  supertest('http://baddomainasdf.com')
    .post('/')
    .expect(200));

1) errors if the domain does not exist:
   TypeError: Cannot read property 'status' of undefined
    at Test._assertStatus (node_modules/supertest/lib/test.js:263:11)
    at Test._assertFunction (node_modules/supertest/lib/test.js:281:11)
    at Test.assert (node_modules/supertest/lib/test.js:171:18)
    at assert (node_modules/supertest/lib/test.js:131:12)
    at node_modules/supertest/lib/test.js:128:5
    at Test.Request.callback (node_modules/supertest/node_modules/superagent/lib/node/index.js:718:3)
    at ClientRequest.req.once.err (node_modules/supertest/node_modules/superagent/lib/node/index.js:646:10)
    at Socket.socketErrorListener (_http_client.js:389:9)
    at emitErrorNT (internal/streams/destroy.js:64:8)
    at process._tickCallback (internal/process/next_tick.js:152:19)

It seems any case of an error around the response, either from a system error or some other kind of "Unhandled Error" (e.g., malformed JSON like mentioned above), causes problems when using .expect() since there's not really a response object to compare to. Using .end() or .then() fixes the error a bit better, but just requires doing expect() statements in the .end() or .then() block.

it('errors if the domain does not exist', (done) => {
  supertest('http://baddomainasdf.com')
    .post('/')
    .end((err, res) => {
      // res is undefined here
      console.log(err);
      done(err);
    });
});

1) errors if the domain does not exist:
   Error: getaddrinfo ENOTFOUND baddomainasdf.com baddomainasdf.com:80
    at errnoException (dns.js:55:10)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:97:26)

@fedika
Copy link

fedika commented Feb 6, 2019

I got this error when testing over a secure connection. I fixed it by adding NODE_TLS_REJECT_UNAUTHORIZED=0 as an env var on the test run.

For those wondering why this happens, it can happen because '127.0.0.1' is not listed as a valid IP in your certificate.
The underlying error is ...
Hostname/IP doesn't match certificate's altnames: "IP: 127.0.0.1 is not in the cert's list: "
However, you will not see this error message - Just the spurious and much disliked ...

Cannot read property 'status' of undefined

Hope this helps someone. God bless.

Could you please give me an example how to add NODE_TLS_REJECT_UNAUTHORIZED=0 as an env var on the test run?

@rimiti rimiti added the too-old Item to old label Mar 9, 2019
@rimiti rimiti closed this as completed Mar 9, 2019
@fabianoalmeida
Copy link

I'm facing an error very close to this reported error. I'm passing an Authorization header parameter that isn't getting in my middleware module.

const app = require('../../src/app');
const request = require('supertest')(app);
const ColorFactory = require("../factories/color");
const UserFactory = require("../factories/user");
...
describe('Test', () => {
  it('should be created a new color', async () => {
    const user = await UserFactory.build("user");
    const registerResponse = await request.post('/auth/register').send(user);
    const authorization = `Bearer ${registerResponse.accessToken}`;
    const color = await ColorFactory.build("color");
    const response = await request
      .post('/colors')
      .set('Authorization', authorization)
      .send(color)
    ;
    expect(response.status).toBe(201);
  });
});

And in my middleware is something like that:

require('dotenv/config');
const jwt = require('jsonwebtoken');
const jwtSecret = process.env.JWT_SECRET;

module.exports = (req, res, next) => {
    const authHeader = req.headers.authorization;

    if ( ! authHeader ) {
        return res.status(401).send({ errors: { message: "No token provided" } });
    }

    const parts = authHeader.split(' ');

    if ( ! parts.length === 2 ) {
        return res.status(401).send({ errors: { message: "Token error" } });
    }

    const [ scheme, accessToken ] = parts;

    if ( ! /^Bearer$/i.test( scheme ) ) {
        return res.status(401).send({ errors: { message: "Token malformatted" } });
    }

    jwt.verify( accessToken, jwtSecret, (error, decoded) => {
        if ( error ) {
            console.log(error);
            return res.status(401).send({ errors: { message: "Token invalid" } });
        }
        req.userId = decoded.id;
        req.userToken = accessToken;       
        return next();
    });
};

The variable accessToken is always undifined in the test listed above. When I start the server locally, everything works fine. Anyone have any clue to solve it?

@RahulJuyal
Copy link

->Resolve it

Unhandled Rejection (TypeError): Cannot read property 'status' of undefined
(anonymous function)
I:/ongc/km/src/Login.js:21
18 | props.history.push('/dashboard');
19 | }).catch(error => {
20 | setLoading(false);

21 | if (error.response.status === 401) setError(error.response.data.message);
| ^ 22 | else setError("Something went wrong. Please try again later.");
23 | });
24 | }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
too-old Item to old
Projects
None yet
Development

No branches or pull requests