Files
SnowLuma/packages/protocol/tests/oidb-services/misc/click-inline-keyboard-button.test.ts
DrSmoothl c16064d7e3 refactor(packages): rename @snowluma/bridge → @snowluma/protocol
The package previously named "bridge" houses the protocol-byte layer
(OIDB cmds, msg-push decoders, highway uploaders, element-builder,
event bus). The name "bridge" suggested transport/lifecycle, which it
isn't — that role lives in core/hook and core/bridge/manager. Rename
to match what's actually inside.

This is a pure rename: zero logic changes, all 73 import sites updated
mechanically and TS-verified. core/onebot dependencies key updated.
ESLint override path adjusted for the moved oidb-services directory.

Rename detection threshold: git log --find-renames=20% recommended
when following history across this commit — content-replacement
(@snowluma/bridge → @snowluma/protocol) dropped per-file similarity
below git's default 50% on import-heavy files.
2026-05-23 23:31:03 +08:00

99 lines
3.9 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest';
import { protobuf_decode, protobuf_encode } from '@snowluma/proton';
import type { OidbBase } from '@snowluma/proto-defs/oidb';
import type { Oidb0x112eReq, Oidb0x112eResp } from '@snowluma/proto-defs/oidb-actions/base';
import type { SendPacketResult } from '@snowluma/common/packet-sender';
import { ClickInlineKeyboardButton } from '../../../src/oidb-services/misc/click-inline-keyboard-button';
function makeSender(resp?: Buffer) {
const r: SendPacketResult = {
success: true, gotResponse: true, errorCode: 0, errorMessage: '',
responseData: resp ?? Buffer.alloc(0),
};
return { sendRawPacket: vi.fn(async () => r) };
}
describe('ClickInlineKeyboardButton namespace', () => {
it('declares 0x112E_1', () => {
expect(ClickInlineKeyboardButton.command).toBe(0x112E);
expect(ClickInlineKeyboardButton.subCommand).toBe(1);
});
describe('serialize', () => {
it('widens numeric ids to BigInt for uint_64 fields', () => {
const out = ClickInlineKeyboardButton.serialize({} as any, {
groupId: 12345, botAppid: 67890, buttonId: 'btn', callbackData: 'data', msgSeq: 100,
});
expect(out.groupId).toBe(12345n);
expect(out.botAppid).toBe(67890n);
expect(out.msgSeq).toBe(100n);
});
it('always sends unknown7=0 / unknown9=1 magic values', () => {
const out = ClickInlineKeyboardButton.serialize({} as any, {
groupId: 1, botAppid: 1, buttonId: 'x', callbackData: 'y', msgSeq: 1,
});
expect(out.unknown7).toBe(0);
expect(out.unknown9).toBe(1);
});
it('coerces buttonId / callbackData to strings (defensive)', () => {
const out = ClickInlineKeyboardButton.serialize({} as any, {
groupId: 1, botAppid: 1, buttonId: 123 as any, callbackData: null as any, msgSeq: 1,
});
expect(out.buttonId).toBe('123');
expect(out.callbackData).toBe('');
});
});
describe('deserialize', () => {
it('shapes the response with status/promptType/promptIcon = 0', () => {
expect(ClickInlineKeyboardButton.deserialize({} as any, {
result: 1, errMsg: 'ok', promptText: 'hi',
} as Oidb0x112eResp)).toEqual({
result: 1, errMsg: 'ok', status: 0, promptText: 'hi', promptType: 0, promptIcon: 0,
});
});
it('defaults result/errMsg/promptText when omitted', () => {
expect(ClickInlineKeyboardButton.deserialize({} as any, {} as Oidb0x112eResp)).toEqual({
result: 0, errMsg: '', status: 0, promptText: '', promptType: 0, promptIcon: 0,
});
});
});
describe('invoke (e2e)', () => {
it('routes to OidbSvcTrpcTcp.0x112e_1', async () => {
const sender = makeSender();
await ClickInlineKeyboardButton.invoke(sender, {
groupId: 1, botAppid: 1, buttonId: 'x', callbackData: 'y', msgSeq: 1,
});
expect(sender.sendRawPacket.mock.calls[0]![0]).toBe('OidbSvcTrpcTcp.0x112e_1');
});
it('round-trips a real envelope', async () => {
const sender = makeSender(Buffer.from(protobuf_encode<OidbBase<Oidb0x112eResp>>({
body: { result: 7, errMsg: 'denied', promptText: 'try again' } as any,
})));
const out = await ClickInlineKeyboardButton.invoke(sender, {
groupId: 1, botAppid: 1, buttonId: 'x', callbackData: 'y', msgSeq: 1,
});
expect(out).toMatchObject({ result: 7, errMsg: 'denied', promptText: 'try again' });
});
it('encodes envelope body with all fields', async () => {
const sender = makeSender();
await ClickInlineKeyboardButton.invoke(sender, {
groupId: 12345, botAppid: 67890, buttonId: 'b', callbackData: 'c', msgSeq: 999,
});
const [, bytes] = sender.sendRawPacket.mock.calls[0]!;
const env = protobuf_decode<OidbBase<Oidb0x112eReq>>(bytes);
expect(env.body).toMatchObject({
botAppid: 67890n, msgSeq: 999n, buttonId: 'b', callbackData: 'c',
groupId: 12345n, unknown9: 1,
});
});
});
});