diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2819793..33692e1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,4 +9,6 @@ jobs: - name: Start run: docker-compose -f test.yml up -d - name: Tests - run: docker-compose -f test.yml run --entrypoint "" tests python -m unittest + run: docker-compose -f test.yml run --entrypoint "" tests ./tests/start.py + - name: "Upload coverage to Codecov" + uses: codecov/codecov-action@v1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..33103d9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +coverage.xml diff --git a/Dockerfile b/Dockerfile index 131bfd6..a6c9e70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.9-slim EXPOSE 4785 -RUN pip3 install --no-cache-dir markdown matrix-nio +RUN pip install --no-cache-dir markdown matrix-nio ADD matrix_webhook.py / diff --git a/test.yml b/test.yml index 891b72b..33eee30 100644 --- a/test.yml +++ b/test.yml @@ -1,11 +1,11 @@ version: '3' services: - bot: - build: . - env_file: - - tests/.env tests: - build: tests + build: + context: . + dockerfile: tests/Dockerfile env_file: - tests/.env + volumes: + - ./:/app diff --git a/tests/Dockerfile b/tests/Dockerfile index 2cd55d3..aa27576 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -1,17 +1,17 @@ +# Leverage a synapse base to be able to: +# "from synapse._scripts.register_new_matrix_user import request_registration" 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 +# This variable defaults to /data which is a volume made to keep data. +# Here, we want to trash those (and avoid the permission issues) by using something else ENV SYNAPSE_CONFIG_DIR=/srv +# Generate keys for synapse WORKDIR $SYNAPSE_CONFIG_DIR - -ADD homeserver.yaml . - +ADD tests/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 +RUN pip install --no-cache-dir aiohttp matrix-nio markdown coverage -ADD . . +WORKDIR /app diff --git a/tests/start.py b/tests/start.py new file mode 100755 index 0000000..b27512b --- /dev/null +++ b/tests/start.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +"""Entry point to start an instrumentalized bot for coverage and run tests.""" + +from subprocess import Popen, run +from unittest import main + + +def run_and_test(): + """Launch the bot and its tests.""" + bot = Popen(['coverage', 'run', 'matrix_webhook.py']) + ret = main(module=None, exit=False).result.wasSuccessful() + bot.terminate() + for cmd in ['report', 'html', 'xml']: + run(['coverage', cmd]) + return ret + + +if __name__ == '__main__': + exit(not run_and_test()) diff --git a/tests/tests.py b/tests/tests.py index eed92df..cdb32a8 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -6,7 +6,7 @@ import os import aiohttp import nio -from utils import MATRIX_ID, MATRIX_PW, MATRIX_URL, AbstractBotTest +from .utils import BOT_URL, MATRIX_ID, MATRIX_PW, MATRIX_URL, AbstractBotTest KEY = os.environ['API_KEY'] @@ -16,13 +16,13 @@ class BotTest(AbstractBotTest): 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: + async with session.get(BOT_URL) 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: + async with session.post(BOT_URL, 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: + async with session.post(BOT_URL, 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: + async with session.post(BOT_URL, 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'}) @@ -36,7 +36,7 @@ class BotTest(AbstractBotTest): room = await client.room_create() - url = f'http://bot:4785/{room.room_id}' + url = f'{BOT_URL}/{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'}) diff --git a/tests/utils.py b/tests/utils.py index c794c90..3b4bd09 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -8,6 +8,7 @@ import aiohttp import yaml from synapse._scripts.register_new_matrix_user import request_registration +BOT_URL = 'http://localhost:4785' MATRIX_URL, MATRIX_ID, MATRIX_PW = (os.environ[v] for v in ['MATRIX_URL', 'MATRIX_ID', 'MATRIX_PW']) @@ -19,11 +20,11 @@ class AbstractBotTest(unittest.IsolatedAsyncioTestCase): self.assertTrue( all(await asyncio.gather( wait_available(f'{MATRIX_URL}/_matrix/client/r0/login', 'flows'), - wait_available('http://bot:4785/', 'status'), + wait_available(BOT_URL, 'status'), ))) # Try to register an user for the bot. Don't worry if it already exists. - with open('homeserver.yaml') as f: + with open('/srv/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)