Last active
June 2, 2020 21:20
-
-
Save greut/4dcd1b99381deed0b5b04b6865200ed6 to your computer and use it in GitHub Desktop.
Revamped api.py (with test and 100% coverage)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Slack Web API | |
============= | |
The `Slack Web API`_ let you communicate with Slack. | |
Usage: | |
------ | |
The following example calls the ``api.test`` method which test whether your | |
token is valid. | |
.. code-block:: python | |
import os | |
import asyncio | |
from votebot.api import call | |
token = os.environ['SLACK_TOKEN'] | |
loop = asyncio.get_event_loop() | |
response = loop.run_until_complete(call('api.test', | |
token=token)) | |
print(response) | |
loop.close() | |
.. _Slack Web API: https://api.slack.com/web/ | |
""" | |
import json | |
from collections.abc import Mapping | |
from aiohttp import ClientSession, FormData | |
async def call(method, file=None, **kwargs): | |
""" | |
Perform an API call to Slack. | |
:param file: File pointer | |
:type file: file | |
:Keyword Arguments: | |
All the arguments required by the Slack API. | |
:return: JSON response. | |
:rtype: dict | |
""" | |
# JSON encode any sub-structure... | |
for k, w in kwargs.items(): | |
# list, tuple or dict but not a str. | |
if isinstance(w, (Mapping, list, tuple)): | |
kwargs[k] = json.dumps(w) | |
form = FormData(kwargs) | |
# Handle file upload | |
if file: | |
form.add_field('file', file) | |
with ClientSession() as session: | |
async with session.post('https://slack.com/api/{0}'.format(method), | |
data=form) as response: | |
assert 200 == response.status, response | |
return await response.json() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from urllib.parse import urlencode | |
import pytest | |
from asynctest import patch | |
from votebot.api import call | |
@pytest.fixture(scope='session') | |
def hello_file(tmpdir_factory): | |
fn = tmpdir_factory.mktemp('data').join('hello.txt') | |
fn.write('Hello world!\n') | |
return str(fn) | |
class MockClientSession: | |
def __enter__(self): | |
return MockSession() | |
def __exit__(self, *args): | |
pass | |
class MockSession: | |
def post(self, *args, **kwargs): | |
return MockRequest(*args, **kwargs) | |
class MockRequest: | |
def __init__(self, *args, **kwargs): | |
self.args = args | |
self.kwargs = kwargs | |
async def __aenter__(self): | |
return MockResponse(200, *self.args, **self.kwargs) | |
async def __aexit__(self, *args): | |
pass | |
class MockResponse: | |
def __init__(self, status, *args, **kwargs): | |
self.status = status | |
self.args = args | |
self.kwargs = kwargs | |
async def json(self): | |
return {'ok': False, | |
'error': 'I am a mock', | |
'args': self.args, | |
'kwargs': self.kwargs} | |
@pytest.mark.asyncio | |
async def test_api_simple(): | |
with patch('votebot.api.ClientSession', new=MockClientSession): | |
response = await call('api.test', token='xoxb-123') | |
assert not response['ok'] | |
assert 'I am a mock' == response['error'] | |
assert ('https://slack.com/api/api.test',) == response['args'] | |
data = response['kwargs']['data']('utf-8') | |
assert b'token=xoxb-123' == data | |
@pytest.mark.asyncio | |
async def test_api_subfields(): | |
with patch('votebot.api.ClientSession', new=MockClientSession): | |
response = await call('api.dummy', fields=[1, 2, 3]) | |
data = response['kwargs']['data']('utf-8') | |
assert urlencode({'fields': '[1, 2, 3]'}).encode('utf-8') == data | |
@pytest.mark.asyncio | |
async def test_api_file(hello_file): | |
with patch('votebot.api.ClientSession', new=MockClientSession): | |
with open(hello_file, 'r', encoding='utf-8') as f: | |
response = await call('api.file', file=f) | |
data = response['kwargs']['data'] | |
assert data.is_multipart |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment