"""Tests for core excel parser.""" from io import BytesIO from unittest.mock import MagicMock, patch from apps.core.excel import ( BaseExcelParser, ColumnMapping, FieldError, ParseResult, RowData, RowValidationError, validate_inn, validate_kpp, validate_ogrn, validate_okpo, ) from django.test import TestCase class ValidatorsTest(TestCase): """Tests for validators.""" def test_validate_inn_valid_10_digits(self): """Test valid 10-digit INN.""" self.assertEqual(validate_inn("1234567890"), "1234567890") def test_validate_inn_valid_12_digits(self): """Test valid 12-digit INN.""" self.assertEqual(validate_inn("123456789012"), "123456789012") def test_validate_inn_strips_whitespace(self): """Test INN strips whitespace.""" self.assertEqual(validate_inn(" 1234567890 "), "1234567890") def test_validate_inn_invalid_length(self): """Test INN with invalid length raises ValueError.""" with self.assertRaises(ValueError) as ctx: validate_inn("12345") self.assertIn("10 или 12", str(ctx.exception)) def test_validate_inn_none_returns_none(self): """Test None INN returns None.""" self.assertIsNone(validate_inn(None)) def test_validate_ogrn_valid_13_digits(self): """Test valid 13-digit OGRN.""" self.assertEqual(validate_ogrn("1234567890123"), "1234567890123") def test_validate_ogrn_valid_15_digits(self): """Test valid 15-digit OGRN.""" self.assertEqual(validate_ogrn("123456789012345"), "123456789012345") def test_validate_ogrn_invalid_length(self): """Test OGRN with invalid length raises ValueError.""" with self.assertRaises(ValueError) as ctx: validate_ogrn("12345") self.assertIn("13 или 15", str(ctx.exception)) def test_validate_kpp_valid(self): """Test valid 9-digit KPP.""" self.assertEqual(validate_kpp("123456789"), "123456789") def test_validate_kpp_invalid_length(self): """Test KPP with invalid length raises ValueError.""" with self.assertRaises(ValueError) as ctx: validate_kpp("12345") self.assertIn("9 цифр", str(ctx.exception)) def test_validate_okpo_valid_8_digits(self): """Test valid 8-digit OKPO.""" self.assertEqual(validate_okpo("12345678"), "12345678") def test_validate_okpo_valid_10_digits(self): """Test valid 10-digit OKPO.""" self.assertEqual(validate_okpo("1234567890"), "1234567890") class DataclassesTest(TestCase): """Tests for dataclasses.""" def test_column_mapping_creation(self): """Test ColumnMapping creation.""" mapping = ColumnMapping( column_index=1, field_name="test_field", header_pattern="Test Header", ) self.assertEqual(mapping.column_index, 1) self.assertEqual(mapping.field_name, "test_field") self.assertFalse(mapping.required) def test_column_mapping_with_validator(self): """Test ColumnMapping with validator.""" mapping = ColumnMapping( column_index=1, field_name="inn", header_pattern="ИНН", required=True, validator=validate_inn, ) self.assertTrue(mapping.required) self.assertIsNotNone(mapping.validator) def test_row_data_creation(self): """Test RowData creation.""" data = RowData( row_number=5, data={"field1": "value1", "field2": 123}, ) self.assertEqual(data.row_number, 5) self.assertEqual(data.data["field1"], "value1") def test_field_error_creation(self): """Test FieldError creation.""" error = FieldError( field="inn", message="Invalid INN", value="12345", ) self.assertEqual(error.field, "inn") self.assertEqual(error.message, "Invalid INN") def test_row_validation_error_creation(self): """Test RowValidationError creation.""" error = RowValidationError( row_number=10, errors=[FieldError(field="inn", message="Invalid", value="x")], ) self.assertEqual(error.row_number, 10) self.assertEqual(len(error.errors), 1) def test_parse_result_creation(self): """Test ParseResult creation.""" result = ParseResult( success=True, records_created=5, records_failed=1, errors=[], load_batch="batch-123", ) self.assertTrue(result.success) self.assertEqual(result.records_created, 5) self.assertEqual(result.load_batch, "batch-123") class BaseExcelParserTest(TestCase): """Tests for BaseExcelParser.""" def test_parser_abstract_methods(self): """Test parser has abstract methods.""" with self.assertRaises(TypeError): BaseExcelParser() def test_concrete_parser_implementation(self): """Test concrete parser implementation.""" class TestParser(BaseExcelParser): def get_column_mappings(self): return [ ColumnMapping(column_index=1, field_name="inn", header_pattern="ИНН", required=True), ColumnMapping(column_index=2, field_name="name", header_pattern="Наименование"), ] def create_record(self, row_data: dict): return MagicMock(id=1) parser = TestParser() mappings = parser.get_column_mappings() self.assertEqual(len(mappings), 2) self.assertEqual(mappings[0].field_name, "inn")