Files
SnowLuma/packages/core/tests/actions/interaction.test.ts
T
TanTan fa9c73363d
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
SnowLuma v2.4.2 source snapshot
2026-11-13 09:02:00 +08:00

90 lines
3.9 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { protobuf_encode } from '@snowluma/proton';
import type { OidbBase } from '@snowluma/proto-defs/oidb';
import type { Oidb0x9083Resp } from '@snowluma/proto-defs/oidb-actions/base';
// Post-namespace-migration: InteractionApi is a thin facade and
// production code routes through the namespace path (sender →
// sendRawPacket). Tests now assert against the bridge mock's
// sendRawPacket directly — no need for module-level mocks on the
// bridge-oidb internals.
import { InteractionApi } from '../../src/bridge/apis/interaction';
import { mockBridge } from './_helpers';
describe('apis/interaction', () => {
it('sendPoke group: groupUin set, friendUin=0', async () => {
const bridge = mockBridge();
await new InteractionApi(bridge as any).sendPoke(true, 12345, 67890);
expect(bridge.sendRawPacket.mock.calls[0]![0]).toBe('OidbSvcTrpcTcp.0xed3_1');
});
it('sendPoke friend: friendUin set, groupUin=0, targetUin defaults to peer', async () => {
const bridge = mockBridge();
await new InteractionApi(bridge as any).sendPoke(false, 67890);
expect(bridge.sendRawPacket.mock.calls[0]![0]).toBe('OidbSvcTrpcTcp.0xed3_1');
});
it('sendLike forwards target + count to 0x7e5_104', async () => {
const bridge = mockBridge();
await new InteractionApi(bridge as any).sendLike(10001, 3);
expect(bridge.sendRawPacket.mock.calls[0]![0]).toBe('OidbSvcTrpcTcp.0x7e5_104');
});
it('setReaction picks _1 for set and _2 for unset', async () => {
// setReaction now forwards through the SetReaction namespace, which
// calls bridge.sendRawPacket directly.
const bridge = mockBridge();
const api = new InteractionApi(bridge as any);
await api.setReaction(12345, 99, '128516', true);
await api.setReaction(12345, 99, '128516', false);
const cmds = bridge.sendRawPacket.mock.calls.map((c: any[]) => c[0]);
expect(cmds).toEqual(['OidbSvcTrpcTcp.0x9082_1', 'OidbSvcTrpcTcp.0x9082_2']);
});
it('setEssence picks _1 for enable and _2 for disable', async () => {
const bridge = mockBridge();
const api = new InteractionApi(bridge as any);
await api.setEssence(12345, 99, 0, true);
await api.setEssence(12345, 99, 0, false);
const cmds = bridge.sendRawPacket.mock.calls.map((c: any[]) => c[0]);
expect(cmds).toEqual(['OidbSvcTrpcTcp.0xeac_1', 'OidbSvcTrpcTcp.0xeac_2']);
});
it('getEmojiLikes decodes user list, returns the cookie, and reports isLast', async () => {
const bridge = mockBridge();
bridge.sendRawPacket.mockResolvedValueOnce({
success: true,
gotResponse: true,
errorCode: 0,
errorMessage: '',
responseData: Buffer.from(
protobuf_encode<OidbBase<Oidb0x9083Resp>>({
body: {
users: [{ uin: 10001n }, { uin: 20002n }],
cookie: 'next-page',
isLast: false,
},
}),
),
});
const out = await new InteractionApi(bridge as any).getEmojiLikes(12345, 99, '128516');
expect(out.users).toEqual([{ uin: 10001 }, { uin: 20002 }]);
expect(out.cookie).toBe('next-page');
expect(out.isLast).toBe(false);
});
it('getEmojiLikes reports isLast=true when no cookie comes back', async () => {
const bridge = mockBridge();
bridge.sendRawPacket.mockResolvedValueOnce({
success: true,
gotResponse: true,
errorCode: 0,
errorMessage: '',
responseData: Buffer.from(protobuf_encode<OidbBase<Oidb0x9083Resp>>({ body: {} })),
});
const out = await new InteractionApi(bridge as any).getEmojiLikes(12345, 99, '128516');
expect(out.users).toEqual([]);
expect(out.isLast).toBe(true);
});
});