UNPKG

@goa/goa

Version:

The Goa Source Code For Compilation Into @Goa/Koa That Includes Modules, Tests, Types And Dependencies.

173 lines (150 loc) 4.44 kB
import { equal } from '@zoroaster/assert' import Context, { ConsoleMock } from '../../context' /** @type {TestSuite} */ const TS = { context: [Context, ConsoleMock], async 'responds'({ app, startApp }, _) { app.use((ctx) => { ctx.body = 'something else' ctx.throw(418, 'boom') }) await startApp() .get('/') .assert(418) .assert('Content-Type', 'text/plain; charset=utf-8') .assert('Content-Length', 4) }, async 'unsets all headers'({ app, startApp }, _) { app.use((ctx) => { ctx.set('Vary', 'Accept-Encoding') ctx.set('X-CSRF-Token', 'asdf') ctx.body = 'response' ctx.throw(418, 'boom') }) await startApp() .get('/') .assert(418) .assert('Content-Type', 'text/plain; charset=utf-8') .assert('Content-Length', 4) .assert('vary', null) .assert('x-csrf-token', null) }, async 'sets headers specified in the error'({ app, startApp }, _) { app.use((ctx) => { ctx.set('Vary', 'Accept-Encoding') ctx.set('X-CSRF-Token', 'asdf') ctx.body = 'response' throw Object.assign(new Error('boom'), { status: 418, expose: true, headers: { 'X-New-Header': 'Value', }, }) }) await startApp() .get('/') .assert(418) .assert('Content-Type', 'text/plain; charset=utf-8') .assert('X-New-Header', 'Value') .assert('vary', null) .assert('x-csrf-token', null) }, async 'ignores error after headerSent'({ app, start, expectError }, _) { const p = expectError({ message: 'mock error', headerSent: true }) app.use(async ctx => { ctx.status = 200 ctx.set('X-Foo', 'Bar') ctx.flushHeaders() throw new Error('mock error') ctx.body = 'response' }) await start(app.callback()) .get('/') .assert('X-Foo', 'Bar') .assert(200) await p }, 'when invalid err.status': { 'not number': { async 'responds 500'({ app, startApp }, _) { app.use((ctx) => { ctx.body = 'something else' const err = new Error('some error') err.status = 'notnumber' throw err }) await startApp() .get('/') .assert(500, 'Internal Server Error') .assert('Content-Type', 'text/plain; charset=utf-8') }, }, 'when ENOENT error': { async 'responds 404'({ app, startApp }, _) { app.use((ctx) => { ctx.body = 'something else' const err = new Error('test for ENOENT') err.code = 'ENOENT' throw err }) await startApp() .get('/') .assert(404, 'Not Found') .assert('Content-Type', 'text/plain; charset=utf-8') }, }, 'not http status code': { async 'responds 500'({ app, startApp }, _) { app.use((ctx) => { ctx.body = 'something else' const err = new Error('some error') err.status = 9999 throw err }) await startApp() .get('/') .assert(500, 'Internal Server Error') .assert('Content-Type', 'text/plain; charset=utf-8') }, }, }, 'when non-error thrown': { async 'responds with non-error thrown message'({ app, startApp }, _) { app.use(() => { throw 'string error' }) await startApp() .get('/') .assert(500, 'Internal Server Error') .assert('Content-Type', 'text/plain; charset=utf-8') }, 'uses res.getHeaderNames() accessor when available'({ makeContext }, _) { let removed = 0 const ctx = makeContext() ctx.app.emit = () => {} ctx.res = { getHeaderNames: () => ['content-type', 'content-length'], removeHeader: () => removed++, end: () => {}, emit: () => {}, } ctx.onerror(new Error('error')) equal(removed, 2) }, async 'stringifies error if it is an object'({ app, startApp, expectError }, _) { const p = expectError('Error: non-error thrown: {"key":"value"}') app.use(async () => { throw { key: 'value' } // eslint-disable-line no-throw-literal }) await startApp() .get('/') .assert(500, 'Internal Server Error') await p }, }, } export default TS /** * @typedef {import('../../context').TestSuite} TestSuite */