{ "info": { "author": "Joscha G\u00f6tzer", "author_email": "joscha.goetzer@gmail.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6" ], "description": "=============\nTgIntegration\n=============\n\n.. image:: https://img.shields.io/pypi/v/tgintegration.svg\n :target: https://pypi.python.org/pypi/tgintegration\n\n.. image:: https://img.shields.io/travis/JosXa/tgintegration.svg\n :target: https://travis-ci.org/JosXa/tgintegration\n\n.. image:: https://readthedocs.org/projects/tgintegration/badge/?version=latest\n :target: https://tgintegration.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n.. image:: https://pyup.io/repos/github/JosXa/tgintegration/shield.svg\n :target: https://pyup.io/repos/github/JosXa/tgintegration/\n :alt: Updates\n\n\nAn Integration Test Framework for `Bots on Telegram Messenger `_\non top of `Pyrogram `_.\n\nNo more mocking of every single Bot API object, just test your bot in real-world scenarios.\n\n* Free software: MIT license\n\n.. * Documentation: https://tgintegration.readthedocs.io.\n\n\nFeatures\n--------\n\n* Log into a Telegram user account and interact with bots\n* Send messages and wait for the response\n* Perform inline queries and match the expected result\n* Automate everything about Telegram bots\n\nInstallation\n------------\n\nAll hail pip!\n\n.. code-block:: console\n\n $ pip install tgintegration --upgrade\n\nRequirements\n------------\n\n`Same as Pyrogram `_:\n\n- Python 3.4 or higher.\n- A `Telegram API key `_.\n\nUsage\n-----\n\nSuppose we want to write integration tests for `@BotListBot `_\nby sending it a couple of messages and asserting that it responds the way it should.\nFirst, let's create a ``BotIntegrationClient``:\n\n.. code-block:: python\n\n from tgintegration import BotIntegrationClient\n\n client = BotIntegrationClient(\n bot_under_test='@BotListBot',\n session_name='my_account', # Arbitrary file path to the Pyrogram session file\n api_id=API_ID, # See \"Requirements\" above, ...\n api_hash=API_HASH, # alternatively use a `config.ini` file\n max_wait_response=15, # Maximum timeout for bot responses\n min_wait_consecutive=2 # Minimum time to wait for consecutive messages\n )\n\n client.start()\n client.clear_chat() # Let's start with a blank screen\n\nNow let's send the ``/start`` command to the ``bot_under_test`` and \"await\" exactly three messages:\n\n.. code-block:: python\n\n response = client.send_command_await(\"start\", num_expected=3)\n\n assert response.num_messages == 3\n assert response.messages[0].sticker # First message is a sticker\n\nThe result should look like this:\n\n.. image:: https://github.com/JosXa/tgintegration/blob/master/docs/images/start_botlistbot.png\n :alt: Sending /start to @BotListBot\n\nLet's examine these buttons in the response...\n\n.. code-block:: python\n\n # Extract first (and only) inline keyboard from the replies\n inline_keyboard = response.inline_keyboards[0]\n\n # Three buttons in the first row\n assert len(inline_keyboard.rows[0]) == 3\n\nWe can also query and press the inline keyboard buttons:\n\n.. code-block:: python\n\n # Click the first button matching the pattern\n examples = response.inline_keyboards[0].press_button_await(pattern=r'.*Examples')\n\n assert \"Examples for contributing to the BotList\" in examples.full_text\n\nAs the bot edits the message, ``press_button_await`` automatically listens for ``MessageEdited``\nupdates and picks up on the edit, returning it as ``Response``.\n\n.. image:: https://github.com/JosXa/tgintegration/blob/master/docs/images/examples_botlistbot.png\n :alt: Get Examples from @BotListBot\n\nSo what happens when we send an invalid query or the bot fails to respond?\n\n.. code-block:: python\n\n try:\n # The following instruction will raise an `InvalidResponseError` after\n # `client.max_wait_response` seconds. This is because we passed `raise_no_response = True`\n # in the client initialization.\n client.send_command_await(\"ayylmao\", raise_=True)\n except InvalidResponseError:\n print(\"Raised.\") # Ok\n\nThe ``BotIntegrationClient`` is based off a regular Pyrogram ``Client``, meaning that,\nin addition to the ``send_*_await`` methods, all normal Pyro methods still work:\n\n.. code-block:: python\n\n client.send_message(client.bot_under_test, \"Hello from Pyrogram\")\n\n # `send_*_await` methods automatically use the `bot_under_test` as peer:\n res = client.send_message_await(\"Hello from TgIntegration\", max_wait=2, raise_=False)\n # If `raise_` is explicitly set to False, no exception is raised:\n assert res.empty\n # Note that when no response is expected and no validation thereof is necessary, ...\n client.send_photo_await(\"media/photo.jpg\", max_wait=0, raise_=False)\n client.send_voice_await(\"media/voice.ogg\", max_wait=0, raise_=False)\n # ... it makes more sense to use the \"unawaitable\" methods:\n client.send_photo(client.bot_under_test, \"media/photo.jpg\")\n client.send_voice(client.bot_under_test, \"media/voice.ogg\")\n\n\n\n\nCustom awaitable actions\n========================\n\nThe main logic for the timeout between sending a message and receiving a response from the user\nis handled in the ``act_await_response`` method:\n\n.. code-block:: python\n\n def act_await_response(self, action: AwaitableAction) -> Response: ...\n\nIt expects an ``AwaitableAction`` which is a plan for a message to be sent, while the\n``BotIntegrationClient`` just makes it easy and removes a lot of the boilerplate code to\ncreate these actions.\n\nAfter executing the action, the client collects all incoming messages that match the ``filters``\nand adds them to the response. Thus you can think of a ``Response`` object as a collection of\nmessages returned by the peer in reaction to the executed ``AwaitableAction``.\n\n.. code-block:: python\n\n from tgintegration import AwaitableAction, Response\n from pyrogram import Filters\n\n peer = '@BotListBot'\n\n action = AwaitableAction(\n func=client.send_message,\n kwargs=dict(\n chat_id=peer,\n text=\"**Hello World**\",\n parse_mode=\"markdown\"\n ),\n # Wait for messages only by the peer we're interacting with\n filters=Filters.user(peer) & Filters.incoming,\n # Time out and raise after 15 seconds\n max_wait=15\n )\n\n response = client.act_await_response(action) # type: Response\n\n\n\nIntegrating with test frameworks\n--------------------------------\n\nTODO\n\n* py.test\n* unittest\n\n\nCredits\n-------\n\nThis package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.\n\n.. _Cookiecutter: https://github.com/audreyr/cookiecutter\n.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage\n\n\n\n=======\nHistory\n=======\n\n0.1.0 (2018-04-30)\n------------------\n\n* First release on PyPI.\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/JosXa/tgintegration", "keywords": "test,telegram,integration,bot,automation", "license": "MIT license", "maintainer": "", "maintainer_email": "", "name": "tgintegration", "package_url": "https://pypi.org/project/tgintegration/", "platform": "", "project_url": "https://pypi.org/project/tgintegration/", "project_urls": { "Homepage": "https://github.com/JosXa/tgintegration" }, "release_url": "https://pypi.org/project/tgintegration/0.2.4/", "requires_dist": [ "pyrogram (>=0.7.4)" ], "requires_python": "", "summary": "An Integration Test Library for Telegram Messenger Bots on top of Pyrogram.", "version": "0.2.4" }, "last_serial": 3947950, "releases": { "0.1.2": [ { "comment_text": "", "digests": { "md5": "c8a94ef4af72cb89fc841f6ec5a6b458", "sha256": "c68af6c085c087a8e524d93e183504e284106dd7917b0a7868d3092b96a04d2b" }, "downloads": -1, "filename": "tgintegration-0.1.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c8a94ef4af72cb89fc841f6ec5a6b458", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11748, "upload_time": "2018-04-30T22:53:20", "url": "https://files.pythonhosted.org/packages/9d/02/1831e3c46d2d184e4889cbeef6530cdb1f6319b0ae1015dae4da5a1f77ac/tgintegration-0.1.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "67f272d88e77d11815046fbd25166cec", "sha256": "8a54737ff26e2b78a185df33116b5ddf22c82da4589c615070b1f224bb144b1a" }, "downloads": -1, "filename": "tgintegration-0.1.2.tar.gz", "has_sig": false, "md5_digest": "67f272d88e77d11815046fbd25166cec", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 171063, "upload_time": "2018-04-30T22:53:21", "url": "https://files.pythonhosted.org/packages/5a/98/14dec61773230e80e9e364a616cf62676a9a4ec953dd20eb121f327938de/tgintegration-0.1.2.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "457a313ad223ad84b78aa44dffaaa986", "sha256": "0e63659e072d053d5601f959df68810f8fa537ef311f5af271eee2eac9a7b929" }, "downloads": -1, "filename": "tgintegration-0.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "457a313ad223ad84b78aa44dffaaa986", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 30104, "upload_time": "2018-05-10T23:24:14", "url": "https://files.pythonhosted.org/packages/8d/b2/cd71469fb9e027f83d5a6061281554faabd8e6e153423910a5552db2ad20/tgintegration-0.2.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f44905f3aab89a08219c9fb73c9708fd", "sha256": "98ade108a335194b3257a6e5b9630d3630c0502512502229f03d8a49b056385b" }, "downloads": -1, "filename": "tgintegration-0.2.0.tar.gz", "has_sig": false, "md5_digest": "f44905f3aab89a08219c9fb73c9708fd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 178463, "upload_time": "2018-05-10T23:24:16", "url": "https://files.pythonhosted.org/packages/ad/44/2c2a303640e1cdbc616fd8413773dea6e1e7c07b996ea9d3b4591dd7518f/tgintegration-0.2.0.tar.gz" } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "17a57173838635829e339e6a959057af", "sha256": "89ff0d3fb9ca6694216bd396a14d1c3c3dcbc7691744949c74c4d206a0052b52" }, "downloads": -1, "filename": "tgintegration-0.2.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "17a57173838635829e339e6a959057af", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 42494, "upload_time": "2018-05-27T13:59:14", "url": "https://files.pythonhosted.org/packages/94/fe/524dbe8c7dfc8c031a7ebda3049ebe3a0cb939b9e66d388df75f971179ef/tgintegration-0.2.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8ffcf5785d158ea2582ecf887af97363", "sha256": "73f7f9c0bb935bb4f270b28a8f78a312582531a0661072951548517a0da72675" }, "downloads": -1, "filename": "tgintegration-0.2.2.tar.gz", "has_sig": false, "md5_digest": "8ffcf5785d158ea2582ecf887af97363", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 182577, "upload_time": "2018-05-27T13:59:16", "url": "https://files.pythonhosted.org/packages/02/b8/7e936b5c22a1807c4ffbc77b32dc839a0780b27c4325340d2cf76bb70711/tgintegration-0.2.2.tar.gz" } ], "0.2.3": [ { "comment_text": "", "digests": { "md5": "e52efab625824b29530600786784fd22", "sha256": "b05a54046096d2c9b25856aeed38449000b5f5eff2fc1bb76e5350e5240c5f35" }, "downloads": -1, "filename": "tgintegration-0.2.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "e52efab625824b29530600786784fd22", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 42634, "upload_time": "2018-05-31T14:22:18", "url": "https://files.pythonhosted.org/packages/35/89/d4b4483997a395bfb41e21276fefde4180b575f2298101a77c00247a0f70/tgintegration-0.2.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5391e5d962350cc7c6ecd2fc5b9b4c94", "sha256": "0f71e53103d64e7dd6e4901a5d32d4d70c3bbd2ef4924dde3665c27ffa7a22c3" }, "downloads": -1, "filename": "tgintegration-0.2.3.tar.gz", "has_sig": false, "md5_digest": "5391e5d962350cc7c6ecd2fc5b9b4c94", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 182634, "upload_time": "2018-05-31T14:22:19", "url": "https://files.pythonhosted.org/packages/b7/40/b141035b819d2cb10440001bf1eb20f0273adc3cd796e9d5f375e5fcd072/tgintegration-0.2.3.tar.gz" } ], "0.2.4": [ { "comment_text": "", "digests": { "md5": "acaae98bec600e3c54ae74c01ff3011f", "sha256": "436e974d9f873a9a027c38cc8c5a859f6a7de7fda1eddcaa5f72daa4f003d9ef" }, "downloads": -1, "filename": "tgintegration-0.2.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "acaae98bec600e3c54ae74c01ff3011f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 42917, "upload_time": "2018-06-10T18:45:30", "url": "https://files.pythonhosted.org/packages/0f/83/b782311c4ab6b39436bd8238fa937ec3a4f57fe15cc0bf4f52c3c859f4b6/tgintegration-0.2.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "665c97c65f1b6c035c9206791717fdf5", "sha256": "12a498ef3b4e0bf27600bcf75b0dd4ad968a6a1e3c6e96668a2524fe8a3a14e2" }, "downloads": -1, "filename": "tgintegration-0.2.4.tar.gz", "has_sig": false, "md5_digest": "665c97c65f1b6c035c9206791717fdf5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 182767, "upload_time": "2018-06-10T18:45:32", "url": "https://files.pythonhosted.org/packages/37/73/f867427cc04aee127a6dd14e9a93c539b27d12098338af04640c0a50df3f/tgintegration-0.2.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "acaae98bec600e3c54ae74c01ff3011f", "sha256": "436e974d9f873a9a027c38cc8c5a859f6a7de7fda1eddcaa5f72daa4f003d9ef" }, "downloads": -1, "filename": "tgintegration-0.2.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "acaae98bec600e3c54ae74c01ff3011f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 42917, "upload_time": "2018-06-10T18:45:30", "url": "https://files.pythonhosted.org/packages/0f/83/b782311c4ab6b39436bd8238fa937ec3a4f57fe15cc0bf4f52c3c859f4b6/tgintegration-0.2.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "665c97c65f1b6c035c9206791717fdf5", "sha256": "12a498ef3b4e0bf27600bcf75b0dd4ad968a6a1e3c6e96668a2524fe8a3a14e2" }, "downloads": -1, "filename": "tgintegration-0.2.4.tar.gz", "has_sig": false, "md5_digest": "665c97c65f1b6c035c9206791717fdf5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 182767, "upload_time": "2018-06-10T18:45:32", "url": "https://files.pythonhosted.org/packages/37/73/f867427cc04aee127a6dd14e9a93c539b27d12098338af04640c0a50df3f/tgintegration-0.2.4.tar.gz" } ] }