Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions __tests__/context/assert.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
const { describe, it } = require('node:test')
const context = require('../../test-helpers/context')
const assert = require('node:assert/strict')
const httpAssert = require('http-assert')
const Koa = require('../..')

describe('ctx.assert(value, status)', () => {
it('should throw an error', () => {
Expand All @@ -20,4 +22,81 @@ describe('ctx.assert(value, status)', () => {
}
assert(assertionRan)
})

it('should throw Koa HttpError instances', () => {
const ctx = context()

assert.throws(() => {
ctx.assert(false, 404, 'custom message')
}, err => {
assert.strictEqual(err instanceof Koa.HttpError, true)
assert.strictEqual(err.status, 404)
assert.strictEqual(err.message, 'custom message')
assert.strictEqual(err.expose, true)
Comment on lines +26 to +35

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Add a test for ctx.assert(false) without an explicit status to cover the default 500 error case.

The new test only exercises ctx.assert(false, 404, ...). Please add a sibling test for ctx.assert(false) (and/or ctx.assert(false, 'message')) that checks the thrown Koa.HttpError has the default 500 status and correct expose flag, so the non-explicit-status path is also covered for regressions.

return true
})
})

it('should throw Koa HttpError instances with default status', () => {
const ctx = context()

assert.throws(() => {
ctx.assert(false, 'custom message without status')
}, err => {
assert.strictEqual(err instanceof Koa.HttpError, true)
assert.strictEqual(err.status, 500)
assert.strictEqual(err.message, 'custom message without status')
assert.strictEqual(err.expose, false)
return true
})
})

it('should throw Koa HttpError instances from assertion helpers', () => {
const ctx = context()

assert.throws(() => {
ctx.assert.equal('actual', 'expected', 400, 'custom message')
}, err => {
assert.strictEqual(err instanceof Koa.HttpError, true)
assert.strictEqual(err.status, 400)
assert.strictEqual(err.message, 'custom message')
assert.strictEqual(err.expose, true)
return true
})
})
Comment on lines +54 to +66

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Consider adding a test for an additional assertion helper or the default-status path for helpers.

This currently exercises only ctx.assert.equal with an explicit 400 status. Since all http-assert helpers are wrapped, add a test that either uses a different helper (e.g. ctx.assert.ok / ctx.assert.notEqual) or omits the status argument, then assert the thrown error is still a Koa.HttpError. That will show the wrapper behaves correctly across helpers and argument shapes.

Suggested change
it('should throw Koa HttpError instances from assertion helpers', () => {
const ctx = context()
assert.throws(() => {
ctx.assert.equal('actual', 'expected', 400, 'custom message')
}, err => {
assert.strictEqual(err instanceof Koa.HttpError, true)
assert.strictEqual(err.status, 400)
assert.strictEqual(err.message, 'custom message')
assert.strictEqual(err.expose, true)
return true
})
})
it('should throw Koa HttpError instances from assertion helpers', () => {
const ctx = context()
assert.throws(() => {
ctx.assert.equal('actual', 'expected', 400, 'custom message')
}, err => {
assert.strictEqual(err instanceof Koa.HttpError, true)
assert.strictEqual(err.status, 400)
assert.strictEqual(err.message, 'custom message')
assert.strictEqual(err.expose, true)
return true
})
})
it('should throw Koa HttpError instances from assertion helpers without explicit status', () => {
const ctx = context()
assert.throws(() => {
ctx.assert.ok(false, 'custom message without status')
}, err => {
assert.strictEqual(err instanceof Koa.HttpError, true)
assert.strictEqual(err.status, 500)
assert.strictEqual(err.message, 'custom message without status')
assert.strictEqual(err.expose, false)
return true
})
})


it('should throw Koa HttpError instances from assertion helpers without explicit status', () => {
const ctx = context()

assert.throws(() => {
ctx.assert.ok(false, 'custom helper message without status')
}, err => {
assert.strictEqual(err instanceof Koa.HttpError, true)
assert.strictEqual(err.status, 500)
assert.strictEqual(err.message, 'custom helper message without status')
assert.strictEqual(err.expose, false)
return true
})
})

it('should rethrow non-http assertion helper errors unchanged', () => {
const ctx = context()
const originalFail = httpAssert.fail
const error = new Error('custom helper failure')

httpAssert.fail = function () {
throw error
}

try {
assert.throws(() => {
ctx.assert.fail()
}, err => {
assert.strictEqual(err, error)
return true
})
} finally {
httpAssert.fail = originalFail
}
})
})
23 changes: 22 additions & 1 deletion lib/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,27 @@ const Cookies = require('cookies')

const COOKIES = Symbol('context#cookies')

function rethrowKoaHttpError (fn, args) {
try {
return fn(...args)
} catch (err) {
if (err && typeof err.status === 'number') {
const props = Object.assign({}, err)
props.stack = err.stack
throw createError(err.status, err.message, props)
}
throw err
}
}
Comment thread
sourcery-ai[bot] marked this conversation as resolved.

function assert (...args) {
return rethrowKoaHttpError(httpAssert, args)
}

for (const method of Object.keys(httpAssert)) {
assert[method] = (...args) => rethrowKoaHttpError(httpAssert[method], args)
}

/**
* Context prototype.
*/
Expand Down Expand Up @@ -69,7 +90,7 @@ const proto = module.exports = {
* @api public
*/

assert: httpAssert,
assert,

/**
* Throw an error with `status` (default 500) and
Expand Down