This repository has been archived on 2026-09-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BPOS-TMP-REPO/packages/contracts/src/__tests__/mail.test.ts
T

67 lines
3.2 KiB
TypeScript

/** 邮件契约 —— 账号入参按 kind 分两形,默认值与视图不带密文 */
import { describe, expect, it } from 'vitest';
import {
mailAccountInputSchema,
mailAccountViewSchema,
mailSendInputSchema,
MAIL_ACCOUNT_KINDS,
} from '../mail.ts';
describe('mailAccountInputSchema', () => {
it('imap-smtp:只给地址与名字,腾讯的服务器 / 端口 / TLS / 文件夹全部有默认值', () => {
const parsed = mailAccountInputSchema.parse({ kind: 'imap-smtp', name: '销售信箱', address: 'sales@we.com' });
expect(parsed.kind).toBe('imap-smtp');
if (parsed.kind !== 'imap-smtp') throw new Error('unreachable');
expect(parsed.settings).toEqual({
imapHost: 'imap.exmail.qq.com',
imapPort: 993,
imapTls: true,
smtpHost: 'smtp.exmail.qq.com',
smtpPort: 465,
smtpTls: true,
folder: 'INBOX',
});
expect(parsed.enabled).toBe(true);
expect(parsed.isDefault).toBe(false);
expect(parsed.pollIntervalSec).toBe(30);
expect(parsed.channelId).toBeNull();
expect(parsed.backfillFrom).toBeNull();
expect(parsed.secret).toBeUndefined();
});
it('wecom:corpId 必填,地址不由人填(探测回填)', () => {
const parsed = mailAccountInputSchema.parse({ kind: 'wecom', name: '应用邮箱', settings: { corpId: 'ww123' } });
if (parsed.kind !== 'wecom') throw new Error('unreachable');
expect(parsed.settings.apiBase).toBe('https://qyapi.weixin.qq.com');
expect('address' in parsed).toBe(false);
expect(mailAccountInputSchema.safeParse({ kind: 'wecom', name: 'x', settings: {} }).success).toBe(false);
});
it('轮询间隔下限 10 秒;地址必须是带 TLD 的邮箱;kind 只认两种', () => {
expect(mailAccountInputSchema.safeParse({ kind: 'imap-smtp', name: 'a', address: 'a@b.com', pollIntervalSec: 5 }).success).toBe(false);
expect(mailAccountInputSchema.safeParse({ kind: 'imap-smtp', name: 'a', address: 'not-mail' }).success).toBe(false);
// 漏了 TLD 的地址(sales@corp)是打字错误,在 API 边界就拦下 —— 别拖到 SMTP 才炸
expect(mailAccountInputSchema.safeParse({ kind: 'imap-smtp', name: 'a', address: 'sales@corp' }).success).toBe(false);
expect(mailAccountInputSchema.safeParse({ kind: 'pop3', name: 'a' }).success).toBe(false);
expect(MAIL_ACCOUNT_KINDS).toEqual(['imap-smtp', 'wecom']);
});
});
describe('mailAccountViewSchema', () => {
it('视图只有 secretBound,没有任何密文 / 密码字段', () => {
const keys = Object.keys(mailAccountViewSchema.options[0]!.shape);
expect(keys).toContain('secretBound');
expect(keys.some((k) => /cipher|password|secret$/i.test(k))).toBe(false);
});
});
describe('mailSendInputSchema', () => {
it('收件人至少一个、主题必填;附件默认空数组;requestedBy 必带 kind', () => {
const ok = mailSendInputSchema.safeParse({ to: ['a@b.com'], subject: 'hi', text: 'x', requestedBy: { kind: 'ops' } });
expect(ok.success).toBe(true);
if (ok.success) expect(ok.data.attachments).toEqual([]);
expect(mailSendInputSchema.safeParse({ to: [], subject: 'hi', text: 'x', requestedBy: { kind: 'ops' } }).success).toBe(false);
expect(mailSendInputSchema.safeParse({ to: ['a@b.com'], subject: 'hi', text: 'x' }).success).toBe(false);
});
});