import os import unittest from urllib.parse import urljoin import requests _DEFAULT_BASE_URL = 'http://hubapp' _DEFAULT_ADMIN_USERNAME = 'admin' _DEFAULT_ADMIN_PASSWORD = 'password' class BaseUrlSession(requests.Session): def __init__(self, base_url=None, *args, **kwargs): self.base_url = base_url super().__init__(*args, **kwargs) def request(self, method, url, *args, **kwargs): url = urljoin(self.base_url, url) return super().request(method, url, *args, **kwargs) class HubTestCase(unittest.TestCase): require_api = False require_backoffice = False require_frontend = False def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # get base URL from environment variable self.base_url = os.getenv('BASE_URL', _DEFAULT_BASE_URL) # ensure base_url ends with a slash if not self.base_url.endswith('/'): self.base_url += '/' self.session = BaseUrlSession(base_url=self.base_url) def setUp(self, *args, **kwargs): super().setUp(*args, **kwargs) if self.require_api and os.getenv('SERVE_API') not in ['y', 'Y', 'yes']: self.skipTest('environment: SERVE_API=no') if self.require_backoffice and os.getenv('SERVE_BACKOFFICE') not in ['y', 'Y', 'yes']: self.skipTest('environment: SERVE_BACKOFFICE=no') if self.require_frontend and os.getenv('SERVE_FRONTEND') not in ['y', 'Y', 'yes']: self.skipTest('environment: SERVE_FRONTEND=no') def tearDown(self, *args, **kwargs): super().tearDown(*args, **kwargs) # close the session to avoid warning self.session.close() class HubApiTestCase(HubTestCase): require_api = True def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._admin_session = None def tearDown(self, *args, **kwargs): super().tearDown(*args, **kwargs) # close an open admin session to avoid warning if self._admin_session is not None: self._admin_session.close() @property def admin_session(self): if self._admin_session is not None: return self._admin_session try: session = BaseUrlSession(base_url=self.base_url) login_success = self.api_login( session, username=os.getenv('DJANGO_CREATE_ADMIN_USERNAME', _DEFAULT_ADMIN_USERNAME), password=os.getenv('DJANGO_CREATE_ADMIN_PASSWORD', _DEFAULT_ADMIN_PASSWORD), ) if login_success: self._admin_session = session return session else: self.fail('Cannot login into admin session via API.') except Exception: session.close() raise def api_login(self, session: requests.Session, username: str, password: str) -> bool: response = session.post('api/auth/get-token', data={'username': username, 'password': password}) if not response.ok: self.fail(f'API Auth Get-Token returned error {response.status_code}: {response.text}') # extract token token = response.json().get('token') if token is None: return False # store token session.token = token session.headers['Authorization'] = 'Token ' + token return True def logout(self, session: requests.Session): self.headers['Authorization'] = None