/** * 自定义断言工具 * 提供项目特定的断言方法 */ import { expect } from 'vitest'; /** * 验证钉钉消息格式 * * @param {object} message - 消息对象 * @param {string} expectedType - 期望的消息类型 */ export function assertDingTalkMessage(message, expectedType) { expect(message).toBeDefined(); expect(message).toBeTypeOf('object'); expect(message.msgtype).toBe(expectedType); switch (expectedType) { case 'text': expect(message.text).toBeDefined(); expect(message.text.content).toBeTypeOf('string'); break; case 'markdown': expect(message.markdown).toBeDefined(); expect(message.markdown.title).toBeTypeOf('string'); expect(message.markdown.text).toBeTypeOf('string'); break; case 'link': expect(message.link).toBeDefined(); expect(message.link.title).toBeTypeOf('string'); expect(message.link.text).toBeTypeOf('string'); expect(message.link.messageUrl).toBeTypeOf('string'); break; case 'actionCard': expect(message.actionCard).toBeDefined(); expect(message.actionCard.title).toBeTypeOf('string'); expect(message.actionCard.text).toBeTypeOf('string'); break; case 'feedCard': expect(message.feedCard).toBeDefined(); expect(message.feedCard.links).toBeInstanceOf(Array); break; } } /** * 验证 @ 功能配置 * * @param {object} message - 消息对象 * @param {object} expectedAt - 期望的 @ 配置 */ export function assertAtConfiguration(message, expectedAt) { expect(message.at).toBeDefined(); if (expectedAt.atMobiles) { expect(message.at.atMobiles).toEqual(expectedAt.atMobiles); } if (expectedAt.atUserIds) { expect(message.at.atUserIds).toEqual(expectedAt.atUserIds); } if (expectedAt.isAtAll !== undefined) { expect(message.at.isAtAll).toBe(expectedAt.isAtAll); } } /** * 验证 ActionCard 按钮配置 * * @param {object} actionCard - ActionCard 对象 * @param {object} expectedButtons - 期望的按钮配置 */ export function assertActionCardButtons(actionCard, expectedButtons) { if (expectedButtons.single) { expect(actionCard.singleTitle).toBe(expectedButtons.single.title); expect(actionCard.singleURL).toBe(expectedButtons.single.url); expect(actionCard.btns).toBeUndefined(); } else if (expectedButtons.multiple) { expect(actionCard.btns).toBeInstanceOf(Array); expect(actionCard.btns).toHaveLength(expectedButtons.multiple.length); expectedButtons.multiple.forEach((expectedBtn, index) => { expect(actionCard.btns[index].title).toBe(expectedBtn.title); expect(actionCard.btns[index].actionURL).toBe(expectedBtn.actionURL); }); expect(actionCard.singleTitle).toBeUndefined(); expect(actionCard.singleURL).toBeUndefined(); } if (expectedButtons.orientation !== undefined) { expect(actionCard.btnOrientation).toBe(expectedButtons.orientation); } } /** * 验证 FeedCard 链接配置 * * @param {object} feedCard - FeedCard 对象 * @param {Array} expectedLinks - 期望的链接配置 */ export function assertFeedCardLinks(feedCard, expectedLinks) { expect(feedCard.links).toBeInstanceOf(Array); expect(feedCard.links).toHaveLength(expectedLinks.length); expectedLinks.forEach((expectedLink, index) => { const link = feedCard.links[index]; expect(link.title).toBe(expectedLink.title); expect(link.messageURL).toBe(expectedLink.messageURL); if (expectedLink.picURL) { expect(link.picURL).toBe(expectedLink.picURL); } }); } /** * 验证配置对象结构 * * @param {object} config - 配置对象 * @param {Array} requiredFields - 必需字段列表 */ export function assertConfigStructure(config, requiredFields = []) { expect(config).toBeDefined(); expect(config).toBeTypeOf('object'); requiredFields.forEach(field => { expect(config).toHaveProperty(field); }); } /** * 验证错误对象 * * @param {Error} error - 错误对象 * @param {string} expectedMessage - 期望的错误消息(可选) * @param {string} expectedCode - 期望的错误代码(可选) */ export function assertError(error, expectedMessage, expectedCode) { expect(error).toBeInstanceOf(Error); if (expectedMessage) { expect(error.message).toContain(expectedMessage); } if (expectedCode) { expect(error.code).toBe(expectedCode); } } /** * 验证 HTTP 请求选项 * * @param {object} options - 请求选项 * @param {object} expected - 期望的选项 */ export function assertHttpOptions(options, expected) { expect(options).toBeDefined(); expect(options).toBeTypeOf('object'); if (expected.hostname) { expect(options.hostname).toBe(expected.hostname); } if (expected.path) { expect(options.path).toBe(expected.path); } if (expected.method) { expect(options.method).toBe(expected.method); } if (expected.headers) { expect(options.headers).toEqual(expect.objectContaining(expected.headers)); } } /** * 验证 URL 格式 * * @param {string} url - URL 字符串 */ export function assertValidUrl(url) { expect(url).toBeTypeOf('string'); expect(url.length).toBeGreaterThan(0); expect(() => new URL(url)).not.toThrow(); } /** * 验证 JSON 字符串 * * @param {string} jsonString - JSON 字符串 * @returns {object} 解析后的对象 */ export function assertValidJson(jsonString) { expect(jsonString).toBeTypeOf('string'); let parsed; expect(() => { parsed = JSON.parse(jsonString); }).not.toThrow(); return parsed; } /** * 验证数组包含特定元素 * * @param {Array} array - 数组 * @param {*} element - 要查找的元素 */ export function assertArrayContains(array, element) { expect(array).toBeInstanceOf(Array); expect(array).toContain(element); } /** * 验证对象深度相等 * * @param {object} actual - 实际对象 * @param {object} expected - 期望对象 */ export function assertDeepEqual(actual, expected) { expect(actual).toEqual(expected); } /** * 验证函数抛出特定错误 * * @param {Function} fn - 要测试的函数 * @param {string|RegExp} expectedError - 期望的错误消息或正则表达式 */ export function assertThrows(fn, expectedError) { if (typeof expectedError === 'string') { expect(fn).toThrow(expectedError); } else if (expectedError instanceof RegExp) { expect(fn).toThrow(expectedError); } else { expect(fn).toThrow(); } }