import { describe, expect, it } from 'vitest';
import { segments } from '../src/messages/segments';
describe('segments.text', () => {
it('wraps a string as a text segment', () => {
expect(segments.text('hello')).toEqual({ type: 'text', data: { text: 'hello' } });
});
it('keeps empty text', () => {
expect(segments.text('')).toEqual({ type: 'text', data: { text: '' } });
});
});
describe('segments.face', () => {
it('stringifies a numeric face id', () => {
expect(segments.face(14)).toEqual({ type: 'face', data: { id: '14' } });
});
it('keeps a string face id', () => {
expect(segments.face('178')).toEqual({ type: 'face', data: { id: '178' } });
});
it('stringifies zero', () => {
expect(segments.face(0)).toEqual({ type: 'face', data: { id: '0' } });
});
});
describe('segments.at', () => {
it('stringifies a numeric qq and omits empty options', () => {
expect(segments.at(10001)).toEqual({ type: 'at', data: { qq: '10001' } });
});
it('supports at-all', () => {
expect(segments.at('all')).toEqual({ type: 'at', data: { qq: 'all' } });
});
it('includes name when provided', () => {
expect(segments.at(10001, { name: 'luma' })).toEqual({
type: 'at',
data: { qq: '10001', name: 'luma' },
});
});
it('includes uid when provided', () => {
expect(segments.at(10001, { uid: 'u_abc' })).toEqual({
type: 'at',
data: { qq: '10001', uid: 'u_abc' },
});
});
it('includes both name and uid', () => {
expect(segments.at(10001, { name: 'luma', uid: 'u_abc' })).toEqual({
type: 'at',
data: { qq: '10001', name: 'luma', uid: 'u_abc' },
});
});
it('omits empty name and uid', () => {
expect(segments.at(10001, { name: '', uid: '' })).toEqual({
type: 'at',
data: { qq: '10001' },
});
});
});
describe('segments.reply', () => {
it('stringifies a numeric message id', () => {
expect(segments.reply(7)).toEqual({ type: 'reply', data: { id: '7' } });
});
it('keeps a string message id', () => {
expect(segments.reply('abc')).toEqual({ type: 'reply', data: { id: 'abc' } });
});
});
describe('segments.customReply', () => {
it('builds an inline quote without requiring a cached message id', () => {
expect(
segments.customReply([segments.text('SnowLuma')], {
qq: 10001,
time: 1700000000,
seq: 42,
}),
).toEqual({
type: 'reply',
data: {
message: [{ type: 'text', data: { text: 'SnowLuma' } }],
qq: 10001,
time: 1700000000,
seq: 42,
},
});
});
it('accepts a plain quote string without metadata', () => {
expect(segments.customReply('quoted')).toEqual({
type: 'reply',
data: { message: 'quoted' },
});
});
});
describe('segments.image', () => {
it('uses only the file when no options are given', () => {
expect(segments.image('/tmp/a.png')).toEqual({
type: 'image',
data: { file: '/tmp/a.png' },
});
});
it('spreads image options after file', () => {
expect(
segments.image('base64://abc', {
type: 'flash',
subType: 1,
summary: 'pic',
url: 'https://example.com/a.png',
}),
).toEqual({
type: 'image',
data: {
file: 'base64://abc',
type: 'flash',
subType: 1,
summary: 'pic',
url: 'https://example.com/a.png',
},
});
});
});
describe('segments.record', () => {
it('uses only the file when no options are given', () => {
expect(segments.record('/tmp/a.amr')).toEqual({
type: 'record',
data: { file: '/tmp/a.amr' },
});
});
it('spreads record options after file', () => {
expect(segments.record('/tmp/a.amr', { url: 'https://example.com/a.amr' })).toEqual({
type: 'record',
data: { file: '/tmp/a.amr', url: 'https://example.com/a.amr' },
});
});
});
describe('segments.video', () => {
it('uses only the file when no options are given', () => {
expect(segments.video('/tmp/a.mp4')).toEqual({
type: 'video',
data: { file: '/tmp/a.mp4' },
});
});
it('spreads video options after file', () => {
expect(
segments.video('/tmp/a.mp4', {
url: 'https://example.com/a.mp4',
thumb: '/tmp/thumb.jpg',
}),
).toEqual({
type: 'video',
data: {
file: '/tmp/a.mp4',
url: 'https://example.com/a.mp4',
thumb: '/tmp/thumb.jpg',
},
});
});
});
describe('segments.json', () => {
it('keeps a JSON string as-is', () => {
expect(segments.json('{"app":"com.tencent.miniapp"}')).toEqual({
type: 'json',
data: { data: '{"app":"com.tencent.miniapp"}' },
});
});
it('stringifies a JSON object', () => {
expect(segments.json({ app: 'com.tencent.miniapp', desc: 'hi' })).toEqual({
type: 'json',
data: { data: '{"app":"com.tencent.miniapp","desc":"hi"}' },
});
});
});
describe('segments.xml', () => {
it('uses only the xml payload when no options are given', () => {
expect(segments.xml('')).toEqual({
type: 'xml',
data: { data: '' },
});
});
it('spreads xml options after data', () => {
expect(segments.xml('', { id: '12345' })).toEqual({
type: 'xml',
data: { data: '', id: '12345' },
});
});
});
describe('segments.poke', () => {
it('omits id when it is not provided', () => {
expect(segments.poke(1)).toEqual({ type: 'poke', data: { type: 1 } });
});
it('includes a numeric id', () => {
expect(segments.poke(1, -1)).toEqual({ type: 'poke', data: { type: 1, id: -1 } });
});
it('keeps string type and id', () => {
expect(segments.poke('1', '0')).toEqual({ type: 'poke', data: { type: '1', id: '0' } });
});
it('includes an id of 0', () => {
expect(segments.poke(1, 0)).toEqual({ type: 'poke', data: { type: 1, id: 0 } });
});
});
describe('segments.forward', () => {
it('mirrors the id onto res_id and forward_id', () => {
expect(segments.forward('res-9')).toEqual({
type: 'forward',
data: { id: 'res-9', res_id: 'res-9', forward_id: 'res-9' },
});
});
});
describe('segments.node', () => {
it('stores user_id, nickname, and string content', () => {
expect(segments.node(10001, 'luma', 'hello')).toEqual({
type: 'node',
data: { user_id: 10001, nickname: 'luma', content: 'hello' },
});
});
it('stores a single segment as content', () => {
expect(segments.node(10001, 'luma', { type: 'text', data: { text: 'hi' } })).toEqual({
type: 'node',
data: {
user_id: 10001,
nickname: 'luma',
content: { type: 'text', data: { text: 'hi' } },
},
});
});
it('stores a segment array as content', () => {
expect(segments.node(10001, 'luma', [{ type: 'text', data: { text: 'hi' } }])).toEqual({
type: 'node',
data: {
user_id: 10001,
nickname: 'luma',
content: [{ type: 'text', data: { text: 'hi' } }],
},
});
});
});
describe('segments.share', () => {
it('passes required share fields through', () => {
expect(segments.share({ url: 'https://example.com', title: 'Example' })).toEqual({
type: 'share',
data: { url: 'https://example.com', title: 'Example' },
});
});
it('passes optional share fields through', () => {
expect(
segments.share({
url: 'https://example.com',
title: 'Example',
content: 'desc',
image: 'https://example.com/a.png',
}),
).toEqual({
type: 'share',
data: {
url: 'https://example.com',
title: 'Example',
content: 'desc',
image: 'https://example.com/a.png',
},
});
});
});
describe('segments.music', () => {
it('passes platform music id data through', () => {
expect(segments.music({ type: '163', id: '12345' })).toEqual({
type: 'music',
data: { type: '163', id: '12345' },
});
});
it('passes custom music data through', () => {
expect(
segments.music({
type: 'custom',
url: 'https://example.com/song',
audio: 'https://example.com/song.mp3',
title: 'Song',
image: 'https://example.com/cover.jpg',
content: 'Artist',
}),
).toEqual({
type: 'music',
data: {
type: 'custom',
url: 'https://example.com/song',
audio: 'https://example.com/song.mp3',
title: 'Song',
image: 'https://example.com/cover.jpg',
content: 'Artist',
},
});
});
});
describe('segments.location', () => {
it('passes numeric coordinates and labels through', () => {
expect(
segments.location({
lat: 39.9,
lon: 116.4,
title: 'Beijing',
content: 'Tiananmen',
}),
).toEqual({
type: 'location',
data: {
lat: 39.9,
lon: 116.4,
title: 'Beijing',
content: 'Tiananmen',
},
});
});
it('passes string coordinates through', () => {
expect(segments.location({ lat: '31.2', lon: '121.5' })).toEqual({
type: 'location',
data: { lat: '31.2', lon: '121.5' },
});
});
});
describe('segments.contact', () => {
it('builds a qq contact with a numeric id', () => {
expect(segments.contact('qq', 10001)).toEqual({
type: 'contact',
data: { type: 'qq', id: 10001 },
});
});
it('builds a group contact with a string id', () => {
expect(segments.contact('group', '123456')).toEqual({
type: 'contact',
data: { type: 'group', id: '123456' },
});
});
});
describe('segments.raw', () => {
it('builds an arbitrary typed segment', () => {
expect(segments.raw('dice', { result: 6 })).toEqual({
type: 'dice',
data: { result: 6 },
});
});
});