diff --git a/tests/common.py b/tests/common.py
index a7d5cbe..66d67c6 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -17,6 +17,7 @@ along with this program. If not, see .
"""
+import secrets
from .credentials import CREDS
async def login(acc_name: str, test_cli):
@@ -44,3 +45,45 @@ async def get_uid(token, test_cli):
rjson = await resp.json
return rjson['id']
+
+
+def email() -> str:
+ return f'{secrets.token_hex(5)}@{secrets.token_hex(5)}.com'
+
+
+class TestClient:
+ """Test client that wraps pytest-sanic's TestClient and a test
+ user and adds authorization headers to test requests."""
+ def __init__(self, test_cli, test_user):
+ self.cli = test_cli
+ self.user = test_user
+
+ def __getitem__(self, key):
+ return self.user[key]
+
+ def _inject_auth(self, kwargs: dict) -> list:
+ """Inject the test user's API key into the test request before
+ passing the request on to the underlying TestClient."""
+ headers = kwargs.get('headers', {})
+ headers['authorization'] = self.user['token']
+ return headers
+
+ async def get(self, *args, **kwargs):
+ """Send a GET request."""
+ kwargs['headers'] = self._inject_auth(kwargs)
+ return await self.cli.get(*args, **kwargs)
+
+ async def post(self, *args, **kwargs):
+ """Send a POST request."""
+ kwargs['headers'] = self._inject_auth(kwargs)
+ return await self.cli.post(*args, **kwargs)
+
+ async def patch(self, *args, **kwargs):
+ """Send a PATCH request."""
+ kwargs['headers'] = self._inject_auth(kwargs)
+ return await self.cli.patch(*args, **kwargs)
+
+ async def delete(self, *args, **kwargs):
+ """Send a DELETE request."""
+ kwargs['headers'] = self._inject_auth(kwargs)
+ return await self.cli.delete(*args, **kwargs)
diff --git a/tests/conftest.py b/tests/conftest.py
index 48c5726..f12f610 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -17,7 +17,7 @@ along with this program. If not, see .
"""
-import asyncio
+import secrets
import sys
import os
@@ -27,8 +27,14 @@ import pytest
# this is very hacky.
sys.path.append(os.getcwd())
+from tests.common import email, TestClient
+
from run import app as main_app, set_blueprints
+from litecord.auth import create_user
+from litecord.blueprints.auth import make_token
+from litecord.blueprints.users import delete_user
+
@pytest.fixture(name='app')
def _test_app(unused_tcp_port, event_loop):
@@ -61,3 +67,68 @@ def _test_app(unused_tcp_port, event_loop):
def _test_cli(app):
"""Give a test client."""
return app.test_client()
+
+# code shamelessly stolen from my elixire mr
+# https://gitlab.com/elixire/elixire/merge_requests/52
+async def _user_fixture_setup(app):
+ username = secrets.token_hex(6)
+ password = secrets.token_hex(6)
+ user_email = email()
+
+ # TODO context?
+
+ user_id, pwd_hash = await create_user(
+ username, user_email, password, app.db, app.loop)
+
+ # generate a token for api access
+ user_token = make_token(user_id, pwd_hash)
+
+ return {'id': user_id, 'token': user_token,
+ 'email': user_email, 'username': username,
+ 'password': password}
+
+
+async def _user_fixture_teardown(app, udata: dict):
+ await delete_user(udata['id'], db=app.db)
+
+
+@pytest.fixture(name='test_user')
+async def test_user_fixture(app):
+ """Yield a randomly generated test user."""
+ udata = await _user_fixture_setup(app)
+ yield udata
+ await _user_fixture_teardown(app, udata)
+
+
+@pytest.fixture
+async def test_cli_user(test_cli, test_user):
+ """Yield a TestClient instance that contains a randomly generated
+ user."""
+ yield TestClient(test_cli, test_user)
+
+
+@pytest.fixture
+async def test_cli_admin(test_cli):
+ """Yield a TestClient referencing an admin.
+
+ This does not use the test_user because if a given test uses both
+ test_cli_user and test_cli_admin, test_cli_admin will just point to that
+ same test_cli_user, which isn't acceptable.
+ """
+ test_user = await _user_fixture_setup(test_cli.app)
+
+ await test_cli.app.db.execute("""
+ UPDATE users SET admin = true WHERE user_id = $1
+ """, test_user['id'])
+
+ await test_cli.app.db.execute("""
+ INSERT INTO domain_owners (domain_id, user_id)
+ VALUES (0, $1)
+ ON CONFLICT ON CONSTRAINT domain_owners_pkey
+ DO UPDATE
+ SET user_id = $1
+ WHERE domain_owners.domain_id = 0
+ """, test_user['id'])
+
+ yield TestClient(test_cli, test_user)
+ await _user_fixture_teardown(test_cli.app, test_user)
diff --git a/tests/test_guild.py b/tests/test_guild.py
index f4aee70..dcb850e 100644
--- a/tests/test_guild.py
+++ b/tests/test_guild.py
@@ -23,19 +23,16 @@ import pytest
from tests.common import login
@pytest.mark.asyncio
-async def test_guild_create(test_cli):
+async def test_guild_create(test_cli_user):
"""Test the creation of a guild, in three stages:
- creating it
- checking the list
- deleting it
"""
- token = await login('normal', test_cli)
g_name = secrets.token_hex(5)
# stage 1: create
- resp = await test_cli.post('/api/v6/guilds', headers={
- 'Authorization': token
- }, json={
+ resp = await test_cli_user.post('/api/v6/guilds', json={
'name': g_name,
'region': None,
})
@@ -53,9 +50,7 @@ async def test_guild_create(test_cli):
guild_id = created['id']
# stage 2: test
- resp = await test_cli.get('/api/v6/users/@me/guilds', headers={
- 'Authorization': token
- })
+ resp = await test_cli_user.get('/api/v6/users/@me/guilds')
assert resp.status_code == 200
rjson = await resp.json
@@ -85,8 +80,6 @@ async def test_guild_create(test_cli):
assert our_guild['name'] == created['name']
# stage 3: deletion
- resp = await test_cli.delete(f'/api/v6/guilds/{guild_id}', headers={
- 'Authorization': token
- })
+ resp = await test_cli_user.delete(f'/api/v6/guilds/{guild_id}')
assert resp.status_code == 204