chz-telegram-bot 0.7.13 → 0.7.15
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.
- package/dist/dtos/propertyProviderSets.d.ts +0 -1
- package/dist/dtos/propertyProviderSets.d.ts.map +1 -1
- package/dist/entities/actions/commandAction.d.ts +1 -1
- package/dist/entities/actions/commandAction.d.ts.map +1 -1
- package/dist/entities/actions/commandAction.js +2 -2
- package/dist/helpers/builders/commandActionBuilder.d.ts.map +1 -1
- package/dist/helpers/builders/commandActionBuilder.js +2 -3
- package/package.json +4 -1
- package/eslint.config.ts +0 -62
- package/src/builtin/helpAction.ts +0 -17
- package/src/dtos/chatHistoryMessage.ts +0 -22
- package/src/dtos/chatInfo.ts +0 -12
- package/src/dtos/commandTriggerCheckResult.ts +0 -40
- package/src/dtos/cooldownInfo.ts +0 -10
- package/src/dtos/incomingMessage.ts +0 -71
- package/src/dtos/incomingQuery.ts +0 -14
- package/src/dtos/messageInfo.ts +0 -15
- package/src/dtos/propertyProviderSets.ts +0 -21
- package/src/dtos/replyInfo.ts +0 -9
- package/src/dtos/responses/delay.ts +0 -28
- package/src/dtos/responses/imageMessage.ts +0 -41
- package/src/dtos/responses/inlineQueryResponse.ts +0 -26
- package/src/dtos/responses/reaction.ts +0 -30
- package/src/dtos/responses/textMessage.ts +0 -44
- package/src/dtos/responses/unpin.ts +0 -27
- package/src/dtos/responses/videoMessage.ts +0 -41
- package/src/dtos/userInfo.ts +0 -8
- package/src/entities/actions/commandAction.ts +0 -275
- package/src/entities/actions/inlineQueryAction.ts +0 -83
- package/src/entities/actions/replyCaptureAction.ts +0 -110
- package/src/entities/actions/scheduledAction.ts +0 -182
- package/src/entities/botInstance.ts +0 -92
- package/src/entities/cachedStateFactory.ts +0 -14
- package/src/entities/context/baseContext.ts +0 -111
- package/src/entities/context/chatContext.ts +0 -135
- package/src/entities/context/inlineQueryContext.ts +0 -63
- package/src/entities/context/messageContext.ts +0 -250
- package/src/entities/context/replyContext.ts +0 -260
- package/src/entities/states/actionStateBase.ts +0 -6
- package/src/entities/taskRecord.ts +0 -11
- package/src/helpers/builders/commandActionBuilder.ts +0 -214
- package/src/helpers/builders/inlineQueryActionBuilder.ts +0 -71
- package/src/helpers/builders/scheduledActionBuilder.ts +0 -143
- package/src/helpers/mapUtils.ts +0 -28
- package/src/helpers/noop.ts +0 -20
- package/src/helpers/objectFromEntries.ts +0 -7
- package/src/helpers/timeConvertions.ts +0 -13
- package/src/helpers/toArray.ts +0 -3
- package/src/helpers/traceFactory.ts +0 -11
- package/src/index.ts +0 -33
- package/src/main.ts +0 -76
- package/src/services/actionProcessingService.ts +0 -125
- package/src/services/actionProcessors/baseProcessor.ts +0 -67
- package/src/services/actionProcessors/commandActionProcessor.ts +0 -231
- package/src/services/actionProcessors/inlineQueryActionProcessor.ts +0 -165
- package/src/services/actionProcessors/scheduledActionProcessor.ts +0 -136
- package/src/services/jsonFileStorage.ts +0 -181
- package/src/services/nodeTimeoutScheduler.ts +0 -79
- package/src/services/responseProcessingQueue.ts +0 -57
- package/src/services/telegramApi.ts +0 -278
- package/src/types/action.ts +0 -15
- package/src/types/actionState.ts +0 -4
- package/src/types/cachedValueAccessor.ts +0 -1
- package/src/types/capture.ts +0 -33
- package/src/types/commandCondition.ts +0 -9
- package/src/types/commandTrigger.ts +0 -1
- package/src/types/events.ts +0 -286
- package/src/types/externalAliases.ts +0 -18
- package/src/types/handlers.ts +0 -26
- package/src/types/inputFile.ts +0 -4
- package/src/types/messageSendingOptions.ts +0 -10
- package/src/types/messageTypes.ts +0 -21
- package/src/types/propertyProvider.ts +0 -14
- package/src/types/response.ts +0 -51
- package/src/types/scheduler.ts +0 -20
- package/src/types/storage.ts +0 -23
- package/src/types/timeValues.ts +0 -33
- package/src/types/trace.ts +0 -5
- package/tests/dtos/commandTriggerCheckResult.test.ts +0 -301
- package/tests/entities/actions/inlineQueryAction.test.ts +0 -359
- package/tests/entities/actions/replyCaptureAction.test.ts +0 -501
- package/tests/entities/cachedStateFactory.test.ts +0 -98
- package/tests/entities/context/chatContext.test.ts +0 -606
- package/tests/entities/context/messageContext.test.ts +0 -370
- package/tests/entities/states/actionStateBase.test.ts +0 -138
- package/tests/entities/taskRecord.test.ts +0 -195
- package/tests/helpers/mapUtils.test.ts +0 -163
- package/tests/helpers/timeConvertions.test.ts +0 -129
- package/tests/services/actionProcessors/baseActionProcessor.test.ts +0 -359
- package/tests/services/actionProcessors/commandActionProcessor.test.ts +0 -268
- package/tests/services/actionProcessors/inlineQueryActionProcessor.test.ts +0 -616
- package/tests/services/actionProcessors/processorTestHelpers.ts +0 -147
- package/tests/services/actionProcessors/scheduledActionProcessor.test.ts +0 -153
- package/tests/services/jsonFileStorage.test.ts +0 -927
- package/tests/services/nodeTimeoutScheduler.test.ts +0 -421
- package/tests/services/responseProcessingQueue.test.ts +0 -388
- package/tsconfig.build.json +0 -8
- package/tsconfig.json +0 -118
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from 'bun:test';
|
|
2
|
-
import { CommandTriggerCheckResult } from '../../src/dtos/commandTriggerCheckResult';
|
|
3
|
-
|
|
4
|
-
describe('CommandTriggerCheckResult', () => {
|
|
5
|
-
describe('static factory methods', () => {
|
|
6
|
-
describe('Trigger', () => {
|
|
7
|
-
test('should create result with shouldExecute true', () => {
|
|
8
|
-
const result = CommandTriggerCheckResult.Trigger();
|
|
9
|
-
|
|
10
|
-
expect(result.shouldExecute).toBe(true);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('should create result with empty matchResults', () => {
|
|
14
|
-
const result = CommandTriggerCheckResult.Trigger();
|
|
15
|
-
|
|
16
|
-
expect(result.matchResults).toEqual([]);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test('should create result with skipCooldown false', () => {
|
|
20
|
-
const result = CommandTriggerCheckResult.Trigger();
|
|
21
|
-
|
|
22
|
-
expect(result.skipCooldown).toBe(false);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test('should create result with no reason', () => {
|
|
26
|
-
const result = CommandTriggerCheckResult.Trigger();
|
|
27
|
-
|
|
28
|
-
expect(result.reason).toBeUndefined();
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('DoNotTrigger', () => {
|
|
33
|
-
test('should create result with shouldExecute false', () => {
|
|
34
|
-
const result = CommandTriggerCheckResult.DoNotTrigger(
|
|
35
|
-
'TriggerNotSatisfied'
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
expect(result.shouldExecute).toBe(false);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('should create result with skipCooldown false', () => {
|
|
42
|
-
const result = CommandTriggerCheckResult.DoNotTrigger(
|
|
43
|
-
'CustomConditionNotMet'
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
expect(result.skipCooldown).toBe(false);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test('should store the reason', () => {
|
|
50
|
-
const result =
|
|
51
|
-
CommandTriggerCheckResult.DoNotTrigger('UserForbidden');
|
|
52
|
-
|
|
53
|
-
expect(result.reason).toBe('UserForbidden');
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test('should create result with empty matchResults', () => {
|
|
57
|
-
const result = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
58
|
-
|
|
59
|
-
expect(result.matchResults).toEqual([]);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('DontTriggerAndSkipCooldown', () => {
|
|
64
|
-
test('should create result with shouldExecute false', () => {
|
|
65
|
-
const result =
|
|
66
|
-
CommandTriggerCheckResult.DontTriggerAndSkipCooldown(
|
|
67
|
-
'ActionDisabled'
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
expect(result.shouldExecute).toBe(false);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test('should create result with skipCooldown true', () => {
|
|
74
|
-
const result =
|
|
75
|
-
CommandTriggerCheckResult.DontTriggerAndSkipCooldown(
|
|
76
|
-
'ActionDisabled'
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
expect(result.skipCooldown).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test('should store the reason', () => {
|
|
83
|
-
const result =
|
|
84
|
-
CommandTriggerCheckResult.DontTriggerAndSkipCooldown(
|
|
85
|
-
'ChatForbidden'
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
expect(result.reason).toBe('ChatForbidden');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test('should create result with empty matchResults', () => {
|
|
92
|
-
const result =
|
|
93
|
-
CommandTriggerCheckResult.DontTriggerAndSkipCooldown(
|
|
94
|
-
'OnCooldown'
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
expect(result.matchResults).toEqual([]);
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe('constructor', () => {
|
|
103
|
-
test('should set all properties correctly', () => {
|
|
104
|
-
const matchResults = [['test'] as unknown as RegExpExecArray];
|
|
105
|
-
const result = new CommandTriggerCheckResult(
|
|
106
|
-
true,
|
|
107
|
-
matchResults,
|
|
108
|
-
false,
|
|
109
|
-
'Other'
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
expect(result.shouldExecute).toBe(true);
|
|
113
|
-
expect(result.matchResults).toBe(matchResults);
|
|
114
|
-
expect(result.skipCooldown).toBe(false);
|
|
115
|
-
expect(result.reason).toBe('Other');
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test('should allow undefined reason', () => {
|
|
119
|
-
const result = new CommandTriggerCheckResult(true, [], false);
|
|
120
|
-
|
|
121
|
-
expect(result.reason).toBeUndefined();
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
describe('mergeWith', () => {
|
|
126
|
-
test('should merge shouldExecute with OR logic - both false', () => {
|
|
127
|
-
const result1 = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
128
|
-
const result2 = CommandTriggerCheckResult.DoNotTrigger(
|
|
129
|
-
'TriggerNotSatisfied'
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
const merged = result1.mergeWith(result2);
|
|
133
|
-
|
|
134
|
-
expect(merged.shouldExecute).toBe(false);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
test('should merge shouldExecute with OR logic - first true', () => {
|
|
138
|
-
const result1 = CommandTriggerCheckResult.Trigger();
|
|
139
|
-
const result2 = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
140
|
-
|
|
141
|
-
const merged = result1.mergeWith(result2);
|
|
142
|
-
|
|
143
|
-
expect(merged.shouldExecute).toBe(true);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test('should merge shouldExecute with OR logic - second true', () => {
|
|
147
|
-
const result1 = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
148
|
-
const result2 = CommandTriggerCheckResult.Trigger();
|
|
149
|
-
|
|
150
|
-
const merged = result1.mergeWith(result2);
|
|
151
|
-
|
|
152
|
-
expect(merged.shouldExecute).toBe(true);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
test('should merge shouldExecute with OR logic - both true', () => {
|
|
156
|
-
const result1 = CommandTriggerCheckResult.Trigger();
|
|
157
|
-
const result2 = CommandTriggerCheckResult.Trigger();
|
|
158
|
-
|
|
159
|
-
const merged = result1.mergeWith(result2);
|
|
160
|
-
|
|
161
|
-
expect(merged.shouldExecute).toBe(true);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
test('should concatenate matchResults', () => {
|
|
165
|
-
const match1 = ['match1'] as unknown as RegExpExecArray;
|
|
166
|
-
const match2 = ['match2'] as unknown as RegExpExecArray;
|
|
167
|
-
const result1 = new CommandTriggerCheckResult(
|
|
168
|
-
true,
|
|
169
|
-
[match1],
|
|
170
|
-
false
|
|
171
|
-
);
|
|
172
|
-
const result2 = new CommandTriggerCheckResult(
|
|
173
|
-
false,
|
|
174
|
-
[match2],
|
|
175
|
-
false
|
|
176
|
-
);
|
|
177
|
-
|
|
178
|
-
const merged = result1.mergeWith(result2);
|
|
179
|
-
|
|
180
|
-
expect(merged.matchResults).toEqual([match1, match2]);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
test('should merge skipCooldown with OR logic - both false', () => {
|
|
184
|
-
const result1 = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
185
|
-
const result2 = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
186
|
-
|
|
187
|
-
const merged = result1.mergeWith(result2);
|
|
188
|
-
|
|
189
|
-
expect(merged.skipCooldown).toBe(false);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
test('should merge skipCooldown with OR logic - first true', () => {
|
|
193
|
-
const result1 =
|
|
194
|
-
CommandTriggerCheckResult.DontTriggerAndSkipCooldown(
|
|
195
|
-
'ActionDisabled'
|
|
196
|
-
);
|
|
197
|
-
const result2 = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
198
|
-
|
|
199
|
-
const merged = result1.mergeWith(result2);
|
|
200
|
-
|
|
201
|
-
expect(merged.skipCooldown).toBe(true);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
test('should merge skipCooldown with OR logic - second true', () => {
|
|
205
|
-
const result1 = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
206
|
-
const result2 =
|
|
207
|
-
CommandTriggerCheckResult.DontTriggerAndSkipCooldown(
|
|
208
|
-
'ActionDisabled'
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
const merged = result1.mergeWith(result2);
|
|
212
|
-
|
|
213
|
-
expect(merged.skipCooldown).toBe(true);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
test('should take reason from other result', () => {
|
|
217
|
-
const result1 =
|
|
218
|
-
CommandTriggerCheckResult.DoNotTrigger('UserForbidden');
|
|
219
|
-
const result2 =
|
|
220
|
-
CommandTriggerCheckResult.DoNotTrigger('ChatForbidden');
|
|
221
|
-
|
|
222
|
-
const merged = result1.mergeWith(result2);
|
|
223
|
-
|
|
224
|
-
expect(merged.reason).toBe('ChatForbidden');
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
test('should be chainable', () => {
|
|
228
|
-
const result1 = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
229
|
-
const result2 = CommandTriggerCheckResult.DoNotTrigger('Other');
|
|
230
|
-
const result3 = CommandTriggerCheckResult.Trigger();
|
|
231
|
-
|
|
232
|
-
const merged = result1.mergeWith(result2).mergeWith(result3);
|
|
233
|
-
|
|
234
|
-
expect(merged.shouldExecute).toBe(true);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
test('should use reduce pattern correctly', () => {
|
|
238
|
-
const results = [
|
|
239
|
-
CommandTriggerCheckResult.DoNotTrigger('Other'),
|
|
240
|
-
CommandTriggerCheckResult.DoNotTrigger('TriggerNotSatisfied'),
|
|
241
|
-
CommandTriggerCheckResult.Trigger()
|
|
242
|
-
];
|
|
243
|
-
|
|
244
|
-
const final = results.reduce(
|
|
245
|
-
(acc, curr) => acc.mergeWith(curr),
|
|
246
|
-
CommandTriggerCheckResult.DoNotTrigger('Other')
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
expect(final.shouldExecute).toBe(true);
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
describe('SkipTriggerReasons', () => {
|
|
254
|
-
test('should accept UserIdMissing reason', () => {
|
|
255
|
-
const result =
|
|
256
|
-
CommandTriggerCheckResult.DoNotTrigger('UserIdMissing');
|
|
257
|
-
expect(result.reason).toBe('UserIdMissing');
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
test('should accept UserForbidden reason', () => {
|
|
261
|
-
const result =
|
|
262
|
-
CommandTriggerCheckResult.DoNotTrigger('UserForbidden');
|
|
263
|
-
expect(result.reason).toBe('UserForbidden');
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
test('should accept OnCooldown reason', () => {
|
|
267
|
-
const result = CommandTriggerCheckResult.DoNotTrigger('OnCooldown');
|
|
268
|
-
expect(result.reason).toBe('OnCooldown');
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
test('should accept CustomConditionNotMet reason', () => {
|
|
272
|
-
const result = CommandTriggerCheckResult.DoNotTrigger(
|
|
273
|
-
'CustomConditionNotMet'
|
|
274
|
-
);
|
|
275
|
-
expect(result.reason).toBe('CustomConditionNotMet');
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
test('should accept TriggerNotSatisfied reason', () => {
|
|
279
|
-
const result = CommandTriggerCheckResult.DoNotTrigger(
|
|
280
|
-
'TriggerNotSatisfied'
|
|
281
|
-
);
|
|
282
|
-
expect(result.reason).toBe('TriggerNotSatisfied');
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
test('should accept ActionDisabled reason', () => {
|
|
286
|
-
const result =
|
|
287
|
-
CommandTriggerCheckResult.DontTriggerAndSkipCooldown(
|
|
288
|
-
'ActionDisabled'
|
|
289
|
-
);
|
|
290
|
-
expect(result.reason).toBe('ActionDisabled');
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
test('should accept ChatForbidden reason', () => {
|
|
294
|
-
const result =
|
|
295
|
-
CommandTriggerCheckResult.DontTriggerAndSkipCooldown(
|
|
296
|
-
'ChatForbidden'
|
|
297
|
-
);
|
|
298
|
-
expect(result.reason).toBe('ChatForbidden');
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
});
|
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, mock } from 'bun:test';
|
|
2
|
-
import { InlineQueryAction } from '../../../src/entities/actions/inlineQueryAction';
|
|
3
|
-
import {
|
|
4
|
-
InlineQueryContextInternal,
|
|
5
|
-
InlineQueryContext
|
|
6
|
-
} from '../../../src/entities/context/inlineQueryContext';
|
|
7
|
-
import { ActionKey } from '../../../src/types/action';
|
|
8
|
-
import { TypedEventEmitter, BotEventType } from '../../../src/types/events';
|
|
9
|
-
import { Noop } from '../../../src/helpers/noop';
|
|
10
|
-
import {
|
|
11
|
-
createMockStorage,
|
|
12
|
-
createMockScheduler
|
|
13
|
-
} from '../../services/actionProcessors/processorTestHelpers';
|
|
14
|
-
import { IncomingInlineQuery } from '../../../src/dtos/incomingQuery';
|
|
15
|
-
import { ChatInfo } from '../../../src/dtos/chatInfo';
|
|
16
|
-
import { TraceId } from '../../../src/types/trace';
|
|
17
|
-
|
|
18
|
-
function createMockInlineContext(
|
|
19
|
-
queryText: string,
|
|
20
|
-
_isActive: boolean = true
|
|
21
|
-
): InlineQueryContextInternal {
|
|
22
|
-
const storage = createMockStorage();
|
|
23
|
-
const scheduler = createMockScheduler();
|
|
24
|
-
const eventEmitter = new TypedEventEmitter();
|
|
25
|
-
const action = new InlineQueryAction(
|
|
26
|
-
mock(() => Promise.resolve()),
|
|
27
|
-
'test.action',
|
|
28
|
-
() => true,
|
|
29
|
-
/test/
|
|
30
|
-
);
|
|
31
|
-
const query = new IncomingInlineQuery(
|
|
32
|
-
'query-123',
|
|
33
|
-
queryText,
|
|
34
|
-
123,
|
|
35
|
-
'test-trace' as TraceId
|
|
36
|
-
);
|
|
37
|
-
const chatInfo = new ChatInfo(12345, 'Test Chat', []);
|
|
38
|
-
|
|
39
|
-
const ctx = new InlineQueryContextInternal(
|
|
40
|
-
storage,
|
|
41
|
-
scheduler,
|
|
42
|
-
eventEmitter,
|
|
43
|
-
action,
|
|
44
|
-
query,
|
|
45
|
-
chatInfo,
|
|
46
|
-
'TestBot'
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
return ctx;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
describe('InlineQueryAction', () => {
|
|
53
|
-
describe('constructor', () => {
|
|
54
|
-
test('should set name correctly', () => {
|
|
55
|
-
const action = new InlineQueryAction(
|
|
56
|
-
mock(() => Promise.resolve()),
|
|
57
|
-
'test.action',
|
|
58
|
-
() => true,
|
|
59
|
-
/test/
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
expect(action.name).toBe('test.action');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('should set pattern correctly', () => {
|
|
66
|
-
const pattern = /search (.*)/gi;
|
|
67
|
-
const action = new InlineQueryAction(
|
|
68
|
-
mock(() => Promise.resolve()),
|
|
69
|
-
'search-action',
|
|
70
|
-
() => true,
|
|
71
|
-
pattern
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
expect(action.pattern).toBe(pattern);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('should generate key with inline prefix', () => {
|
|
78
|
-
const action = new InlineQueryAction(
|
|
79
|
-
mock(() => Promise.resolve()),
|
|
80
|
-
'test.action',
|
|
81
|
-
() => true,
|
|
82
|
-
/test/
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
expect(action.key).toBe('inline:test-action' as ActionKey);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('should replace dots with dashes in key', () => {
|
|
89
|
-
const action = new InlineQueryAction(
|
|
90
|
-
mock(() => Promise.resolve()),
|
|
91
|
-
'my.action.name',
|
|
92
|
-
() => true,
|
|
93
|
-
/test/
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// Note: only first dot is replaced due to String.replace behavior
|
|
97
|
-
expect(action.key).toBe('inline:my-action.name' as ActionKey);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test('should store handler', () => {
|
|
101
|
-
const handler = mock(() => Promise.resolve());
|
|
102
|
-
const action = new InlineQueryAction(
|
|
103
|
-
handler,
|
|
104
|
-
'test',
|
|
105
|
-
() => true,
|
|
106
|
-
/test/
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
expect(action.handler).toBe(handler);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
test('should store isActiveProvider', () => {
|
|
113
|
-
const provider = () => true;
|
|
114
|
-
const action = new InlineQueryAction(
|
|
115
|
-
mock(() => Promise.resolve()),
|
|
116
|
-
'test',
|
|
117
|
-
provider,
|
|
118
|
-
/test/
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
expect(action.isActiveProvider).toBe(provider);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
describe('exec', () => {
|
|
126
|
-
test('should throw if context is not initialized', () => {
|
|
127
|
-
// Note: isInitialized property no longer exists as context is always initialized
|
|
128
|
-
// with all required properties at construction time
|
|
129
|
-
// This test case is no longer applicable
|
|
130
|
-
const ctx = createMockInlineContext('test query');
|
|
131
|
-
|
|
132
|
-
// Verify context is properly initialized
|
|
133
|
-
expect(ctx.action).toBeDefined();
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test('should return NoResponse if action is not active', async () => {
|
|
137
|
-
const action = new InlineQueryAction(
|
|
138
|
-
mock(() => Promise.resolve()),
|
|
139
|
-
'test',
|
|
140
|
-
() => false,
|
|
141
|
-
/test/
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
const ctx = createMockInlineContext('test query');
|
|
145
|
-
const result = await action.exec(ctx);
|
|
146
|
-
|
|
147
|
-
expect(result).toBe(Noop.NoResponse);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test('should return NoResponse if pattern does not match', async () => {
|
|
151
|
-
const handler = mock(() => Promise.resolve());
|
|
152
|
-
const action = new InlineQueryAction(
|
|
153
|
-
handler,
|
|
154
|
-
'test',
|
|
155
|
-
() => true,
|
|
156
|
-
/nomatch/
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
const ctx = createMockInlineContext('test query');
|
|
160
|
-
const result = await action.exec(ctx);
|
|
161
|
-
|
|
162
|
-
expect(result).toBe(Noop.NoResponse);
|
|
163
|
-
expect(handler).not.toHaveBeenCalled();
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test('should execute handler when pattern matches', async () => {
|
|
167
|
-
const handler = mock(() => Promise.resolve());
|
|
168
|
-
const action = new InlineQueryAction(
|
|
169
|
-
handler,
|
|
170
|
-
'test',
|
|
171
|
-
() => true,
|
|
172
|
-
/test/
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
const ctx = createMockInlineContext('test query');
|
|
176
|
-
await action.exec(ctx);
|
|
177
|
-
|
|
178
|
-
expect(handler).toHaveBeenCalledTimes(1);
|
|
179
|
-
expect(handler).toHaveBeenCalledWith(ctx);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
test('should set matchResults on context when pattern matches', async () => {
|
|
183
|
-
const action = new InlineQueryAction(
|
|
184
|
-
mock(() => Promise.resolve()),
|
|
185
|
-
'test',
|
|
186
|
-
() => true,
|
|
187
|
-
/(\w+) query/
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
const ctx = createMockInlineContext('test query');
|
|
191
|
-
await action.exec(ctx);
|
|
192
|
-
|
|
193
|
-
expect(ctx.matchResults.length).toBe(1);
|
|
194
|
-
expect(ctx.matchResults[0][0]).toBe('test query');
|
|
195
|
-
expect(ctx.matchResults[0][1]).toBe('test');
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
test('should handle global regex with multiple matches', async () => {
|
|
199
|
-
const action = new InlineQueryAction(
|
|
200
|
-
mock(() => Promise.resolve()),
|
|
201
|
-
'test',
|
|
202
|
-
() => true,
|
|
203
|
-
/\w+/g
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
const ctx = createMockInlineContext('hello world test');
|
|
207
|
-
await action.exec(ctx);
|
|
208
|
-
|
|
209
|
-
expect(ctx.matchResults.length).toBe(3);
|
|
210
|
-
expect(ctx.matchResults[0][0]).toBe('hello');
|
|
211
|
-
expect(ctx.matchResults[1][0]).toBe('world');
|
|
212
|
-
expect(ctx.matchResults[2][0]).toBe('test');
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
test('should limit regex matches to 100', async () => {
|
|
216
|
-
// Create a query that would match many times
|
|
217
|
-
const longQuery = 'a '.repeat(150);
|
|
218
|
-
const action = new InlineQueryAction(
|
|
219
|
-
mock(() => Promise.resolve()),
|
|
220
|
-
'test',
|
|
221
|
-
() => true,
|
|
222
|
-
/a/g
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
const ctx = createMockInlineContext(longQuery);
|
|
226
|
-
await action.exec(ctx);
|
|
227
|
-
|
|
228
|
-
// 1 initial match + 100 additional matches = 101 max
|
|
229
|
-
expect(ctx.matchResults.length).toBeLessThanOrEqual(101);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test('should emit inlineActionExecuting event before handler', async () => {
|
|
233
|
-
const events: string[] = [];
|
|
234
|
-
const handler = mock(() => {
|
|
235
|
-
events.push('handler');
|
|
236
|
-
return Promise.resolve();
|
|
237
|
-
});
|
|
238
|
-
const action = new InlineQueryAction(
|
|
239
|
-
handler,
|
|
240
|
-
'test',
|
|
241
|
-
() => true,
|
|
242
|
-
/test/
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
const ctx = createMockInlineContext('test query');
|
|
246
|
-
ctx.observability.eventEmitter.on(
|
|
247
|
-
BotEventType.inlineActionExecuting,
|
|
248
|
-
() => {
|
|
249
|
-
events.push('executing');
|
|
250
|
-
}
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
await action.exec(ctx);
|
|
254
|
-
|
|
255
|
-
expect(events).toEqual(['executing', 'handler']);
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
test('should emit inlineActionExecuted event after handler', async () => {
|
|
259
|
-
const events: string[] = [];
|
|
260
|
-
const handler = mock(() => {
|
|
261
|
-
events.push('handler');
|
|
262
|
-
return Promise.resolve();
|
|
263
|
-
});
|
|
264
|
-
const action = new InlineQueryAction(
|
|
265
|
-
handler,
|
|
266
|
-
'test',
|
|
267
|
-
() => true,
|
|
268
|
-
/test/
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
const ctx = createMockInlineContext('test query');
|
|
272
|
-
ctx.observability.eventEmitter.on(
|
|
273
|
-
BotEventType.inlineActionExecuted,
|
|
274
|
-
() => {
|
|
275
|
-
events.push('executed');
|
|
276
|
-
}
|
|
277
|
-
);
|
|
278
|
-
|
|
279
|
-
await action.exec(ctx);
|
|
280
|
-
|
|
281
|
-
expect(events).toEqual(['handler', 'executed']);
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
test('should return context responses after execution', async () => {
|
|
285
|
-
const action = new InlineQueryAction(
|
|
286
|
-
mock((ctx: InlineQueryContext) => {
|
|
287
|
-
ctx.showInlineQueryResult({
|
|
288
|
-
type: 'article',
|
|
289
|
-
id: '1',
|
|
290
|
-
title: 'Test',
|
|
291
|
-
input_message_content: { message_text: 'test' }
|
|
292
|
-
});
|
|
293
|
-
return Promise.resolve();
|
|
294
|
-
}),
|
|
295
|
-
'test',
|
|
296
|
-
() => true,
|
|
297
|
-
/test/
|
|
298
|
-
);
|
|
299
|
-
|
|
300
|
-
const ctx = createMockInlineContext('test query');
|
|
301
|
-
const result = await action.exec(ctx);
|
|
302
|
-
|
|
303
|
-
expect(result.length).toBe(1);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
test('should reset regex lastIndex before matching', async () => {
|
|
307
|
-
const pattern = /test/g;
|
|
308
|
-
pattern.lastIndex = 100; // Simulate a previously used regex
|
|
309
|
-
|
|
310
|
-
const action = new InlineQueryAction(
|
|
311
|
-
mock(() => Promise.resolve()),
|
|
312
|
-
'test',
|
|
313
|
-
() => true,
|
|
314
|
-
pattern
|
|
315
|
-
);
|
|
316
|
-
|
|
317
|
-
const ctx = createMockInlineContext('test query');
|
|
318
|
-
await action.exec(ctx);
|
|
319
|
-
|
|
320
|
-
expect(ctx.matchResults.length).toBe(1);
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
describe('isActiveProvider integration', () => {
|
|
325
|
-
test('should receive context in isActiveProvider', async () => {
|
|
326
|
-
const providerMock = mock(() => true);
|
|
327
|
-
const action = new InlineQueryAction(
|
|
328
|
-
mock(() => Promise.resolve()),
|
|
329
|
-
'test',
|
|
330
|
-
providerMock,
|
|
331
|
-
/test/
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
const ctx = createMockInlineContext('test query');
|
|
335
|
-
await action.exec(ctx);
|
|
336
|
-
|
|
337
|
-
expect(providerMock).toHaveBeenCalledWith(ctx);
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
test('should evaluate isActiveProvider on each exec', async () => {
|
|
341
|
-
let isActive = true;
|
|
342
|
-
const action = new InlineQueryAction(
|
|
343
|
-
mock(() => Promise.resolve()),
|
|
344
|
-
'test',
|
|
345
|
-
() => isActive,
|
|
346
|
-
/test/
|
|
347
|
-
);
|
|
348
|
-
|
|
349
|
-
const ctx1 = createMockInlineContext('test query');
|
|
350
|
-
const result1 = await action.exec(ctx1);
|
|
351
|
-
expect(result1).not.toBe(Noop.NoResponse);
|
|
352
|
-
|
|
353
|
-
isActive = false;
|
|
354
|
-
const ctx2 = createMockInlineContext('test query');
|
|
355
|
-
const result2 = await action.exec(ctx2);
|
|
356
|
-
expect(result2).toBe(Noop.NoResponse);
|
|
357
|
-
});
|
|
358
|
-
});
|
|
359
|
-
});
|