From 19b60ad3b39e89171b27976f32f954a1e651995b Mon Sep 17 00:00:00 2001 From: Ovv Date: Fri, 12 Jul 2019 16:50:43 +0200 Subject: [PATCH] Update pytest plugin --- .isort.cfg | 4 + README.rst | 2 +- docs/testing.rst | 74 ++++---- slack/tests/conftest.py | 156 ++++++++++------- slack/tests/data/methods.py | 211 ++++++++++++++++++++++ slack/tests/plugin.py | 12 +- slack/tests/test_actions.py | 56 +++--- slack/tests/test_commands.py | 44 ++--- slack/tests/test_events.py | 130 +++++++------- slack/tests/test_examples.py | 114 ++++++++++++ slack/tests/test_io.py | 328 +++++++++++++++++++---------------- slack/tests/test_sansio.py | 26 +-- tox.ini | 9 +- 13 files changed, 779 insertions(+), 387 deletions(-) create mode 100644 slack/tests/test_examples.py diff --git a/.isort.cfg b/.isort.cfg index 8eb3479..7592462 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -6,3 +6,7 @@ no_lines_before=FIRSTPARTY skip=docs/conf.py skip_glob=.tox,.eggs,build not_skip=__init__.py +multi_line_output=3 +include_trailing_comma=True +force_grid_wrap=0 +use_parentheses=True diff --git a/README.rst b/README.rst index 7019915..6fb7acf 100644 --- a/README.rst +++ b/README.rst @@ -44,7 +44,7 @@ Quickstart from slack.io.sync import SlackAPI session = requests.session() - slack_client = SlackAPI(token=TOKEN, session=session) + client = SlackAPI(token=TOKEN, session=session) data = client.query(slack.methods.AUTH_TEST) pprint.pprint(data) diff --git a/docs/testing.rst b/docs/testing.rst index 8f9cf6b..ba163e5 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -25,19 +25,15 @@ Available fixtures This fixture can be parametrized to return one or more available event from :class:`slack.tests.data.Events` and :class:`slack.tests.data.Messages`. - .. code:: python - - @pytest.mark.parametrize('slack_event', ('channel_deleted', 'simple'), indirect=True) - def test_events(slack_event): - assert True + .. literalinclude:: ../slack/tests/test_examples.py + :start-after: # START: TEST EVENTS + :end-before: # END: TEST EVENTS To only get :class:`slack.tests.data.Messages` members you can parametrize the test that way: - .. code:: python - - @pytest.mark.parametrize("slack_event", {**slack.tests.data.Messages.__members__}, indirect=True) - async def test_messages(self, slack_event): - assert slack_event["event"]["type"] == "message" + .. literalinclude:: ../slack/tests/test_examples.py + :start-after: # START: TEST MESSAGES + :end-before: # END: TEST MESSAGES .. function:: slack.tests.plugin.slack_action @@ -47,11 +43,9 @@ Available fixtures This fixture can be parametrized to return one or more available action from :class:`slack.tests.data.InteractiveMessage` or :class:`slack.tests.data.DialogSubmission`. - .. code:: python - - @pytest.mark.parametrize('slack_action', ('button_ok', 'button_cancel'), indirect=True) - def test_actions(slack_action): - assert True + .. literalinclude:: ../slack/tests/test_examples.py + :start-after: # START: TEST ACTIONS + :end-before: # END: TEST ACTIONS .. function:: slack.tests.plugin.slack_command @@ -60,11 +54,9 @@ Available fixtures This fixture can be parametrized to return one or more available command from :class:`slack.tests.data.Commands`. - .. code:: python - - @pytest.mark.parametrize('slack_command', ('text', 'no_text'), indirect=True) - def test_commands(slack_command): - assert True + .. literalinclude:: ../slack/tests/test_examples.py + :start-after: # START: TEST COMMANDS + :end-before: # END: TEST COMMANDS .. function:: slack.tests.plugin.slack_client @@ -76,33 +68,35 @@ Available fixtures - body: ``{'ok': True}`` - headers: ``{'content-type': 'application/json; charset=utf-8'}`` - This can be parametrize with the ``_request`` parameter. - - .. code:: python + Parametrize a reponse: - @pytest.mark.asyncio - @pytest.mark.parametrize('slack_client', ({'_request': {'body': {'ok': True, 'hello': 'world'}}},), - indirect=True) - async def test_client(slack_client): - data = await slack_client.query(slack.methods.AUTH_TEST) - assert data == {'ok': True, 'hello': 'world'} + .. literalinclude:: ../slack/tests/test_examples.py + :start-after: # START: TEST CLIENT CUSTOM BODY + :end-before: # END: TEST CLIENT CUSTOM BODY The ``body`` parameter of a request can be a string corresponding to one of the methods available in :class:`slack.tests.data.Methods`. - For multiple requests you can set the ``_request`` parameter to a ``list``. + .. literalinclude:: ../slack/tests/test_examples.py + :start-after: # START: TEST CLIENT BODY + :end-before: # END: TEST CLIENT BODY + + Parametrize multiple responses: + + .. literalinclude:: ../slack/tests/test_examples.py + :start-after: # START: TEST CLIENT STATUS + :end-before: # END: TEST CLIENT STATUS + + .. literalinclude:: ../slack/tests/test_examples.py + :start-after: # START: TEST CLIENT ITER + :end-before: # END: TEST CLIENT ITER + + Parametrize multiple run: - .. code:: python + .. literalinclude:: ../slack/tests/test_examples.py + :start-after: # START: TEST CLIENT MULTIPLE RUN + :end-before: # END: TEST CLIENT MULTIPLE RUN - @pytest.mark.asyncio - @pytest.mark.parametrize('slack_client', ({'_request': [ - {'body': 'channels'}, - {'status': 500} - ]},), indirect=True) - async def test_client(slack_client): - data1 = await slack_client.query(slack.methods.AUTH_TEST) - with pytest.raises(slack.exceptions.HTTPException): - await slack_client.query(slack.methods.AUTH_TEST) Available data ============== diff --git a/slack/tests/conftest.py b/slack/tests/conftest.py index 9a8ba25..7d8a38e 100644 --- a/slack/tests/conftest.py +++ b/slack/tests/conftest.py @@ -1,25 +1,21 @@ import copy import json import time -import functools from unittest.mock import Mock import pytest -import requests import asynctest -from slack.events import Event, EventRouter, MessageRouter +from slack.events import EventRouter, MessageRouter from slack.io.abc import SlackAPI -from slack.actions import Action from slack.actions import Router as ActionRouter from slack.commands import Router as CommandRouter -from slack.commands import Command from . import data try: from slack.io.requests import SlackAPI as SlackAPIRequest except ImportError: - SlackAPIRequest = None # type: ignore + SlackAPIRequest = int # type: ignore TOKEN = "abcdefg" @@ -53,83 +49,117 @@ def events(url): return events -@pytest.fixture(params=(FakeIO,)) -def io_client(request): - return request.param +@pytest.fixture(params=({},)) +def slack_client(request): + if "status" not in request.param: + request.param["status"] = 200 -@pytest.fixture(params=({"token": TOKEN},)) -def client(request, io_client): - default_request = { - "status": 200, - "body": {"ok": True}, - "headers": {"content-type": "application/json; charset=utf-8"}, - } + if "body" not in request.param: + request.param["body"] = {"ok": True} - if "_request" not in request.param: - request.param["_request"] = default_request - elif isinstance(request.param["_request"], dict): - request.param["_request"] = _default_response(request.param["_request"]) - elif isinstance(request.param["_request"], list): - for index, item in enumerate(request.param["_request"]): - request.param["_request"][index] = _default_response(item) - else: - raise ValueError("Invalid `_request` parameters: %s", request.param["_request"]) + if "headers" not in request.param: + request.param["headers"] = {"content-type": "application/json; charset=utf-8"} - if "token" not in request.param: - request.param["token"] = TOKEN + client_param = request.param.get("client_parameters", {}) + if "token" not in client_param: + client_param["token"] = TOKEN - slackclient = io_client( - **{k: v for k, v in request.param.items() if not k.startswith("_")} - ) + if "client" in request.param: + client = request.param["client"] + else: + client = FakeIO - if isinstance(request.param["_request"], dict): - return_value = ( - request.param["_request"]["status"], - json.dumps(request.param["_request"]["body"]).encode(), - request.param["_request"]["headers"], + slackclient = client(**client_param) + + if all( + isinstance(value, list) + for value in ( + request.param["status"], + request.param["body"], + request.param["headers"], ) + ): + responses = [] + for status, body, headers in zip( + request.param["status"], request.param["body"], request.param["headers"] + ): + responses.append((status, json.dumps(_fill_body(body)).encode(), headers)) + if isinstance(slackclient, SlackAPIRequest): - slackclient._request = Mock(return_value=return_value) + slackclient._request = Mock(side_effect=responses) else: - slackclient._request = asynctest.CoroutineMock(return_value=return_value) - else: - responses = [ - ( - response["status"], - json.dumps(response["body"]).encode(), - response["headers"], + slackclient._request = asynctest.CoroutineMock(side_effect=responses) + elif any( + isinstance(value, list) + for value in ( + request.param["status"], + request.param["body"], + request.param["headers"], + ) + ): + if not isinstance(request.param["status"], list): + request.param["status"] = [request.param["status"]] + if not isinstance(request.param["body"], list): + request.param["body"] = [request.param["body"]] + if not isinstance(request.param["headers"], list): + request.param["headers"] = [request.param["headers"]] + + responses = list() + for index, _ in enumerate( + max( + request.param["status"], + request.param["body"], + request.param["headers"], + key=lambda x: len(x), ) - for response in request.param["_request"] - ] + ): + try: + status = request.param["status"][index] + except IndexError: + status = request.param["status"][0] + + try: + body = request.param["body"][index] + except IndexError: + body = request.param["body"][0] + + try: + headers = request.param["headers"][index] + except IndexError: + headers = request.param["headers"][0] + + responses.append((status, json.dumps(_fill_body(body)).encode(), headers)) + if isinstance(slackclient, SlackAPIRequest): slackclient._request = Mock(side_effect=responses) else: slackclient._request = asynctest.CoroutineMock(side_effect=responses) + else: + return_value = ( + request.param["status"], + json.dumps(_fill_body(request.param["body"])).encode(), + request.param["headers"], + ) + if isinstance(slackclient, SlackAPIRequest): + slackclient._request = Mock(return_value=return_value) + else: + slackclient._request = asynctest.CoroutineMock(return_value=return_value) + print(return_value) return slackclient -def _default_response(response): - default_response = { - "status": 200, - "body": {"ok": True}, - "headers": {"content-type": "application/json; charset=utf-8"}, - } - response = {**default_response, **response} - if "content-type" not in response["headers"]: - response["headers"]["content-type"] = default_response["headers"][ - "content-type" - ] - if isinstance(response["body"], str): - response["body"] = copy.deepcopy(data.Methods[response["body"]].value) - return response +def _fill_body(body): + if isinstance(body, str): + body = copy.deepcopy(data.Methods[body].value) + return body @pytest.fixture( params={**data.Events.__members__, **data.Messages.__members__} # type: ignore ) -def event(request): +def slack_event(request): if isinstance(request.param, str): try: payload = copy.deepcopy(data.Events[request.param].value) @@ -142,7 +172,7 @@ def event(request): @pytest.fixture(params={**data.Messages.__members__}) # type: ignore -def message(request): +def slack_message(request): if isinstance(request.param, str): payload = copy.deepcopy(data.Messages[request.param].value) else: @@ -178,7 +208,7 @@ def message_router(): **data.MessageAction.__members__, # type: ignore } ) -def action(request): +def slack_action(request): if isinstance(request.param, str): try: payload = copy.deepcopy(data.InteractiveMessage[request.param].value) @@ -219,7 +249,7 @@ def action_router(): @pytest.fixture(params={**data.Commands.__members__}) -def command(request): +def slack_command(request): if isinstance(request.param, str): payload = copy.deepcopy(data.Commands[request.param].value) else: diff --git a/slack/tests/data/methods.py b/slack/tests/data/methods.py index 375e895..1fd5322 100644 --- a/slack/tests/data/methods.py +++ b/slack/tests/data/methods.py @@ -93,6 +93,213 @@ }, } +USERS = { + "ok": True, + "members": [ + { + "id": "W012A3CDE", + "team_id": "T012AB3C4", + "name": "spengler", + "deleted": False, + "color": "9f69e7", + "real_name": "spengler", + "tz": "America/Los_Angeles", + "tz_label": "Pacific Daylight Time", + "tz_offset": -25200, + "profile": { + "avatar_hash": "ge3b51ca72de", + "status_text": "Print is dead", + "status_emoji": ":books:", + "real_name": "Egon Spengler", + "display_name": "spengler", + "real_name_normalized": "Egon Spengler", + "display_name_normalized": "spengler", + "email": "spengler@ghostbusters.example.com", + "image_24": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_32": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_48": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_72": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_192": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_512": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "team": "T012AB3C4", + }, + "is_admin": True, + "is_owner": False, + "is_primary_owner": False, + "is_restricted": False, + "is_ultra_restricted": False, + "is_bot": False, + "updated": 1502138686, + "is_app_user": False, + "has_2fa": False, + }, + { + "id": "W07QCRPA4", + "team_id": "T0G9PQBBK", + "name": "glinda", + "deleted": False, + "color": "9f69e7", + "real_name": "Glinda Southgood", + "tz": "America/Los_Angeles", + "tz_label": "Pacific Daylight Time", + "tz_offset": -25200, + "profile": { + "avatar_hash": "8fbdd10b41c6", + "image_24": "https://a.slack-edge.com...png", + "image_32": "https://a.slack-edge.com...png", + "image_48": "https://a.slack-edge.com...png", + "image_72": "https://a.slack-edge.com...png", + "image_192": "https://a.slack-edge.com...png", + "image_512": "https://a.slack-edge.com...png", + "image_1024": "https://a.slack-edge.com...png", + "image_original": "https://a.slack-edge.com...png", + "first_name": "Glinda", + "last_name": "Southgood", + "title": "Glinda the Good", + "phone": "", + "skype": "", + "real_name": "Glinda Southgood", + "real_name_normalized": "Glinda Southgood", + "display_name": "Glinda the Fairly Good", + "display_name_normalized": "Glinda the Fairly Good", + "email": "glenda@south.oz.coven", + }, + "is_admin": True, + "is_owner": False, + "is_primary_owner": False, + "is_restricted": False, + "is_ultra_restricted": False, + "is_bot": False, + "updated": 1480527098, + "has_2fa": False, + }, + { + "id": "W012A3CDE", + "team_id": "T012AB3C4", + "name": "spengler", + "deleted": True, + "color": "9f69e7", + "real_name": "spengler", + "tz": "America/Los_Angeles", + "tz_label": "Pacific Daylight Time", + "tz_offset": -25200, + "profile": { + "avatar_hash": "ge3b51ca72de", + "status_text": "Print is dead", + "status_emoji": ":books:", + "real_name": "Egon Spengler", + "display_name": "spengler", + "real_name_normalized": "Egon Spengler", + "display_name_normalized": "spengler", + "email": "spengler@ghostbusters.example.com", + "image_24": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_32": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_48": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_72": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_192": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "image_512": "https://.../avatar/e3b51ca72dee4ef87916ae2b9240df50.jpg", + "team": "T012AB3C4", + }, + "is_admin": True, + "is_owner": False, + "is_primary_owner": False, + "is_restricted": False, + "is_ultra_restricted": False, + "is_bot": False, + "updated": 1502138686, + "is_app_user": False, + "has_2fa": False, + }, + ], +} + +USERS_ITER = { + "ok": True, + "response_metadata": {"next_cursor": "wxyz"}, + "members": [ + { + "id": "W07QCRPA4", + "team_id": "T0G9PQBBK", + "name": "glinda", + "deleted": False, + "color": "9f69e7", + "real_name": "Glinda Southgood", + "tz": None, + "tz_label": "Pacific Daylight Time", + "tz_offset": -25200, + "profile": { + "avatar_hash": "8fbdd10b41c6", + "image_24": "https://a.slack-edge.com...png", + "image_32": "https://a.slack-edge.com...png", + "image_48": "https://a.slack-edge.com...png", + "image_72": "https://a.slack-edge.com...png", + "image_192": "https://a.slack-edge.com...png", + "image_512": "https://a.slack-edge.com...png", + "image_1024": "https://a.slack-edge.com...png", + "image_original": "https://a.slack-edge.com...png", + "first_name": "Glinda", + "last_name": "Southgood", + "title": "Glinda the Good", + "phone": "", + "skype": "", + "real_name": "Glinda Southgood", + "real_name_normalized": "Glinda Southgood", + "display_name": "Glinda the Fairly Good", + "display_name_normalized": "Glinda the Fairly Good", + "email": "glenda@south.oz.coven", + }, + "is_admin": True, + "is_owner": False, + "is_primary_owner": False, + "is_restricted": False, + "is_ultra_restricted": False, + "is_bot": False, + "updated": 1480527098, + "has_2fa": False, + }, + { + "id": "W07QCRPA4", + "team_id": "T0G9PQBBK", + "name": "glinda", + "deleted": False, + "color": "9f69e7", + "real_name": "Glinda Southgood", + "tz": "America/Los_Angeles", + "tz_label": "Pacific Daylight Time", + "tz_offset": -25200, + "profile": { + "avatar_hash": "8fbdd10b41c6", + "image_24": "https://a.slack-edge.com...png", + "image_32": "https://a.slack-edge.com...png", + "image_48": "https://a.slack-edge.com...png", + "image_72": "https://a.slack-edge.com...png", + "image_192": "https://a.slack-edge.com...png", + "image_512": "https://a.slack-edge.com...png", + "image_1024": "https://a.slack-edge.com...png", + "image_original": "https://a.slack-edge.com...png", + "first_name": "Glinda", + "last_name": "Southgood", + "title": "Glinda the Good", + "phone": "", + "skype": "", + "real_name": "Glinda Southgood", + "real_name_normalized": "Glinda Southgood", + "display_name": "Glinda the Fairly Good", + "display_name_normalized": "Glinda the Fairly Good", + "email": "glenda@south.oz.coven", + }, + "is_admin": True, + "is_owner": False, + "is_primary_owner": False, + "is_restricted": False, + "is_ultra_restricted": False, + "is_bot": True, + "updated": 1480527098, + "has_2fa": False, + }, + ], +} + AUTH_TEST = { "ok": True, "url": "https://testteam.slack.com/", @@ -116,6 +323,8 @@ class Methods(Enum): - channels - channels_iter (channels with a cursor) + - users + - users_iter (users with a cursor) - users_info - auth_test - rtm_connect @@ -124,6 +333,8 @@ class Methods(Enum): channels_iter = CHANNELS_ITER channels = CHANNELS + users_iter = USERS_ITER + users = USERS users_info = USERS_INFO auth_test = AUTH_TEST rtm_connect = RTM_CONNECT diff --git a/slack/tests/plugin.py b/slack/tests/plugin.py index 584ef68..1890a98 100644 --- a/slack/tests/plugin.py +++ b/slack/tests/plugin.py @@ -1,8 +1,10 @@ import pytest from . import data -from .conftest import event as slack_event -from .conftest import action as slack_action -from .conftest import client as slack_client -from .conftest import command as slack_command -from .conftest import message as slack_message +from .conftest import ( + slack_event, + slack_action, + slack_client, + slack_command, + slack_message, +) diff --git a/slack/tests/test_actions.py b/slack/tests/test_actions.py index 0e66961..e3127ed 100644 --- a/slack/tests/test_actions.py +++ b/slack/tests/test_actions.py @@ -6,37 +6,39 @@ class TestActions: - def test_from_http(self, action): - act = Action.from_http(action) + def test_from_http(self, slack_action): + act = Action.from_http(slack_action) assert isinstance(act, slack.actions.Action) - def test_parsing_token(self, action): - slack.actions.Action.from_http(action, verification_token="supersecuretoken") + def test_parsing_token(self, slack_action): + slack.actions.Action.from_http( + slack_action, verification_token="supersecuretoken" + ) - def test_parsing_team_id(self, action): - slack.actions.Action.from_http(action, team_id="T000AAA0A") + def test_parsing_team_id(self, slack_action): + slack.actions.Action.from_http(slack_action, team_id="T000AAA0A") - def test_parsing_wrong_token(self, action): + def test_parsing_wrong_token(self, slack_action): with pytest.raises(slack.exceptions.FailedVerification): - slack.actions.Action.from_http(action, verification_token="xxx") + slack.actions.Action.from_http(slack_action, verification_token="xxx") - def test_parsing_wrong_team_id(self, action): + def test_parsing_wrong_team_id(self, slack_action): with pytest.raises(slack.exceptions.FailedVerification): - slack.actions.Action.from_http(action, team_id="xxx") + slack.actions.Action.from_http(slack_action, team_id="xxx") - def test_mapping_access(self, action): - act = Action.from_http(action) + def test_mapping_access(self, slack_action): + act = Action.from_http(slack_action) assert act["callback_id"] == "test_action" - def test_mapping_delete(self, action): - act = Action.from_http(action) + def test_mapping_delete(self, slack_action): + act = Action.from_http(slack_action) assert act["callback_id"] == "test_action" del act["callback_id"] with pytest.raises(KeyError): print(act["callback_id"]) - def test_mapping_set(self, action): - act = Action.from_http(action) + def test_mapping_set(self, slack_action): + act = Action.from_http(slack_action) assert act["callback_id"] == "test_action" act["callback_id"] = "foo" assert act["callback_id"] == "foo" @@ -124,11 +126,11 @@ def handler(): assert len(action_router._routes["test_action"]["*"]) == 1 assert action_router._routes["test_action"]["*"][0] is handler - def test_dispath(self, action, action_router): + def test_dispath(self, slack_action, action_router): def handler(): pass - act = Action.from_http(action) + act = Action.from_http(slack_action) action_router.register("test_action", handler) handlers = list() @@ -137,22 +139,22 @@ def handler(): assert len(handlers) == 1 assert handlers[0] is handler - def test_no_dispatch(self, action, action_router): + def test_no_dispatch(self, slack_action, action_router): def handler(): pass - act = Action.from_http(action) + act = Action.from_http(slack_action) action_router.register("xxx", handler) for h in action_router.dispatch(act): assert False @pytest.fixture(params={**data.InteractiveMessage.__members__}) - def test_dispatch_details(self, action, action_router): + def test_dispatch_details(self, slack_action, action_router): def handler(): pass - act = Action.from_http(action) + act = Action.from_http(slack_action) action_router.register("test_action", handler, name="ok") action_router.register("test_action", handler, name="cancel") @@ -162,11 +164,13 @@ def handler(): assert len(handlers) == 1 assert handlers[0] is handler - def test_dispatch_action_specific_registration_methods(self, action, action_router): + def test_dispatch_action_specific_registration_methods( + self, slack_action, action_router + ): def handler(): pass - act = Action.from_http(action) + act = Action.from_http(slack_action) if act["type"] in ("interactive_message", "message_action"): action_router.register_interactive_message("test_action", handler) @@ -210,14 +214,14 @@ def handler(): assert len(handlers) == 1 assert handlers[0] is handler - def test_multiple_dispatch(self, action, action_router): + def test_multiple_dispatch(self, slack_action, action_router): def handler(): pass def handler_bis(): pass - act = Action.from_http(action) + act = Action.from_http(slack_action) action_router.register("test_action", handler) action_router.register("test_action", handler_bis) diff --git a/slack/tests/test_commands.py b/slack/tests/test_commands.py index 3480a54..c3a2fc6 100644 --- a/slack/tests/test_commands.py +++ b/slack/tests/test_commands.py @@ -4,37 +4,37 @@ class TestCommand: - def test_fixture(self, command): - com = Command(command) + def test_fixture(self, slack_command): + com = Command(slack_command) assert isinstance(com, slack.commands.Command) - def test_parsing_token(self, command): - slack.commands.Command(command, verification_token="supersecuretoken") + def test_parsing_token(self, slack_command): + slack.commands.Command(slack_command, verification_token="supersecuretoken") - def test_parsing_team_id(self, command): - slack.commands.Command(command, team_id="T000AAA0A") + def test_parsing_team_id(self, slack_command): + slack.commands.Command(slack_command, team_id="T000AAA0A") - def test_parsing_wrong_token(self, command): + def test_parsing_wrong_token(self, slack_command): with pytest.raises(slack.exceptions.FailedVerification): - slack.commands.Command(command, verification_token="xxx") + slack.commands.Command(slack_command, verification_token="xxx") - def test_parsing_wrong_team_id(self, command): + def test_parsing_wrong_team_id(self, slack_command): with pytest.raises(slack.exceptions.FailedVerification): - slack.commands.Command(command, team_id="xxx") + slack.commands.Command(slack_command, team_id="xxx") - def test_mapping_access(self, command): - com = Command(command) + def test_mapping_access(self, slack_command): + com = Command(slack_command) assert com["user_id"] == "U000AA000" - def test_mapping_delete(self, command): - com = Command(command) + def test_mapping_delete(self, slack_command): + com = Command(slack_command) assert com["user_id"] == "U000AA000" del com["user_id"] with pytest.raises(KeyError): print(com["user_id"]) - def test_mapping_set(self, command): - com = Command(command) + def test_mapping_set(self, slack_command): + com = Command(slack_command) assert com["user_id"] == "U000AA000" com["user_id"] = "foo" assert com["user_id"] == "foo" @@ -70,27 +70,27 @@ def handler_bis(): assert command_router._routes["/test"][0] is handler assert command_router._routes["/test"][1] is handler_bis - def test_dispath(self, command, command_router): + def test_dispath(self, slack_command, command_router): def handler(): pass handlers = list() command_router.register("/test", handler) - for h in command_router.dispatch(command): + for h in command_router.dispatch(slack_command): handlers.append(h) assert len(handlers) == 1 assert handlers[0] is handler - def test_no_dispatch(self, command, command_router): + def test_no_dispatch(self, slack_command, command_router): def handler(): pass command_router.register("/xxx", handler) - for h in command_router.dispatch(command): + for h in command_router.dispatch(slack_command): assert False - def test_multiple_dispatch(self, command, command_router): + def test_multiple_dispatch(self, slack_command, command_router): def handler(): pass @@ -101,7 +101,7 @@ def handler_bis(): command_router.register("/test", handler) command_router.register("/test", handler_bis) - for h in command_router.dispatch(command): + for h in command_router.dispatch(slack_command): handlers.append(h) assert len(handlers) == 2 diff --git a/slack/tests/test_events.py b/slack/tests/test_events.py index 3b77837..dc7cc4b 100644 --- a/slack/tests/test_events.py +++ b/slack/tests/test_events.py @@ -8,24 +8,24 @@ class TestEvents: - def test_clone_event(self, event): - ev = Event.from_http(event) + def test_clone_event(self, slack_event): + ev = Event.from_http(slack_event) clone = ev.clone() assert clone == ev - def test_modify_clone(self, event): - ev = Event.from_http(event) + def test_modify_clone(self, slack_event): + ev = Event.from_http(slack_event) clone = ev.clone() clone["text"] = "aaaaa" assert clone != ev - def test_parsing(self, event): - http_event = slack.events.Event.from_http(event) - rtm_event = slack.events.Event.from_rtm(event["event"]) + def test_parsing(self, slack_event): + http_event = slack.events.Event.from_http(slack_event) + rtm_event = slack.events.Event.from_rtm(slack_event["event"]) assert isinstance(http_event, slack.events.Event) assert isinstance(rtm_event, slack.events.Event) - assert http_event.event == rtm_event.event == event["event"] + assert http_event.event == rtm_event.event == slack_event["event"] assert rtm_event.metadata is None assert http_event.metadata == { "token": "supersecuretoken", @@ -38,22 +38,22 @@ def test_parsing(self, event): "event_time": 123456789, } - def test_parsing_token(self, event): - slack.events.Event.from_http(event, verification_token="supersecuretoken") + def test_parsing_token(self, slack_event): + slack.events.Event.from_http(slack_event, verification_token="supersecuretoken") - def test_parsing_team_id(self, event): - slack.events.Event.from_http(event, team_id="T000AAA0A") + def test_parsing_team_id(self, slack_event): + slack.events.Event.from_http(slack_event, team_id="T000AAA0A") - def test_parsing_wrong_token(self, event): + def test_parsing_wrong_token(self, slack_event): with pytest.raises(slack.exceptions.FailedVerification): - slack.events.Event.from_http(event, verification_token="xxx") + slack.events.Event.from_http(slack_event, verification_token="xxx") - def test_parsing_wrong_team_id(self, event): + def test_parsing_wrong_team_id(self, slack_event): with pytest.raises(slack.exceptions.FailedVerification): - slack.events.Event.from_http(event, team_id="xxx") + slack.events.Event.from_http(slack_event, team_id="xxx") @pytest.mark.parametrize( - "event", + "slack_event", [ "pin_added", "reaction_added", @@ -66,12 +66,12 @@ def test_parsing_wrong_team_id(self, event): ], indirect=True, ) - def test_mapping_access(self, event): - ev = Event.from_http(event) + def test_mapping_access(self, slack_event): + ev = Event.from_http(slack_event) assert ev["user"] == "U000AA000" @pytest.mark.parametrize( - "event", + "slack_event", [ "pin_added", "reaction_added", @@ -84,15 +84,15 @@ def test_mapping_access(self, event): ], indirect=True, ) - def test_mapping_delete(self, event): - ev = Event.from_http(event) + def test_mapping_delete(self, slack_event): + ev = Event.from_http(slack_event) assert ev["user"] == "U000AA000" del ev["user"] with pytest.raises(KeyError): print(ev["user"]) @pytest.mark.parametrize( - "event", + "slack_event", [ "pin_added", "reaction_added", @@ -105,18 +105,20 @@ def test_mapping_delete(self, event): ], indirect=True, ) - def test_mapping_set(self, event): - ev = Event.from_http(event) + def test_mapping_set(self, slack_event): + ev = Event.from_http(slack_event) assert ev["user"] == "U000AA000" ev["user"] = "foo" assert ev["user"] == "foo" class TestMessage: - @pytest.mark.parametrize("event", {**data.Messages.__members__}, indirect=True) - def test_parsing(self, event): - http_event = slack.events.Event.from_http(event) - rtm_event = slack.events.Event.from_rtm(event["event"]) + @pytest.mark.parametrize( + "slack_event", {**data.Messages.__members__}, indirect=True + ) + def test_parsing(self, slack_event): + http_event = slack.events.Event.from_http(slack_event) + rtm_event = slack.events.Event.from_rtm(slack_event["event"]) assert isinstance(http_event, slack.events.Message) assert isinstance(rtm_event, slack.events.Message) @@ -150,24 +152,24 @@ def test_serialize_attachments(self): "attachments": '{"hello": "world"}', } - def test_response(self, message): - msg = Event.from_http(message) + def test_response(self, slack_message): + msg = Event.from_http(slack_message) rep = msg.response() assert isinstance(rep, slack.events.Message) assert rep["channel"] == "C00000A00" - def test_response_not_in_thread(self, message): - msg = Event.from_http(message) + def test_response_not_in_thread(self, slack_message): + msg = Event.from_http(slack_message) rep = msg.response(in_thread=False) assert rep == {"channel": "C00000A00"} - def test_response_in_thread(self, message): - msg = Event.from_http(message) + def test_response_in_thread(self, slack_message): + msg = Event.from_http(slack_message) rep = msg.response(in_thread=True) assert rep == {"channel": "C00000A00", "thread_ts": "123456789.000001"} - def test_response_thread_default(self, message): - msg = Event.from_http(message) + def test_response_thread_default(self, slack_message): + msg = Event.from_http(slack_message) rep = msg.response() if "thread_ts" in msg or "thread_ts" in msg.get("message", {}): assert rep == {"channel": "C00000A00", "thread_ts": "123456789.000001"} @@ -212,12 +214,12 @@ def handler_bis(): assert event_router._routes["channel_deleted"]["*"]["*"][0] is handler assert event_router._routes["channel_deleted"]["*"]["*"][1] is handler_bis - @pytest.mark.parametrize("event", {**data.Events.__members__}, indirect=True) - def test_dispatch(self, event, event_router): + @pytest.mark.parametrize("slack_event", {**data.Events.__members__}, indirect=True) + def test_dispatch(self, slack_event, event_router): def handler(): pass - ev = Event.from_http(event) + ev = Event.from_http(slack_event) handlers = list() event_router.register("channel_deleted", handler) @@ -230,24 +232,24 @@ def handler(): assert len(handlers) == 1 assert handlers[0] is handler - @pytest.mark.parametrize("event", {**data.Events.__members__}, indirect=True) - def test_no_dispatch(self, event, event_router): + @pytest.mark.parametrize("slack_event", {**data.Events.__members__}, indirect=True) + def test_no_dispatch(self, slack_event, event_router): def handler(): pass - ev = Event.from_http(event) + ev = Event.from_http(slack_event) event_router.register("xxx", handler) for h in event_router.dispatch(ev): assert False - @pytest.mark.parametrize("event", {**data.Events.__members__}, indirect=True) - def test_dispatch_details(self, event, event_router): + @pytest.mark.parametrize("slack_event", {**data.Events.__members__}, indirect=True) + def test_dispatch_details(self, slack_event, event_router): def handler(): pass - ev = Event.from_http(event) + ev = Event.from_http(slack_event) handlers = list() event_router.register("channel_deleted", handler, channel="C00000A00") @@ -260,15 +262,15 @@ def handler(): assert len(handlers) == 1 assert handlers[0] is handler - @pytest.mark.parametrize("event", {**data.Events.__members__}, indirect=True) - def test_multiple_dispatch(self, event, event_router): + @pytest.mark.parametrize("slack_event", {**data.Events.__members__}, indirect=True) + def test_multiple_dispatch(self, slack_event, event_router): def handler(): pass def handler_bis(): pass - ev = Event.from_http(event) + ev = Event.from_http(slack_event) handlers = list() event_router.register("channel_deleted", handler) @@ -328,11 +330,11 @@ def handler_bis(): assert message_router._routes["*"][None][re.compile(".*")][0] is handler assert message_router._routes["*"][None][re.compile(".*")][1] is handler_bis - def test_dispatch(self, message_router, message): + def test_dispatch(self, message_router, slack_message): def handler(): pass - msg = Event.from_http(message) + msg = Event.from_http(slack_message) message_router.register(".*", handler) handlers = list() @@ -342,21 +344,21 @@ def handler(): assert len(handlers) == 1 assert handlers[0] is handler - def test_no_dispatch(self, message_router, message): + def test_no_dispatch(self, message_router, slack_message): def handler(): pass - msg = Event.from_http(message) + msg = Event.from_http(slack_message) message_router.register("xxx", handler) for h in message_router.dispatch(msg): assert False - def test_dispatch_pattern(self, message_router, message): + def test_dispatch_pattern(self, message_router, slack_message): def handler(): pass - msg = Event.from_http(message) + msg = Event.from_http(slack_message) message_router.register("hello", handler) handlers = list() @@ -366,14 +368,14 @@ def handler(): assert len(handlers) == 1 assert handlers[0] is handler - def test_multiple_dispatch(self, message_router, message): + def test_multiple_dispatch(self, message_router, slack_message): def handler(): pass def handler_bis(): pass - msg = Event.from_http(message) + msg = Event.from_http(slack_message) message_router.register(".*", handler) message_router.register(".*", handler_bis) @@ -386,14 +388,14 @@ def handler_bis(): assert handlers[0] is handler assert handlers[1] is handler_bis - def test_multiple_dispatch_pattern(self, message_router, message): + def test_multiple_dispatch_pattern(self, message_router, slack_message): def handler(): pass def handler_bis(): pass - msg = Event.from_http(message) + msg = Event.from_http(slack_message) message_router.register("hello", handler) message_router.register("hello", handler_bis) @@ -406,11 +408,11 @@ def handler_bis(): assert handlers[0] is handler assert handlers[1] is handler_bis - def test_dispatch_channel(self, message_router, message): + def test_dispatch_channel(self, message_router, slack_message): def handler(): pass - msg = Event.from_http(message) + msg = Event.from_http(slack_message) message_router.register("hello", handler, channel="C00000A00") handlers = list() @@ -420,12 +422,12 @@ def handler(): assert len(handlers) == 1 assert handlers[0] is handler - @pytest.mark.parametrize("message", ("channel_topic",), indirect=True) - def test_dispatch_subtype(self, message_router, message): + @pytest.mark.parametrize("slack_message", ("channel_topic",), indirect=True) + def test_dispatch_subtype(self, message_router, slack_message): def handler(): pass - msg = Event.from_http(message) + msg = Event.from_http(slack_message) message_router.register(".*", handler, subtype="channel_topic") handlers = list() diff --git a/slack/tests/test_examples.py b/slack/tests/test_examples.py new file mode 100644 index 0000000..b3f73b5 --- /dev/null +++ b/slack/tests/test_examples.py @@ -0,0 +1,114 @@ +import pytest +import slack +import slack.actions +import slack.commands +import slack.exceptions + + +# START: TEST EVENTS +@pytest.mark.parametrize("slack_event", ("channel_deleted", "simple"), indirect=True) +def test_events(slack_event): + assert slack_event["event"]["type"] in ("channel_deleted", "message") + + +# END: TEST EVENTS + + +# START: TEST MESSAGES +@pytest.mark.parametrize( + "slack_event", {**slack.tests.data.Messages.__members__}, indirect=True +) +def test_messages(slack_event): + assert slack_event["event"]["type"] == "message" + + +# END: TEST MESSAGES + + +# START: TEST ACTIONS +@pytest.mark.parametrize("slack_action", ("button_ok", "button_cancel"), indirect=True) +def test_actions(slack_action): + action = slack.actions.Action.from_http(slack_action) + assert action["type"] == "interactive_message" + + +# END: TEST ACTIONS + + +# START: TEST COMMANDS +@pytest.mark.parametrize("slack_command", ("text", "no_text"), indirect=True) +def test_commands(slack_command): + command = slack.commands.Command(slack_command) + assert command["command"] == "/test" + + +# END: TEST COMMANDS + + +# START: TEST CLIENT BODY +@pytest.mark.asyncio +@pytest.mark.parametrize("slack_client", ({"body": "auth_test"},), indirect=True) +async def test_client_body(slack_client): + data = await slack_client.query(slack.methods.AUTH_TEST) + assert data["team"] == "TestTeam Workspace" + + +# END: TEST CLIENT BODY + + +# START: TEST CLIENT CUSTOM BODY +@pytest.mark.asyncio +@pytest.mark.parametrize( + "slack_client", ({"body": {"ok": True, "hello": "world"}},), indirect=True +) +async def test_client_custom_body(slack_client): + data = await slack_client.query(slack.methods.AUTH_TEST) + assert data == {"ok": True, "hello": "world"} + + +# END: TEST CLIENT CUSTOM BODY + + +# START: TEST CLIENT ITER +@pytest.mark.asyncio +@pytest.mark.parametrize( + "slack_client", ({"body": ["channels_iter", "channels"]},), indirect=True +) +async def test_client_iter(slack_client): + async for channel in slack_client.iter(slack.methods.CHANNELS_LIST): + print(channel) + + +# END: TEST CLIENT ITER + +# START: TEST CLIENT STATUS +@pytest.mark.asyncio +@pytest.mark.parametrize("slack_client", ({"status": [200, 500]},), indirect=True) +async def test_client_status(slack_client): + + await slack_client.query(slack.methods.AUTH_TEST) + + with pytest.raises(slack.exceptions.HTTPException): + await slack_client.query(slack.methods.AUTH_TEST) + + +# END: TEST CLIENT STATUS + + +# START: TEST CLIENT MULTIPLE RUN +@pytest.mark.asyncio +@pytest.mark.parametrize( + "slack_client,ok", + (({"status": 200}, True), ({"status": 500}, False)), + indirect=["slack_client"], +) +async def test_client_multiple_run(slack_client, ok): + + if ok: + await slack_client.query(slack.methods.AUTH_TEST) + else: + with pytest.raises(slack.exceptions.HTTPException): + await slack_client.query(slack.methods.AUTH_TEST) + + +# END: TEST CLIENT MULTIPLE RUN diff --git a/slack/tests/test_io.py b/slack/tests/test_io.py index a5b9743..e5b5a3d 100644 --- a/slack/tests/test_io.py +++ b/slack/tests/test_io.py @@ -20,48 +20,54 @@ @pytest.mark.asyncio class TestABC: - async def test_query(self, client, token): - rep = await client.query(methods.AUTH_TEST) - client._request.assert_called_once() - assert client._request.call_args[0][0] == "POST" - assert client._request.call_args[0][1] == "https://slack.com/api/auth.test" - assert client._request.call_args[0][2] == { + async def test_query(self, slack_client, token): + rep = await slack_client.query(methods.AUTH_TEST) + slack_client._request.assert_called_once() + assert slack_client._request.call_args[0][0] == "POST" + assert ( + slack_client._request.call_args[0][1] == "https://slack.com/api/auth.test" + ) + assert slack_client._request.call_args[0][2] == { "Content-type": "application/json; charset=utf-8", "Authorization": f"Bearer {token}", } - assert client._request.call_args[0][3] == "{}" + assert slack_client._request.call_args[0][3] == "{}" assert rep == {"ok": True} - async def test_query_url(self, client): - await client.query("auth.test") - assert client._request.call_args[0][1] == "https://slack.com/api/auth.test" + async def test_query_url(self, slack_client): + await slack_client.query("auth.test") + assert ( + slack_client._request.call_args[0][1] == "https://slack.com/api/auth.test" + ) - async def test_query_long_url(self, client): - await client.query("https://slack.com/api/auth.test") - assert client._request.call_args[0][1] == "https://slack.com/api/auth.test" + async def test_query_long_url(self, slack_client): + await slack_client.query("https://slack.com/api/auth.test") + assert ( + slack_client._request.call_args[0][1] == "https://slack.com/api/auth.test" + ) - async def test_query_webhook_url(self, client): - await client.query("https://hooks.slack.com/abcdef") - assert client._request.call_args[0][1] == "https://hooks.slack.com/abcdef" + async def test_query_webhook_url(self, slack_client): + await slack_client.query("https://hooks.slack.com/abcdef") + assert slack_client._request.call_args[0][1] == "https://hooks.slack.com/abcdef" - async def test_query_data(self, client, token): + async def test_query_data(self, slack_client, token): data = {"hello": "world"} called_with = json.dumps(data.copy()) - await client.query(methods.AUTH_TEST, data) - assert client._request.call_args[0][3] == called_with + await slack_client.query(methods.AUTH_TEST, data) + assert slack_client._request.call_args[0][3] == called_with - async def test_query_data_webhook(self, client, token): + async def test_query_data_webhook(self, slack_client, token): data = {"hello": "world"} called_with = data.copy() - await client.query("https://hooks.slack.com/abcdef", data) - assert client._request.call_args[0][3] == json.dumps(called_with) + await slack_client.query("https://hooks.slack.com/abcdef", data) + assert slack_client._request.call_args[0][3] == json.dumps(called_with) - async def test_query_headers(self, client, token): + async def test_query_headers(self, slack_client, token): custom_headers = { "hello": "world", "Content-type": "application/json; charset=utf-8", @@ -69,22 +75,22 @@ async def test_query_headers(self, client, token): } called_headers = custom_headers.copy() - await client.query("https://hooks.slack.com/abcdef", headers=custom_headers) - assert client._request.call_args[0][2] == called_headers + await slack_client.query( + "https://hooks.slack.com/abcdef", headers=custom_headers + ) + assert slack_client._request.call_args[0][2] == called_headers @pytest.mark.parametrize( - "client", - ({"_request": [{"body": "channels_iter"}, {"body": "channels"}]},), - indirect=True, + "slack_client", ({"body": ["channels_iter", "channels"]},), indirect=True ) - async def test_iter(self, client, token, itercursor): + async def test_iter(self, slack_client, token, itercursor): channels = 0 - async for _ in client.iter(methods.CHANNELS_LIST): # noQa: F841 + async for _ in slack_client.iter(methods.CHANNELS_LIST): # noQa: F841 channels += 1 assert channels == 4 - assert client._request.call_count == 2 - client._request.assert_called_with( + assert slack_client._request.call_count == 2 + slack_client._request.assert_called_with( "POST", "https://slack.com/api/channels.list", {}, @@ -92,96 +98,90 @@ async def test_iter(self, client, token, itercursor): ) @pytest.mark.parametrize( - "client", - ({"_request": [{"body": "channels_iter"}, {"body": "channels"}]},), - indirect=True, + "slack_client", ({"body": ["channels_iter", "channels"]},), indirect=True ) - async def test_iter_itermode_iterkey(self, client, token, itercursor): + async def test_iter_itermode_iterkey(self, slack_client, token, itercursor): channels = 0 - async for _ in client.iter( + async for _ in slack_client.iter( "channels.list", itermode="cursor", iterkey="channels" ): # noQa: F841 channels += 1 assert channels == 4 - assert client._request.call_count == 2 - client._request.assert_called_with( + assert slack_client._request.call_count == 2 + slack_client._request.assert_called_with( "POST", "https://slack.com/api/channels.list", {}, {"limit": 200, "token": token, "cursor": itercursor}, ) - async def test_iter_not_supported(self, client): + async def test_iter_not_supported(self, slack_client): with pytest.raises(ValueError): - async for _ in client.iter(methods.AUTH_TEST): # noQa: F841 + async for _ in slack_client.iter(methods.AUTH_TEST): # noQa: F841 pass with pytest.raises(ValueError): - async for _ in client.iter("channels.list"): # noQa: F841 + async for _ in slack_client.iter("channels.list"): # noQa: F841 pass with pytest.raises(ValueError): - async for _ in client.iter( + async for _ in slack_client.iter( "https://slack.com/api/channels.list" ): # noQa: F841 pass @pytest.mark.parametrize( - "client", - ({"_request": [{"body": "channels_iter"}, {"body": "channels"}]},), - indirect=True, + "slack_client", ({"body": ["channels_iter", "channels"]},), indirect=True ) - async def test_iter_wait(self, client): - client.sleep = asynctest.CoroutineMock() + async def test_iter_wait(self, slack_client): + slack_client.sleep = asynctest.CoroutineMock() channels = 0 - async for _ in client.iter(methods.CHANNELS_LIST, minimum_time=2): # noQa: F841 + async for _ in slack_client.iter( + methods.CHANNELS_LIST, minimum_time=2 + ): # noQa: F841 channels += 1 assert channels == 4 - assert client._request.call_count == 2 - assert client.sleep.call_count == 1 - assert 2 > client.sleep.call_args[0][0] > 1.9 + assert slack_client._request.call_count == 2 + assert slack_client.sleep.call_count == 1 + assert 2 > slack_client.sleep.call_args[0][0] > 1.9 @pytest.mark.parametrize( - "client", - ({"_request": [{"body": "channels_iter"}, {"body": "channels"}]},), - indirect=True, + "slack_client", ({"body": ["channels_iter", "channels"]},), indirect=True ) - async def test_iter_no_wait(self, client): - client.sleep = asynctest.CoroutineMock() + async def test_iter_no_wait(self, slack_client): + slack_client.sleep = asynctest.CoroutineMock() channels = 0 - async for _ in client.iter(methods.CHANNELS_LIST, minimum_time=1): # noQa: F841 + async for _ in slack_client.iter( + methods.CHANNELS_LIST, minimum_time=1 + ): # noQa: F841 channels += 1 await asyncio.sleep(0.5) assert channels == 4 - assert client._request.call_count == 2 - assert client.sleep.call_count == 0 + assert slack_client._request.call_count == 2 + assert slack_client.sleep.call_count == 0 @pytest.mark.parametrize( - "client", - ({"_request": [{"body": "auth_test"}, {"body": "users_info"}]},), - indirect=True, + "slack_client", ({"body": ["auth_test", "users_info"]},), indirect=True ) - async def test_find_bot_id(self, client): - bot_id = await client._find_bot_id() + async def test_find_bot_id(self, slack_client): + bot_id = await slack_client._find_bot_id() assert bot_id == "B0AAA0A00" - @pytest.mark.parametrize( - "client", ({"_request": {"body": "rtm_connect"}},), indirect=True - ) - async def test_find_rtm_url(self, client): - url = await client._find_rtm_url() + @pytest.mark.parametrize("slack_client", ({"body": "rtm_connect"},), indirect=True) + async def test_find_rtm_url(self, slack_client): + url = await slack_client._find_rtm_url() assert url == "wss://testteam.slack.com/012345678910" - async def test_incoming_rtm(self, client, rtm_iterator): - client._rtm = rtm_iterator + async def test_incoming_rtm(self, slack_client, rtm_iterator): + slack_client._rtm = rtm_iterator events = [] - async for event in client._incoming_from_rtm( + async for event in slack_client._incoming_from_rtm( "wss://testteam.slack.com/012345678910", "B0AAA0A00" ): assert isinstance(event, slack.events.Event) @@ -189,11 +189,11 @@ async def test_incoming_rtm(self, client, rtm_iterator): assert len(events) > 0 @pytest.mark.parametrize("rtm_iterator", (("goodbye",),), indirect=True) - async def test_incoming_rtm_reconnect(self, client, rtm_iterator): - client._rtm = rtm_iterator + async def test_incoming_rtm_reconnect(self, slack_client, rtm_iterator): + slack_client._rtm = rtm_iterator events = [] - async for event in client._incoming_from_rtm( + async for event in slack_client._incoming_from_rtm( "wss://testteam.slack.com/012345678910", "B0AAA0A00" ): events.append(event) @@ -201,11 +201,11 @@ async def test_incoming_rtm_reconnect(self, client, rtm_iterator): assert len(events) == 0 @pytest.mark.parametrize("rtm_iterator", (("message_bot",),), indirect=True) - async def test_incoming_rtm_discard_bot_id(self, client, rtm_iterator): - client._rtm = rtm_iterator + async def test_incoming_rtm_discard_bot_id(self, slack_client, rtm_iterator): + slack_client._rtm = rtm_iterator events = [] - async for event in client._incoming_from_rtm( + async for event in slack_client._incoming_from_rtm( "wss://testteam.slack.com/012345678910", "B0AAA0A00" ): events.append(event) @@ -213,11 +213,11 @@ async def test_incoming_rtm_discard_bot_id(self, client, rtm_iterator): assert len(events) == 0 @pytest.mark.parametrize("rtm_iterator", (("reconnect_url",),), indirect=True) - async def test_incoming_rtm_skip(self, client, rtm_iterator): - client._rtm = rtm_iterator + async def test_incoming_rtm_skip(self, slack_client, rtm_iterator): + slack_client._rtm = rtm_iterator events = [] - async for event in client._incoming_from_rtm( + async for event in slack_client._incoming_from_rtm( "wss://testteam.slack.com/012345678910", "B0AAA0A00" ): events.append(event) @@ -225,30 +225,40 @@ async def test_incoming_rtm_skip(self, client, rtm_iterator): assert len(events) == 0 -@pytest.mark.parametrize("io_client", (SlackAPIRequest,), indirect=True) class TestNoAsync: - def test_query(self, client, token): - rep = client.query(methods.AUTH_TEST) - client._request.assert_called_once() - assert client._request.call_args[0][0] == "POST" - assert client._request.call_args[0][1] == "https://slack.com/api/auth.test" - assert client._request.call_args[0][2] == { + @pytest.mark.parametrize( + "slack_client", ({"client": SlackAPIRequest},), indirect=True + ) + def test_query(self, slack_client, token): + rep = slack_client.query(methods.AUTH_TEST) + slack_client._request.assert_called_once() + assert slack_client._request.call_args[0][0] == "POST" + assert ( + slack_client._request.call_args[0][1] == "https://slack.com/api/auth.test" + ) + assert slack_client._request.call_args[0][2] == { "Content-type": "application/json; charset=utf-8", "Authorization": f"Bearer {token}", } - assert client._request.call_args[0][3] == "{}" + assert slack_client._request.call_args[0][3] == "{}" assert rep == {"ok": True} - def test_query_data(self, client): + @pytest.mark.parametrize( + "slack_client", ({"client": SlackAPIRequest},), indirect=True + ) + def test_query_data(self, slack_client): data = {"hello": "world"} called_with = json.dumps(data.copy()) - client.query(methods.AUTH_TEST, data) - assert client._request.call_args[0][3] == called_with + slack_client.query(methods.AUTH_TEST, data) + assert slack_client._request.call_args[0][3] == called_with - def test_query_headers(self, client, token): + @pytest.mark.parametrize( + "slack_client", ({"client": SlackAPIRequest},), indirect=True + ) + def test_query_headers(self, slack_client, token): custom_headers = { "hello": "world", "Content-type": "application/json; charset=utf-8", @@ -256,22 +266,22 @@ def test_query_headers(self, client, token): } called_headers = custom_headers.copy() - client.query("https://hooks.slack.com/abcdef", headers=custom_headers) - assert client._request.call_args[0][2] == called_headers + slack_client.query("https://hooks.slack.com/abcdef", headers=custom_headers) + assert slack_client._request.call_args[0][2] == called_headers @pytest.mark.parametrize( - "client", - ({"_request": [{"body": "channels_iter"}, {"body": "channels"}]},), + "slack_client", + ({"client": SlackAPIRequest, "body": ["channels_iter", "channels"]},), indirect=True, ) - def test_iter(self, client, token, itercursor): + def test_iter(self, slack_client, token, itercursor): channels = 0 - for _ in client.iter(methods.CHANNELS_LIST): # noQa: F841 + for _ in slack_client.iter(methods.CHANNELS_LIST): # noQa: F841 channels += 1 assert channels == 4 - assert client._request.call_count == 2 - client._request.assert_called_with( + assert slack_client._request.call_count == 2 + slack_client._request.assert_called_with( "POST", "https://slack.com/api/channels.list", {}, @@ -279,100 +289,114 @@ def test_iter(self, client, token, itercursor): ) @pytest.mark.parametrize( - "client", - ({"_request": [{"body": "channels_iter"}, {"body": "channels"}]},), + "slack_client", + ({"client": SlackAPIRequest, "body": ["channels_iter", "channels"]},), indirect=True, ) - def test_iter_wait(self, client): - client.sleep = asynctest.CoroutineMock() + def test_iter_wait(self, slack_client): + slack_client.sleep = asynctest.CoroutineMock() channels = 0 - for _ in client.iter(methods.CHANNELS_LIST, minimum_time=2): # noQa: F841 + for _ in slack_client.iter(methods.CHANNELS_LIST, minimum_time=2): # noQa: F841 channels += 1 assert channels == 4 - assert client._request.call_count == 2 - assert client.sleep.call_count == 1 - assert 2 > client.sleep.call_args[0][0] > 1.9 + assert slack_client._request.call_count == 2 + assert slack_client.sleep.call_count == 1 + assert 2 > slack_client.sleep.call_args[0][0] > 1.9 @pytest.mark.parametrize( - "client", - ({"_request": [{"body": "channels_iter"}, {"body": "channels"}]},), + "slack_client", + ({"client": SlackAPIRequest, "body": ["channels_iter", "channels"]},), indirect=True, ) - def test_iter_no_wait(self, client): - client.sleep = asynctest.CoroutineMock() + def test_iter_no_wait(self, slack_client): + slack_client.sleep = asynctest.CoroutineMock() channels = 0 - for _ in client.iter(methods.CHANNELS_LIST, minimum_time=1): # noQa: F841 + for _ in slack_client.iter(methods.CHANNELS_LIST, minimum_time=1): # noQa: F841 channels += 1 time.sleep(0.5) assert channels == 4 - assert client._request.call_count == 2 - assert client.sleep.call_count == 0 + assert slack_client._request.call_count == 2 + assert slack_client.sleep.call_count == 0 @pytest.mark.parametrize( - "client", - ({"_request": [{"body": "auth_test"}, {"body": "users_info"}]},), + "slack_client", + ({"client": SlackAPIRequest, "body": ["auth_test", "users_info"]},), indirect=True, ) - def test_find_bot_id(self, client): - bot_id = client._find_bot_id() + def test_find_bot_id(self, slack_client): + bot_id = slack_client._find_bot_id() assert bot_id == "B0AAA0A00" @pytest.mark.parametrize( - "client", ({"_request": {"body": "rtm_connect"}},), indirect=True + "slack_client", + ({"client": SlackAPIRequest, "body": "rtm_connect"},), + indirect=True, ) - def test_find_rtm_url(self, client): - url = client._find_rtm_url() + def test_find_rtm_url(self, slack_client): + url = slack_client._find_rtm_url() assert url == "wss://testteam.slack.com/012345678910" - def test_incoming_rtm(self, client, rtm_iterator_non_async): - client._rtm = rtm_iterator_non_async + @pytest.mark.parametrize( + "slack_client", ({"client": SlackAPIRequest},), indirect=True + ) + def test_incoming_rtm(self, slack_client, rtm_iterator_non_async): + slack_client._rtm = rtm_iterator_non_async events = [] - for event in client._incoming_from_rtm( + for event in slack_client._incoming_from_rtm( "wss://testteam.slack.com/012345678910", "B0AAA0A00" ): assert isinstance(event, slack.events.Event) events.append(event) assert len(events) > 0 + @pytest.mark.parametrize( + "slack_client", ({"client": SlackAPIRequest},), indirect=True + ) @pytest.mark.parametrize("rtm_iterator_non_async", (("goodbye",),), indirect=True) - def test_incoming_rtm_reconnect(self, client, rtm_iterator_non_async): - client._rtm = rtm_iterator_non_async + def test_incoming_rtm_reconnect(self, slack_client, rtm_iterator_non_async): + slack_client._rtm = rtm_iterator_non_async events = [] - for event in client._incoming_from_rtm( + for event in slack_client._incoming_from_rtm( "wss://testteam.slack.com/012345678910", "B0AAA0A00" ): events.append(event) assert len(events) == 0 + @pytest.mark.parametrize( + "slack_client", ({"client": SlackAPIRequest},), indirect=True + ) @pytest.mark.parametrize( "rtm_iterator_non_async", (("message_bot",),), indirect=True ) - def test_incoming_rtm_discard_bot_id(self, client, rtm_iterator_non_async): - client._rtm = rtm_iterator_non_async + def test_incoming_rtm_discard_bot_id(self, slack_client, rtm_iterator_non_async): + slack_client._rtm = rtm_iterator_non_async events = [] - for event in client._incoming_from_rtm( + for event in slack_client._incoming_from_rtm( "wss://testteam.slack.com/012345678910", "B0AAA0A00" ): events.append(event) assert len(events) == 0 + @pytest.mark.parametrize( + "slack_client", ({"client": SlackAPIRequest},), indirect=True + ) @pytest.mark.parametrize( "rtm_iterator_non_async", (("reconnect_url",),), indirect=True ) - def test_incoming_rtm_skip(self, client, rtm_iterator_non_async): - client._rtm = rtm_iterator_non_async + def test_incoming_rtm_skip(self, slack_client, rtm_iterator_non_async): + slack_client._rtm = rtm_iterator_non_async events = [] - for event in client._incoming_from_rtm( + for event in slack_client._incoming_from_rtm( "wss://testteam.slack.com/012345678910", "B0AAA0A00" ): events.append(event) @@ -385,8 +409,8 @@ def test_sleep(self, token): delay = 1 start = datetime.datetime.now() with requests.Session() as session: - client = SlackAPIRequest(session=session, token=token) - client.sleep(delay) + slack_client = SlackAPIRequest(session=session, token=token) + slack_client.sleep(delay) stop = datetime.datetime.now() assert ( datetime.timedelta(seconds=delay + 1) @@ -396,8 +420,8 @@ def test_sleep(self, token): def test__request(self, token): with requests.Session() as session: - client = SlackAPIRequest(session=session, token=token) - response = client._request( + slack_client = SlackAPIRequest(session=session, token=token) + response = slack_client._request( "POST", "https://slack.com/api//api.test", {}, {"token": token} ) @@ -411,8 +435,8 @@ async def test_sleep(self, token): delay = 1 start = datetime.datetime.now() async with aiohttp.ClientSession() as session: - client = SlackAPIAiohttp(session=session, token=token) - await client.sleep(delay) + slack_client = SlackAPIAiohttp(session=session, token=token) + await slack_client.sleep(delay) stop = datetime.datetime.now() assert ( datetime.timedelta(seconds=delay + 1) @@ -423,8 +447,8 @@ async def test_sleep(self, token): @pytest.mark.asyncio async def test__request(self, token): async with aiohttp.ClientSession() as session: - client = SlackAPIAiohttp(session=session, token=token) - response = await client._request( + slack_client = SlackAPIAiohttp(session=session, token=token) + response = await slack_client._request( "POST", "https://slack.com/api//api.test", {}, {"token": token} ) @@ -438,8 +462,8 @@ async def test_function(): delay = 1 start = datetime.datetime.now() session = asks.Session() - client = SlackAPITrio(session=session, token=token) - await client.sleep(delay) + slack_client = SlackAPITrio(session=session, token=token) + await slack_client.sleep(delay) stop = datetime.datetime.now() return ( datetime.timedelta(seconds=delay + 1) @@ -452,8 +476,8 @@ async def test_function(): def test__request(self, token): async def test_function(): session = asks.Session() - client = SlackAPITrio(session=session, token=token) - response = await client._request( + slack_client = SlackAPITrio(session=session, token=token) + response = await slack_client._request( "POST", "https://slack.com/api//api.test", {}, {"token": token} ) return response[0], response[1] @@ -467,8 +491,8 @@ async def test_function(): delay = 1 start = datetime.datetime.now() session = asks.Session() - client = SlackAPICurio(session=session, token=token) - await client.sleep(delay) + slack_client = SlackAPICurio(session=session, token=token) + await slack_client.sleep(delay) stop = datetime.datetime.now() return ( datetime.timedelta(seconds=delay + 1) @@ -481,8 +505,8 @@ async def test_function(): def test__request(self, token): async def test_function(): session = asks.Session() - client = SlackAPICurio(session=session, token=token) - response = await client._request( + slack_client = SlackAPICurio(session=session, token=token) + response = await slack_client._request( "POST", "https://slack.com/api//api.test", {}, {"token": token} ) return response[0], response[1] diff --git a/slack/tests/test_sansio.py b/slack/tests/test_sansio.py index 4ea252a..fa6586c 100644 --- a/slack/tests/test_sansio.py +++ b/slack/tests/test_sansio.py @@ -90,9 +90,9 @@ def test_prepare_request_body_hook(self, token, payload, result): assert "Content-type" in headers assert headers["Content-type"] == "application/json; charset=utf-8" - def test_prepare_request_body_message(self, token, message): + def test_prepare_request_body_message(self, token, slack_message): - msg = Event.from_http(message) + msg = Event.from_http(slack_message) _, body, headers = sansio.prepare_request(methods.AUTH_TEST, msg, {}, {}, token) assert isinstance(body, str) @@ -108,9 +108,9 @@ def test_prepare_request_body_message(self, token, message): assert isinstance(body.get("attachments", ""), str) assert body["token"] == token - def test_prepare_request_body_message_force_json(self, token, message): + def test_prepare_request_body_message_force_json(self, token, slack_message): - msg = Event.from_http(message) + msg = Event.from_http(slack_message) _, body, headers = sansio.prepare_request( methods.AUTH_REVOKE, msg, {}, {}, token, as_json=True ) @@ -120,9 +120,9 @@ def test_prepare_request_body_message_force_json(self, token, message): assert "Content-type" in headers assert headers["Content-type"] == "application/json; charset=utf-8" - def test_prepare_request_message_hook(self, token, message): + def test_prepare_request_message_hook(self, token, slack_message): - msg = Event.from_http(message) + msg = Event.from_http(slack_message) _, body, headers = sansio.prepare_request( "https://hooks.slack.com/abcdefg", msg, {}, {}, token ) @@ -414,15 +414,15 @@ def test_validate_request_signature_too_old(self): class TestIncomingEvent: - @pytest.mark.parametrize("event", ("bot", "bot_edit"), indirect=True) - def test_discard_event(self, event): - ev = Event.from_http(event) + @pytest.mark.parametrize("slack_event", ("bot", "bot_edit"), indirect=True) + def test_discard_event(self, slack_event): + ev = Event.from_http(slack_event) assert sansio.discard_event(ev, "B0AAA0A00") is True - def test_not_discard_event(self, event): - ev = Event.from_http(event) + def test_not_discard_event(self, slack_event): + ev = Event.from_http(slack_event) assert sansio.discard_event(ev, "B0AAA0A01") is False - def test_no_need_reconnect(self, event): - ev = Event.from_http(event) + def test_no_need_reconnect(self, slack_event): + ev = Event.from_http(slack_event) assert sansio.need_reconnect(ev) is False diff --git a/tox.ini b/tox.ini index aaa7646..4a00629 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = format, py36, py37 +envlist = format, pytest, py36, py37 skipsdist= True [testenv] @@ -15,6 +15,13 @@ commands = poetry run black slack examples poetry run isort --recursive slack examples + +[testenv:pytest] +whitelist_externals = poetry +commands = + poetry install -E requests -E aiohttp -E curio -E trio + poetry run pytest test --verbose --cov + [testenv:py37] whitelist_externals = poetry commands =