Files
dingtalk-bot/tests/unit/message.test.js

940 lines
30 KiB
JavaScript

/**
* message.js 文件单元测试
*/
import { describe, expect, it } from 'vitest';
import { MESSAGE_TYPES } from '../../src/config.js';
import {
buildActionCardMessage,
buildFeedCardMessage,
buildLinkMessage,
buildMarkdownMessage,
buildMessage,
buildTextMessage,
getMessageSummary,
validateMessage,
} from '../../src/message.js';
import { assertDingTalkMessage } from '../helpers/assertions.js';
describe('测试 message.js 文件', () => {
describe('测试 buildTextMessage 函数', () => {
it('应该构建基本的文本消息', () => {
const message = buildTextMessage('Hello, World!');
assertDingTalkMessage(message, MESSAGE_TYPES.TEXT);
expect(message.msgtype).toBe(MESSAGE_TYPES.TEXT);
expect(message.text.content).toBe('Hello, World!');
expect(message.at).toBeUndefined();
});
it('应该构建包含@手机号的文本消息', () => {
const atMobiles = ['13800138000', '13900139000'];
const message = buildTextMessage('Hello, World!', atMobiles);
expect(message.msgtype).toBe(MESSAGE_TYPES.TEXT);
expect(message.text.content).toBe('Hello, World!');
expect(message.at).toEqual({
atMobiles: ['13800138000', '13900139000'],
isAtAll: false,
});
});
it('应该构建@所有人的文本消息', () => {
const message = buildTextMessage('Hello, World!', [], true);
expect(message.msgtype).toBe(MESSAGE_TYPES.TEXT);
expect(message.text.content).toBe('Hello, World!');
expect(message.at).toEqual({
atMobiles: [],
isAtAll: true,
});
});
it('应该构建同时包含@手机号和@所有人的文本消息', () => {
const atMobiles = ['13800138000'];
const message = buildTextMessage('Hello, World!', atMobiles, true);
expect(message.at).toEqual({
atMobiles: ['13800138000'],
isAtAll: true,
});
});
it('应该对缺少内容抛出错误', () => {
expect(() => buildTextMessage()).toThrow('Content is required for text message');
expect(() => buildTextMessage('')).toThrow('Content is required for text message');
expect(() => buildTextMessage(null)).toThrow('Content is required for text message');
expect(() => buildTextMessage(123)).toThrow('Content is required for text message');
});
it('应该处理空的@手机号数组', () => {
const message = buildTextMessage('Hello, World!', []);
expect(message.at).toBeUndefined();
});
it('应该处理 null/undefined 的@手机号', () => {
const message1 = buildTextMessage('Hello, World!', null);
const message2 = buildTextMessage('Hello, World!', undefined);
expect(message1.at).toBeUndefined();
expect(message2.at).toBeUndefined();
});
});
describe('测试 buildMarkdownMessage 函数', () => {
it('应该构建基本的 Markdown 消息', () => {
const message = buildMarkdownMessage('标题', '## Markdown 内容');
assertDingTalkMessage(message, MESSAGE_TYPES.MARKDOWN);
expect(message.msgtype).toBe(MESSAGE_TYPES.MARKDOWN);
expect(message.markdown.title).toBe('标题');
expect(message.markdown.text).toBe('## Markdown 内容');
expect(message.at).toBeUndefined();
});
it('应该构建包含@手机号的 Markdown 消息', () => {
const atMobiles = ['13800138000', '13900139000'];
const message = buildMarkdownMessage('标题', '## Markdown 内容', atMobiles);
expect(message.msgtype).toBe(MESSAGE_TYPES.MARKDOWN);
expect(message.markdown.title).toBe('标题');
expect(message.markdown.text).toBe('## Markdown 内容\n\n@13800138000 @13900139000');
expect(message.at).toEqual({
atMobiles: ['13800138000', '13900139000'],
isAtAll: false,
});
});
it('应该构建@所有人的 Markdown 消息', () => {
const message = buildMarkdownMessage('标题', '## Markdown 内容', [], true);
expect(message.msgtype).toBe(MESSAGE_TYPES.MARKDOWN);
expect(message.markdown.text).toBe('## Markdown 内容\n\n@所有人');
expect(message.at).toEqual({
atMobiles: [],
isAtAll: true,
});
});
it('应该构建同时包含@手机号和@所有人的 Markdown 消息', () => {
const atMobiles = ['13800138000'];
const message = buildMarkdownMessage('标题', '## Markdown 内容', atMobiles, true);
expect(message.markdown.text).toBe('## Markdown 内容\n\n@13800138000\n\n@所有人');
expect(message.at).toEqual({
atMobiles: ['13800138000'],
isAtAll: true,
});
});
it('应该对缺少标题抛出错误', () => {
expect(() => buildMarkdownMessage()).toThrow('Title is required for markdown message');
expect(() => buildMarkdownMessage('')).toThrow('Title is required for markdown message');
expect(() => buildMarkdownMessage(null)).toThrow('Title is required for markdown message');
expect(() => buildMarkdownMessage(123)).toThrow('Title is required for markdown message');
});
it('应该对缺少内容抛出错误', () => {
expect(() => buildMarkdownMessage('标题')).toThrow(
'Content is required for markdown message',
);
expect(() => buildMarkdownMessage('标题', '')).toThrow(
'Content is required for markdown message',
);
expect(() => buildMarkdownMessage('标题', null)).toThrow(
'Content is required for markdown message',
);
expect(() => buildMarkdownMessage('标题', 123)).toThrow(
'Content is required for markdown message',
);
});
});
describe('测试 buildLinkMessage 函数', () => {
it('应该构建基本的链接消息', () => {
const message = buildLinkMessage('链接标题', '链接描述', 'https://example.com');
assertDingTalkMessage(message, MESSAGE_TYPES.LINK);
expect(message.msgtype).toBe(MESSAGE_TYPES.LINK);
expect(message.link.title).toBe('链接标题');
expect(message.link.text).toBe('链接描述');
expect(message.link.messageUrl).toBe('https://example.com');
expect(message.link.picUrl).toBeUndefined();
});
it('应该构建包含图片 URL 的链接消息', () => {
const message = buildLinkMessage(
'链接标题',
'链接描述',
'https://example.com',
'https://example.com/image.jpg',
);
expect(message.link.picUrl).toBe('https://example.com/image.jpg');
});
it('应该忽略无效的图片 URL', () => {
const message = buildLinkMessage(
'链接标题',
'链接描述',
'https://example.com',
'not-a-valid-url',
);
expect(message.link.picUrl).toBeUndefined();
});
it('应该忽略非字符串的图片 URL', () => {
const message = buildLinkMessage('链接标题', '链接描述', 'https://example.com', 123);
expect(message.link.picUrl).toBeUndefined();
});
it('应该对缺少标题抛出错误', () => {
expect(() => buildLinkMessage()).toThrow('Title is required for link message');
expect(() => buildLinkMessage('')).toThrow('Title is required for link message');
expect(() => buildLinkMessage(null)).toThrow('Title is required for link message');
expect(() => buildLinkMessage(123)).toThrow('Title is required for link message');
});
it('应该对缺少内容抛出错误', () => {
expect(() => buildLinkMessage('标题')).toThrow('Content is required for link message');
expect(() => buildLinkMessage('标题', '')).toThrow('Content is required for link message');
expect(() => buildLinkMessage('标题', null)).toThrow('Content is required for link message');
expect(() => buildLinkMessage('标题', 123)).toThrow('Content is required for link message');
});
it('应该对缺少链接 URL 抛出错误', () => {
expect(() => buildLinkMessage('标题', '内容')).toThrow(
'Link URL is required for link message',
);
expect(() => buildLinkMessage('标题', '内容', '')).toThrow(
'Link URL is required for link message',
);
expect(() => buildLinkMessage('标题', '内容', null)).toThrow(
'Link URL is required for link message',
);
expect(() => buildLinkMessage('标题', '内容', 123)).toThrow(
'Link URL is required for link message',
);
});
it('应该对无效的链接 URL 格式抛出错误', () => {
expect(() => buildLinkMessage('标题', '内容', 'not-a-url')).toThrow(
'Link URL must be a valid HTTP/HTTPS URL',
);
expect(() => buildLinkMessage('标题', '内容', 'ftp://example.com')).toThrow(
'Link URL must be a valid HTTP/HTTPS URL',
);
});
it('应该接受 HTTP 和 HTTPS URL', () => {
const httpMessage = buildLinkMessage('标题', '内容', 'http://example.com');
const httpsMessage = buildLinkMessage('标题', '内容', 'https://example.com');
expect(httpMessage.link.messageUrl).toBe('http://example.com');
expect(httpsMessage.link.messageUrl).toBe('https://example.com');
});
});
describe('测试 buildActionCardMessage 函数', () => {
it('应该构建单按钮 ActionCard 消息', () => {
const options = {
btnOrientation: '0',
singleTitle: '查看详情',
singleURL: 'https://example.com/detail',
};
const message = buildActionCardMessage('ActionCard 标题', 'ActionCard 内容', options);
assertDingTalkMessage(message, MESSAGE_TYPES.ACTION_CARD);
expect(message.msgtype).toBe(MESSAGE_TYPES.ACTION_CARD);
expect(message.actionCard.title).toBe('ActionCard 标题');
expect(message.actionCard.text).toBe('ActionCard 内容');
expect(message.actionCard.btnOrientation).toBe('0');
expect(message.actionCard.singleTitle).toBe('查看详情');
expect(message.actionCard.singleURL).toBe('https://example.com/detail');
expect(message.actionCard.btns).toBeUndefined();
});
it('应该构建多按钮 ActionCard 消息', () => {
const options = {
btnOrientation: '1',
buttons: [
{ title: '按钮1', actionURL: 'https://example.com/action1' },
{ title: '按钮2', actionURL: 'https://example.com/action2' },
],
};
const message = buildActionCardMessage('ActionCard 标题', 'ActionCard 内容', options);
expect(message.msgtype).toBe(MESSAGE_TYPES.ACTION_CARD);
expect(message.actionCard.btnOrientation).toBe('1');
expect(message.actionCard.btns).toEqual([
{ title: '按钮1', actionURL: 'https://example.com/action1' },
{ title: '按钮2', actionURL: 'https://example.com/action2' },
]);
expect(message.actionCard.singleTitle).toBeUndefined();
expect(message.actionCard.singleURL).toBeUndefined();
});
it('应该使用默认的按钮方向', () => {
const options = {
singleTitle: '查看详情',
singleURL: 'https://example.com/detail',
};
const message = buildActionCardMessage('ActionCard 标题', 'ActionCard 内容', options);
expect(message.actionCard.btnOrientation).toBe('0');
});
it('应该处理空选项', () => {
expect(() => buildActionCardMessage('标题', '内容', {})).toThrow(
'actionCard requires either singleTitle/singleURL or buttons',
);
});
it('应该处理未定义的选项', () => {
expect(() => buildActionCardMessage('标题', '内容')).toThrow(
'actionCard requires either singleTitle/singleURL or buttons',
);
});
it('应该对缺少标题抛出错误', () => {
expect(() => buildActionCardMessage()).toThrow('Title is required for actionCard message');
expect(() => buildActionCardMessage('')).toThrow('Title is required for actionCard message');
expect(() => buildActionCardMessage(null)).toThrow(
'Title is required for actionCard message',
);
expect(() => buildActionCardMessage(123)).toThrow('Title is required for actionCard message');
});
it('应该对缺少内容抛出错误', () => {
expect(() => buildActionCardMessage('标题')).toThrow(
'Content is required for actionCard message',
);
expect(() => buildActionCardMessage('标题', '')).toThrow(
'Content is required for actionCard message',
);
expect(() => buildActionCardMessage('标题', null)).toThrow(
'Content is required for actionCard message',
);
expect(() => buildActionCardMessage('标题', 123)).toThrow(
'Content is required for actionCard message',
);
});
it('应该对既没有单按钮也没有按钮数组的情况抛出错误', () => {
expect(() => buildActionCardMessage('标题', '内容', {})).toThrow(
'actionCard requires either singleTitle/singleURL or buttons',
);
});
it('应该处理空的按钮数组', () => {
const options = { buttons: [] };
expect(() => buildActionCardMessage('标题', '内容', options)).toThrow(
'actionCard requires either singleTitle/singleURL or buttons',
);
});
it('应该处理非数组的按钮', () => {
const options = { buttons: 'not-an-array' };
expect(() => buildActionCardMessage('标题', '内容', options)).toThrow(
'actionCard requires either singleTitle/singleURL or buttons',
);
});
it('当同时提供单按钮和按钮数组时应该优先使用单按钮', () => {
const options = {
singleTitle: '单按钮',
singleURL: 'https://example.com/single',
buttons: [{ title: '多按钮', actionURL: 'https://example.com/multi' }],
};
const message = buildActionCardMessage('标题', '内容', options);
expect(message.actionCard.singleTitle).toBe('单按钮');
expect(message.actionCard.singleURL).toBe('https://example.com/single');
expect(message.actionCard.btns).toEqual([
{ title: '多按钮', actionURL: 'https://example.com/multi' },
]);
});
});
describe('测试 buildFeedCardMessage 函数', () => {
it('应该构建 FeedCard 消息', () => {
const links = [
{
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',
},
];
const message = buildFeedCardMessage(links);
assertDingTalkMessage(message, MESSAGE_TYPES.FEED_CARD);
expect(message.msgtype).toBe(MESSAGE_TYPES.FEED_CARD);
expect(message.feedCard.links).toEqual(links);
});
it('应该构建包含单个链接的 FeedCard 消息', () => {
const links = [
{
title: '单个新闻',
messageURL: 'https://example.com/news',
picURL: 'https://example.com/pic.jpg',
},
];
const message = buildFeedCardMessage(links);
expect(message.feedCard.links).toHaveLength(1);
expect(message.feedCard.links[0]).toEqual(links[0]);
});
it('应该对缺少链接抛出错误', () => {
expect(() => buildFeedCardMessage()).toThrow('FeedCard requires a non-empty links array');
expect(() => buildFeedCardMessage(null)).toThrow('FeedCard requires a non-empty links array');
expect(() => buildFeedCardMessage('not-an-array')).toThrow(
'FeedCard requires a non-empty links array',
);
});
it('应该对空链接数组抛出错误', () => {
expect(() => buildFeedCardMessage([])).toThrow('FeedCard requires a non-empty links array');
});
it('应该正确映射链接属性', () => {
const links = [
{
title: '测试标题',
messageURL: 'https://test.com',
picURL: 'https://test.com/pic.jpg',
extraProperty: 'should be ignored',
},
];
const message = buildFeedCardMessage(links);
expect(message.feedCard.links[0]).toEqual({
title: '测试标题',
messageURL: 'https://test.com',
picURL: 'https://test.com/pic.jpg',
});
expect(message.feedCard.links[0].extraProperty).toBeUndefined();
});
});
describe('测试 buildMessage 函数', () => {
it('应该根据配置构建文本消息', () => {
const config = {
messageType: 'text',
content: 'Hello, World!',
atMobiles: ['13800138000'],
atAll: false,
};
const message = buildMessage(config);
expect(message.msgtype).toBe(MESSAGE_TYPES.TEXT);
expect(message.text.content).toBe('Hello, World!');
expect(message.at.atMobiles).toEqual(['13800138000']);
});
it('应该根据配置构建 Markdown 消息', () => {
const config = {
messageType: 'markdown',
title: 'Markdown 标题',
content: '## Markdown 内容',
atMobiles: [],
atAll: true,
};
const message = buildMessage(config);
expect(message.msgtype).toBe(MESSAGE_TYPES.MARKDOWN);
expect(message.markdown.title).toBe('Markdown 标题');
expect(message.at.isAtAll).toBe(true);
});
it('应该根据配置构建链接消息', () => {
const config = {
messageType: 'link',
title: '链接标题',
content: '链接描述',
linkUrl: 'https://example.com',
picUrl: 'https://example.com/pic.jpg',
};
const message = buildMessage(config);
expect(message.msgtype).toBe(MESSAGE_TYPES.LINK);
expect(message.link.title).toBe('链接标题');
expect(message.link.messageUrl).toBe('https://example.com');
expect(message.link.picUrl).toBe('https://example.com/pic.jpg');
});
it('应该根据配置构建 ActionCard 消息', () => {
const config = {
messageType: 'actionCard',
title: 'ActionCard 标题',
content: 'ActionCard 内容',
btnOrientation: '1',
buttons: [{ title: '按钮1', actionURL: 'https://example.com/action1' }],
};
const message = buildMessage(config);
expect(message.msgtype).toBe(MESSAGE_TYPES.ACTION_CARD);
expect(message.actionCard.title).toBe('ActionCard 标题');
expect(message.actionCard.btnOrientation).toBe('1');
expect(message.actionCard.btns).toHaveLength(1);
});
it('应该根据配置构建 FeedCard 消息', () => {
const config = {
messageType: 'feedCard',
feedLinks: [
{
title: '新闻1',
messageURL: 'https://example.com/news1',
picURL: 'https://example.com/pic1.jpg',
},
],
};
const message = buildMessage(config);
expect(message.msgtype).toBe(MESSAGE_TYPES.FEED_CARD);
expect(message.feedCard.links).toHaveLength(1);
});
it('应该对不支持的消息类型抛出错误', () => {
const config = {
messageType: 'unsupported',
content: 'Test content',
};
expect(() => buildMessage(config)).toThrow('Unsupported message type: unsupported');
});
});
describe('测试 validateMessage 函数', () => {
it('应该验证有效的文本消息', () => {
const message = {
msgtype: 'text',
text: {
content: 'Hello, World!',
},
};
const result = validateMessage(message);
expect(result.isValid).toBe(true);
expect(result.errors).toEqual([]);
});
it('应该验证有效的 Markdown 消息', () => {
const message = {
msgtype: 'markdown',
markdown: {
title: '标题',
text: '## 内容',
},
};
const result = validateMessage(message);
expect(result.isValid).toBe(true);
expect(result.errors).toEqual([]);
});
it('应该验证有效的链接消息', () => {
const message = {
msgtype: 'link',
link: {
title: '链接标题',
text: '链接描述',
messageUrl: 'https://example.com',
},
};
const result = validateMessage(message);
expect(result.isValid).toBe(true);
expect(result.errors).toEqual([]);
});
it('应该验证有效的单按钮 ActionCard 消息', () => {
const message = {
msgtype: 'actionCard',
actionCard: {
title: 'ActionCard 标题',
text: 'ActionCard 内容',
singleTitle: '查看详情',
singleURL: 'https://example.com',
},
};
const result = validateMessage(message);
expect(result.isValid).toBe(true);
expect(result.errors).toEqual([]);
});
it('应该验证有效的多按钮 ActionCard 消息', () => {
const message = {
msgtype: 'actionCard',
actionCard: {
title: 'ActionCard 标题',
text: 'ActionCard 内容',
btns: [
{ title: '按钮1', actionURL: 'https://example.com/action1' },
{ title: '按钮2', actionURL: 'https://example.com/action2' },
],
},
};
const result = validateMessage(message);
expect(result.isValid).toBe(true);
expect(result.errors).toEqual([]);
});
it('应该验证有效的 FeedCard 消息', () => {
const message = {
msgtype: 'feedCard',
feedCard: {
links: [
{
title: '新闻1',
messageURL: 'https://example.com/news1',
picURL: 'https://example.com/pic1.jpg',
},
],
},
};
const result = validateMessage(message);
expect(result.isValid).toBe(true);
expect(result.errors).toEqual([]);
});
it('应该拒绝 null/undefined 消息', () => {
expect(validateMessage(null).isValid).toBe(false);
expect(validateMessage(undefined).isValid).toBe(false);
expect(validateMessage('not-an-object').isValid).toBe(false);
});
it('应该拒绝没有 msgtype 的消息', () => {
const message = {
text: { content: 'Hello' },
};
const result = validateMessage(message);
expect(result.isValid).toBe(false);
expect(result.errors).toContain('Invalid or missing msgtype');
});
it('应该拒绝带有无效 msgtype 的消息', () => {
const message = {
msgtype: 'invalid',
text: { content: 'Hello' },
};
const result = validateMessage(message);
expect(result.isValid).toBe(false);
expect(result.errors).toContain('Invalid or missing msgtype');
});
it('应该拒绝没有内容的文本消息', () => {
const message = {
msgtype: 'text',
text: {},
};
const result = validateMessage(message);
expect(result.isValid).toBe(false);
expect(result.errors).toContain('Text message must have content');
});
it('应该拒绝没有标题或内容的 Markdown 消息', () => {
const message1 = {
msgtype: 'markdown',
markdown: { text: '内容' },
};
const message2 = {
msgtype: 'markdown',
markdown: { title: '标题' },
};
expect(validateMessage(message1).isValid).toBe(false);
expect(validateMessage(message2).isValid).toBe(false);
});
it('应该拒绝缺少字段的链接消息', () => {
const message = {
msgtype: 'link',
link: { title: '标题' },
};
const result = validateMessage(message);
expect(result.isValid).toBe(false);
expect(result.errors).toContain('Link message must have title, text, and messageUrl');
});
it('应该拒绝单按钮不完整的 ActionCard 消息', () => {
const message = {
msgtype: 'actionCard',
actionCard: {
title: '标题',
text: '内容',
singleTitle: '按钮',
// missing singleURL
},
};
const result = validateMessage(message);
expect(result.isValid).toBe(false);
expect(result.errors).toContain(
'ActionCard single button requires both singleTitle and singleURL',
);
});
it('应该拒绝带有无效按钮的 ActionCard 消息', () => {
const message = {
msgtype: 'actionCard',
actionCard: {
title: '标题',
text: '内容',
btns: [
{ title: '按钮1' }, // missing actionURL
],
},
};
const result = validateMessage(message);
expect(result.isValid).toBe(false);
expect(result.errors).toContain('Each ActionCard button must have title and actionURL');
});
it('应该拒绝没有链接的 FeedCard 消息', () => {
const message = {
msgtype: 'feedCard',
feedCard: {},
};
const result = validateMessage(message);
expect(result.isValid).toBe(false);
expect(result.errors).toContain('FeedCard must have a non-empty links array');
});
it('应该拒绝带有无效链接的 FeedCard 消息', () => {
const message = {
msgtype: 'feedCard',
feedCard: {
links: [
{ title: '新闻1' }, // missing messageURL and picURL
],
},
};
const result = validateMessage(message);
expect(result.isValid).toBe(false);
expect(result.errors).toContain('Each FeedCard link must have title, messageURL and picURL');
});
});
describe('测试 getMessageSummary 函数', () => {
it('应该返回文本消息的摘要', () => {
const message = {
msgtype: 'text',
text: {
content: 'Hello, World!',
},
};
const summary = getMessageSummary(message);
expect(summary).toBe('Type: text, Content: "Hello, World!"');
});
it('应该截断长文本内容', () => {
const longContent = 'A'.repeat(60);
const message = {
msgtype: 'text',
text: {
content: longContent,
},
};
const summary = getMessageSummary(message);
expect(summary).toContain(`Type: text, Content: "${'A'.repeat(50)}..."`);
});
it('应该返回 Markdown 消息的摘要', () => {
const message = {
msgtype: 'markdown',
markdown: {
title: 'Markdown 标题',
text: '## Markdown 内容',
},
};
const summary = getMessageSummary(message);
expect(summary).toBe('Type: markdown, Title: "Markdown 标题", Text: "## Markdown 内容"');
});
it('应该返回链接消息的摘要', () => {
const message = {
msgtype: 'link',
link: {
title: '链接标题',
text: '链接描述',
messageUrl: 'https://example.com',
},
};
const summary = getMessageSummary(message);
expect(summary).toBe('Type: link, Title: "链接标题", URL: "https://example.com"');
});
it('应该返回单按钮 ActionCard 消息的摘要', () => {
const message = {
msgtype: 'actionCard',
actionCard: {
title: 'ActionCard 标题',
text: 'ActionCard 内容',
singleTitle: '查看详情',
},
};
const summary = getMessageSummary(message);
expect(summary).toBe('Type: actionCard, Title: "ActionCard 标题", Single: "查看详情"');
});
it('应该返回多按钮 ActionCard 消息的摘要', () => {
const message = {
msgtype: 'actionCard',
actionCard: {
title: 'ActionCard 标题',
text: 'ActionCard 内容',
btns: [
{ title: '按钮1', actionURL: 'https://example.com/action1' },
{ title: '按钮2', actionURL: 'https://example.com/action2' },
],
},
};
const summary = getMessageSummary(message);
expect(summary).toBe('Type: actionCard, Title: "ActionCard 标题", Buttons: 2');
});
it('应该返回 FeedCard 消息的摘要', () => {
const message = {
msgtype: 'feedCard',
feedCard: {
links: [
{
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',
},
],
},
};
const summary = getMessageSummary(message);
expect(summary).toBe('Type: feedCard, Links: 2');
});
it('应该包含 @所有人 信息', () => {
const message = {
msgtype: 'text',
text: {
content: 'Hello, World!',
},
at: {
isAtAll: true,
atMobiles: [],
},
};
const summary = getMessageSummary(message);
expect(summary).toBe('Type: text, Content: "Hello, World!", @All: true');
});
it('应该包含 @手机号 信息', () => {
const message = {
msgtype: 'text',
text: {
content: 'Hello, World!',
},
at: {
isAtAll: false,
atMobiles: ['13800138000', '13900139000'],
},
};
const summary = getMessageSummary(message);
expect(summary).toBe('Type: text, Content: "Hello, World!", @Mobiles: 2');
});
it('应该同时包含 @所有人 和 @手机号 信息', () => {
const message = {
msgtype: 'text',
text: {
content: 'Hello, World!',
},
at: {
isAtAll: true,
atMobiles: ['13800138000'],
},
};
const summary = getMessageSummary(message);
expect(summary).toBe('Type: text, Content: "Hello, World!", @All: true, @Mobiles: 1');
});
it('应该处理无效的消息', () => {
expect(getMessageSummary(null)).toBe('Invalid message');
expect(getMessageSummary({})).toBe('Invalid message');
expect(getMessageSummary({ msgtype: null })).toBe('Invalid message');
});
});
});