mirror of https://github.com/home-assistant/core
252 lines
6.9 KiB
Python
252 lines
6.9 KiB
Python
"""Tests for the telegram_bot integration."""
|
|
|
|
from collections.abc import AsyncGenerator, Generator
|
|
from datetime import datetime
|
|
from typing import Any
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from telegram import Bot, Chat, Message, User
|
|
from telegram.constants import ChatType
|
|
|
|
from homeassistant.components.telegram_bot import (
|
|
CONF_ALLOWED_CHAT_IDS,
|
|
CONF_TRUSTED_NETWORKS,
|
|
DOMAIN,
|
|
)
|
|
from homeassistant.const import (
|
|
CONF_API_KEY,
|
|
CONF_PLATFORM,
|
|
CONF_URL,
|
|
EVENT_HOMEASSISTANT_START,
|
|
)
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
|
|
@pytest.fixture
|
|
def config_webhooks() -> dict[str, Any]:
|
|
"""Fixture for a webhooks platform configuration."""
|
|
return {
|
|
DOMAIN: [
|
|
{
|
|
CONF_PLATFORM: "webhooks",
|
|
CONF_URL: "https://test",
|
|
CONF_TRUSTED_NETWORKS: ["127.0.0.1"],
|
|
CONF_API_KEY: "1234567890:ABC",
|
|
CONF_ALLOWED_CHAT_IDS: [
|
|
# "me"
|
|
12345678,
|
|
# Some chat
|
|
-123456789,
|
|
],
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def config_polling() -> dict[str, Any]:
|
|
"""Fixture for a polling platform configuration."""
|
|
return {
|
|
DOMAIN: [
|
|
{
|
|
CONF_PLATFORM: "polling",
|
|
CONF_API_KEY: "1234567890:ABC",
|
|
CONF_ALLOWED_CHAT_IDS: [
|
|
# "me"
|
|
12345678,
|
|
# Some chat
|
|
-123456789,
|
|
],
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_register_webhook() -> Generator[None]:
|
|
"""Mock calls made by telegram_bot when (de)registering webhook."""
|
|
with (
|
|
patch(
|
|
"homeassistant.components.telegram_bot.webhooks.PushBot.register_webhook",
|
|
return_value=True,
|
|
),
|
|
patch(
|
|
"homeassistant.components.telegram_bot.webhooks.PushBot.deregister_webhook",
|
|
return_value=True,
|
|
),
|
|
):
|
|
yield
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_external_calls() -> Generator[None]:
|
|
"""Mock calls that make calls to the live Telegram API."""
|
|
test_user = User(123456, "Testbot", True)
|
|
message = Message(
|
|
message_id=12345,
|
|
date=datetime.now(),
|
|
chat=Chat(id=123456, type=ChatType.PRIVATE),
|
|
)
|
|
|
|
class BotMock(Bot):
|
|
"""Mock bot class."""
|
|
|
|
__slots__ = ()
|
|
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
"""Initialize BotMock instance."""
|
|
super().__init__(*args, **kwargs)
|
|
self._bot_user = test_user
|
|
|
|
with (
|
|
patch("homeassistant.components.telegram_bot.Bot", BotMock),
|
|
patch.object(BotMock, "get_me", return_value=test_user),
|
|
patch.object(BotMock, "bot", test_user),
|
|
patch.object(BotMock, "send_message", return_value=message),
|
|
patch("telegram.ext.Updater._bootstrap"),
|
|
):
|
|
yield
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_generate_secret_token() -> Generator[str]:
|
|
"""Mock secret token generated for webhook."""
|
|
mock_secret_token = "DEADBEEF12345678DEADBEEF87654321"
|
|
with patch(
|
|
"homeassistant.components.telegram_bot.webhooks.secrets.choice",
|
|
side_effect=mock_secret_token,
|
|
):
|
|
yield mock_secret_token
|
|
|
|
|
|
@pytest.fixture
|
|
def incorrect_secret_token():
|
|
"""Mock incorrect secret token."""
|
|
return "AAAABBBBCCCCDDDDEEEEFFFF00009999"
|
|
|
|
|
|
@pytest.fixture
|
|
def update_message_command():
|
|
"""Fixture for mocking an incoming update of type message/command."""
|
|
return {
|
|
"update_id": 1,
|
|
"message": {
|
|
"message_id": 1,
|
|
"from": {
|
|
"id": 12345678,
|
|
"is_bot": False,
|
|
"first_name": "Firstname",
|
|
"username": "some_username",
|
|
"language_code": "en",
|
|
},
|
|
"chat": {
|
|
"id": -123456789,
|
|
"title": "SomeChat",
|
|
"type": "group",
|
|
"all_members_are_administrators": True,
|
|
},
|
|
"date": 1644518189,
|
|
"text": "/command",
|
|
"entities": [
|
|
{
|
|
"type": "bot_command",
|
|
"offset": 0,
|
|
"length": 7,
|
|
}
|
|
],
|
|
},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def update_message_text():
|
|
"""Fixture for mocking an incoming update of type message/text."""
|
|
return {
|
|
"update_id": 1,
|
|
"message": {
|
|
"message_id": 1,
|
|
"date": 1441645532,
|
|
"from": {
|
|
"id": 12345678,
|
|
"is_bot": False,
|
|
"last_name": "Test Lastname",
|
|
"first_name": "Test Firstname",
|
|
"username": "Testusername",
|
|
},
|
|
"chat": {
|
|
"last_name": "Test Lastname",
|
|
"id": 1111111,
|
|
"type": "private",
|
|
"first_name": "Test Firstname",
|
|
"username": "Testusername",
|
|
},
|
|
"text": "HELLO",
|
|
},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def unauthorized_update_message_text(update_message_text):
|
|
"""Fixture for mocking an incoming update of type message/text that is not in our `allowed_chat_ids`."""
|
|
update_message_text["message"]["from"]["id"] = 1234
|
|
update_message_text["message"]["chat"]["id"] = 1234
|
|
return update_message_text
|
|
|
|
|
|
@pytest.fixture
|
|
def update_callback_query():
|
|
"""Fixture for mocking an incoming update of type callback_query."""
|
|
return {
|
|
"update_id": 1,
|
|
"callback_query": {
|
|
"id": "4382bfdwdsb323b2d9",
|
|
"from": {
|
|
"id": 12345678,
|
|
"type": "private",
|
|
"is_bot": False,
|
|
"last_name": "Test Lastname",
|
|
"first_name": "Test Firstname",
|
|
"username": "Testusername",
|
|
},
|
|
"chat_instance": "aaa111",
|
|
"data": "Data from button callback",
|
|
"inline_message_id": "1234csdbsk4839",
|
|
},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
async def webhook_platform(
|
|
hass: HomeAssistant,
|
|
config_webhooks: dict[str, Any],
|
|
mock_register_webhook: None,
|
|
mock_external_calls: None,
|
|
mock_generate_secret_token: str,
|
|
) -> AsyncGenerator[None]:
|
|
"""Fixture for setting up the webhooks platform using appropriate config and mocks."""
|
|
await async_setup_component(
|
|
hass,
|
|
DOMAIN,
|
|
config_webhooks,
|
|
)
|
|
await hass.async_block_till_done()
|
|
yield
|
|
await hass.async_stop()
|
|
|
|
|
|
@pytest.fixture
|
|
async def polling_platform(
|
|
hass: HomeAssistant, config_polling: dict[str, Any], mock_external_calls: None
|
|
) -> None:
|
|
"""Fixture for setting up the polling platform using appropriate config and mocks."""
|
|
await async_setup_component(
|
|
hass,
|
|
DOMAIN,
|
|
config_polling,
|
|
)
|
|
# Fire this event to start polling
|
|
hass.bus.fire(EVENT_HOMEASSISTANT_START)
|
|
await hass.async_block_till_done()
|