Bot & Automation

jorgasisten

/root/hermes-projects/jorgasisten

tests/test_sheet_router.py text
from jorgasisten.schemas import SheetSchema
from jorgasisten.services.sheet_router import fallback_decision, select_best_schema, should_prefer_sheet_read


def test_select_best_schema_uses_headers_and_samples() -> None:
    catalog = [
        SheetSchema(title="Booking", headers=["Nama", "Tanggal", "Motor"], sample_rows=[{"Nama": "Budi"}]),
        SheetSchema(title="Stok", headers=["Produk", "Qty"], sample_rows=[{"Produk": "Oli MPX"}]),
    ]

    schema, confidence = select_best_schema("Ada stok Oli MPX berapa?", catalog)

    assert schema is not None
    assert schema.title == "Stok"
    assert confidence >= 50


def test_fallback_create_requires_key_value_data() -> None:
    decision = fallback_decision("Catat data baru Budi", [SheetSchema(title="Customer", headers=["Nama"])])

    assert decision.operation == "create"
    assert decision.confidence <= 55
    assert decision.missing_fields


def test_fallback_plain_message_uses_general_chat() -> None:
    decision = fallback_decision("halo", [SheetSchema(title="Customer", headers=["Nama"])])

    assert decision.intent == "chat_umum"
    assert decision.operation == "chat"
    assert decision.sheet_name == ""


def test_fallback_general_question_does_not_force_sheet_read() -> None:
    decision = fallback_decision("apa itu busi motor?", [SheetSchema(title="Customer", headers=["Nama"])])

    assert decision.intent == "chat_umum"
    assert decision.operation == "chat"
    assert decision.sheet_name == ""


def test_fallback_price_question_prefers_sheet_read_with_query_filter() -> None:
    catalog = [
        SheetSchema(title="Products", headers=["Nama", "Harga"], sample_rows=[{"Nama": "Oli MPX", "Harga": "50000"}])
    ]

    decision = fallback_decision("ada harga oli mpx?", catalog)

    assert decision.operation == "read"
    assert decision.sheet_name == "Products"
    assert decision.filters == {"query": "oli mpx"}
    assert should_prefer_sheet_read("ada harga oli mpx?", catalog) is True


def test_fallback_create_sheet_command() -> None:
    decision = fallback_decision(
        "buat sheet baru Booking dengan kolom Nama, Nomor WA, Motor, Status",
        [],
    )

    assert decision.intent == "struktur_sheet"
    assert decision.operation == "create_sheet"
    assert decision.sheet_name == "Booking"
    assert decision.data["headers"] == ["Nama", "Nomor WA", "Motor", "Status"]


def test_fallback_update_headers_command() -> None:
    decision = fallback_decision("ubah kolom sheet Products jadi Nama Produk, Harga, Stok", [])

    assert decision.operation == "update_headers"
    assert decision.sheet_name == "Products"
    assert decision.data["headers"] == ["Nama Produk", "Harga", "Stok"]


def test_fallback_rename_sheet_command() -> None:
    decision = fallback_decision("rename sheet Products jadi Produk", [])

    assert decision.operation == "rename_sheet"
    assert decision.sheet_name == "Products"
    assert decision.data["new_sheet_name"] == "Produk"


def test_fallback_delete_sheet_command() -> None:
    decision = fallback_decision("hapus sheet penuh Produk Lama", [])

    assert decision.operation == "delete_sheet"
    assert decision.sheet_name == "Produk Lama"
    assert decision.data["confirm_delete"] is True