"""Unit tests for report_payment_group_payment logic.""" from unittest.mock import call, MagicMock, patch import pytest from payment.constants.constants import REPORT_TYPE from payment.logic import report_payment_group_payment as logic from payment.logic.exceptions import EntityDoesNotExist from tests.conftest import TestConfig from tests.utils.factories import ReportPaymentGroupPaymentFactory @patch('payment.logic.report_payment_group_payment.ReportPaymentGroupPayment') @patch('payment.logic.report_payment_group_payment.PaymentGroupPayment') def test_create_or_update_report_create(mock_pgp, mock_report_model, faker): """Test create_or_update_report creates a new record when none exists.""" mock_payment_group_payment = MagicMock() mock_payment_group_payment.reports = [] mock_pgp.get_by_id_or_error.return_value = mock_payment_group_payment mock_new_report = ReportPaymentGroupPaymentFactory.build() mock_report_model.create.return_value = mock_new_report params = { 'payment_group_payment_id': faker.pyint(), 'report_export_url': faker.uri(), 'report_type': REPORT_TYPE.APPROVAL, } result = logic.create_or_update_report(**params) assert mock_pgp.get_by_id_or_error.call_args_list == [ call(params['payment_group_payment_id']) ] assert mock_report_model.create.call_args_list == [call(**params)] report, is_created = result assert report == mock_new_report assert is_created is True @patch('payment.logic.report_payment_group_payment.ReportPaymentGroupPayment') @patch('payment.logic.report_payment_group_payment.PaymentGroupPayment') def test_create_or_update_report_update(mock_pgp, mock_report_model, faker): """Test create_or_update_report updates an existing record.""" new_url = faker.uri() existing_report = ReportPaymentGroupPaymentFactory.create() mock_payment_group_payment = MagicMock() mock_payment_group_payment.reports = [existing_report] mock_pgp.get_by_id_or_error.return_value = mock_payment_group_payment params = { 'payment_group_payment_id': existing_report.payment_group_payment_id, 'report_export_url': new_url, 'report_type': existing_report.report_type, } result = logic.create_or_update_report(**params) assert mock_report_model.commit_changes.called assert not mock_report_model.create.called report, is_created = result assert report == existing_report assert report.report_export_url == new_url assert is_created is False @patch('payment.logic.report_payment_group_payment.ReportPaymentGroupPayment') def test_get_report(mock_report_model, faker): """Test get_report returns the report instance.""" mock_report = ReportPaymentGroupPaymentFactory.build() mock_report_model.get_by_id.return_value = mock_report result = logic.get_report( report_payment_group_payment_id=mock_report.report_payment_group_payment_id ) assert mock_report_model.get_by_id.call_args_list == [ call(mock_report.report_payment_group_payment_id) ] assert result == mock_report @patch('payment.logic.report_payment_group_payment.ReportPaymentGroupPayment') def test_get_report_not_found(mock_report_model, faker): """Test get_report raises EntityDoesNotExist when report not found.""" report_id = faker.pyint() mock_report_model.get_by_id.return_value = None with pytest.raises(EntityDoesNotExist): logic.get_report(report_payment_group_payment_id=report_id) assert mock_report_model.get_by_id.call_args_list == [call(report_id)] @patch('payment.logic.report_payment_group_payment.ReportPaymentGroupPayment') def test_delete_report(mock_report_model, faker): """Test delete_report deletes the record via delete_by_id.""" mock_report = ReportPaymentGroupPaymentFactory.build() mock_report_model.get_by_id.return_value = mock_report logic.delete_report( report_payment_group_payment_id=mock_report.report_payment_group_payment_id ) assert mock_report_model.get_by_id.call_args_list == [ call(mock_report.report_payment_group_payment_id) ] assert mock_report_model.delete_by_id.call_args_list == [ call(mock_report.report_payment_group_payment_id) ] @patch('payment.logic.report_payment_group_payment.ReportPaymentGroupPayment') def test_delete_report_not_found(mock_report_model, faker): """Test delete_report raises EntityDoesNotExist when report not found.""" report_id = faker.pyint() mock_report_model.get_by_id.return_value = None with pytest.raises(EntityDoesNotExist): logic.delete_report(report_payment_group_payment_id=report_id) assert mock_report_model.get_by_id.call_args_list == [call(report_id)] assert not mock_report_model.delete_by_id.called @patch('payment.logic.report_payment_group_payment.ReportPaymentGroupPayment') @patch('payment.logic.report_payment_group_payment.PaymentGroupPayment') def test_get_by_payment_group_payment(mock_pgp, mock_report_model, faker): """Test get_by_payment_group_payment returns list of reports.""" payment_group_payment_id = faker.pyint() mock_reports = [ReportPaymentGroupPaymentFactory.build()] mock_payment_group_payment = MagicMock() mock_payment_group_payment.reports = mock_reports mock_pgp.get_by_id_or_error.return_value = mock_payment_group_payment result = logic.get_by_payment_group_payment(payment_group_payment_id) assert mock_pgp.get_by_id_or_error.call_args_list == [ call(payment_group_payment_id) ] assert result == mock_reports @patch('payment.logic.report_payment_group_payment.ReportPaymentGroupPayment') @patch('payment.logic.report_payment_group_payment.get_s3_client') @patch('payment.logic.report_payment_group_payment.create_presigned_url') def test_get_download(mock_create_url, mock_s3_client, mock_report_model, faker): """Test get_download returns presigned URL dict.""" report = ReportPaymentGroupPaymentFactory.build() mock_client = 'mock_s3_client' mock_presigned_url = faker.uri() mock_report_model.get_by_id_or_error.return_value = report mock_s3_client.return_value = mock_client mock_create_url.return_value = mock_presigned_url bucket_name = TestConfig.S3_PAYMENTS_BUCKET_NAME s3_prefix = 's3://' start_index = len(s3_prefix) + len(bucket_name) + 1 key = report.report_export_url[start_index:] result = logic.get_download( report_payment_group_payment_id=report.report_payment_group_payment_id ) assert mock_report_model.get_by_id_or_error.call_args_list == [ call(report.report_payment_group_payment_id) ] assert mock_s3_client.called assert not key.startswith('/') assert mock_create_url.call_args_list == [call(bucket_name, mock_client, key)] assert result == {'download_url': mock_presigned_url} @patch('payment.logic.report_payment_group_payment.ReportPaymentGroupPayment') def test_get_download_not_found(mock_report_model, faker): """Test get_download raises EntityDoesNotExist when report not found.""" report_id = faker.pyint() mock_report_model.get_by_id_or_error.side_effect = Exception('Not found') with pytest.raises(Exception, match='Not found'): logic.get_download(report_payment_group_payment_id=report_id) assert mock_report_model.get_by_id_or_error.call_args_list == [call(report_id)]