邮件路由契约 15 条:账号 CRUD / 探测 / 立即拉取 / 试发 / 入站出站列表 / 附件与原件 / 重新投递

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
This commit is contained in:
xcs
2026-08-25 23:59:57 +08:00
co-authored by Claude Fable 5
parent 411fecc8c6
commit 7c6e399b57
3 changed files with 212 additions and 0 deletions
@@ -0,0 +1,33 @@
/**
* 邮件路由的归属:15 条全部进契约,注册表建得起来(字面 / 参数模版互不撞),
* 读标两端、写归运营中心(设计稿 §7.2)。
*/
import { describe, expect, it } from 'vitest';
import * as contracts from '@contracts';
import { MAIL_ROUTES } from '@contracts';
import { buildRouteRegistry, routesOf } from '../route-registry.ts';
describe('邮件路由契约', () => {
it('15 条全在契约命名空间里,注册表能建起来', () => {
const all = routesOf(Object.values(contracts));
const registry = buildRouteRegistry(all);
expect(MAIL_ROUTES).toHaveLength(15);
for (const route of MAIL_ROUTES) {
expect(registry.has(route.method, route.path)).toBe(true);
}
});
it('读标两端,写归 ops', () => {
for (const route of MAIL_ROUTES) {
if (route.method === 'GET') expect(route.access).toEqual(['design', 'ops']);
else expect(route.access).toBe('ops');
}
});
it('未存草稿探测与已存账号探测是两条不同的路', () => {
const registry = buildRouteRegistry(routesOf(Object.values(contracts)));
expect(registry.lookup('POST', '/api/gov/mail/accounts/probe')).toBe('ops');
expect(registry.lookup('POST', '/api/gov/mail/accounts/acc-1/probe')).toBe('ops');
expect(registry.lookup('GET', '/api/gov/mail/inbound/m-1/attachments/0')).toEqual(['design', 'ops']);
});
});