@yaebal/test 0.0.1 → 0.1.0
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/README.md +214 -2
- package/lib/index.d.ts +166 -13
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +308 -32
- package/lib/index.js.map +1 -1
- package/lib/index.test.js +149 -2
- package/lib/index.test.js.map +1 -1
- package/package.json +2 -2
- package/src/index.test.ts +220 -1
- package/src/index.ts +495 -34
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# @yaebal/test
|
|
2
2
|
|
|
3
|
-
testing utilities for yaebal bots
|
|
3
|
+
testing utilities for yaebal bots — a fake `Api` that records every call (and can drive real
|
|
4
|
+
`before`/`after`/`onError` hooks, simulate failures, and retries), update factories for every
|
|
5
|
+
update kind telegram sends, context builders, and helpers for webhook/keyboard assertions.
|
|
6
|
+
|
|
7
|
+
zero dependency on any test runner or assertion library — works with `node:test`, vitest,
|
|
8
|
+
bun:test, jest, ava, anything that can `await` a promise and call `assert`.
|
|
4
9
|
|
|
5
10
|
## install
|
|
6
11
|
|
|
@@ -12,7 +17,7 @@ pnpm add -D @yaebal/test
|
|
|
12
17
|
|
|
13
18
|
```ts
|
|
14
19
|
import { callbackUpdate, createContext, messageUpdate, mockApi, runMiddleware } from "@yaebal/test";
|
|
15
|
-
import { expect, test } from "vitest";
|
|
20
|
+
import { expect, test } from "vitest"; // or node:test, or whatever you use
|
|
16
21
|
|
|
17
22
|
test("replies to /start", async () => {
|
|
18
23
|
const { api, calls } = mockApi();
|
|
@@ -35,6 +40,213 @@ test("callback query", async () => {
|
|
|
35
40
|
});
|
|
36
41
|
```
|
|
37
42
|
|
|
43
|
+
or skip a step with the `*Context` shortcuts:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { messageContext, runMiddleware } from "@yaebal/test";
|
|
47
|
+
|
|
48
|
+
const ctx = messageContext({ text: "/start", chatId: 42 });
|
|
49
|
+
await runMiddleware(bot, ctx);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## mockApi
|
|
53
|
+
|
|
54
|
+
`mockApi(options?)` returns a fake `Api` plus inspection helpers. Every method records
|
|
55
|
+
`{ method, params }` into `calls` and resolves to a sensible default: an auto-incrementing
|
|
56
|
+
`{ message_id }` for `send*`/`copyMessage`/`forwardMessage`, `true` for `answerCallbackQuery`,
|
|
57
|
+
a stub bot for `getMe`, `{}` otherwise.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
const { api, calls, hooks, lastCall, callsTo, setResult, reset } = mockApi();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- **`calls`** — every recorded call, in order.
|
|
64
|
+
- **`lastCall(method?)`** — the most recent call, optionally filtered to a method.
|
|
65
|
+
- **`callsTo(method)`** — every call to a given method, in order.
|
|
66
|
+
- **`setResult(method, result)`** — override a method's canned result/error after creation.
|
|
67
|
+
- **`reset()`** — clears `calls` and per-method attempt counters (keeps hooks and overrides).
|
|
68
|
+
- **`hooks`** — the `before`/`after`/`onError` arrays your code under test registered on the api.
|
|
69
|
+
|
|
70
|
+
### canned results & error simulation
|
|
71
|
+
|
|
72
|
+
Pass `results` to control exactly what a method returns — a static value, an `Error` (which
|
|
73
|
+
makes the call throw, e.g. `TelegramError`), or a function of `(params, attempt)`:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { TelegramError } from "@yaebal/core";
|
|
77
|
+
import { mockApi } from "@yaebal/test";
|
|
78
|
+
|
|
79
|
+
const { api } = mockApi({
|
|
80
|
+
results: {
|
|
81
|
+
sendMessage: { message_id: 42 },
|
|
82
|
+
getChat: () => ({ id: 1, type: "private" }),
|
|
83
|
+
// fails twice, then succeeds — great for testing retry plugins like @yaebal/again
|
|
84
|
+
getMe: (params, attempt) =>
|
|
85
|
+
attempt <= 2 ? new TelegramError("getMe", 429, "retry after 0") : { id: 1, is_bot: true, first_name: "bot" },
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### real hooks, not no-ops
|
|
91
|
+
|
|
92
|
+
Unlike a bare stub, `before`/`after`/`onError` registered on a `mockApi()` actually run through
|
|
93
|
+
the call pipeline — register a hook exactly as you would on the production `Api` and it fires,
|
|
94
|
+
including retries requested by an `onError` hook (see [`@yaebal/again`](../again)'s retry
|
|
95
|
+
policy). The mock never actually waits on a requested `delayMs`, so retry tests settle instantly:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
const { api } = mockApi({ results: { sendMessage: new TelegramError("sendMessage", 429, "retry after 0") } });
|
|
99
|
+
|
|
100
|
+
api.onError((_method, _error, attempt) => (attempt === 1 ? { retry: true } : undefined));
|
|
101
|
+
|
|
102
|
+
await api.sendMessage({ chat_id: 1 }); // retries once, then throws (no result override for attempt 2)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## contexts
|
|
106
|
+
|
|
107
|
+
`createContext(update, api?, updateType?)` wraps an `Update` in a core `Context`. The api
|
|
108
|
+
defaults to a fresh `mockApi().api`; the update type is auto-detected via `detectUpdateType`
|
|
109
|
+
unless you pass `updateType`. Run a composer's middleware against it with
|
|
110
|
+
`runMiddleware(composer, ctx)` — it resolves once the chain settles.
|
|
111
|
+
|
|
112
|
+
`messageContext(options?, api?)` and `callbackContext(options?, api?)` build the update and the
|
|
113
|
+
context in one call, for the two most common cases.
|
|
114
|
+
|
|
115
|
+
## building updates
|
|
116
|
+
|
|
117
|
+
Factories exist for every update kind telegram sends:
|
|
118
|
+
|
|
119
|
+
| factory | update key |
|
|
120
|
+
|:---------------------------|:-----------------------|
|
|
121
|
+
| `messageUpdate` | `message` |
|
|
122
|
+
| `editedMessageUpdate` | `edited_message` |
|
|
123
|
+
| `channelPostUpdate` | `channel_post` |
|
|
124
|
+
| `editedChannelPostUpdate` | `edited_channel_post` |
|
|
125
|
+
| `callbackUpdate` | `callback_query` |
|
|
126
|
+
| `inlineQueryUpdate` | `inline_query` |
|
|
127
|
+
| `chosenInlineResultUpdate` | `chosen_inline_result` |
|
|
128
|
+
| `shippingQueryUpdate` | `shipping_query` |
|
|
129
|
+
| `preCheckoutQueryUpdate` | `pre_checkout_query` |
|
|
130
|
+
| `pollUpdate` | `poll` |
|
|
131
|
+
| `pollAnswerUpdate` | `poll_answer` |
|
|
132
|
+
| `myChatMemberUpdate` | `my_chat_member` |
|
|
133
|
+
| `chatMemberUpdate` | `chat_member` |
|
|
134
|
+
| `chatJoinRequestUpdate` | `chat_join_request` |
|
|
135
|
+
|
|
136
|
+
`createUpdate` is the escape hatch for anything else, filling in a fresh `update_id`.
|
|
137
|
+
`detectUpdateType` infers which payload key an update carries.
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { createUpdate, detectUpdateType, pollUpdate } from "@yaebal/test";
|
|
141
|
+
|
|
142
|
+
const poll = pollUpdate({ question: "coffee or tea?", options: ["coffee", "tea"] });
|
|
143
|
+
|
|
144
|
+
// hand-build any update shape; update_id is filled in for you
|
|
145
|
+
const custom = createUpdate({
|
|
146
|
+
edited_message: { message_id: 1, date: 0, chat: { id: 1, type: "private" } },
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
detectUpdateType(custom); // → "edited_message"
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## inline keyboards
|
|
153
|
+
|
|
154
|
+
`findButton(markup, match)` searches a `reply_markup`-shaped object (e.g. from a recorded call's
|
|
155
|
+
params) for a button whose text matches a string or regex, returning it with its `row`/`col`:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { findButton, messageContext, mockApi, runMiddleware } from "@yaebal/test";
|
|
159
|
+
|
|
160
|
+
const { api, calls } = mockApi();
|
|
161
|
+
await runMiddleware(bot, messageContext({ text: "/menu" }, api));
|
|
162
|
+
|
|
163
|
+
const next = findButton(calls[0]?.params?.reply_markup, "Next »");
|
|
164
|
+
assert.equal(next?.callback_data, "page:2");
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## webhooks & runners
|
|
168
|
+
|
|
169
|
+
`webhookRequest(update, options?)` builds a `Request` the way telegram would POST it to a
|
|
170
|
+
webhook handler (`@yaebal/core`'s `webhookCallback`, or `@yaebal/web`'s `webhook`):
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { webhookRequest } from "@yaebal/test";
|
|
174
|
+
import { webhookCallback } from "@yaebal/core";
|
|
175
|
+
|
|
176
|
+
const handler = webhookCallback(bot, { secretToken: "s3cret" });
|
|
177
|
+
const res = await handler(webhookRequest(messageUpdate({ text: "hi" }), { secretToken: "s3cret" }));
|
|
178
|
+
assert.equal(res.status, 200);
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`collectUpdates()` gives you a minimal `UpdateSink` (the `{ handleUpdate }` shape webhooks and
|
|
182
|
+
runners expect) that just records what it receives — handy when you don't need a full `Bot`:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
import { collectUpdates, messageUpdate } from "@yaebal/test";
|
|
186
|
+
|
|
187
|
+
const { sink, updates } = collectUpdates();
|
|
188
|
+
await sink.handleUpdate(messageUpdate({ text: "hi" }));
|
|
189
|
+
assert.equal(updates.length, 1);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`withFetch(handler, fn)` stubs `globalThis.fetch` for the duration of `fn`, restoring the
|
|
193
|
+
original afterwards even if `fn` throws — for code that proxies uploads or downloads:
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { withFetch } from "@yaebal/test";
|
|
197
|
+
|
|
198
|
+
await withFetch(
|
|
199
|
+
async (url) => new Response(new Uint8Array([1, 2, 3]), { headers: { "content-type": "image/jpeg" } }),
|
|
200
|
+
async () => {
|
|
201
|
+
const res = await panelHandler(request);
|
|
202
|
+
assert.equal(res.status, 200);
|
|
203
|
+
},
|
|
204
|
+
);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## api reference
|
|
208
|
+
|
|
209
|
+
| export | signature | description |
|
|
210
|
+
|:---------------------------|:----------------------------------------------------------------|:-----------------------------------------------------------------------------|
|
|
211
|
+
| `mockApi` | `(options?: MockApiOptions) => MockApi` | fake `Api` recording every call, with working hooks and configurable results |
|
|
212
|
+
| `createUpdate` | `(partial?: Partial<Update>) => Update` | build an update, filling in a fresh `update_id` |
|
|
213
|
+
| `messageUpdate` | `(options?: MessageUpdateOptions) => Update` | build a `message` update |
|
|
214
|
+
| `editedMessageUpdate` | `(options?: MessageUpdateOptions) => Update` | build an `edited_message` update |
|
|
215
|
+
| `channelPostUpdate` | `(options?: MessageUpdateOptions) => Update` | build a `channel_post` update |
|
|
216
|
+
| `editedChannelPostUpdate` | `(options?: MessageUpdateOptions) => Update` | build an `edited_channel_post` update |
|
|
217
|
+
| `callbackUpdate` | `(options?: CallbackUpdateOptions) => Update` | build a `callback_query` update |
|
|
218
|
+
| `inlineQueryUpdate` | `(options?: InlineQueryUpdateOptions) => Update` | build an `inline_query` update |
|
|
219
|
+
| `chosenInlineResultUpdate` | `(options?: ChosenInlineResultUpdateOptions) => Update` | build a `chosen_inline_result` update |
|
|
220
|
+
| `shippingQueryUpdate` | `(options?: ShippingQueryUpdateOptions) => Update` | build a `shipping_query` update |
|
|
221
|
+
| `preCheckoutQueryUpdate` | `(options?: PreCheckoutQueryUpdateOptions) => Update` | build a `pre_checkout_query` update |
|
|
222
|
+
| `pollUpdate` | `(options?: PollUpdateOptions) => Update` | build a `poll` update |
|
|
223
|
+
| `pollAnswerUpdate` | `(options?: PollAnswerUpdateOptions) => Update` | build a `poll_answer` update |
|
|
224
|
+
| `myChatMemberUpdate` | `(options?: ChatMemberUpdateOptions) => Update` | build a `my_chat_member` update |
|
|
225
|
+
| `chatMemberUpdate` | `(options?: ChatMemberUpdateOptions) => Update` | build a `chat_member` update |
|
|
226
|
+
| `chatJoinRequestUpdate` | `(options?: ChatJoinRequestUpdateOptions) => Update` | build a `chat_join_request` update |
|
|
227
|
+
| `createContext` | `(update, api?, updateType?) => Context` | wrap an update in a core `Context` |
|
|
228
|
+
| `messageContext` | `(options?: MessageUpdateOptions, api?: Api) => Context` | build a `message` update and wrap it in one call |
|
|
229
|
+
| `callbackContext` | `(options?: CallbackUpdateOptions, api?: Api) => Context` | build a `callback_query` update and wrap it in one call |
|
|
230
|
+
| `runMiddleware` | `(composer: Composer<C>, ctx: C) => Promise<void>` | run a composer's middleware against a context |
|
|
231
|
+
| `detectUpdateType` | `(update: Update) => UpdateName` | infer the payload key; defaults to `"message"` |
|
|
232
|
+
| `findButton` | `(markup, match: string \| RegExp) => FoundButton \| undefined` | find an inline keyboard button by text |
|
|
233
|
+
| `collectUpdates` | `() => UpdateCollector` | a minimal `UpdateSink` that records what it receives |
|
|
234
|
+
| `webhookRequest` | `(update, options?: WebhookRequestOptions) => Request` | build a webhook POST request carrying an update |
|
|
235
|
+
| `withFetch` | `(handler: typeof fetch, fn) => Promise<T>` | stub `globalThis.fetch` for `fn`, restoring it after |
|
|
236
|
+
|
|
237
|
+
### interfaces
|
|
238
|
+
|
|
239
|
+
| type | fields |
|
|
240
|
+
|:------------------------|:-------------------------------------------------------------------------------------------------------------------------|
|
|
241
|
+
| `RecordedCall` | `method: string` · `params: Record<string, unknown> \| undefined` |
|
|
242
|
+
| `MockApiOptions` | `results?: Record<string, unknown \| Error \| ((params, attempt: number) => unknown)>` |
|
|
243
|
+
| `MockApi` | `api: Api` · `calls: RecordedCall[]` · `hooks` · `lastCall` · `callsTo` · `setResult` · `reset` |
|
|
244
|
+
| `MessageUpdateOptions` | `text?: string` · `chatId?: number` · `fromId?: number` · `chatType?: "private" \| "group" \| "supergroup" \| "channel"` |
|
|
245
|
+
| `CallbackUpdateOptions` | `data?: string` · `chatId?: number` · `fromId?: number` |
|
|
246
|
+
| `FoundButton` | the button's own fields, plus `row: number` · `col: number` |
|
|
247
|
+
| `UpdateCollector` | `sink: UpdateSink` · `updates: Update[]` |
|
|
248
|
+
| `WebhookRequestOptions` | `url?: string` · `method?: string` · `secretToken?: string` · `headers?: Record<string, string>` |
|
|
249
|
+
|
|
38
250
|
---
|
|
39
251
|
|
|
40
252
|
part of [**yaebal**](https://github.com/neverlane/yaebal) — a type-safe, runtime-agnostic Telegram Bot API framework. MIT.
|
package/lib/index.d.ts
CHANGED
|
@@ -1,48 +1,164 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @yaebal/test — testing utilities for yaebal bots
|
|
2
|
+
* @yaebal/test — testing utilities for yaebal bots, with zero dependency on any
|
|
3
|
+
* test runner or assertion library. Works with `node:test`, vitest, bun:test,
|
|
4
|
+
* jest, ava — anything that can `await` a promise and call `assert`.
|
|
3
5
|
*
|
|
4
6
|
* every plugin test used to hand-build fake updates and a mock api. this package
|
|
5
|
-
* extracts that boilerplate: {@link mockApi} records every call
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* extracts that boilerplate: {@link mockApi} records every call (and can drive
|
|
8
|
+
* real `before`/`after`/`onError` hooks and simulate failures), the `*Update`
|
|
9
|
+
* factories produce real {@link Update} shapes for every update kind, and
|
|
10
|
+
* {@link createContext} wraps one in a core {@link Context}.
|
|
8
11
|
*/
|
|
9
|
-
import { type Api, type Composer, Context, type Message, type Update, type UpdateName } from "@yaebal/core";
|
|
12
|
+
import { type AfterHook, type Api, type BeforeHook, type Composer, Context, type ErrorHook, type Message, type Update, type UpdateName, type UpdateSink } from "@yaebal/core";
|
|
13
|
+
/** the payload type for a given update kind — reuses core's `Update` shape, no extra types package needed. */
|
|
14
|
+
type Payload<K extends UpdateName> = NonNullable<Update[K]>;
|
|
10
15
|
/** a single recorded api call: the method name and the params it was given. */
|
|
11
16
|
export interface RecordedCall {
|
|
12
17
|
method: string;
|
|
13
18
|
params: Record<string, unknown> | undefined;
|
|
14
19
|
}
|
|
15
|
-
/** result
|
|
20
|
+
/** a canned result for one method: a static value, an `Error` to throw, or a function of `(params, attempt)`. */
|
|
21
|
+
export type MockResult = unknown | Error | ((params: Record<string, unknown> | undefined, attempt: number) => unknown);
|
|
22
|
+
export interface MockApiOptions {
|
|
23
|
+
/**
|
|
24
|
+
* per-method canned results/errors, keyed by method name — overrides the
|
|
25
|
+
* built-in defaults. a function receives `attempt`, a 1-based count of how
|
|
26
|
+
* many times that method has been called (including retries), so you can
|
|
27
|
+
* simulate "fails twice, then succeeds": `sendMessage: (p, a) => a <= 2 ? new
|
|
28
|
+
* TelegramError(...) : { message_id: 1 }`.
|
|
29
|
+
*/
|
|
30
|
+
results?: Record<string, MockResult>;
|
|
31
|
+
}
|
|
32
|
+
/** result of {@link mockApi}: the fake `api`, its recorded calls, and inspection helpers. */
|
|
16
33
|
export interface MockApi {
|
|
17
34
|
api: Api;
|
|
18
35
|
calls: RecordedCall[];
|
|
36
|
+
/** hooks registered on `api` via `before`/`after`/`onError` — inspect them or invoke them yourself. */
|
|
37
|
+
hooks: {
|
|
38
|
+
before: BeforeHook[];
|
|
39
|
+
after: AfterHook[];
|
|
40
|
+
onError: ErrorHook[];
|
|
41
|
+
};
|
|
42
|
+
/** the most recent recorded call, optionally filtered to a method. */
|
|
43
|
+
lastCall(method?: string): RecordedCall | undefined;
|
|
44
|
+
/** every recorded call to a given method, in call order. */
|
|
45
|
+
callsTo(method: string): RecordedCall[];
|
|
46
|
+
/** set (or replace) the canned result/error for a method after creation. */
|
|
47
|
+
setResult(method: string, result: MockResult): void;
|
|
48
|
+
/** clear recorded calls and per-method attempt counters. keeps hooks and result overrides. */
|
|
49
|
+
reset(): void;
|
|
19
50
|
}
|
|
20
51
|
/**
|
|
21
52
|
* a fake {@link Api} whose every method records `{ method, params }` into `calls`
|
|
22
|
-
* and resolves to a sensible default (`
|
|
23
|
-
* `answerCallbackQuery`, `{}` otherwise)
|
|
24
|
-
* `onError`
|
|
53
|
+
* and resolves to a sensible default (auto-incrementing `message_id` for `send*`,
|
|
54
|
+
* `true` for `answerCallbackQuery`, `{}` otherwise) — or to whatever `options.results`
|
|
55
|
+
* says. `before`/`after`/`onError` are real hook registrars (not no-ops): register
|
|
56
|
+
* a hook the same way you would on the production `Api` and it actually runs,
|
|
57
|
+
* including retries requested by an `onError` hook. the mock never actually waits
|
|
58
|
+
* on a requested `delayMs` — retries settle instantly, so tests stay fast.
|
|
25
59
|
*/
|
|
26
|
-
export declare function mockApi(): MockApi;
|
|
60
|
+
export declare function mockApi(options?: MockApiOptions): MockApi;
|
|
27
61
|
/** build an {@link Update} from a partial, filling in a fresh `update_id`. */
|
|
28
62
|
export declare function createUpdate(partial?: Partial<Update>): Update;
|
|
29
|
-
/** options
|
|
63
|
+
/** options shared by the message-shaped factories (`message`, `edited_message`, `channel_post`, ...). */
|
|
30
64
|
export interface MessageUpdateOptions {
|
|
31
65
|
text?: string;
|
|
32
66
|
chatId?: number;
|
|
33
67
|
fromId?: number;
|
|
34
68
|
chatType?: "private" | "group" | "supergroup" | "channel";
|
|
35
69
|
}
|
|
36
|
-
/** build a message {@link Update}. */
|
|
70
|
+
/** build a `message` {@link Update}. */
|
|
37
71
|
export declare function messageUpdate(options?: MessageUpdateOptions): Update;
|
|
72
|
+
/** build an `edited_message` {@link Update}. */
|
|
73
|
+
export declare function editedMessageUpdate(options?: MessageUpdateOptions): Update;
|
|
74
|
+
/** build a `channel_post` {@link Update}. */
|
|
75
|
+
export declare function channelPostUpdate(options?: MessageUpdateOptions): Update;
|
|
76
|
+
/** build an `edited_channel_post` {@link Update}. */
|
|
77
|
+
export declare function editedChannelPostUpdate(options?: MessageUpdateOptions): Update;
|
|
38
78
|
/** options for {@link callbackUpdate}. */
|
|
39
79
|
export interface CallbackUpdateOptions {
|
|
40
80
|
data?: string;
|
|
41
81
|
chatId?: number;
|
|
42
82
|
fromId?: number;
|
|
43
83
|
}
|
|
44
|
-
/** build a callback_query {@link Update}. */
|
|
84
|
+
/** build a `callback_query` {@link Update}. */
|
|
45
85
|
export declare function callbackUpdate(options?: CallbackUpdateOptions): Update;
|
|
86
|
+
/** options for {@link inlineQueryUpdate}. */
|
|
87
|
+
export interface InlineQueryUpdateOptions {
|
|
88
|
+
query?: string;
|
|
89
|
+
fromId?: number;
|
|
90
|
+
id?: string;
|
|
91
|
+
offset?: string;
|
|
92
|
+
chatType?: Payload<"inline_query">["chat_type"];
|
|
93
|
+
}
|
|
94
|
+
/** build an `inline_query` {@link Update}. */
|
|
95
|
+
export declare function inlineQueryUpdate(options?: InlineQueryUpdateOptions): Update;
|
|
96
|
+
/** options for {@link chosenInlineResultUpdate}. */
|
|
97
|
+
export interface ChosenInlineResultUpdateOptions {
|
|
98
|
+
resultId?: string;
|
|
99
|
+
fromId?: number;
|
|
100
|
+
query?: string;
|
|
101
|
+
inlineMessageId?: string;
|
|
102
|
+
}
|
|
103
|
+
/** build a `chosen_inline_result` {@link Update}. */
|
|
104
|
+
export declare function chosenInlineResultUpdate(options?: ChosenInlineResultUpdateOptions): Update;
|
|
105
|
+
/** options for {@link shippingQueryUpdate}. */
|
|
106
|
+
export interface ShippingQueryUpdateOptions {
|
|
107
|
+
id?: string;
|
|
108
|
+
fromId?: number;
|
|
109
|
+
invoicePayload?: string;
|
|
110
|
+
shippingAddress?: Partial<Payload<"shipping_query">["shipping_address"]>;
|
|
111
|
+
}
|
|
112
|
+
/** build a `shipping_query` {@link Update}. */
|
|
113
|
+
export declare function shippingQueryUpdate(options?: ShippingQueryUpdateOptions): Update;
|
|
114
|
+
/** options for {@link preCheckoutQueryUpdate}. */
|
|
115
|
+
export interface PreCheckoutQueryUpdateOptions {
|
|
116
|
+
id?: string;
|
|
117
|
+
fromId?: number;
|
|
118
|
+
currency?: string;
|
|
119
|
+
totalAmount?: number;
|
|
120
|
+
invoicePayload?: string;
|
|
121
|
+
}
|
|
122
|
+
/** build a `pre_checkout_query` {@link Update}. */
|
|
123
|
+
export declare function preCheckoutQueryUpdate(options?: PreCheckoutQueryUpdateOptions): Update;
|
|
124
|
+
/** options for {@link pollUpdate}. */
|
|
125
|
+
export interface PollUpdateOptions {
|
|
126
|
+
id?: string;
|
|
127
|
+
question?: string;
|
|
128
|
+
options?: string[];
|
|
129
|
+
isClosed?: boolean;
|
|
130
|
+
}
|
|
131
|
+
/** build a `poll` {@link Update}. */
|
|
132
|
+
export declare function pollUpdate(options?: PollUpdateOptions): Update;
|
|
133
|
+
/** options for {@link pollAnswerUpdate}. */
|
|
134
|
+
export interface PollAnswerUpdateOptions {
|
|
135
|
+
pollId?: string;
|
|
136
|
+
fromId?: number;
|
|
137
|
+
optionIds?: number[];
|
|
138
|
+
}
|
|
139
|
+
/** build a `poll_answer` {@link Update}. */
|
|
140
|
+
export declare function pollAnswerUpdate(options?: PollAnswerUpdateOptions): Update;
|
|
141
|
+
/** options for {@link myChatMemberUpdate} / {@link chatMemberUpdate}. */
|
|
142
|
+
export interface ChatMemberUpdateOptions {
|
|
143
|
+
chatId?: number;
|
|
144
|
+
fromId?: number;
|
|
145
|
+
userId?: number;
|
|
146
|
+
oldStatus?: string;
|
|
147
|
+
newStatus?: string;
|
|
148
|
+
}
|
|
149
|
+
/** build a `my_chat_member` {@link Update} (the bot's own membership changed). */
|
|
150
|
+
export declare function myChatMemberUpdate(options?: ChatMemberUpdateOptions): Update;
|
|
151
|
+
/** build a `chat_member` {@link Update} (another member's membership changed). */
|
|
152
|
+
export declare function chatMemberUpdate(options?: ChatMemberUpdateOptions): Update;
|
|
153
|
+
/** options for {@link chatJoinRequestUpdate}. */
|
|
154
|
+
export interface ChatJoinRequestUpdateOptions {
|
|
155
|
+
chatId?: number;
|
|
156
|
+
fromId?: number;
|
|
157
|
+
userChatId?: number;
|
|
158
|
+
bio?: string;
|
|
159
|
+
}
|
|
160
|
+
/** build a `chat_join_request` {@link Update}. */
|
|
161
|
+
export declare function chatJoinRequestUpdate(options?: ChatJoinRequestUpdateOptions): Update;
|
|
46
162
|
/** infer which payload key an update carries; defaults to `"message"`. */
|
|
47
163
|
export declare function detectUpdateType(update: Update): UpdateName;
|
|
48
164
|
/**
|
|
@@ -50,7 +166,44 @@ export declare function detectUpdateType(update: Update): UpdateName;
|
|
|
50
166
|
* {@link mockApi}; pass `updateType` to override the auto-detected one.
|
|
51
167
|
*/
|
|
52
168
|
export declare function createContext(update: Update, api?: Api, updateType?: UpdateName): Context;
|
|
169
|
+
/** shortcut: build a `message` update and wrap it in a {@link Context} in one call. */
|
|
170
|
+
export declare function messageContext(options?: MessageUpdateOptions, api?: Api): Context;
|
|
171
|
+
/** shortcut: build a `callback_query` update and wrap it in a {@link Context} in one call. */
|
|
172
|
+
export declare function callbackContext(options?: CallbackUpdateOptions, api?: Api): Context;
|
|
53
173
|
/** run a composer's middleware against a context. resolves when the chain settles. */
|
|
54
174
|
export declare function runMiddleware<C extends Context>(composer: Composer<C>, ctx: C): Promise<void>;
|
|
175
|
+
/** an inline keyboard button found by {@link findButton}, with its position. */
|
|
176
|
+
export interface FoundButton {
|
|
177
|
+
text: string;
|
|
178
|
+
row: number;
|
|
179
|
+
col: number;
|
|
180
|
+
[key: string]: unknown;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* search an inline keyboard (a `reply_markup`-shaped object, e.g. from a
|
|
184
|
+
* recorded `sendMessage` call's params) for a button whose text matches a
|
|
185
|
+
* string or regex. returns the button (plus its `row`/`col`) or `undefined`.
|
|
186
|
+
*/
|
|
187
|
+
export declare function findButton(markup: {
|
|
188
|
+
inline_keyboard?: Array<Array<Record<string, unknown>>>;
|
|
189
|
+
} | undefined, match: string | RegExp): FoundButton | undefined;
|
|
190
|
+
/** result of {@link collectUpdates}: an {@link UpdateSink} plus the updates it received, in order. */
|
|
191
|
+
export interface UpdateCollector {
|
|
192
|
+
sink: UpdateSink;
|
|
193
|
+
updates: Update[];
|
|
194
|
+
}
|
|
195
|
+
/** a minimal {@link UpdateSink} (the `{ handleUpdate }` shape `webhookCallback`/runners expect) that just records. */
|
|
196
|
+
export declare function collectUpdates(): UpdateCollector;
|
|
197
|
+
/** options for {@link webhookRequest}. */
|
|
198
|
+
export interface WebhookRequestOptions {
|
|
199
|
+
url?: string;
|
|
200
|
+
method?: string;
|
|
201
|
+
secretToken?: string;
|
|
202
|
+
headers?: Record<string, string>;
|
|
203
|
+
}
|
|
204
|
+
/** build a `Request` carrying `update` as JSON, as telegram would POST it to a webhook handler. */
|
|
205
|
+
export declare function webhookRequest(update: Update, options?: WebhookRequestOptions): Request;
|
|
206
|
+
/** stub `globalThis.fetch` for the duration of `fn`, restoring the original afterwards (even on throw). */
|
|
207
|
+
export declare function withFetch<T>(handler: typeof fetch, fn: () => T | Promise<T>): Promise<T>;
|
|
55
208
|
export type { Message };
|
|
56
209
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|