Files
iklim-sandbox/tests/test_geo_alarm.py
T
2026-09-09 16:21:13 +03:00

182 lines
7.1 KiB
Python
Raw 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.
from __future__ import annotations
import csv
import json
import os
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
from common.security import TokenStore
from common import ApiError
from geo_alarm import CsvRegistrationProcessor, normalize_turkish_name
REGISTRATION_ONE = "f7587d9e-2481-4b4c-818d-c8d1946851b7"
REGISTRATION_TWO = "57d1e2ba-bf2d-4ef3-b078-523060b2000c"
ACCOUNT_ID = "2f04f1b5-1c0a-4c4e-b0a7-0ba6e9b7f2e1"
class FakeClient:
def __init__(self, env_file: Path) -> None:
self.token_store = TokenStore(env_file)
class FakeService:
def __init__(self, env_file: Path) -> None:
self.client = FakeClient(env_file)
self.payloads = []
def get_account_id(self):
return ACCOUNT_ID
def list_cities(self):
return [{"id": 6, "name": "Ankara"}, {"id": 34, "name": "İstanbul"}]
def list_districts(self, city_id):
return {
6: [{"id": 557, "name": "Çankaya"}],
34: [{"id": 347, "name": "Kadıköy"}],
}[city_id]
def create_registration(self, payload, idempotency_key):
self.payloads.append(payload)
registration_id = REGISTRATION_ONE if len(self.payloads) == 1 else REGISTRATION_TWO
warnings = ["test warning"] if len(self.payloads) == 1 else []
return 200, registration_id, warnings
class RecoveringService(FakeService):
def create_registration(self, payload, idempotency_key):
self.payloads.append(payload)
raise ApiError("duplicate", status_code=409)
def find_by_recipient_id(self, recipient_id):
return 200, REGISTRATION_ONE, []
class GeoAlarmTest(unittest.TestCase):
def test_turkish_exact_normalization(self) -> None:
self.assertEqual(normalize_turkish_name(" İSTANBUL "), "istanbul")
self.assertEqual(normalize_turkish_name("IĞDIR"), "ığdır")
self.assertEqual(normalize_turkish_name("ÇANKAYA"), "çankaya")
self.assertNotEqual(normalize_turkish_name("I"), normalize_turkish_name("İ"))
def test_csv_processing_and_webhook_transition(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
env_file = root / ".env"
env_file.write_text("IKLIM_WEBHOOK_INITIALIZED=false\n", encoding="utf-8")
csv_file = root / "nowcast-geo-alarm-registrations.csv"
csv_file.write_text(
"city;district;recipientId\n"
" anKARA ; ÇANKAYA ;recipient-001\n"
"Ankara;Olmayan;recipient-invalid\n"
"İSTANBUL;KADIKÖY;recipient-002\n",
encoding="utf-8",
)
webhook_file = root / "webhook.json"
webhook_file.write_text(
json.dumps(
{
"url": "https://customer.example/webhook",
"httpMethod": "POST",
"contentType": "application/json",
"authentication": {
"selected": "BASIC",
"options": {
"BASIC": {"username": "user", "password": "pass"}
},
},
}
),
encoding="utf-8",
)
nowcast_filter_file = root / "nowcast-geo-alarm-filter.json"
nowcast_filter_file.write_text(
json.dumps({"precipitation": {"intensities": ["LIGHT"]}}),
encoding="utf-8",
)
service = FakeService(env_file)
with patch.dict(
os.environ, {"IKLIM_WEBHOOK_INITIALIZED": "false"}, clear=True
):
CsvRegistrationProcessor(
service,
csv_path=csv_file,
webhook_config_path=webhook_file,
nowcast_filter_config_path=nowcast_filter_file,
).run()
with csv_file.open("r", encoding="utf-8-sig", newline="") as handle:
rows = list(csv.DictReader(handle, delimiter=";"))
self.assertEqual(
list(rows[0]),
["city", "district", "recipientId", "status", "httpStatus", "registrationId"],
)
self.assertEqual(rows[0]["status"], "SUCCESS")
self.assertEqual(rows[0]["registrationId"], REGISTRATION_ONE)
self.assertEqual(rows[1]["status"], "FAILED")
self.assertEqual(rows[1]["httpStatus"], "NOT_SENT")
self.assertEqual(rows[2]["status"], "SUCCESS")
self.assertEqual(service.payloads[0]["webhook"]["url"], "https://customer.example/webhook")
self.assertNotIn("accountId", service.payloads[0]["webhook"])
self.assertEqual(service.payloads[1]["webhook"], {"accountId": ACCOUNT_ID})
self.assertIn("IKLIM_WEBHOOK_INITIALIZED=true", env_file.read_text())
def test_conflict_is_recovered_by_recipient_id(self) -> None:
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
env_file = root / ".env"
env_file.write_text("IKLIM_WEBHOOK_INITIALIZED=false\n", encoding="utf-8")
csv_file = root / "nowcast-geo-alarm-registrations.csv"
csv_file.write_text(
"city;district;recipientId\nAnkara;Çankaya;recipient-001\n",
encoding="utf-8",
)
webhook_file = root / "webhook.json"
webhook_file.write_text(
json.dumps(
{
"url": "https://customer.example/webhook",
"httpMethod": "POST",
"contentType": "application/json",
"authentication": {
"selected": "BASIC",
"options": {
"BASIC": {"username": "user", "password": "pass"}
},
},
}
),
encoding="utf-8",
)
nowcast_filter_file = root / "nowcast-geo-alarm-filter.json"
nowcast_filter_file.write_text(
json.dumps({"precipitation": {"intensities": ["LIGHT"]}}),
encoding="utf-8",
)
with patch.dict(
os.environ, {"IKLIM_WEBHOOK_INITIALIZED": "false"}, clear=True
):
CsvRegistrationProcessor(
RecoveringService(env_file),
csv_path=csv_file,
webhook_config_path=webhook_file,
nowcast_filter_config_path=nowcast_filter_file,
).run()
with csv_file.open("r", encoding="utf-8-sig", newline="") as handle:
row = next(csv.DictReader(handle, delimiter=";"))
self.assertEqual(row["status"], "SUCCESS")
self.assertEqual(row["httpStatus"], "HTTP_409")
self.assertEqual(row["registrationId"], REGISTRATION_ONE)
if __name__ == "__main__":
unittest.main()