import base64 import os import random import string import tempfile from typing import Tuple, Any import pytest from werkzeug.test import Client from atheneum import create_app, init_db, register_blueprints from atheneum.model import User from atheneum.service import user_service def add_test_user() -> Tuple[str, str]: test_username = 'test_' + ''.join( random.choices(string.ascii_letters + string.digits, k=17)).strip() test_password = ''.join( random.choices(string.ascii_letters + string.digits, k=32)).strip() user_service.register(test_username, test_password, User.ROLE_ADMIN) return test_username, test_password @pytest.fixture def app(): """Create and configure a new app instance for each test.""" # create a temporary file to isolate the database for each test db_fd, db_path = tempfile.mkstemp() # create the app with common test config app = create_app({ 'TESTING': True, 'DATABASE': db_path, }) register_blueprints(app) # create the database and load test data with app.app_context(): init_db() test_username, test_password = add_test_user() app.config['test_username'] = test_username app.config['test_password'] = test_password # get_db().executescript(_data_sql) yield app # close and remove the temporary database os.close(db_fd) os.unlink(db_path) @pytest.fixture def client(app): """A test client for the app.""" return app.test_client() @pytest.fixture def runner(app): """A test runner for the app's Click commands.""" return app.test_cli_runner() class AuthActions(object): def __init__(self, client: Client, username: str = "", password: str = ""): self._client = client self.username: str = username self.password: str = password self.token: str = "" def configure(self, username, password) -> Any: self.username = username self.password = password return self def login(self): auth_header = self.get_authorization_header_basic() result = self._client.post( '/auth/login', headers={ auth_header[0]: auth_header[1] } ) self.token = result.json['token'] return result def bump(self): auth_header = self.get_authorization_header_token() return self._client.post( '/auth/bump', headers={ auth_header[0]: auth_header[1] } ) def logout(self): auth_header = self.get_authorization_header_token() return self._client.post( '/auth/logout', headers={ auth_header[0]: auth_header[1] } ) def get_authorization_header_basic(self) -> Tuple[str, str]: credentials = base64.b64encode( '{}:{}'.format(self.username, self.password).encode('utf8')) \ .decode('utf8').strip() return 'Authorization', 'Basic {}'.format(credentials) def get_authorization_header_token(self) -> Tuple[str, str]: credentials = base64.b64encode( '{}:{}'.format(self.username, self.token).encode('utf8')) \ .decode('utf8').strip() return 'Authorization', 'Token {}'.format(credentials) @pytest.fixture def auth(client: Client): return AuthActions(client, client.application.config.get('test_username'), client.application.config.get('test_password'))