"""Fixtures for lambda testing.""" import os import textwrap import mysql.connector from py.xml import html import pytest from pytest_html.extras import url from utils.dockerized_lambda_api_client import DockerizedLambdaAPIClient QA_BASE_URL = os.environ.get( 'QA_BASE_URL', 'http://contract-lifecycle-automation-lambda:8080' ) JIRA_PREFIX_URL = 'https://theorchard.atlassian.net/browse/' PYTEST_REPORT_PREFIX = 'contract_lifecycle_automation lambda integration tests results' PYTEST_REPORT_SUMMARY = textwrap.dedent(""" Lambda for validating contract lifecycle automation """).splitlines() def dockerized_lambda_api_client(headers): """Create dockerized lambda object.""" return DockerizedLambdaAPIClient(QA_BASE_URL, headers) @pytest.fixture(scope='session') def basic_headers(): """Return basic headers.""" return {'Content-Type': 'application/json'} def query_the_db(query, values=None): """Execute a query against docker db.""" cnx = mysql.connector.connect( host='contract-lifecycle-automation-mysql', port='3306', database='royalty_accounting', user='db_user', password='db_pass' ) cursor = cnx.cursor() try: if values: cursor.execute(query, values) else: cursor.execute(query) cnx.commit() return cursor.lastrowid finally: cursor.close() cnx.close() def create_account_fixture(account_id): """Create account db fixture.""" query = """ INSERT INTO royalty_accounting.account ( account_id, account_name, created_by, created_at, last_modified_by, last_modified ) VALUES ( %s, 'TEST ACCOUNT', 'test', '2021-04-12 02:38:45.000000', 'test', '2021-04-12 02:38:45.000000' ) """ query_the_db(query, (account_id,)) def create_contract_fixture(contract_id): """Create contract db fixture.""" query = """ INSERT INTO royalty_accounting.contract ( contract_id, reference_signing_entity_id, contract_name, contract_type, term_start, term_end, created_by, created_at, last_modified_by, last_modified ) VALUES ( %s, 1, 'test', 'distribution', '2022-06-06', '2022-06-09', 'vz', '2022-06-06 03:43:02', 'vz', '2022-06-06 03:43:05' ) """ query_the_db(query, (contract_id,)) def create_acccount_contract_fixture(account_id, contract_id): """Create account_contract db fixture.""" query = """INSERT INTO royalty_accounting.account_contract ( account_id, contract_id ) VALUES (%s, %s) """ query_the_db(query, (account_id, contract_id)) def create_contract_lifecycle_schedule_fixture( contract_id, renewal_type, termination_notice_detail_id=None, renewal_offset_detail_id=None, ): """Create contract_lifecycle_schedule db fixture.""" query = """ INSERT INTO royalty_accounting.contract_lifecycle_schedule ( contract_id, termination_notice_detail_id, renewal_offset_detail_id, collection_period_detail_id, renewal_type, schedule_end, created_by, created_at, last_modified_by, last_modified, deleted_by, deleted_at ) VALUES ( %s, %s, %s, null, %s, null, 'test', '2024-11-06 13:08:06', 'test', '2024-11-06 13:08:11', null, null )""" contract_lifecycle_schedule_id = query_the_db( query, ( contract_id, termination_notice_detail_id, renewal_offset_detail_id, renewal_type ) ) return contract_lifecycle_schedule_id def create_contract_lifecycle_fixture( contract_id, contract_lifecycle_schedule_id, lifecycle_status, lifecycle_term_start='2023-11-06', renewal_effective=None, termination_effective=None ): """Create contract_lifecycle db fixture.""" query = """ INSERT INTO royalty_accounting.contract_lifecycle ( contract_id, contract_lifecycle_schedule_id, lifecycle_status, lifecycle_term_start, lifecycle_term_end, renewal_effective, termination_notice_deadline, termination_notice_received, termination_effective, collection_start, collection_end, created_by, created_at, last_modified_by, last_modified, deleted_by, deleted_at ) VALUES ( %s, %s, %s, %s, '2023-11-22', %s, null, null, %s, null, null, 'test', '2024-11-06 13:09:26', 'test', '2024-11-06 13:10:34', null, null )""" contract_lifecycle_id = query_the_db( query, ( contract_id, contract_lifecycle_schedule_id, lifecycle_status, lifecycle_term_start, renewal_effective, termination_effective ) ) return contract_lifecycle_id def create_contract_lifecycle_schedule_detail_fixture(): """Create contract_lifecycle_schedule_detail db fixture.""" query = """ INSERT INTO royalty_accounting.contract_lifecycle_schedule_detail ( period_interval, period_type ) VALUES ( 20, 'day' )""" contract_lifecycle_schedule_detail_id = query_the_db(query) return contract_lifecycle_schedule_detail_id @pytest.fixture def clean_db(): """Clean tables between runs.""" tables = [ 'account', 'contract', 'account_contract', 'contract_lifecycle_schedule', 'contract_lifecycle', 'contract_lifecycle_schedule_detail' ] query_the_db('SET FOREIGN_KEY_CHECKS = 0;') for table in tables: query_the_db(f'DELETE FROM `{table}`') query_the_db(f'ALTER TABLE `{table}` AUTO_INCREMENT = 1') query_the_db('SET FOREIGN_KEY_CHECKS = 1;') def check_db_empty(compare_func, table=''): """Check whether table is empty.""" cnx = mysql.connector.connect( host='contract-lifecycle-automation-mysql', port='3306', database='royalty_accounting', user='db_user', password='db_pass' ) cursor = cnx.cursor() cursor.execute('SELECT * FROM {}'.format(table)) cursor.fetchall() rc = cursor.rowcount assert compare_func(rc, 0) cursor.close() cnx.close() def get_db_field_value(table, column, condition): """Retrieve the value of the specified column from a table based on a condition.""" cnx = mysql.connector.connect( host='contract-lifecycle-automation-mysql', port='3306', database='royalty_accounting', user='db_user', password='db_pass' ) cursor = cnx.cursor() query = 'SELECT {} FROM {} WHERE {}'.format(column, table, condition) cursor.execute(query) result = cursor.fetchone() if result is not None: value = result[0] else: value = None cursor.close() cnx.close() return value @pytest.hookimpl(optionalhook=True) def pytest_html_results_summary(prefix, summary, postfix): """Populate report with info and summary.""" prefix.extend([html.p(PYTEST_REPORT_PREFIX)]) summary.extend([html.p(PYTEST_REPORT_SUMMARY)]) def pytest_html_results_table_header(cells): """Create results table header.""" cells.insert(1, html.th('Jira ID')) cells.insert(2, html.th('Description')) cells.pop() def pytest_html_results_table_row(report, cells): """Populate results table row.""" jira_ids = getattr(report, 'jira_ids', []) jira_links = [] for index, item in enumerate(jira_ids): link = url('{}{}'.format(JIRA_PREFIX_URL, item), item) if index == 0: jira_links.append(html.a(link['name'], href=link['content'])) else: jira_links.append(', ') jira_links.append(html.a(link['name'], href=link['content'])) jira_links_html = html.td(*jira_links) cells.insert(1, jira_links_html) cells.insert(2, html.td(report.description)) cells.pop() @pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item, call): """Populate results table.""" outcome = yield report = outcome.get_result() report.description = str(item.function.__doc__) if item.get_closest_marker('jira') is not None: to_populate = [] for item in item.get_closest_marker('jira').args: to_populate.append(item) report.jira_ids = to_populate else: report.jira_id = []