SnowLuma v2.4.2 source snapshot
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
Publish MCP to npm / Build, test, and publish MCP (push) Waiting to run
Publish SDK to npm / Build, test, and publish SDK (push) Waiting to run
Sync action catalog to docs / sync (push) Waiting to run
Publish UI to npm / Build and publish UI (push) Waiting to run
Build and Release / preflight (push) Waiting to run
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
Publish MCP to npm / Build, test, and publish MCP (push) Waiting to run
Publish SDK to npm / Build, test, and publish SDK (push) Waiting to run
Sync action catalog to docs / sync (push) Waiting to run
Publish UI to npm / Build and publish UI (push) Waiting to run
Build and Release / preflight (push) Waiting to run
This commit is contained in:
commit
fa9c73363d
1367 files changed
+355735
No files matched your search
@@ -0,0 +1,190 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
protobuf_encode,
|
||||
type bool,
|
||||
type pb,
|
||||
type pb_repeated,
|
||||
type uint_32,
|
||||
type uint_64,
|
||||
} from '@snowluma/proton';
|
||||
import type { MessageBody } from '@snowluma/proto-defs/message';
|
||||
|
||||
import { assertValidMessageElement } from '../../src/element-manifest';
|
||||
import { decodeRichBody } from '../../src/msg-push/rich-body-decoder';
|
||||
|
||||
interface MarkdownFixture {
|
||||
content?: pb<1, string>;
|
||||
processMsg?: pb<4, string>;
|
||||
summary?: pb<5, string>;
|
||||
extType?: pb<6, uint_32>;
|
||||
}
|
||||
|
||||
interface KeyboardPermissionFixture {
|
||||
type?: pb<1, uint_32>;
|
||||
roleIds?: pb_repeated<2, string>;
|
||||
userIds?: pb_repeated<3, string>;
|
||||
}
|
||||
|
||||
interface KeyboardActionFixture {
|
||||
type?: pb<1, uint_32>;
|
||||
permission?: pb<2, KeyboardPermissionFixture>;
|
||||
clickLimit?: pb<3, uint_32>;
|
||||
unsupportedTips?: pb<4, string>;
|
||||
data?: pb<5, string>;
|
||||
atBotShowChannelList?: pb<6, bool>;
|
||||
reply?: pb<7, bool>;
|
||||
enter?: pb<8, bool>;
|
||||
anchor?: pb<9, uint_32>;
|
||||
}
|
||||
|
||||
interface KeyboardRenderFixture {
|
||||
label?: pb<1, string>;
|
||||
visitedLabel?: pb<2, string>;
|
||||
style?: pb<3, uint_32>;
|
||||
}
|
||||
|
||||
interface KeyboardButtonFixture {
|
||||
id?: pb<1, string>;
|
||||
render?: pb<2, KeyboardRenderFixture>;
|
||||
action?: pb<3, KeyboardActionFixture>;
|
||||
}
|
||||
|
||||
interface KeyboardRowFixture {
|
||||
buttons?: pb_repeated<1, KeyboardButtonFixture>;
|
||||
}
|
||||
|
||||
interface KeyboardFixture {
|
||||
rows?: pb_repeated<1, KeyboardRowFixture>;
|
||||
botAppid?: pb<2, uint_64>;
|
||||
}
|
||||
|
||||
interface KeyboardExtraFixture {
|
||||
keyboard?: pb<1, KeyboardFixture>;
|
||||
}
|
||||
|
||||
function commonBody(serviceType: number, businessType: number, pbElem: Uint8Array): MessageBody {
|
||||
return {
|
||||
richText: {
|
||||
elems: [{ commonElem: { serviceType, businessType, pbElem } } as never],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe('decodeRichBody / bot markdown (#337)', () => {
|
||||
it('emits the original markdown and removes its plain-text compatibility sibling', () => {
|
||||
const pbElem = protobuf_encode<MarkdownFixture>({
|
||||
content: '# Weather\n**Sunny**',
|
||||
processMsg: 'Weather: Sunny',
|
||||
summary: 'Weather',
|
||||
extType: 3,
|
||||
});
|
||||
const body: MessageBody = {
|
||||
richText: {
|
||||
elems: [
|
||||
{ text: { str: 'Weather: Sunny' } } as never,
|
||||
{ commonElem: { serviceType: 45, businessType: 1, pbElem } } as never,
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
expect(decodeRichBody(body, true)).toEqual([
|
||||
{ type: 'markdown', text: '# Weather\n**Sunny**' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('decodes the current extended bot-markdown business type', () => {
|
||||
const pbElem = protobuf_encode<MarkdownFixture>({ content: '## Agent answer' });
|
||||
expect(decodeRichBody(commonBody(45, 4, pbElem), true)).toEqual([
|
||||
{ type: 'markdown', text: '## Agent answer' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps fallback text when the markdown protobuf is malformed', () => {
|
||||
const body: MessageBody = {
|
||||
richText: {
|
||||
elems: [
|
||||
{ text: { str: 'readable fallback' } } as never,
|
||||
{
|
||||
commonElem: {
|
||||
serviceType: 45,
|
||||
businessType: 1,
|
||||
pbElem: Uint8Array.of(0x0a, 0x05, 0x41),
|
||||
},
|
||||
} as never,
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
expect(decodeRichBody(body, true)).toEqual([{ type: 'text', text: 'readable fallback' }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('decodeRichBody / inline keyboard (#337)', () => {
|
||||
const pbElem = protobuf_encode<KeyboardExtraFixture>({
|
||||
keyboard: {
|
||||
botAppid: 9_007_199_254_740_993n,
|
||||
rows: [
|
||||
{
|
||||
buttons: [
|
||||
{
|
||||
id: 'btn-1',
|
||||
render: { label: 'Run', visitedLabel: 'Done', style: 1 },
|
||||
action: {
|
||||
type: 2,
|
||||
permission: { type: 2, roleIds: ['admin'], userIds: ['u_10001'] },
|
||||
clickLimit: 3,
|
||||
unsupportedTips: 'Admins only',
|
||||
data: 'callback-data',
|
||||
atBotShowChannelList: true,
|
||||
reply: false,
|
||||
enter: true,
|
||||
anchor: 9,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
it.each([46, 50, 51])(
|
||||
'decodes service %i business 1 without losing uint64 app id',
|
||||
(serviceType) => {
|
||||
const elements = decodeRichBody(commonBody(serviceType, 1, pbElem), true);
|
||||
expect(elements).toEqual([
|
||||
{
|
||||
type: 'inline_keyboard',
|
||||
botAppid: '9007199254740993',
|
||||
rows: [
|
||||
{
|
||||
buttons: [
|
||||
{
|
||||
id: 'btn-1',
|
||||
label: 'Run',
|
||||
visitedLabel: 'Done',
|
||||
style: 1,
|
||||
type: 2,
|
||||
clickLimit: 3,
|
||||
unsupportedTips: 'Admins only',
|
||||
data: 'callback-data',
|
||||
atBotShowChannelList: true,
|
||||
permissionType: 2,
|
||||
specifyRoleIds: ['admin'],
|
||||
specifyUserIds: ['u_10001'],
|
||||
isReply: false,
|
||||
enter: true,
|
||||
anchor: 9,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
expect(() => assertValidMessageElement(elements[0], 'D')).not.toThrow();
|
||||
},
|
||||
);
|
||||
|
||||
it('does not reinterpret an unsupported business type as a keyboard', () => {
|
||||
expect(decodeRichBody(commonBody(46, 2, pbElem), true)).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user