grammy-testing
v0.26.0
Published
Testing framework for grammY-based Telegram bots. Drives a real bot in-process, captures every outgoing API call, and dispatches synthetic updates.
Maintainers
Readme
Production-grade testing infrastructure for grammY bots.
docs. npm. examples.
Why
Testing a Telegram bot used to mean spinning up a real token, sending live messages, and hoping the Telegram API behaved. grammY ships no testing tools itself, and existing community solutions are either unmaintained, Deno-only, or too low-level to be ergonomic.
grammy-testing drives your real bot in-process. No token. No network. No sleep timers.
Dispatch a synthetic update, the bot handles it exactly as it would in production, and you
assert on the captured replies.
Quick Start
npm install --save-dev grammy-testing// bot.ts
bot.command('start', async (ctx) => {
await ctx.reply('Welcome! Use /help to see available commands.');
});// bot.spec.ts
import { prepareBot } from 'grammy-testing';
const { chats } = await prepareBot(createBot());
const user = chats.newUser();
await user.sendCommand('/start');
expect(user.replies.lastOrThrow().text).toContain('Welcome');Features
Actors & chat types
- Create users and admins with custom profiles (
chats.newUser(),chats.newAdmin()) - Create groups, supergroups, and channels (
chats.newGroup(),chats.newSupergroup(),chats.newChannel()) - Place users into group contexts (
group.own(user))
Dispatch — send anything a real user can send
- Text messages, commands, photos, documents, stickers, polls, dice, locations, contacts
- Callback queries, inline queries, reactions, media groups
- Member join/leave events, chat member status changes
- Channel posts, forwarded messages, business account messages
Reply & request assertions
user.replies.lastOrThrow()— the last reply sent to this usergroup.messages.last— the latest message in a group contextchats.outgoing.requests— every raw Telegram API call the bot made
Session & state injection
mockSession(initial)— seed a pre-set session state for unit testingmockChatSession(initial)— per-chat session injectionmockState(initial)— conversations and state machine testing
Isolation utilities
prepareMiddleware(fn)— test a single middleware without a full botprepareComposer(Composer)— test a composer class in isolation
Ecosystem
- Works with Vitest and Jest
- TypeScript-first — all types exported
- Low-level API available for advanced and custom scenarios
Plugin interop
| Plugin | How it installs | Supported since |
| --------------------------------- | ----------------------------------------------------------------------- | ----------------- |
| @grammyjs/conversations | bot.use(conversations()) | v0.21.0 |
| @grammyjs/menu | bot.use(menu) | v0.21.0 |
| @grammyjs/parse-mode | formatting utilities, no transformer | v0.21.0 |
| @grammyjs/chat-members | bot.use(chatMembers(...)) / bot.api.config.use(hydrateChatMember()) | v0.21.0 / v0.23.0 |
| grammy-media-groups | bot.api.config.use(mediaGroupTransformer(...)) | v0.24.0 |
| @grammyjs/files | bot.api.config.use(hydrateFiles(...)) | v0.23.0 |
| @grammyjs/hydrate | bot.api.config.use(hydrateApi()) + bot.use(hydrate()) | v0.23.0 |
| @grammyjs/auto-retry | bot.api.config.use(autoRetry(...)) | v0.23.0 |
| @grammyjs/transformer-throttler | bot.api.config.use(throttler(...)) | v0.23.0 |
Examples
26 self-contained bots with matching test files live in examples/:
| # | Scenario |
| --- | -------------------------------------------------------------------------------------------------------- |
| 01 | Echo bot — simplest text-echo handler |
| 02 | Command bot — /start and /help |
| 03 | Greeting bot — per-user name with fallback |
| 04 | Chat-type filter — private vs. group routing |
| 05 | Inline keyboard — regex handler with keyboard |
| 06 | Callback query — inline keyboard responses |
| 07 | Session counter — persistent per-user state |
| 08 | Chat settings — mockChatSession usage |
| 09 | Photo bot — caption extraction |
| 10 | Document bot — file-ID and MIME type reply |
| 11 | Poll bot — quiz creation and answer scoring |
| 12 | Group welcome — new_chat_members service event |
| 13 | Admin guard — getChatMember status check |
| 14 | Moderation bot — banChatMember / restrictChatMember |
| 15 | Channel post bot — channel_post handler |
| 16 | Reactions bot — message_reaction handler |
| 17 | Dice game — incoming dice value evaluation |
| 18 | Middleware test — isolation with prepareMiddleware |
| 19 | Composer test — isolation with prepareComposer |
| 20 | Multi-chat scenario — cross-chat summary posting |
| 21 | Files bot — @grammyjs/files — file.getUrl() from ctx.getFile() |
| 22 | Hydrate bot — @grammyjs/hydrate — hydrated replies with delete() |
| 23 | Auto-retry bot — @grammyjs/auto-retry — broadcast with error handling |
| 24 | Guest mode bot — answerGuestQuery for guest_message updates |
| 25 | Rich message bot — sendRichMessage with a draft preview |
| 26 | Reaction removal bot — deleteMessageReaction via /clearreactions |
Documentation
Full API reference, step-by-step guides, and recipes are available at drsmile444.github.io/grammy-testing/.
The examples/ directory also covers a wide range of real-world patterns — from the simplest echo bot to multi-chat scenarios with sessions and admin guards.
Credits
grammy-testing stands on the shoulders of:
- grammy_tests by dcdunkan — the original testing concept for grammY bots that inspired this library's design
- ua-anti-spam-bot by MoC-OSS — a real-world bot whose test patterns shaped the high-level API
License
MIT — see LICENSE.
