/** * 钉钉 API 响应数据夹具 * 包含各种钉钉 API 响应用于测试 */ // 成功响应 export const successResponses = { // 标准成功响应 standard: { errcode: 0, errmsg: 'ok', }, // 带消息 ID 的成功响应 withMessageId: { errcode: 0, errmsg: 'ok', message_id: 'msg789012', }, }; // 错误响应 export const errorResponses = { // 无效的 access_token invalidToken: { errcode: 310000, errmsg: 'keywords not in content', }, // 消息内容中不包含任何关键词 noKeywords: { errcode: 310000, errmsg: 'keywords not in content', }, // 消息发送频率超过限制 rateLimited: { errcode: 130101, errmsg: 'send too fast', }, // 机器人被停用 robotDisabled: { errcode: 300001, errmsg: 'robot is disabled', }, // 签名验证失败 signatureError: { errcode: 310000, errmsg: 'sign not match', }, // IP 地址不在白名单中 ipNotAllowed: { errcode: 310000, errmsg: 'ip not allow', }, // 消息格式错误 invalidFormat: { errcode: 300002, errmsg: 'param is invalid', }, // 消息内容为空 emptyContent: { errcode: 300003, errmsg: 'content is empty', }, // 消息长度超过限制 contentTooLong: { errcode: 300004, errmsg: 'content too long', }, // @ 的手机号格式错误 invalidMobile: { errcode: 300005, errmsg: 'mobile format error', }, // ActionCard 按钮数量超过限制 tooManyButtons: { errcode: 300006, errmsg: 'too many buttons', }, // FeedCard 链接数量超过限制 tooManyLinks: { errcode: 300007, errmsg: 'too many links', }, // 服务器内部错误 internalError: { errcode: 500000, errmsg: 'internal server error', }, // 服务不可用 serviceUnavailable: { errcode: 503000, errmsg: 'service unavailable', }, }; // HTTP 状态码响应 export const httpStatusResponses = { // 200 OK ok: { statusCode: 200, data: successResponses.standard, }, // 400 Bad Request badRequest: { statusCode: 400, data: { errcode: 400000, errmsg: 'bad request', }, }, // 401 Unauthorized unauthorized: { statusCode: 401, data: { errcode: 401000, errmsg: 'unauthorized', }, }, // 403 Forbidden forbidden: { statusCode: 403, data: { errcode: 403000, errmsg: 'forbidden', }, }, // 404 Not Found notFound: { statusCode: 404, data: { errcode: 404000, errmsg: 'not found', }, }, // 429 Too Many Requests tooManyRequests: { statusCode: 429, data: errorResponses.rateLimited, }, // 500 Internal Server Error internalServerError: { statusCode: 500, data: errorResponses.internalError, }, // 502 Bad Gateway badGateway: { statusCode: 502, data: { errcode: 502000, errmsg: 'bad gateway', }, }, // 503 Service Unavailable serviceUnavailable: { statusCode: 503, data: errorResponses.serviceUnavailable, }, // 504 Gateway Timeout gatewayTimeout: { statusCode: 504, data: { errcode: 504000, errmsg: 'gateway timeout', }, }, }; // 网络错误响应 export const networkErrors = { // 连接被拒绝 connectionRefused: { code: 'ECONNREFUSED', message: 'connect ECONNREFUSED 127.0.0.1:443', }, // 连接超时 connectionTimeout: { code: 'ETIMEDOUT', message: 'connect ETIMEDOUT', }, // DNS 解析失败 dnsError: { code: 'ENOTFOUND', message: 'getaddrinfo ENOTFOUND oapi.dingtalk.com', }, // 网络不可达 networkUnreachable: { code: 'ENETUNREACH', message: 'network is unreachable', }, // 连接被重置 connectionReset: { code: 'ECONNRESET', message: 'socket hang up', }, // SSL/TLS 错误 sslError: { code: 'DEPTH_ZERO_SELF_SIGNED_CERT', message: 'self signed certificate', }, }; // 特殊响应场景 export const specialResponses = { // 空响应体 emptyBody: { statusCode: 200, data: '', }, // 非 JSON 响应 nonJsonResponse: { statusCode: 200, data: 'This is not JSON', }, // 格式错误的 JSON malformedJson: { statusCode: 200, data: '{"errcode": 0, "errmsg": "ok"', }, // 缺少必需字段的响应 missingFields: { statusCode: 200, data: { errcode: 0, // 缺少 errmsg }, }, // 字段类型错误的响应 wrongFieldTypes: { statusCode: 200, data: { errcode: '0', // 应该是数字 errmsg: 123, // 应该是字符串 }, }, }; // 响应时间模拟 export const responseTimings = { // 快速响应 (< 100ms) fast: 50, // 正常响应 (100-500ms) normal: 200, // 慢响应 (500-2000ms) slow: 1000, // 非常慢的响应 (> 2000ms) verySlow: 3000, // 超时响应 (> 5000ms) timeout: 6000, }; // 批量响应场景 export const batchResponses = { // 全部成功 allSuccess: [ successResponses.standard, successResponses.withMessageId, successResponses.standard, ], // 部分失败 partialFailure: [ successResponses.standard, errorResponses.rateLimited, successResponses.standard, ], // 全部失败 allFailure: [ errorResponses.invalidToken, errorResponses.rateLimited, errorResponses.robotDisabled, ], }; // 用于测试的完整响应对象 export const fullResponses = { textSuccess: { request: { msgtype: 'text', text: { content: 'Hello, World!', }, at: { atMobiles: [], atUserIds: [], isAtAll: false, }, }, response: successResponses.standard, }, markdownSuccess: { request: { msgtype: 'markdown', markdown: { title: 'Markdown 标题', text: '## 标题\n这是一个 **Markdown** 消息', }, at: { atMobiles: [], atUserIds: [], isAtAll: false, }, }, response: successResponses.withMessageId, }, actionCardError: { request: { msgtype: 'actionCard', actionCard: { title: 'ActionCard 标题', text: 'ActionCard 内容', singleTitle: '查看详情', singleURL: 'https://example.com', }, }, response: errorResponses.noKeywords, }, }; export const dingTalkResponses = { success: successResponses, error: errorResponses, httpStatus: httpStatusResponses, network: networkErrors, special: specialResponses, timing: responseTimings, batch: batchResponses, full: fullResponses, };