Files
invoice-master-poc-v2/tests/utils/test_utils.py
2026-01-27 23:58:17 +01:00

236 lines
9.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Tests for shared utility modules.
"""
import pytest
from shared.utils.text_cleaner import TextCleaner
from shared.utils.format_variants import FormatVariants
from shared.utils.validators import FieldValidators
class TestTextCleaner:
"""Tests for TextCleaner class."""
def test_clean_unicode_dashes(self):
"""Test normalization of various dash types."""
# en-dash
assert TextCleaner.clean_unicode("5561234567") == "556123-4567"
# em-dash
assert TextCleaner.clean_unicode("556123—4567") == "556123-4567"
# minus sign
assert TextCleaner.clean_unicode("5561234567") == "556123-4567"
def test_clean_unicode_spaces(self):
"""Test normalization of various space types."""
# non-breaking space
assert TextCleaner.clean_unicode("1\xa0234") == "1 234"
# zero-width space removed
assert TextCleaner.clean_unicode("123\u200b456") == "123456"
def test_ocr_digit_corrections(self):
"""Test OCR error corrections for digit fields."""
# O -> 0
assert TextCleaner.apply_ocr_digit_corrections("556O23") == "556023"
# l -> 1
assert TextCleaner.apply_ocr_digit_corrections("556l23") == "556123"
# S -> 5
assert TextCleaner.apply_ocr_digit_corrections("5S6123") == "556123"
# Mixed
assert TextCleaner.apply_ocr_digit_corrections("S56l23-4S67") == "556123-4567"
def test_extract_digits(self):
"""Test digit extraction with OCR correction."""
assert TextCleaner.extract_digits("556123-4567") == "5561234567"
assert TextCleaner.extract_digits("556O23-4567", apply_ocr_correction=True) == "5560234567"
# Without OCR correction, only extracts actual digits
assert TextCleaner.extract_digits("ABC 123 DEF", apply_ocr_correction=False) == "123"
# With OCR correction, standalone letters are not converted
# (they need to be adjacent to digits to be corrected)
assert TextCleaner.extract_digits("A 123 B", apply_ocr_correction=True) == "123"
def test_normalize_amount_text(self):
"""Test amount text normalization."""
assert TextCleaner.normalize_amount_text("1 234,56 kr") == "1234,56"
assert TextCleaner.normalize_amount_text("SEK 1234.56") == "1234.56"
assert TextCleaner.normalize_amount_text("1 234 567,89 kronor") == "1234567,89"
class TestFormatVariants:
"""Tests for FormatVariants class."""
def test_organisation_number_variants(self):
"""Test organisation number variant generation."""
variants = FormatVariants.organisation_number_variants("5561234567")
assert "5561234567" in variants # 纯数字
assert "556123-4567" in variants # 带横线
assert "SE556123456701" in variants # VAT格式
def test_organisation_number_from_vat(self):
"""Test extracting org number from VAT format."""
variants = FormatVariants.organisation_number_variants("SE556123456701")
assert "5561234567" in variants
assert "556123-4567" in variants
def test_bankgiro_variants(self):
"""Test Bankgiro variant generation."""
# 8 digits
variants = FormatVariants.bankgiro_variants("53939484")
assert "53939484" in variants
assert "5393-9484" in variants
# 7 digits
variants = FormatVariants.bankgiro_variants("1234567")
assert "1234567" in variants
assert "123-4567" in variants
def test_plusgiro_variants(self):
"""Test Plusgiro variant generation."""
variants = FormatVariants.plusgiro_variants("12345678")
assert "12345678" in variants
assert "1234567-8" in variants
def test_amount_variants(self):
"""Test amount variant generation."""
variants = FormatVariants.amount_variants("1234.56")
assert "1234.56" in variants
assert "1234,56" in variants
assert "1 234,56" in variants or "1234,56" in variants # Swedish format
def test_date_variants(self):
"""Test date variant generation."""
variants = FormatVariants.date_variants("2024-12-29")
assert "2024-12-29" in variants # ISO
assert "29.12.2024" in variants # European
assert "29/12/2024" in variants # European slash
assert "20241229" in variants # Compact
assert "29 december 2024" in variants # Swedish text
def test_invoice_number_variants(self):
"""Test invoice number variant generation."""
variants = FormatVariants.invoice_number_variants("INV-2024-001")
assert "INV-2024-001" in variants
assert "INV2024001" in variants # No separators
assert "inv-2024-001" in variants # Lowercase
def test_get_variants_dispatch(self):
"""Test get_variants dispatches to correct method."""
# Organisation number
org_variants = FormatVariants.get_variants("supplier_organisation_number", "5561234567")
assert "556123-4567" in org_variants
# Bankgiro
bg_variants = FormatVariants.get_variants("Bankgiro", "53939484")
assert "5393-9484" in bg_variants
# Amount
amount_variants = FormatVariants.get_variants("Amount", "1234.56")
assert "1234,56" in amount_variants
class TestFieldValidators:
"""Tests for FieldValidators class."""
def test_luhn_checksum_valid(self):
"""Test Luhn validation with valid numbers."""
# Valid Bankgiro numbers (with correct check digit)
assert FieldValidators.luhn_checksum("53939484") is True
# Valid OCR numbers
assert FieldValidators.luhn_checksum("1234567897") is True # check digit 7
def test_luhn_checksum_invalid(self):
"""Test Luhn validation with invalid numbers."""
assert FieldValidators.luhn_checksum("53939485") is False # wrong check digit
assert FieldValidators.luhn_checksum("1234567890") is False
def test_calculate_luhn_check_digit(self):
"""Test Luhn check digit calculation."""
# For "123456789", the check digit should make it valid
check = FieldValidators.calculate_luhn_check_digit("123456789")
full_number = "123456789" + str(check)
assert FieldValidators.luhn_checksum(full_number) is True
def test_is_valid_organisation_number(self):
"""Test organisation number validation."""
# Valid (with correct Luhn checksum)
# Note: Need actual valid org numbers for this test
# Using a well-known one: 5565006245 (placeholder)
pass # Skip without real test data
def test_is_valid_bankgiro(self):
"""Test Bankgiro validation."""
# Valid 8-digit Bankgiro with Luhn
assert FieldValidators.is_valid_bankgiro("53939484") is True
# Invalid (wrong length)
assert FieldValidators.is_valid_bankgiro("123") is False
assert FieldValidators.is_valid_bankgiro("123456789") is False # 9 digits
def test_format_bankgiro(self):
"""Test Bankgiro formatting."""
assert FieldValidators.format_bankgiro("53939484") == "5393-9484"
assert FieldValidators.format_bankgiro("1234567") == "123-4567"
assert FieldValidators.format_bankgiro("123") is None
def test_is_valid_plusgiro(self):
"""Test Plusgiro validation."""
# Valid Plusgiro (2-8 digits with Luhn)
assert FieldValidators.is_valid_plusgiro("18") is True # minimal
# Invalid (wrong length)
assert FieldValidators.is_valid_plusgiro("1") is False
def test_format_plusgiro(self):
"""Test Plusgiro formatting."""
assert FieldValidators.format_plusgiro("12345678") == "1234567-8"
assert FieldValidators.format_plusgiro("123456") == "12345-6"
def test_is_valid_amount(self):
"""Test amount validation."""
assert FieldValidators.is_valid_amount("1234.56") is True
assert FieldValidators.is_valid_amount("1 234,56") is True
assert FieldValidators.is_valid_amount("abc") is False
assert FieldValidators.is_valid_amount("-100") is False # below min
assert FieldValidators.is_valid_amount("100000000") is False # above max
def test_parse_amount(self):
"""Test amount parsing."""
assert FieldValidators.parse_amount("1234.56") == 1234.56
assert FieldValidators.parse_amount("1 234,56") == 1234.56
assert FieldValidators.parse_amount("1.234,56") == 1234.56 # German
assert FieldValidators.parse_amount("1,234.56") == 1234.56 # US
def test_is_valid_date(self):
"""Test date validation."""
assert FieldValidators.is_valid_date("2024-12-29") is True
assert FieldValidators.is_valid_date("29.12.2024") is True
assert FieldValidators.is_valid_date("29/12/2024") is True
assert FieldValidators.is_valid_date("not a date") is False
assert FieldValidators.is_valid_date("1900-01-01") is False # out of range
def test_format_date_iso(self):
"""Test date ISO formatting."""
assert FieldValidators.format_date_iso("29.12.2024") == "2024-12-29"
assert FieldValidators.format_date_iso("29/12/2024") == "2024-12-29"
assert FieldValidators.format_date_iso("2024-12-29") == "2024-12-29"
def test_validate_field_dispatch(self):
"""Test validate_field dispatches correctly."""
# Organisation number
is_valid, error = FieldValidators.validate_field("supplier_organisation_number", "")
assert is_valid is False
# Amount
is_valid, error = FieldValidators.validate_field("Amount", "1234.56")
assert is_valid is True
# Date
is_valid, error = FieldValidators.validate_field("InvoiceDate", "2024-12-29")
assert is_valid is True
if __name__ == "__main__":
pytest.main([__file__, "-v"])