@zhin.js/core 1.0.46 → 1.0.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Notice 抽象层测试
3
+ */
4
+ import { Notice, NoticeBase, NoticeType } from '../src/notice.js';
5
+
6
+ describe('Notice', () => {
7
+ // ============================================================================
8
+ // Notice.from()
9
+ // ============================================================================
10
+ describe('Notice.from()', () => {
11
+ it('应合并原始数据与基础结构', () => {
12
+ const raw = { original_field: 'test', group_id: 12345 };
13
+ const base: NoticeBase = {
14
+ $id: 'n_001',
15
+ $adapter: 'onebot11' as any,
16
+ $bot: 'bot1',
17
+ $type: 'group_member_increase',
18
+ $channel: { id: '12345', type: 'group' },
19
+ $timestamp: 1000,
20
+ };
21
+ const notice = Notice.from(raw, base);
22
+
23
+ expect(notice.$id).toBe('n_001');
24
+ expect(notice.$adapter).toBe('onebot11');
25
+ expect(notice.$bot).toBe('bot1');
26
+ expect(notice.$type).toBe('group_member_increase');
27
+ expect(notice.$channel.id).toBe('12345');
28
+ expect(notice.$channel.type).toBe('group');
29
+ expect(notice.$timestamp).toBe(1000);
30
+ // 原始字段保留
31
+ expect(notice.original_field).toBe('test');
32
+ expect(notice.group_id).toBe(12345);
33
+ });
34
+
35
+ it('应保留可选字段 $operator 和 $target', () => {
36
+ const raw = {};
37
+ const base: NoticeBase = {
38
+ $id: 'n_002',
39
+ $adapter: 'icqq' as any,
40
+ $bot: 'bot2',
41
+ $type: 'group_member_decrease',
42
+ $subType: 'kick',
43
+ $channel: { id: '67890', type: 'group' },
44
+ $operator: { id: '111', name: '管理员' },
45
+ $target: { id: '222', name: '被踢者' },
46
+ $timestamp: 2000,
47
+ };
48
+ const notice = Notice.from(raw, base);
49
+
50
+ expect(notice.$subType).toBe('kick');
51
+ expect(notice.$operator).toEqual({ id: '111', name: '管理员' });
52
+ expect(notice.$target).toEqual({ id: '222', name: '被踢者' });
53
+ });
54
+
55
+ it('$operator 和 $target 应可以为 undefined', () => {
56
+ const notice = Notice.from({}, {
57
+ $id: 'n_003',
58
+ $adapter: 'onebot11' as any,
59
+ $bot: 'bot1',
60
+ $type: 'friend_add',
61
+ $channel: { id: '100', type: 'private' },
62
+ $timestamp: 3000,
63
+ });
64
+
65
+ expect(notice.$operator).toBeUndefined();
66
+ expect(notice.$target).toBeUndefined();
67
+ expect(notice.$subType).toBeUndefined();
68
+ });
69
+ });
70
+
71
+ // ============================================================================
72
+ // NoticeType
73
+ // ============================================================================
74
+ describe('NoticeType', () => {
75
+ it('应接受所有预定义类型', () => {
76
+ const types: NoticeType[] = [
77
+ 'group_member_increase',
78
+ 'group_member_decrease',
79
+ 'group_admin_change',
80
+ 'group_ban',
81
+ 'group_recall',
82
+ 'friend_recall',
83
+ 'friend_add',
84
+ 'group_poke',
85
+ 'friend_poke',
86
+ 'group_transfer',
87
+ ];
88
+ expect(types).toHaveLength(10);
89
+ });
90
+
91
+ it('应接受自定义扩展类型', () => {
92
+ const customType: NoticeType = 'custom_adapter_event';
93
+ expect(customType).toBe('custom_adapter_event');
94
+ });
95
+ });
96
+
97
+ // ============================================================================
98
+ // NoticeChannel
99
+ // ============================================================================
100
+ describe('NoticeChannel', () => {
101
+ it('应支持 group 类型', () => {
102
+ const notice = Notice.from({}, {
103
+ $id: '1',
104
+ $adapter: 'onebot11' as any,
105
+ $bot: 'b',
106
+ $type: 'group_member_increase',
107
+ $channel: { id: '123', type: 'group' },
108
+ $timestamp: 0,
109
+ });
110
+ expect(notice.$channel.type).toBe('group');
111
+ });
112
+
113
+ it('应支持 private 类型', () => {
114
+ const notice = Notice.from({}, {
115
+ $id: '2',
116
+ $adapter: 'onebot11' as any,
117
+ $bot: 'b',
118
+ $type: 'friend_add',
119
+ $channel: { id: '456', type: 'private' },
120
+ $timestamp: 0,
121
+ });
122
+ expect(notice.$channel.type).toBe('private');
123
+ });
124
+
125
+ it('应支持 channel 类型', () => {
126
+ const notice = Notice.from({}, {
127
+ $id: '3',
128
+ $adapter: 'kook' as any,
129
+ $bot: 'b',
130
+ $type: 'group_member_increase',
131
+ $channel: { id: '789', type: 'channel' },
132
+ $timestamp: 0,
133
+ });
134
+ expect(notice.$channel.type).toBe('channel');
135
+ });
136
+ });
137
+
138
+ // ============================================================================
139
+ // 典型场景
140
+ // ============================================================================
141
+ describe('典型场景', () => {
142
+ it('群成员入群通知', () => {
143
+ const raw = { group_id: 12345, user_id: 67890, operator_id: 11111 };
144
+ const notice = Notice.from(raw, {
145
+ $id: 'inc_001',
146
+ $adapter: 'onebot11' as any,
147
+ $bot: 'mybot',
148
+ $type: 'group_member_increase',
149
+ $subType: 'approve',
150
+ $channel: { id: '12345', type: 'group' },
151
+ $operator: { id: '11111', name: '管理员' },
152
+ $target: { id: '67890', name: '新成员' },
153
+ $timestamp: Date.now(),
154
+ });
155
+
156
+ expect(notice.$type).toBe('group_member_increase');
157
+ expect(notice.$subType).toBe('approve');
158
+ expect(notice.group_id).toBe(12345);
159
+ expect(notice.user_id).toBe(67890);
160
+ });
161
+
162
+ it('群消息撤回通知', () => {
163
+ const raw = { group_id: 100, user_id: 200, operator_id: 300, message_id: 'msg_42' };
164
+ const notice = Notice.from(raw, {
165
+ $id: 'recall_001',
166
+ $adapter: 'icqq' as any,
167
+ $bot: 'bot1',
168
+ $type: 'group_recall',
169
+ $subType: 'recall',
170
+ $channel: { id: '100', type: 'group' },
171
+ $operator: { id: '300', name: '撤回者' },
172
+ $target: { id: '200', name: '消息发送者' },
173
+ $timestamp: Date.now(),
174
+ });
175
+
176
+ expect(notice.$type).toBe('group_recall');
177
+ expect(notice.message_id).toBe('msg_42');
178
+ });
179
+
180
+ it('好友戳一戳通知', () => {
181
+ const raw = { user_id: 100, operator_id: 100, target_id: 200, action: '戳了戳' };
182
+ const notice = Notice.from(raw, {
183
+ $id: 'poke_001',
184
+ $adapter: 'icqq' as any,
185
+ $bot: 'bot1',
186
+ $type: 'friend_poke',
187
+ $subType: 'poke',
188
+ $channel: { id: '100', type: 'private' },
189
+ $operator: { id: '100', name: '操作者' },
190
+ $target: { id: '200', name: '被戳者' },
191
+ $timestamp: Date.now(),
192
+ });
193
+
194
+ expect(notice.$type).toBe('friend_poke');
195
+ expect(notice.action).toBe('戳了戳');
196
+ });
197
+ });
198
+ });
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Request 抽象层测试
3
+ */
4
+ import { Request, RequestBase, RequestType } from '../src/request.js';
5
+
6
+ describe('Request', () => {
7
+ // ============================================================================
8
+ // Request.from()
9
+ // ============================================================================
10
+ describe('Request.from()', () => {
11
+ it('应合并原始数据与基础结构', () => {
12
+ const raw = { flag: 'abc123', extra_data: 42 };
13
+ const base: RequestBase = {
14
+ $id: 'req_001',
15
+ $adapter: 'onebot11' as any,
16
+ $bot: 'bot1',
17
+ $type: 'friend_add',
18
+ $channel: { id: '100', type: 'private' },
19
+ $sender: { id: '200', name: '请求者' },
20
+ $comment: '请加我好友',
21
+ $timestamp: 1000,
22
+ $approve: async () => {},
23
+ $reject: async () => {},
24
+ };
25
+ const request = Request.from(raw, base);
26
+
27
+ expect(request.$id).toBe('req_001');
28
+ expect(request.$adapter).toBe('onebot11');
29
+ expect(request.$bot).toBe('bot1');
30
+ expect(request.$type).toBe('friend_add');
31
+ expect(request.$channel.type).toBe('private');
32
+ expect(request.$sender).toEqual({ id: '200', name: '请求者' });
33
+ expect(request.$comment).toBe('请加我好友');
34
+ expect(request.$timestamp).toBe(1000);
35
+ // 原始字段保留
36
+ expect(request.flag).toBe('abc123');
37
+ expect(request.extra_data).toBe(42);
38
+ });
39
+
40
+ it('$comment 和 $subType 应可以为 undefined', () => {
41
+ const request = Request.from({}, {
42
+ $id: 'req_002',
43
+ $adapter: 'icqq' as any,
44
+ $bot: 'bot1',
45
+ $type: 'group_add',
46
+ $channel: { id: '300', type: 'group' },
47
+ $sender: { id: '400', name: '申请者' },
48
+ $timestamp: 2000,
49
+ $approve: async () => {},
50
+ $reject: async () => {},
51
+ });
52
+
53
+ expect(request.$comment).toBeUndefined();
54
+ expect(request.$subType).toBeUndefined();
55
+ });
56
+ });
57
+
58
+ // ============================================================================
59
+ // $approve / $reject
60
+ // ============================================================================
61
+ describe('$approve() 和 $reject()', () => {
62
+ it('调用 $approve 应执行同意逻辑', async () => {
63
+ let approved = false;
64
+ let approveRemark: string | undefined;
65
+ const request = Request.from({}, {
66
+ $id: 'req_approve',
67
+ $adapter: 'onebot11' as any,
68
+ $bot: 'bot1',
69
+ $type: 'friend_add',
70
+ $channel: { id: '100', type: 'private' },
71
+ $sender: { id: '200', name: '用户' },
72
+ $timestamp: 0,
73
+ $approve: async (remark?: string) => {
74
+ approved = true;
75
+ approveRemark = remark;
76
+ },
77
+ $reject: async () => {},
78
+ });
79
+
80
+ await request.$approve('备注名');
81
+ expect(approved).toBe(true);
82
+ expect(approveRemark).toBe('备注名');
83
+ });
84
+
85
+ it('调用 $reject 应执行拒绝逻辑', async () => {
86
+ let rejected = false;
87
+ let rejectReason: string | undefined;
88
+ const request = Request.from({}, {
89
+ $id: 'req_reject',
90
+ $adapter: 'onebot11' as any,
91
+ $bot: 'bot1',
92
+ $type: 'group_invite',
93
+ $channel: { id: '300', type: 'group' },
94
+ $sender: { id: '400', name: '邀请者' },
95
+ $timestamp: 0,
96
+ $approve: async () => {},
97
+ $reject: async (reason?: string) => {
98
+ rejected = true;
99
+ rejectReason = reason;
100
+ },
101
+ });
102
+
103
+ await request.$reject('不接受邀请');
104
+ expect(rejected).toBe(true);
105
+ expect(rejectReason).toBe('不接受邀请');
106
+ });
107
+
108
+ it('$approve 无参数调用应不报错', async () => {
109
+ let called = false;
110
+ const request = Request.from({}, {
111
+ $id: 'req_noarg',
112
+ $adapter: 'onebot11' as any,
113
+ $bot: 'bot1',
114
+ $type: 'friend_add',
115
+ $channel: { id: '1', type: 'private' },
116
+ $sender: { id: '2', name: 'user' },
117
+ $timestamp: 0,
118
+ $approve: async () => { called = true; },
119
+ $reject: async () => {},
120
+ });
121
+
122
+ await request.$approve();
123
+ expect(called).toBe(true);
124
+ });
125
+ });
126
+
127
+ // ============================================================================
128
+ // RequestType
129
+ // ============================================================================
130
+ describe('RequestType', () => {
131
+ it('应接受所有预定义类型', () => {
132
+ const types: RequestType[] = ['friend_add', 'group_add', 'group_invite'];
133
+ expect(types).toHaveLength(3);
134
+ });
135
+
136
+ it('应接受自定义扩展类型', () => {
137
+ const customType: RequestType = 'custom_request_type';
138
+ expect(customType).toBe('custom_request_type');
139
+ });
140
+ });
141
+
142
+ // ============================================================================
143
+ // 典型场景
144
+ // ============================================================================
145
+ describe('典型场景', () => {
146
+ it('好友添加请求', async () => {
147
+ let approvedFlag: string | undefined;
148
+ const raw = { flag: 'friend_flag_001', user_id: 12345 };
149
+ const request = Request.from(raw, {
150
+ $id: 'friend_flag_001',
151
+ $adapter: 'onebot11' as any,
152
+ $bot: 'mybot',
153
+ $type: 'friend_add',
154
+ $subType: 'add',
155
+ $channel: { id: '12345', type: 'private' },
156
+ $sender: { id: '12345', name: '新朋友' },
157
+ $comment: '你好,加个好友吧',
158
+ $timestamp: Date.now(),
159
+ $approve: async (remark?: string) => {
160
+ approvedFlag = raw.flag;
161
+ },
162
+ $reject: async () => {},
163
+ });
164
+
165
+ expect(request.$type).toBe('friend_add');
166
+ expect(request.$comment).toBe('你好,加个好友吧');
167
+ expect(request.flag).toBe('friend_flag_001');
168
+ expect(request.user_id).toBe(12345);
169
+
170
+ await request.$approve();
171
+ expect(approvedFlag).toBe('friend_flag_001');
172
+ });
173
+
174
+ it('入群申请', async () => {
175
+ let rejected = false;
176
+ const raw = { flag: 'group_flag_001', user_id: 111, group_id: 222, comment: '想加群' };
177
+ const request = Request.from(raw, {
178
+ $id: 'group_flag_001',
179
+ $adapter: 'icqq' as any,
180
+ $bot: 'bot2',
181
+ $type: 'group_add',
182
+ $subType: 'add',
183
+ $channel: { id: '222', type: 'group' },
184
+ $sender: { id: '111', name: '申请者' },
185
+ $comment: '想加群',
186
+ $timestamp: Date.now(),
187
+ $approve: async () => {},
188
+ $reject: async (reason?: string) => { rejected = true; },
189
+ });
190
+
191
+ expect(request.$type).toBe('group_add');
192
+ expect(request.group_id).toBe(222);
193
+
194
+ await request.$reject('暂不接受');
195
+ expect(rejected).toBe(true);
196
+ });
197
+
198
+ it('群邀请', async () => {
199
+ let approved = false;
200
+ const raw = { flag: 'invite_001', user_id: 333, group_id: 444, group_name: '测试群' };
201
+ const request = Request.from(raw, {
202
+ $id: 'invite_001',
203
+ $adapter: 'onebot11' as any,
204
+ $bot: 'bot1',
205
+ $type: 'group_invite',
206
+ $subType: 'invite',
207
+ $channel: { id: '444', type: 'group' },
208
+ $sender: { id: '333', name: '邀请者' },
209
+ $timestamp: Date.now(),
210
+ $approve: async () => { approved = true; },
211
+ $reject: async () => {},
212
+ });
213
+
214
+ expect(request.$type).toBe('group_invite');
215
+ expect(request.group_name).toBe('测试群');
216
+
217
+ await request.$approve();
218
+ expect(approved).toBe(true);
219
+ });
220
+ });
221
+ });