// 回归测试:asyncRouter 把 async 路由的抛错/reject 转给错误中间件, // 不再让请求静默挂起(Express4 不自动捕获 async reject)。 import { test, before, after } from 'node:test'; import assert from 'node:assert/strict'; import express from 'express'; import http from 'node:http'; import { asyncRouter } from '../src/lib/asyncRouter.js'; let server, base; before(async () => { const r = asyncRouter(); r.get('/ok', async (_q, res) => res.json({ ok: true })); r.get('/async-throw', async () => { throw new Error('boom-async'); }); r.get('/sync-throw', () => { throw new Error('boom-sync'); }); r.get('/mw', (_q, _s, next) => next(), async (_q, res) => res.json({ via: 'mw' })); const app = express(); app.use(r); app.use((err, _q, res, _n) => res.status(500).json({ error: err.message })); // 错误中间件(arity 4)不被包裹 server = http.createServer(app).listen(0); await new Promise((ok) => server.once('listening', ok)); base = `http://127.0.0.1:${server.address().port}`; }); after(() => server.close()); async function get(path) { const res = await fetch(base + path); return { status: res.status, body: await res.json() }; } test('正常 async 路由返回 200', async () => { const r = await get('/ok'); assert.equal(r.status, 200); assert.deepEqual(r.body, { ok: true }); }); test('async 抛错 → 转错误中间件返回 500(不挂起)', async () => { const r = await get('/async-throw'); assert.equal(r.status, 500); assert.equal(r.body.error, 'boom-async'); }); test('同步抛错 → 500', async () => { const r = await get('/sync-throw'); assert.equal(r.status, 500); assert.equal(r.body.error, 'boom-sync'); }); test('sync 中间件 + async handler 链路正常', async () => { const r = await get('/mw'); assert.equal(r.status, 200); assert.deepEqual(r.body, { via: 'mw' }); });