This page is machine-translated from the Russian original. If something reads oddly, the Russian version is the source of truth — open an issue.
Go to the developer console and open the testing tab. This applies to Alice. For other platforms, the link is entered in the corresponding developer console.
You do not need to deploy a server to debug!
Testing uses the same code as running the application.
The only difference is that you use the BotTest class instead of Bot.
import { BotTest } from 'umbot/test';
import { fullPlatforms } from 'umbot/plugins';
const bot = new BotTest();
bot.use(fullPlatforms); // register platforms — without them test() does not know which format to use
await bot.test(); // starts the interactive console
You start it like this:
npm run build && npm run start
# or run the built file directly (a standard CLI project puts the code into dist/)
node ./dist/index.js
A console with your application opens. To exit the testing mode:
isEnd = true at some point (ending the dialog), reach that point in the scenario.test()bot.test() starts, it automatically sends the first message 'Привет' (simulating a session start with
messageId === 0).exit or close the terminal. The session also ends automatically if the bot sets isEnd = true.appMode is forced to 'dev' (unless strict_prod is set explicitly).By default BotTest works with the "auto" platform: when test() and simulate() are called without an explicit platform,
the first registered one is used (with fullPlatforms this is Alice). A platform passed to the constructor
takes priority for test()/simulate() — but the adapter itself still has to be registered with bot.use(...).
run() behaves differently: without an explicit appType it always uses 'alisa', even if the constructor
specifies another platform, so pass appType explicitly: bot.run('telegram', ...).
import { BotTest } from 'umbot/test';
import { fullPlatforms } from 'umbot/plugins';
// The priority platform is Telegram
const bot = new BotTest('telegram');
bot.use(fullPlatforms);
import { BotTest } from 'umbot/test';
import { fullPlatforms } from 'umbot/plugins';
// The priority platform is Alice
const bot = new BotTest('alisa');
bot.use(fullPlatforms);
The platform you test must be registered with
bot.use(...)— otherwiseBotTestwill not find its adapter.
An IBotTestParams object with display settings is passed to test():
| Parameter | Type | Default | Description |
|---|---|---|---|
| isShowResult | boolean | false | Show the full platform response as JSON |
| isShowStorage | boolean | false | Show the storage data (userData and state) |
| isShowTime | boolean | true | Show the request processing time in ms |
const bot = new BotTest();
// Extended testing with all data shown
await bot.test({
isShowResult: true, // Show the platform's JSON response
isShowStorage: true, // Show user and storage data
isShowTime: true, // Show the processing time
});
import { BotTest } from 'umbot/test';
import { TelegramAdapter } from 'umbot/plugins';
const bot = new BotTest('telegram');
bot.use(new TelegramAdapter('your-token'));
bot.setPlatformParams({
intents: [
{
name: 'greeting',
slots: ['hello', 'hi'],
},
],
});
bot.initBotController(MyController);
await bot.test({
isShowResult: true,
isShowStorage: true,
});
BotTest can be used in unit tests to check the logic:
import { BotTest } from 'umbot/test';
import { fullPlatforms } from 'umbot/plugins';
import { MyController } from './MyController';
describe('MyController', () => {
it('should greet user', async () => {
const bot = new BotTest();
bot.use(fullPlatforms); // without a registered platform run() throws an error
bot.initBotController(MyController);
// Run request handling. Important: the payload must be valid for the platform —
// the adapter checks the structure (for example, Alice requires session + request),
// otherwise setQueryData() returns false and the request is rejected
const result = await bot.run(
'alisa',
JSON.stringify({
version: '1.0',
session: { message_id: 0, user_id: 'test-user' },
request: { command: 'hello', original_utterance: 'Hello' },
}),
);
// Check the result — check the content rather than just its presence
expect(result).toBeDefined();
expect(JSON.stringify(result)).toContain('Hello');
});
});
simulate()Instead of building a platform JSON request by hand, you can use simulate() — it generates a valid payload for the given platform and calls run():
import { BotTest } from 'umbot/test';
import { AlisaAdapter, T_ALISA } from 'umbot/plugins';
const bot = new BotTest();
bot.use(new AlisaAdapter());
bot.addCommand('start', ['hello'], (_, ctx) => {
ctx.text = 'Hello!';
});
// Voice platform: the result is the ready platform JSON response
const res = (await bot.simulate('hello', { platform: T_ALISA })) as {
response: { text: string };
};
console.log(res.response.text); // 'Hello!'
For chat platforms (Telegram, VK, Viber, Max), simulate() enables skipAutoReply, so
no message is actually sent to the platform API — even if no token is set:
import { BotTest } from 'umbot/test';
import { TelegramAdapter, T_TELEGRAM } from 'umbot/plugins';
const bot = new BotTest();
bot.use(new TelegramAdapter('your-token'));
bot.addCommand('start', ['hello'], (_, ctx) => {
ctx.text = 'Hello!';
});
// For chat platforms the result is 'ok' (sending is skipped),
// and the response text stays in the controller
await bot.simulate('hello', { platform: T_TELEGRAM });
console.log(bot.getBotController()?.text); // 'Hello!'
simulate(query, options) parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
query |
string |
— | User text |
options.platform |
TAppType |
the constructor's platform or the first registered | The platform to generate the request for |
options.userId |
string |
'test_user' |
User ID |
options.count |
number |
0 |
Message number (0 — a new user/session) |
options.state |
object | string |
{} |
Prefilled session state |
The method returns the same result as run(): a JSON response for voice platforms,
and the string 'ok' for chat platforms, since sending to the API is skipped in simulation mode.
A more detailed example with platform setup and response checks:
import { BotTest } from 'umbot/test';
import { fullPlatforms, T_ALISA } from 'umbot/plugins';
import { MyController } from '../../src/controller/MyController';
describe('MyController', () => {
let bot: BotTest;
beforeAll(() => {
bot = new BotTest();
bot.use(fullPlatforms);
bot.setAppConfig({ isLocalStorage: true });
bot.setPlatformParams({
welcome_text: 'Hello!',
intents: [{ name: 'help', slots: ['help'] }],
});
bot.initBotController(MyController);
});
it('handles welcome', async () => {
const result = await bot.run(
T_ALISA,
JSON.stringify({
version: '1.0',
session: { message_id: 0, user_id: 'test-user' },
request: { command: 'hello', original_utterance: 'Hello' },
}),
);
expect(result).toBeDefined();
});
it('handles help command', async () => {
const result = await bot.run(
T_ALISA,
JSON.stringify({
version: '1.0',
session: { message_id: 1, user_id: 'test-user' },
request: { command: 'help', original_utterance: 'Help' },
}),
);
expect(result).toBeDefined();
});
});
To keep tests off the network and the disk, replace the context's HTTP client and FileAdapter file reading:
import { BotTest } from 'umbot/test';
import { fullPlatforms, FileAdapter } from 'umbot/plugins';
const bot = new BotTest();
bot.use(fullPlatforms);
// HTTP client mock: requests to platform APIs and external services do not go to the network
bot.getAppContext().httpClient = (): Promise<Response> =>
Promise.resolve(new Response(JSON.stringify({ ok: true, result: {} }), { status: 200 }));
// File database mock: tables are read from memory, not from disk
const tables: Record<string, Record<string, Record<string, unknown>>> = { UsersData: {} };
const adapter = new FileAdapter();
adapter.getFileData = (tableName) => {
const data = (tables[tableName] ??= {});
adapter.setCachedFileData(tableName, { data, version: Date.now(), isFileRead: true });
return data;
};
bot.use(adapter);
| Approach | When to use | What you get |
|---|---|---|
bot.test() |
Interactive debugging in the console | A real-time dialog, you type the text yourself |
bot.run(appType, content) |
Automated tests (Jest) | Programmatic access to the result, you can write assertions |
bot.setContent() + bot.run() |
Testing with preset content | Convenient for repeated tests |
Recommendation: use bot.run() for Jest tests — it gives you full control over the input and lets you check the result.
You can exit the testing mode in two ways:
exit in the consolethis.isEnd = true, the dialog ends automaticallyDepending on the options, BotTest prints:
response.text for voice platforms, text for chatbots)isShowResult: true): the full JSON responseisShowStorage: true): the contents of userData and stateisShowTime: true): request processing time in millisecondsFull reference — API v-3.1 · all versions.