Skip to content
Snippets Groups Projects
test_forms.py 3.85 KiB
"""Tests for the file_validator forms."""
import csv
import io
from unittest.mock import MagicMock

from django.core.files.uploadedfile import SimpleUploadedFile

from sage_validation.file_validator.forms import CSVUploadForm


def create_modified_csv(sample_file: SimpleUploadedFile, modifications: dict[str, str]) -> SimpleUploadedFile:
    """
    Modify specific fields in the first row of a CSV file and return a new SimpleUploadedFile.

    Args:
        sample_file (SimpleUploadedFile): The original CSV file.
        modifications (dict): Dictionary of column names to modified values.

    Returns:
        SimpleUploadedFile: The modified CSV file.
    """
    csv_content = sample_file.read().decode("utf-8").splitlines()
    reader = csv.DictReader(csv_content)
    rows = list(reader)

    for key, value in modifications.items():
        rows[0][key] = value

    output = io.StringIO()
    writer = csv.DictWriter(output, fieldnames=reader.fieldnames or [])
    writer.writeheader()
    writer.writerows(rows)

    return SimpleUploadedFile("test_modified.csv", output.getvalue().encode("utf-8"), content_type="text/csv")


def test_valid_csv_upload(sample_input_file: SimpleUploadedFile, mock_meo_database: MagicMock) -> None:
    """Test CSV upload with valid data."""
    form = CSVUploadForm(files={"file": sample_input_file})
    assert form.is_valid(), f"Form errors: {form.errors}"


def test_invalid_file_extension() -> None:
    """Test form rejects non-CSV files."""
    bad_file = SimpleUploadedFile("test.txt", b"Some text content", content_type="text/plain")
    form = CSVUploadForm(files={"file": bad_file})
    assert not form.is_valid()
    assert "File must be in CSV format." in form.errors["file"]


def test_missing_required_columns() -> None:
    """Test form rejects CSV missing required headers."""
    invalid_csv = SimpleUploadedFile("test.csv", b"AccountNumber,CBAccountNumber\n12345,54321", content_type="text/csv")
    form = CSVUploadForm(files={"file": invalid_csv})
    assert not form.is_valid()
    assert "Missing required columns" in str(form.errors)


def test_source_and_trader_type_validation(sample_input_file: SimpleUploadedFile, mock_meo_database: MagicMock) -> None:
    """Test validation for Source and SYSTraderTranType columns."""
    modified_file = create_modified_csv(sample_input_file, {"Source": "90", "SYSTraderTranType": "5"})
    form = CSVUploadForm(files={"file": modified_file})
    assert not form.is_valid()
    assert "Row 1: 'Source' must be 80" in form.errors["file"][0]
    assert "Row 1: 'SYSTraderTranType' must be 4" in form.errors["file"][1]


def test_validate_nominal_analysis_account(sample_input_file: SimpleUploadedFile, mock_meo_database: MagicMock) -> None:
    """Test validation for nominal analysis account."""
    modified_file = create_modified_csv(sample_input_file,
                                        {"NominalAnalysisNominalAnalysisNarrative/1": "Invalid Name"})
    form = CSVUploadForm(files={"file": modified_file})
    assert not form.is_valid()
    assert form.errors["file"][0] == (
        "Row 1: 'AccountNumber' must match 'Sample Narrative' in 'NominalAnalysisNominalAnalysisNarrative/1'"
        ", but found 'Invalid Name'.")


def test_validate_nc_cc_dep_combination_against_meo_sage_account(
        sample_input_file: SimpleUploadedFile, mock_meo_database: MagicMock
) -> None:
    """Test validation for nominal analysis fields against MEO valid Sage accounts."""
    modified_file = create_modified_csv(
        sample_input_file,
        {
            "NominalAnalysisNominalCostCentre/1": "Invalid_CC",
            "NominalAnalysisNominalAccountNumber/1": "Invalid_Account"
        })

    form = CSVUploadForm(files={"file": modified_file})
    assert not form.is_valid()
    assert ("Row 1: 'NominalAnalysisNominalCostCentre/1' (Invalid_CC) is not a valid cost centre."
            in str(form.errors["file"][0]))