setup tests

This commit is contained in:
Guilhem Saurel 2021-06-17 01:23:25 +02:00
parent fb17a87016
commit abe6497421
10 changed files with 3060 additions and 6 deletions

4
tests/.env Normal file
View file

@ -0,0 +1,4 @@
MATRIX_URL=http://tests
MATRIX_ID=bot
MATRIX_PW=pw
API_KEY=ak

17
tests/Dockerfile Normal file
View file

@ -0,0 +1,17 @@
FROM matrixdotorg/synapse
# This defaults to /data which is a volume aiming at keeping data.
# Here, we want to trash those, and avoid the permission issues, so let's use something else
ENV SYNAPSE_CONFIG_DIR=/srv
WORKDIR $SYNAPSE_CONFIG_DIR
ADD homeserver.yaml .
RUN python -m synapse.app.homeserver --config-path homeserver.yaml --generate-keys
RUN chown -R 991:991 .
RUN python -m pip install aiohttp matrix-nio
ADD . .

1
tests/__init__.py Normal file
View file

@ -0,0 +1 @@
"""Make this directory a valid module for unittests autodiscover to work."""

2910
tests/homeserver.yaml Normal file

File diff suppressed because it is too large Load diff

51
tests/tests.py Normal file
View file

@ -0,0 +1,51 @@
"""Main test module."""
import json
import os
import aiohttp
import nio
from utils import MATRIX_ID, MATRIX_PW, MATRIX_URL, AbstractBotTest
KEY = os.environ['API_KEY']
class BotTest(AbstractBotTest):
"""Main test class."""
async def test_errors(self):
"""Check the bot's error paths."""
async with aiohttp.ClientSession() as session:
async with session.get('http://bot:4785') as response:
self.assertEqual(await response.json(), {'status': 400, 'ret': 'Invalid JSON'})
async with session.post('http://bot:4785', data=json.dumps({'toto': 3})) as response:
self.assertEqual(await response.json(), {'status': 400, 'ret': 'Missing text and/or API key property'})
async with session.post('http://bot:4785', data=json.dumps({'text': 3, 'key': None})) as response:
self.assertEqual(await response.json(), {'status': 401, 'ret': 'Invalid API key'})
async with session.post('http://bot:4785', data=json.dumps({'text': 3, 'key': KEY})) as response:
# TODO: we are not sending to a real room, so this should not be "OK"
self.assertEqual(await response.json(), {'status': 200, 'ret': 'OK'})
async def test_message(self):
"""Send a markdown message, and check the result."""
text = '# Hello'
messages = []
client = nio.AsyncClient(MATRIX_URL, MATRIX_ID)
await client.login(MATRIX_PW)
room = await client.room_create()
url = f'http://bot:4785/{room.room_id}'
async with aiohttp.ClientSession() as session:
async with session.post(url, data=json.dumps({'text': text, 'key': KEY})) as response:
self.assertEqual(await response.json(), {'status': 200, 'ret': 'OK'})
sync = await client.sync()
messages = await client.room_messages(room.room_id, sync.next_batch)
message = messages.chunk[0]
self.assertEqual(message.sender, '@bot:tests')
self.assertEqual(message.body, text)
self.assertEqual(message.formatted_body, '<h1>Hello</h1>')
await client.close()

49
tests/utils.py Normal file
View file

@ -0,0 +1,49 @@
"""Utility tools to run tests."""
import asyncio
import os
import time
import unittest
import aiohttp
import yaml
from synapse._scripts.register_new_matrix_user import request_registration
MATRIX_URL, MATRIX_ID, MATRIX_PW = (os.environ[v] for v in ['MATRIX_URL', 'MATRIX_ID', 'MATRIX_PW'])
class AbstractBotTest(unittest.IsolatedAsyncioTestCase):
"""Abstract test class."""
async def asyncSetUp(self):
"""Set up the test environment."""
# Wait for synapse and the bot to answer
self.assertTrue(
all(await asyncio.gather(
wait_available(f'{MATRIX_URL}/_matrix/client/r0/login', 'flows'),
wait_available('http://bot:4785/', 'status'),
)))
# Try to register an user for the bot. Don't worry if it already exists.
with open('homeserver.yaml') as f:
secret = yaml.safe_load(f.read()).get("registration_shared_secret", None)
request_registration(MATRIX_ID, MATRIX_PW, MATRIX_URL, secret, admin=False, user_type=None, exit=lambda x: x)
async def check_json(session: aiohttp.ClientSession, url: str, key: str) -> bool:
"""Ensure a service at a given url answers with valid json containing a certain key."""
try:
async with session.get(url) as response:
data = await response.json()
return key in data
except aiohttp.client_exceptions.ClientConnectorError:
return False
async def wait_available(url: str, key: str, timeout: int = 60) -> bool:
"""Wait until a service answer correctly or timeout."""
start = time.time()
async with aiohttp.ClientSession() as session:
while True:
if await check_json(session, url, key):
return True
if time.time() > start + timeout:
return False