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

Unable to access response headers when using axios 1.x with jest #5017

Closed
johannes-vogel opened this issue Oct 5, 2022 · 4 comments
Closed

Comments

@johannes-vogel
Copy link

johannes-vogel commented Oct 5, 2022

Describe the bug

When using axios to send requests within jest tests, it's not possible to see the response.headers anymore.
This was working fine with axios version 0.x so far.

To Reproduce

I've prepared a small example to show that it it is not working as expected.

test('xxx', (done) => {
  const express = require('express')
  const app = express()
  
  app.get('/test', (req, res) => {
    console.log('request received')
    res.set('x-header', 'value')
    res.send('ok')
  })
  
  const server = app.listen(4004, async () => {
    const a = require('axios')
    const axios = a.create({
      headers: { 'Content-Type': 'application/json' },
      baseURL: 'http://localhost:4004'
    })
    let response = await axios.get('/test')
    console.log(response.headers)
    server.close()
    done()
  })
})

On console, I can see the following log:

  console.log
    AxiosHeaders { '[object Object]': undefined, [Symbol(defaults)]: null }
      at Server.log (/Users/j/Downloads/odata_call (1)../../../../../axios_issue/plain.test.js:18:13)

Expected behavior

I'd expect that the response headers are also accessible within the jest environment.

Solution proposal

I've narrowed it down that the response headers are normalized here:

axios/lib/adapters/http.js

Lines 427 to 433 in 738fa63

const response = {
status: res.statusCode,
statusText: res.statusMessage,
headers: new AxiosHeaders(res.headers),
config,
request: lastRequest
};

Within the setter of the AxiosHeaders there's a strict check whether the headers are an object:
if (utils.isPlainObject(header)) {

Somehow by jest magic, the header.prototype is not Object.prototype (even though it looks like it would be), hence the check returns false, even though it's an object.
In my naive opinion, the strict check is not required.

Another option would be to restore the previous behavior. With version 0.27.2, there was no normalization using AxiosHeaders:

axios/lib/adapters/http.js

Lines 288 to 294 in bc733fe

var response = {
status: res.statusCode,
statusText: res.statusMessage,
headers: res.headers,
config: config,
request: lastRequest
};

Environment

  • axios version 1.0.0
  • express version 4.18.1 (probably unrelated)
  • jest version 29.1.2
  • node version 14.20.0

Additional context/Screenshots

I've also created a small sample repository to reproduce the problem even easier:
https://github.com/johannes-vogel/axios-jest-issue

  • checkout the project
  • npm i
  • node no-jest.js → You'll observe it working without jest
  • npx jest with-jest.test.js → You'll observe the mentioned log output.
@risa
Copy link
Contributor

risa commented Oct 6, 2022

I am experiencing the same issue with axios version 1.0.0.

In plain node (ts-node) headers are returned correctly, e.g. this code returns correctly:

  const result = await axios.get("https://github.com")
  console.log(result.headers.server)

the output is GitHub.com

however in jest, this code fails:

describe("Testing axios against external service", () => {

    it("should return headers ", async () => {
      const result = await axios.get("https://github.com")
      expect(result.status).toBe(200)
      expect(result.headers.server).toBe("GitHub.com")
    })

})

The result.headers.server is undefined.

In my investigation/debugging and tracing it boils down to this function:

axios/lib/utils.js

Lines 129 to 136 in 7a06a36

const isPlainObject = (val) => {
if (kindOf(val) !== 'object') {
return false;
}
const prototype = getPrototypeOf(val);
return prototype === null || prototype === Object.prototype;
}

Specifically this line:

return prototype === null || prototype === Object.prototype;

The response.headers in normal node are correctly identified as plain object, however in jest it does not identify them.

It seems that in jest the prototype is different from the standard Object prototype, although I cannot find where they differ.

@risa
Copy link
Contributor

risa commented Oct 6, 2022

And I am not sure what is exactly the purpose of comparing the prototypes, so I do not feel confident enough to propose a patch here.

@grenik
Copy link

grenik commented Oct 11, 2022

Seems relevant to #5089 which shall be fixed in #5090

@johannes-vogel
Copy link
Author

It's fixed already with version 1.1.2.
@risa and @jasonsaayman Thanks for providing a quick solution 👍

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

No branches or pull requests

3 participants