593 lines
21 KiB
JavaScript
593 lines
21 KiB
JavaScript
/**
|
|
* config.js 模块单元测试
|
|
*/
|
|
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import {
|
|
MESSAGE_TYPES,
|
|
logConfig,
|
|
parseConfig,
|
|
validateMessageType,
|
|
validateWebhookUrl,
|
|
} from '../../src/config.js';
|
|
import { envConfigs } from '../fixtures/configs/valid-configs.js';
|
|
import { assertConfigStructure } from '../helpers/assertions.js';
|
|
import { mockEnvVars } from '../helpers/env-mock.js';
|
|
|
|
describe('测试 config.js 文件', () => {
|
|
let restoreEnv;
|
|
let consoleSpy;
|
|
|
|
beforeEach(() => {
|
|
// Mock console methods
|
|
consoleSpy = {
|
|
log: vi.spyOn(console, 'log').mockImplementation(() => {}),
|
|
};
|
|
});
|
|
|
|
afterEach(() => {
|
|
// Restore console methods
|
|
Object.values(consoleSpy).forEach(spy => spy.mockRestore());
|
|
|
|
// Restore environment variables
|
|
if (restoreEnv) {
|
|
restoreEnv();
|
|
restoreEnv = null;
|
|
}
|
|
});
|
|
|
|
describe('测试 MESSAGE_TYPES 常量', () => {
|
|
it('应该导出正确的消息类型', () => {
|
|
expect(MESSAGE_TYPES).toEqual({
|
|
TEXT: 'text',
|
|
MARKDOWN: 'markdown',
|
|
LINK: 'link',
|
|
ACTION_CARD: 'actionCard',
|
|
FEED_CARD: 'feedCard',
|
|
});
|
|
});
|
|
|
|
it('应该是只读枚举', () => {
|
|
expect(() => {
|
|
MESSAGE_TYPES.NEW_TYPE = 'newType';
|
|
}).not.toThrow(); // JavaScript doesn't prevent this, but it's documented as readonly
|
|
});
|
|
});
|
|
|
|
describe('测试 validateWebhookUrl 函数', () => {
|
|
it('应该验证正确的钉钉 Webhook URL', () => {
|
|
const validUrls = [
|
|
'https://oapi.dingtalk.com/robot/send?access_token=abc123',
|
|
'https://oapi.dingtalk.com/robot/send?access_token=test-token-123',
|
|
'https://oapi.dingtalk.com/robot/send?access_token=1234567890abcdef',
|
|
];
|
|
|
|
validUrls.forEach(url => {
|
|
expect(validateWebhookUrl(url)).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('应该拒绝无效的 Webhook URL', () => {
|
|
const invalidUrls = [
|
|
'',
|
|
null,
|
|
undefined,
|
|
'not-a-url',
|
|
'http://oapi.dingtalk.com/robot/send?access_token=abc123', // http instead of https
|
|
'https://wrong-domain.com/robot/send?access_token=abc123',
|
|
'https://oapi.dingtalk.com/wrong/path?access_token=abc123',
|
|
'https://oapi.dingtalk.com/robot/send', // missing access_token
|
|
'https://oapi.dingtalk.com/robot/send?access_token=', // empty token
|
|
'https://oapi.dingtalk.com/robot/send?wrong_param=abc123',
|
|
];
|
|
|
|
invalidUrls.forEach(url => {
|
|
expect(validateWebhookUrl(url)).toBe(false);
|
|
});
|
|
});
|
|
|
|
it('应该处理非字符串输入', () => {
|
|
expect(validateWebhookUrl(123)).toBe(false);
|
|
expect(validateWebhookUrl({})).toBe(false);
|
|
expect(validateWebhookUrl([])).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('测试 validateMessageType 函数', () => {
|
|
it('应该验证支持的消息类型', () => {
|
|
Object.values(MESSAGE_TYPES).forEach(type => {
|
|
expect(validateMessageType(type)).toBe(true);
|
|
});
|
|
});
|
|
|
|
it('应该拒绝不支持的消息类型', () => {
|
|
const invalidTypes = [
|
|
'unsupported',
|
|
'TEXT', // wrong case
|
|
'MARKDOWN', // wrong case
|
|
'',
|
|
null,
|
|
undefined,
|
|
123,
|
|
];
|
|
|
|
invalidTypes.forEach(type => {
|
|
expect(validateMessageType(type)).toBe(false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('测试 parseConfig 函数', () => {
|
|
describe('有效配置测试', () => {
|
|
it('应该解析基础文本消息配置', async () => {
|
|
restoreEnv = mockEnvVars(envConfigs.basicText);
|
|
|
|
const config = await parseConfig();
|
|
|
|
assertConfigStructure(config, ['webhookUrl', 'messageType', 'content']);
|
|
expect(config.messageType).toBe('text');
|
|
expect(config.content).toBe('Hello, World!');
|
|
expect(config.atAll).toBe(false);
|
|
expect(config.atMobiles).toEqual([]);
|
|
});
|
|
|
|
it('应该解析 Markdown 消息配置', async () => {
|
|
restoreEnv = mockEnvVars(envConfigs.markdown);
|
|
|
|
const config = await parseConfig();
|
|
|
|
expect(config.messageType).toBe('markdown');
|
|
expect(config.title).toBe('Markdown 标题');
|
|
expect(config.content).toContain('Markdown');
|
|
});
|
|
|
|
it('应该解析带 @all 的文本消息配置', async () => {
|
|
restoreEnv = mockEnvVars(envConfigs.textWithAtAll);
|
|
|
|
const config = await parseConfig();
|
|
|
|
expect(config.atAll).toBe(true);
|
|
expect(config.messageType).toBe('text');
|
|
});
|
|
|
|
it('应该正确解析手机号码', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
...envConfigs.basicText,
|
|
INPUT_AT_MOBILES: '13800138000,13900139000,invalid-mobile,15012345678',
|
|
});
|
|
|
|
const config = await parseConfig();
|
|
|
|
expect(config.atMobiles).toEqual(['13800138000', '13900139000', '15012345678']);
|
|
});
|
|
|
|
it('应该解析链接消息配置', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'link',
|
|
INPUT_CONTENT: '链接描述',
|
|
INPUT_TITLE: '链接标题',
|
|
INPUT_LINK_URL: 'https://example.com',
|
|
INPUT_PIC_URL: 'https://example.com/image.jpg',
|
|
});
|
|
|
|
const config = await parseConfig();
|
|
|
|
expect(config.messageType).toBe('link');
|
|
expect(config.title).toBe('链接标题');
|
|
expect(config.linkUrl).toBe('https://example.com');
|
|
expect(config.picUrl).toBe('https://example.com/image.jpg');
|
|
});
|
|
|
|
it('应该解析单按钮 ActionCard 配置', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'actionCard',
|
|
INPUT_CONTENT: 'ActionCard 内容',
|
|
INPUT_TITLE: 'ActionCard 标题',
|
|
INPUT_BTN_ORIENTATION: '0',
|
|
INPUT_SINGLE_TITLE: '查看详情',
|
|
INPUT_SINGLE_URL: 'https://example.com/detail',
|
|
});
|
|
|
|
const config = await parseConfig();
|
|
|
|
expect(config.messageType).toBe('actionCard');
|
|
expect(config.btnOrientation).toBe('0');
|
|
expect(config.singleTitle).toBe('查看详情');
|
|
expect(config.singleURL).toBe('https://example.com/detail');
|
|
expect(config.buttons).toEqual([]);
|
|
});
|
|
|
|
it('应该解析多按钮 ActionCard 配置', async () => {
|
|
const buttons = JSON.stringify([
|
|
{ title: '按钮1', actionURL: 'https://example.com/action1' },
|
|
{ title: '按钮2', actionURL: 'https://example.com/action2' },
|
|
]);
|
|
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'actionCard',
|
|
INPUT_CONTENT: 'ActionCard 内容',
|
|
INPUT_TITLE: 'ActionCard 标题',
|
|
INPUT_BTN_ORIENTATION: '1',
|
|
INPUT_BUTTONS: buttons,
|
|
});
|
|
|
|
const config = await parseConfig();
|
|
|
|
expect(config.messageType).toBe('actionCard');
|
|
expect(config.btnOrientation).toBe('1');
|
|
expect(config.buttons).toHaveLength(2);
|
|
expect(config.buttons[0]).toEqual({
|
|
title: '按钮1',
|
|
actionURL: 'https://example.com/action1',
|
|
});
|
|
});
|
|
|
|
it('应该解析 FeedCard 配置', async () => {
|
|
const feedLinks = JSON.stringify([
|
|
{
|
|
title: '新闻1',
|
|
messageURL: 'https://example.com/news1',
|
|
picURL: 'https://example.com/pic1.jpg',
|
|
},
|
|
{
|
|
title: '新闻2',
|
|
messageURL: 'https://example.com/news2',
|
|
picURL: 'https://example.com/pic2.jpg',
|
|
},
|
|
]);
|
|
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'feedCard',
|
|
INPUT_CONTENT: 'FeedCard content',
|
|
INPUT_FEED_LINKS: feedLinks,
|
|
});
|
|
|
|
const config = await parseConfig();
|
|
|
|
expect(config.messageType).toBe('feedCard');
|
|
expect(config.feedLinks).toHaveLength(2);
|
|
expect(config.feedLinks[0]).toEqual({
|
|
title: '新闻1',
|
|
messageURL: 'https://example.com/news1',
|
|
picURL: 'https://example.com/pic1.jpg',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('无效配置测试', () => {
|
|
it('应该抛出缺少 Webhook URL 的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: '',
|
|
INPUT_MESSAGE_TYPE: 'text',
|
|
INPUT_CONTENT: 'Hello, World!',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow('webhook_url is required');
|
|
});
|
|
|
|
it('应该抛出无效 Webhook URL 格式的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'not-a-valid-url',
|
|
INPUT_MESSAGE_TYPE: 'text',
|
|
INPUT_CONTENT: 'Hello, World!',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow('webhook_url format is invalid');
|
|
});
|
|
|
|
it('应该抛出缺少内容的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'text',
|
|
INPUT_CONTENT: '',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow('content is required');
|
|
});
|
|
|
|
it('应该抛出不支持的消息类型错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'unsupported',
|
|
INPUT_CONTENT: 'Hello, World!',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow('message_type must be one of');
|
|
});
|
|
|
|
it('应该抛出 Markdown 消息缺少标题的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'markdown',
|
|
INPUT_CONTENT: '## Content',
|
|
INPUT_TITLE: '',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow('title is required for markdown message type');
|
|
});
|
|
|
|
it('应该抛出 Link 消息缺少标题的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'link',
|
|
INPUT_CONTENT: 'Link description',
|
|
INPUT_TITLE: '',
|
|
INPUT_LINK_URL: 'https://example.com',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow('title is required for link message type');
|
|
});
|
|
|
|
it('应该抛出缺少链接 URL 的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'link',
|
|
INPUT_CONTENT: 'Link description',
|
|
INPUT_TITLE: 'Link title',
|
|
INPUT_LINK_URL: '',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow('link_url is required for link message type');
|
|
});
|
|
|
|
it('应该抛出无效链接 URL 的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'link',
|
|
INPUT_CONTENT: 'Link description',
|
|
INPUT_TITLE: 'Link title',
|
|
INPUT_LINK_URL: 'not-a-valid-url',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow('link_url must be a valid HTTP/HTTPS URL');
|
|
});
|
|
|
|
it('应该抛出 ActionCard 缺少标题的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'actionCard',
|
|
INPUT_CONTENT: 'ActionCard content',
|
|
INPUT_TITLE: '',
|
|
INPUT_SINGLE_TITLE: 'Button',
|
|
INPUT_SINGLE_URL: 'https://example.com',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow(
|
|
'title is required for actionCard message type',
|
|
);
|
|
});
|
|
|
|
it('应该抛出 ActionCard 缺少按钮的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'actionCard',
|
|
INPUT_CONTENT: 'ActionCard content',
|
|
INPUT_TITLE: 'ActionCard title',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow(
|
|
'actionCard requires either single_title/single_url or buttons',
|
|
);
|
|
});
|
|
|
|
it('应该抛出 ActionCard 无效按钮方向的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'actionCard',
|
|
INPUT_CONTENT: 'ActionCard content',
|
|
INPUT_TITLE: 'ActionCard title',
|
|
INPUT_BTN_ORIENTATION: '2',
|
|
INPUT_SINGLE_TITLE: 'Button',
|
|
INPUT_SINGLE_URL: 'https://example.com',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow("btn_orientation must be '0' or '1'");
|
|
});
|
|
|
|
it('应该抛出 ActionCard 单按钮缺少 URL 的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'actionCard',
|
|
INPUT_CONTENT: 'ActionCard content',
|
|
INPUT_TITLE: 'ActionCard title',
|
|
INPUT_SINGLE_TITLE: 'Button',
|
|
INPUT_SINGLE_URL: '',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow(
|
|
'single_url is required when using single button',
|
|
);
|
|
});
|
|
|
|
it('应该抛出 ActionCard 无效按钮 JSON 的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'actionCard',
|
|
INPUT_CONTENT: 'ActionCard content',
|
|
INPUT_TITLE: 'ActionCard title',
|
|
INPUT_BUTTONS: 'invalid-json',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow(
|
|
'actionCard requires either single_title/single_url or buttons',
|
|
);
|
|
});
|
|
|
|
it('应该抛出 FeedCard 缺少链接的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'feedCard',
|
|
INPUT_CONTENT: '',
|
|
INPUT_FEED_LINKS: '',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow(
|
|
'feed_links is required and must be a non-empty array for feedCard',
|
|
);
|
|
});
|
|
|
|
it('应该抛出 FeedCard 无效链接 JSON 的错误', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'feedCard',
|
|
INPUT_CONTENT: '',
|
|
INPUT_FEED_LINKS: 'invalid-json',
|
|
});
|
|
|
|
await expect(parseConfig()).rejects.toThrow(
|
|
'feed_links is required and must be a non-empty array for feedCard',
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('边界情况', () => {
|
|
it('应该处理按钮方向中的空白字符', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'actionCard',
|
|
INPUT_CONTENT: 'ActionCard content',
|
|
INPUT_TITLE: 'ActionCard title',
|
|
INPUT_BTN_ORIENTATION: ' 1 ',
|
|
INPUT_SINGLE_TITLE: 'Button',
|
|
INPUT_SINGLE_URL: 'https://example.com',
|
|
});
|
|
|
|
const config = await parseConfig();
|
|
expect(config.btnOrientation).toBe('1');
|
|
});
|
|
|
|
it('应该过滤掉无效的手机号码', async () => {
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'text',
|
|
INPUT_CONTENT: 'Hello, World!',
|
|
INPUT_AT_MOBILES: '13800138000,invalid,12345678901,15012345678,abc123',
|
|
});
|
|
|
|
const config = await parseConfig();
|
|
expect(config.atMobiles).toEqual(['13800138000', '15012345678']);
|
|
});
|
|
|
|
it('应该过滤掉无效的按钮', async () => {
|
|
const buttons = JSON.stringify([
|
|
{ title: '有效按钮', actionURL: 'https://example.com/valid' },
|
|
{ title: '', actionURL: 'https://example.com/invalid' }, // 空标题
|
|
{ title: '无效URL', actionURL: 'not-a-url' }, // 无效URL
|
|
{ actionURL: 'https://example.com/no-title' }, // 缺少标题
|
|
{ title: '另一个有效按钮', actionURL: 'https://example.com/valid2' },
|
|
]);
|
|
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'actionCard',
|
|
INPUT_CONTENT: 'ActionCard content',
|
|
INPUT_TITLE: 'ActionCard title',
|
|
INPUT_BUTTONS: buttons,
|
|
});
|
|
|
|
const config = await parseConfig();
|
|
expect(config.buttons).toHaveLength(2);
|
|
expect(config.buttons[0].title).toBe('有效按钮');
|
|
expect(config.buttons[1].title).toBe('另一个有效按钮');
|
|
});
|
|
|
|
it('应该过滤掉无效的 Feed 链接', async () => {
|
|
const feedLinks = JSON.stringify([
|
|
{
|
|
title: '有效链接',
|
|
messageURL: 'https://example.com/valid',
|
|
picURL: 'https://example.com/pic.jpg',
|
|
},
|
|
{
|
|
title: '',
|
|
messageURL: 'https://example.com/invalid',
|
|
picURL: 'https://example.com/pic.jpg',
|
|
}, // 空标题
|
|
{
|
|
title: '无效URL',
|
|
messageURL: 'not-a-url',
|
|
picURL: 'https://example.com/pic.jpg',
|
|
}, // 无效URL
|
|
{
|
|
title: '另一个有效链接',
|
|
messageURL: 'https://example.com/valid2',
|
|
picURL: 'https://example.com/pic2.jpg',
|
|
},
|
|
]);
|
|
|
|
restoreEnv = mockEnvVars({
|
|
INPUT_WEBHOOK_URL: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
INPUT_MESSAGE_TYPE: 'feedCard',
|
|
INPUT_CONTENT: 'FeedCard content',
|
|
INPUT_FEED_LINKS: feedLinks,
|
|
});
|
|
|
|
const config = await parseConfig();
|
|
expect(config.feedLinks).toHaveLength(2);
|
|
expect(config.feedLinks[0].title).toBe('有效链接');
|
|
expect(config.feedLinks[1].title).toBe('另一个有效链接');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('测试 logConfig 函数', () => {
|
|
it('应该记录基本配置信息', () => {
|
|
const config = {
|
|
messageType: 'text',
|
|
content: 'Hello, World!',
|
|
webhookUrl: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
};
|
|
|
|
logConfig(config);
|
|
|
|
expect(consoleSpy.log).toHaveBeenCalledWith('=== Action Configuration ===');
|
|
expect(consoleSpy.log).toHaveBeenCalledWith('Message Type: text');
|
|
expect(consoleSpy.log).toHaveBeenCalledWith('Content Length: 13 characters');
|
|
expect(consoleSpy.log).toHaveBeenCalledWith('Webhook URL: [HIDDEN FOR SECURITY]');
|
|
});
|
|
|
|
it('应该在字段存在时记录可选字段', () => {
|
|
const config = {
|
|
messageType: 'markdown',
|
|
content: 'Markdown content',
|
|
title: 'Test Title',
|
|
atMobiles: ['13800138000', '13900139000'],
|
|
atAll: true,
|
|
linkUrl: 'https://example.com',
|
|
picUrl: 'https://example.com/pic.jpg',
|
|
webhookUrl: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
};
|
|
|
|
logConfig(config);
|
|
|
|
expect(consoleSpy.log).toHaveBeenCalledWith('Title: Test Title');
|
|
expect(consoleSpy.log).toHaveBeenCalledWith('At Mobiles: 2 numbers');
|
|
expect(consoleSpy.log).toHaveBeenCalledWith('At All: true');
|
|
expect(consoleSpy.log).toHaveBeenCalledWith('Link URL: https://example.com');
|
|
expect(consoleSpy.log).toHaveBeenCalledWith('Picture URL: https://example.com/pic.jpg');
|
|
});
|
|
|
|
it('应该在字段不存在时不记录可选字段', () => {
|
|
const config = {
|
|
messageType: 'text',
|
|
content: 'Simple text',
|
|
atMobiles: [],
|
|
atAll: false,
|
|
webhookUrl: 'https://oapi.dingtalk.com/robot/send?access_token=test123',
|
|
};
|
|
|
|
logConfig(config);
|
|
|
|
expect(consoleSpy.log).not.toHaveBeenCalledWith(expect.stringContaining('Title:'));
|
|
expect(consoleSpy.log).not.toHaveBeenCalledWith(expect.stringContaining('At Mobiles:'));
|
|
expect(consoleSpy.log).not.toHaveBeenCalledWith(expect.stringContaining('At All: true'));
|
|
expect(consoleSpy.log).not.toHaveBeenCalledWith(expect.stringContaining('Link URL:'));
|
|
expect(consoleSpy.log).not.toHaveBeenCalledWith(expect.stringContaining('Picture URL:'));
|
|
});
|
|
});
|
|
});
|