cmorten / superdeno

Super-agent driven library for testing Deno HTTP servers.
https://cmorten.github.io/superdeno/
MIT License
124 stars 6 forks source link

SuperDeno does not process headers in the response from Opine #27

Closed g-wozniak closed 3 years ago

g-wozniak commented 3 years ago

SuperDeno does not process headers from Opine

Setup:

Details

When: testing the following Opine handler:

handler: (req: Request, res: Response, next: NextFunction) => {
    console.log(res.headers) // shows:  "x-powered-by": "Opine"
    res.json({ data: 'ok' })
  }

I want the following test:

  await superdeno(app)
    .get('/')
    .expect(200)
    .then((response) => {
      console.log(response.headers)
    })

to return:

{
   "content-type": "application/json",
   "x-powered-by": "Opine"
}

instead of { "content-type": undefined }.

Full response:

Response {
  req: Test {
    _query: [],
    method: "GET",
    url: "http://127.0.0.1:38097/",
    header: {},
    _header: {},
    _callbacks: { "$end": [ [Function] ], "$abort": [ [Function] ] },
    app: [Function: app] {
      emit: [Function],
      ... (other methods)
      request: ServerRequest { app: [Circular] },
      response: Response { app: [Circular] },
      cache: {},
      engines: {},
      settings: {
        "x-powered-by": true,
        etag: "weak",
        "etag fn": [Function: generateETag],
        "query parser": "extended",
        "query parser fn": [Function: parseExtendedQueryString],
        "subdomain offset": 2,
        "trust proxy": false,
        "trust proxy fn": [Function: trustNone],
        view: [Function: View],
        views: "<my dir>/views",
        "jsonp callback name": "callback",
        "view cache": true
      },
      locals: { settings: [Object] },
      mountpath: "/",
      _router: [Function: router] {
        params: [Object],
        _params: [Array],
        caseSensitive: false,
        mergeParams: undefined,
        strict: false,
        stack: [Array]
      }
    },
    _maxRedirects: 0,
    _endCalled: true,
    _callback: [Function],
    xhr: XMLHttpRequestSham {
      id: "1",
      origin: "http://127.0.0.1:38097",
      onreadystatechange: [Function],
      readyState: 4,
      responseText: '{"data":"ok"}',
      responseType: "",
      response: '{"data":"ok"}',
      status: 200,
      statusCode: 200,
      statusText: "OK",
      aborted: false,
      options: {
        requestHeaders: [Object],
        method: "GET",
        url: "http://127.0.0.1:38097/",
        username: undefined,
        password: undefined,
        requestBody: null
      },
      controller: AbortController {},
      getAllResponseHeaders: [Function],
      getResponseHeader: [Function]
    },
    _fullfilledPromise: Promise { [Circular] }
  },
  xhr: XMLHttpRequestSham {
    id: "1",
    origin: "http://127.0.0.1:38097",
    onreadystatechange: [Function],
    readyState: 4,
    responseText: '{"data":"ok"}',
    responseType: "",
    response: '{"data":"ok"}',
    status: 200,
    statusCode: 200,
    statusText: "OK",
    aborted: false,
    options: {
      requestHeaders: {},
      method: "GET",
      url: "http://127.0.0.1:38097/",
      username: undefined,
      password: undefined,
      requestBody: null
    },
    controller: AbortController {},
    getAllResponseHeaders: [Function],
    getResponseHeader: [Function]
  },
  text: '{"data":"ok"}',
  statusText: "OK",
  statusCode: 200,
  status: 200,
  statusType: 2,
  info: false,
  ok: true,
  redirect: false,
  clientError: false,
  serverError: false,
  error: false,
  created: false,
  accepted: false,
  noContent: false,
  badRequest: false,
  unauthorized: false,
  notAcceptable: false,
  forbidden: false,
  notFound: false,
  unprocessableEntity: false,
  headers: { "content-type": undefined },
  header: { "content-type": undefined },
  type: "",
  links: {},
  body: null
}
cmorten commented 3 years ago

Hey @g-wozniak đź‘‹

Thanks for raising - a curious one as we have test coverage for this ( see https://github.com/asos-craigmorten/superdeno/blob/main/test/supertest.opine.test.ts#L164 ) so guessing something has changed subtly in a recent version of Deno or Opine to cause this.

So can try to reproduce, what version of Opine were you using?

g-wozniak commented 3 years ago

Hey. Thanks for the response. Yes I'd imagine as it's quite important bit :) I am using opine@1.3.2.

Adding: res.type("application/json") to the handler didn't help either. I've ruled out Opine because if I launch manually the server and make the call to a similar endpoint I am getting:

content-length: 13
content-type: application/json; charset=utf-8
etag: W/"d-db138f5ff0fed06ff05baf0912c"
x-correlation: f6571c1e-7c63-4f69-9f18-48c5855cb1c6
x-powered-by: Opine
g-wozniak commented 3 years ago

Even if I run:

  import { superdeno, opine } from '../dependencies.ts'
  const app = opine()
  app.get('/', (req, res, next) => {
    res.type("application/json")
    res.json({ data: 'ok' })
  })

  await superdeno(app)
    .get('/')
    .expect(200)
    .then(response => {
      console.log(response.headers)
    })

it throws - { "content-type": undefined } So unless I am blind, doing something obvious wrongly - can't get to the bottom of it. :)

cmorten commented 3 years ago

Hi @g-wozniak, can you see if superdeno@4.2.0 solves the issue for you? If not please re-open!