unjs / h3

⚡️ Minimal H(TTP) framework built for high performance and portability

Home Page:https://h3.unjs.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

question: how to declaratively create `H3Event`'s to test event handlers

juliusmarminge opened this issue · comments

Describe the change

How should one create H3Event's in order to test their event handlers? Assume I just want to run this event handler as a function, without having to create a server and listening to it? I came up with a workaround to use the web-converter and passing it a Request instead, but that feels a bit "hacky" I think

CleanShot 2024-02-25 at 23 58 07@2x

I'd just want to be able to do something like

eventHandler(new H3Event({ /** some options */}))

but the constructor args are very confusing for this use-case

URLs

No response

Additional information

  • Would you be willing to help?

Was just looking for this myself =)

commented

It's very tricky to test h3 without listening to a server.

I did have success with the following:

import { createEvent } from 'h3'

const req = <IncomingMessage>{
  method: 'POST',
  path: '...',
  headers: new Headers(...),
  body: {
    ...
  }
}

const res = <ServerResponse>{}

const event = createEvent(req, res)

// Some internal stuff that h3 does, sometimes needed, sometimes not
event._method = req.method
event._path = req.path
event._headers = req.headers
if (req.body) {
  event._requestBody = req.body
}

// Run the event logic
await app(...).use(...)(event)

// However now you have to deal with handling the raw response object, which is extortionary annoying
expect(res.status).toBe(200) // will most likely fail

Working with https://github.com/ladjs/supertest make things easier and way more reliable.

An example with Vite:

// some.test.ts
import type { App } from 'h3'
import { createApp, eventHandler, toNodeListener } from 'h3'

import type { SuperTest, Test } from 'supertest'
import supertest from 'supertest'

describe('', () => {
  let app: App
  let request: SuperTest<Test>

  beforeEach(() => {
    app = createApp({ debug: false })
    request = supertest(toNodeListener(app))
  })

  it('', async () => {
    app.use('/api/test', eventHandler(() => {
      return 'hello world'
    }))

    const result = await request.get('/api/test').send()

    expect(result.text).toBe('hello world')
  })
})

There are plenty more examples you can look at: https://github.com/unjs/h3/tree/main/test

so that's basically what I had just with the node listener instead of the web handlers

Hi dear @juliusmarminge. With upcoming h3 v2, mockEvent can be used to easily create a mocked (web API backed) event for testing. we use it internally too.