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,151 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { subscribeLogs, type LogEntry } from '@snowluma/common/logger';
|
||||
import type { SendPacketResult } from '@snowluma/common/packet-sender';
|
||||
|
||||
import { SetFriendRemark } from '../../../src/oidb-services/friend/set-friend-remark';
|
||||
import { env, m, s, v } from '../_pb-oracle';
|
||||
|
||||
function successBody(uid = 'resolved-uid', remark = 'best-friend', uin = 0): number[] {
|
||||
return m(1, [...m(1, [...(uin > 0 ? v(3, uin) : []), ...s(7, uid)]), ...s(2, remark)]);
|
||||
}
|
||||
|
||||
function makeDeps(responseBody = successBody()) {
|
||||
const r: SendPacketResult = {
|
||||
success: true,
|
||||
gotResponse: true,
|
||||
errorCode: 0,
|
||||
errorMessage: '',
|
||||
responseData: Buffer.from(env(0x912e, 0, responseBody, false), 'hex'),
|
||||
};
|
||||
return {
|
||||
sendRawPacket: vi.fn(async () => r),
|
||||
resolveUserUid: vi.fn(async () => 'resolved-uid'),
|
||||
identity: { updateFriendRemark: vi.fn() },
|
||||
};
|
||||
}
|
||||
|
||||
describe('SetFriendRemark namespace', () => {
|
||||
it('sends the current QQ 0x912E_0 wire shape for a non-empty remark', async () => {
|
||||
const deps = makeDeps();
|
||||
await SetFriendRemark.invoke(deps, { userId: 10001, remark: 'best-friend' });
|
||||
const [wireName, bytes] = deps.sendRawPacket.mock.calls[0]!;
|
||||
const body = [
|
||||
...m(1, [...m(1, s(7, 'resolved-uid')), ...s(2, 'best-friend')]),
|
||||
// QQ explicitly emits scene=0 for an ordinary friend.
|
||||
...v(2, 0),
|
||||
];
|
||||
expect({
|
||||
wireName,
|
||||
hex: Buffer.from(bytes).toString('hex'),
|
||||
}).toEqual({
|
||||
wireName: 'OidbSvcTrpcTcp.0x912e_0',
|
||||
hex: env(0x912e, 0, body, false),
|
||||
});
|
||||
});
|
||||
|
||||
it('resolves the target UID before encoding', async () => {
|
||||
const deps = makeDeps();
|
||||
await SetFriendRemark.invoke(deps, { userId: 10001, remark: 'best-friend' });
|
||||
expect(deps.resolveUserUid).toHaveBeenCalledWith(10001);
|
||||
});
|
||||
|
||||
it('updates identity only after the server confirms the requested value', async () => {
|
||||
const deps = makeDeps(successBody('resolved-uid', 'best-friend', 10001));
|
||||
|
||||
await SetFriendRemark.invoke(deps, { userId: 10001, remark: 'best-friend' });
|
||||
|
||||
expect(deps.identity.updateFriendRemark).toHaveBeenCalledWith(
|
||||
'resolved-uid',
|
||||
10001,
|
||||
'best-friend',
|
||||
);
|
||||
});
|
||||
|
||||
it('reports local synchronization failures without retrying a confirmed remote update', async () => {
|
||||
const deps = makeDeps(successBody('resolved-uid', 'best-friend', 10001));
|
||||
deps.identity.updateFriendRemark.mockImplementation(() => {
|
||||
throw new Error('identity cache unavailable');
|
||||
});
|
||||
const captured: LogEntry[] = [];
|
||||
const unsubscribe = subscribeLogs((entry) => {
|
||||
if (entry.scope === 'Bridge.Friend') {
|
||||
captured.push(entry);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await expect(
|
||||
SetFriendRemark.invoke(deps, {
|
||||
userId: 10001,
|
||||
remark: 'best-friend',
|
||||
}),
|
||||
).resolves.toBeUndefined();
|
||||
} finally {
|
||||
unsubscribe();
|
||||
}
|
||||
|
||||
expect(deps.sendRawPacket).toHaveBeenCalledTimes(1);
|
||||
expect(captured).toContainEqual(
|
||||
expect.objectContaining({
|
||||
level: 'error',
|
||||
message: expect.stringContaining('identity cache unavailable'),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects a business failure carried inside a successful OIDB response', async () => {
|
||||
const deps = makeDeps(m(3, [...v(2, 120), ...s(3, 'remark rejected')]));
|
||||
|
||||
await expect(
|
||||
SetFriendRemark.invoke(deps, {
|
||||
userId: 10001,
|
||||
remark: 'best-friend',
|
||||
}),
|
||||
).rejects.toThrow(/remark rejected/);
|
||||
expect(deps.identity.updateFriendRemark).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('rejects a response that contains neither a result nor a business error', async () => {
|
||||
const deps = makeDeps([]);
|
||||
|
||||
await expect(
|
||||
SetFriendRemark.invoke(deps, {
|
||||
userId: 10001,
|
||||
remark: 'best-friend',
|
||||
}),
|
||||
).rejects.toThrow(/missing result/);
|
||||
});
|
||||
|
||||
it('rejects a success result for a different target', async () => {
|
||||
const deps = makeDeps(successBody('another-uid'));
|
||||
|
||||
await expect(
|
||||
SetFriendRemark.invoke(deps, {
|
||||
userId: 10001,
|
||||
remark: 'best-friend',
|
||||
}),
|
||||
).rejects.toThrow(/target mismatch/);
|
||||
});
|
||||
|
||||
it('rejects a success result that does not confirm the requested remark', async () => {
|
||||
const deps = makeDeps(successBody('resolved-uid', 'old-remark'));
|
||||
|
||||
await expect(
|
||||
SetFriendRemark.invoke(deps, {
|
||||
userId: 10001,
|
||||
remark: 'best-friend',
|
||||
}),
|
||||
).rejects.toThrow(/does not match/);
|
||||
});
|
||||
|
||||
it('rejects a success result carrying a different numeric account', async () => {
|
||||
const deps = makeDeps(successBody('resolved-uid', 'best-friend', 20002));
|
||||
|
||||
await expect(
|
||||
SetFriendRemark.invoke(deps, {
|
||||
userId: 10001,
|
||||
remark: 'best-friend',
|
||||
}),
|
||||
).rejects.toThrow(/expected UIN 10001, got 20002/);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user