diff --git a/src/context.test.ts b/src/context.test.ts index 7f8619121..579ea8f4c 100644 --- a/src/context.test.ts +++ b/src/context.test.ts @@ -43,6 +43,20 @@ describe('Context', () => { expect(res.headers.get('X-Custom')).toBe('Message') }) + it('c.html() with async', async () => { + const res = await c.html( + new Promise((resolve) => setTimeout(() => resolve('

Hello! Hono!

'), 0)), + 201, + { + 'X-Custom': 'Message', + } + ) + expect(res.status).toBe(201) + expect(res.headers.get('Content-Type')).toMatch('text/html') + expect(await res.text()).toBe('

Hello! Hono!

') + expect(res.headers.get('X-Custom')).toBe('Message') + }) + it('c.redirect()', async () => { let res = c.redirect('/destination') expect(res.status).toBe(302) @@ -67,6 +81,18 @@ describe('Context', () => { expect(foo).toBe('Bar, Buzz') }) + it('c.set() and c.get()', async () => { + expect(c.get('foo')).toBe(undefined) + c.set('foo', 'bar') + expect(c.get('foo')).toBe('bar') + expect(c.get('foo2')).toBe(undefined) + }) + + it('c.notFound()', async () => { + const res = c.notFound() + expect(res).instanceOf(Response) + }) + it('Should set headers if already this.#headers is created by `c.header()`', async () => { c.header('X-Foo', 'Bar') c.header('X-Foo', 'Buzz', { append: true }) @@ -96,6 +122,12 @@ describe('Context', () => { expect(res.headers.get('X-Foo2')).toBe(null) }) + it('c.header() - clear the header when append is true', async () => { + c.header('X-Foo', 'Bar', { append: true }) + c.header('X-Foo', undefined) + expect(c.res.headers.get('X-Foo')).toBe(null) + }) + it('c.body() - multiple header', async () => { const res = c.body('Hi', 200, { 'X-Foo': ['Bar', 'Buzz'], @@ -210,17 +242,64 @@ describe('Context', () => { }) }) +describe('event and executionCtx', () => { + const req = new HonoRequest(new Request('http://localhost/')) + + it('Should return the event if accessing c.event', () => { + const respondWith = vi.fn() + const c = new Context(req, { + // @ts-expect-error the type is not correct + executionCtx: { + respondWith: respondWith, + }, + }) + expect(() => c.event).not.toThrowError() + c.event.respondWith(new Response()) + expect(respondWith).toHaveBeenCalled() + }) + + it('Should throw an error if accessing c.event', () => { + const c = new Context(req) + expect(() => c.event).toThrowError() + }) + + it('Should return the executionCtx if accessing c.executionCtx', () => { + const pathThroughOnException = vi.fn() + const waitUntil = vi.fn() + const c = new Context(req, { + executionCtx: { + passThroughOnException: pathThroughOnException, + waitUntil: waitUntil, + }, + env: {}, + }) + expect(() => c.executionCtx).not.toThrowError() + c.executionCtx.passThroughOnException() + expect(pathThroughOnException).toHaveBeenCalled() + const asyncFunc = async () => {} + c.executionCtx.waitUntil(asyncFunc()) + expect(waitUntil).toHaveBeenCalled() + }) + + it('Should throw an error if accessing c.executionCtx', () => { + const c = new Context(req) + expect(() => c.executionCtx).toThrowError() + }) +}) + describe('Context header', () => { const req = new HonoRequest(new Request('http://localhost/')) let c: Context beforeEach(() => { c = new Context(req) }) + it('Should return only one content-type value', async () => { c.header('Content-Type', 'foo') const res = await c.html('foo') expect(res.headers.get('Content-Type')).toBe('text/html; charset=UTF-8') }) + it('Should rewrite header values correctly', async () => { c.res = await c.html('foo') const res = c.text('foo') @@ -238,12 +317,20 @@ describe('Context header', () => { }) it('Should set cookie headers when re-assigning Response to `c.res`', () => { - c.res = new Response(null) + const cookies = ['foo=bar; Path=/', 'foo2=bar2; Path=/'] const res = new Response(null) - res.headers.append('set-cookie', 'foo=bar; Path=/') - res.headers.append('set-cookie', 'foo2=bar2; Path=/') + res.headers.append('set-cookie', cookies[0]) + res.headers.append('set-cookie', cookies[1]) c.res = res expect(c.res.headers.getSetCookie().length).toBe(2) + + // Re-assign + const newCookies = ['foo3=bar3; Path=/'] + const newResponse = new Response(null) + newResponse.headers.append('set-cookie', newCookies[0]) + c.res = newResponse + expect(c.res.headers.getSetCookie().length).toBe(cookies.length) + expect(c.res.headers.getSetCookie()).toEqual(cookies) }) it('Should keep previous cookies in response headers', () => { diff --git a/src/context.ts b/src/context.ts index e5eaa5815..51702aa08 100644 --- a/src/context.ts +++ b/src/context.ts @@ -237,7 +237,7 @@ export class Context< * ``` */ env: E['Bindings'] = {} - private _var: E['Variables'] = {} + private _var: E['Variables'] | undefined finalized: boolean = false /** * `.error` can get the error object from the middleware if the Handler throws an error. @@ -467,9 +467,9 @@ export class Context< /** * `.set()` can set the value specified by the key. - * + * * @see {@link https://hono.dev/api/context#set-get} - * + * * @example * ```ts * app.use('*', async (c, next) => {