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

This commit is contained in:
TanTan committed 2026-11-13 09:02:00 +08:00
commit fa9c73363d
1367 files changed
+355735

No files matched your search

@@ -0,0 +1,214 @@
import { afterEach, describe, expect, it, vi } from 'vitest';
import * as qzonePublic from '@snowluma/protocol/web/qzone-public';
import { QzoneApi } from '../../src/bridge/apis/qzone';
import { mockApiHub, mockBridge } from './_helpers';
const cookies = { p_skey: 'PSK' };
const feed = {
cell_common: { union_id: { feed_id: 'opaque-id' } },
cell_feed_transfer: { future: true },
};
const comment = { id: 'comment-id', user: { uid: 'commenter' }, unknown: [1, 2] };
const reply = { id: 'reply-id', user: { uid: 'recipient' } };
const content = [{ type: 0, content: 'text', future: { enabled: true } }];
const user = { uin: '10001', uid: 'self-uid', nick: 'self-nick' };
const result = { feeds: [], has_more: false, next_cursor: null, unknown: { preserved: true } };
function makeApi() {
const getCookies = vi.fn().mockResolvedValue(cookies);
const bridge = mockBridge({ apis: { ...mockApiHub(), web: { getCookies } } as never });
return { api: new QzoneApi(bridge as never), bridge, getCookies };
}
const cases = [
{
method: 'getQzoneHomeFeeds',
invoke: (api: QzoneApi) => api.getHomeFeeds(20002, 'cursor'),
args: [cookies, '10001', '20002', 'cursor'],
},
{
method: 'getQzonePublicCapabilities',
invoke: (api: QzoneApi) => api.getPublicCapabilities(),
args: [cookies, '10001'],
},
{
method: 'getQzonePublicFeeds',
invoke: (api: QzoneApi) => api.getPublicFeeds('cursor'),
args: [cookies, '10001', 'cursor'],
},
{
method: 'getQzonePublicFeedDetail',
invoke: (api: QzoneApi) => api.getPublicFeedDetail(feed),
args: [cookies, feed],
},
{
method: 'getQzonePublicComments',
invoke: (api: QzoneApi) => api.getPublicComments(feed, 'cursor'),
args: [cookies, feed, 'cursor'],
},
{
method: 'getQzonePublicReplies',
invoke: (api: QzoneApi) => api.getPublicReplies(feed, comment, 'cursor', 5),
args: [cookies, feed, comment, 'cursor', 5],
},
{
method: 'setQzonePublicUpvote',
invoke: (api: QzoneApi) => api.setPublicUpvote(feed, false),
args: [cookies, feed, false],
},
{
method: 'setQzonePublicLike',
invoke: (api: QzoneApi) => api.setPublicLike(feed, false),
args: [cookies, feed, false],
},
{
method: 'setQzonePublicCommentLike',
invoke: (api: QzoneApi) => api.setPublicCommentLike(feed, comment, false, reply),
args: [cookies, feed, comment, false, reply],
},
{
method: 'commentQzonePublicFeed',
invoke: (api: QzoneApi) => api.commentPublicFeed(feed, content),
args: [cookies, feed, user, content],
},
{
method: 'replyQzonePublicFeed',
invoke: (api: QzoneApi) => api.replyPublicFeed(feed, comment, content, reply),
args: [cookies, feed, user, comment, content, reply],
},
{
method: 'deleteQzonePublicComment',
invoke: (api: QzoneApi) => api.deletePublicComment(feed, comment),
args: [cookies, feed, comment],
},
{
method: 'deleteQzonePublicReply',
invoke: (api: QzoneApi) => api.deletePublicReply(feed, comment, reply),
args: [cookies, feed, comment, reply],
},
{
method: 'setQzonePublicFollow',
invoke: (api: QzoneApi) => api.setPublicFollow(feed, false),
args: [cookies, feed, false],
},
{
method: 'forwardQzonePublicFeed',
invoke: (api: QzoneApi) => api.forwardPublicFeed(feed, 'reason'),
args: [cookies, feed, 'reason'],
},
] as const;
describe('apis/qzone public', () => {
afterEach(() => vi.restoreAllMocks());
it('reads a post by tid using current-account credentials', async () => {
const { api, getCookies } = makeApi();
const tid = '1127000000f1536501000000';
const detail = { feed, attach_info: 'comments-next' };
const request = vi.spyOn(qzonePublic, 'getQzoneFeedDetail').mockResolvedValue(detail);
expect(await api.getFeedDetail(tid)).toBe(detail);
expect(getCookies).toHaveBeenCalledExactlyOnceWith('qzone.qq.com');
expect(request).toHaveBeenCalledExactlyOnceWith(cookies, tid);
});
it('propagates feed detail and cookie failures without replay', async () => {
const { api, getCookies } = makeApi();
const request = vi
.spyOn(qzonePublic, 'getQzoneFeedDetail')
.mockRejectedValue(new Error('denied'));
await expect(api.getFeedDetail('1127000000f1536501000000')).rejects.toThrow('denied');
getCookies.mockRejectedValueOnce(new Error('cookie failure'));
await expect(api.getFeedDetail('1127000000f1536501000000')).rejects.toThrow(
'cookie failure',
);
expect(request).toHaveBeenCalledOnce();
});
it('generates a share card with the account cookies and preserves its notice', async () => {
const { api, getCookies } = makeApi();
const card = { ark: '{}', requires_confirmation: true, notice: '所有人可见' };
const request = vi.spyOn(qzonePublic, 'getQzoneShareArk').mockResolvedValue(card);
expect(await api.getShareArk(feed)).toBe(card);
expect(getCookies).toHaveBeenCalledWith('qzone.qq.com');
expect(request).toHaveBeenCalledExactlyOnceWith(cookies, feed);
request.mockRejectedValueOnce(new Error('share denied'));
await expect(api.getShareArk(feed)).rejects.toThrow('share denied');
});
it.each(cases)(
'$method uses current-account cookies and preserves upstream objects',
async ({ method, invoke, args }) => {
const { api, getCookies } = makeApi();
const request = vi.spyOn(qzonePublic, method).mockResolvedValue(result);
expect(await invoke(api)).toBe(result);
expect(getCookies).toHaveBeenCalledWith('qzone.qq.com');
expect(request).toHaveBeenCalledExactlyOnceWith(...args);
},
);
it.each(cases)(
'$method propagates cookie and upstream failures without replay',
async ({ method, invoke }) => {
const { api, getCookies } = makeApi();
const request = vi
.spyOn(qzonePublic, method)
.mockRejectedValue(new Error('upstream denied'));
await expect(invoke(api)).rejects.toThrow('upstream denied');
getCookies.mockRejectedValueOnce(new Error('cookie failure'));
await expect(invoke(api)).rejects.toThrow('cookie failure');
expect(request).toHaveBeenCalledTimes(1);
},
);
it('keeps documented defaults and omits an optional reply target', async () => {
const { api } = makeApi();
const feeds = vi.spyOn(qzonePublic, 'getQzonePublicFeeds').mockResolvedValue(result);
const replies = vi.spyOn(qzonePublic, 'getQzonePublicReplies').mockResolvedValue(result);
const upvote = vi.spyOn(qzonePublic, 'setQzonePublicUpvote').mockResolvedValue(result);
const like = vi.spyOn(qzonePublic, 'setQzonePublicLike').mockResolvedValue(result);
const commentLike = vi
.spyOn(qzonePublic, 'setQzonePublicCommentLike')
.mockResolvedValue(result);
const follow = vi.spyOn(qzonePublic, 'setQzonePublicFollow').mockResolvedValue(result);
const forward = vi.spyOn(qzonePublic, 'forwardQzonePublicFeed').mockResolvedValue(result);
const replyRequest = vi
.spyOn(qzonePublic, 'replyQzonePublicFeed')
.mockResolvedValue(result);
await api.getPublicFeeds();
await api.getPublicReplies(feed, comment);
await api.setPublicUpvote(feed);
await api.setPublicLike(feed);
await api.setPublicCommentLike(feed, comment);
await api.setPublicFollow(feed);
await api.forwardPublicFeed(feed);
await api.replyPublicFeed(feed, comment, 'text');
expect(feeds).toHaveBeenCalledWith(cookies, '10001', undefined);
expect(replies).toHaveBeenCalledWith(cookies, feed, comment, '', 20);
expect(upvote).toHaveBeenCalledWith(cookies, feed, true);
expect(like).toHaveBeenCalledWith(cookies, feed, true);
expect(commentLike).toHaveBeenCalledWith(cookies, feed, comment, true, undefined);
expect(follow).toHaveBeenCalledWith(cookies, feed, true);
expect(forward).toHaveBeenCalledWith(cookies, feed, '');
expect(replyRequest).toHaveBeenCalledWith(cookies, feed, user, comment, 'text', undefined);
});
it('binds comment authors to the current account even when its uid is unavailable', async () => {
const { api, bridge } = makeApi();
Object.assign(bridge.identity, { selfUid: undefined });
const request = vi.spyOn(qzonePublic, 'commentQzonePublicFeed').mockResolvedValue(result);
await api.commentPublicFeed(feed, 'text');
expect(request).toHaveBeenCalledWith(
cookies,
feed,
{ uin: '10001', uid: '', nick: 'self-nick' },
'text',
);
});
});