from __future__ import annotations
import xml.etree.ElementTree as ET
from datetime import date
from decimal import Decimal
from pathlib import Path
from unittest.mock import Mock
import pytest
from pydantic import SecretStr
from app.integrations.cbr import CbrClient, CbrDataError, parse_dynamic
from app.integrations.gateway import GatewayClient
def test_parse_dynamic_from_fixture(fixtures_dir: Path) -> None:
rates = parse_dynamic((fixtures_dir / "cbr_dynamic_R01375.xml").read_bytes())
assert [r.rate_date for r in rates] == [
date(2026, 10, 1),
date(2026, 10, 2),
date(2026, 10, 3),
date(2026, 10, 6),
date(2026, 10, 7),
date(2026, 10, 8),
]
last = rates[-1]
assert last.nominal == 1
assert last.value == Decimal("12.7516") # запятая -> точка
assert last.rate_per_unit == Decimal("12.7516")
assert all(isinstance(r.value, Decimal) for r in rates)
def test_parse_dynamic_matches_daily_fixture(fixtures_dir: Path) -> None:
"""Сверка двух реальных ответов ЦБ: курс CNY на 08.10 из XML_daily
(windows-1251, кириллица в Name) равен курсу из XML_dynamic."""
daily = ET.fromstring((fixtures_dir / "cbr_daily.xml").read_bytes())
cny = next(v for v in daily.iter("Valute") if v.get("ID") == "R01375")
rates = parse_dynamic((fixtures_dir / "cbr_dynamic_R01375.xml").read_bytes())
assert cny.findtext("CharCode") == "CNY"
assert cny.findtext("Name") == "Юань"
assert rates[-1].value == Decimal(cny.findtext("Value").replace(",", "."))
def test_parse_dynamic_divides_by_nominal_and_decodes_cp1251() -> None:
xml = (
''
'