Bot & Automation

jorgasisten

/root/hermes-projects/jorgasisten

tests/test_sheets_write_behavior.py text
from types import SimpleNamespace

from jorgasisten.services.formatters import format_operation_error
from jorgasisten.services.sheets import (
    _SPREADSHEET_METADATA_CACHE,
    GoogleSheetsClient,
    compute_next_empty_row_number,
    compute_next_empty_row_number_from_grid_rows,
)


def test_compute_next_empty_row_number_uses_first_blank_gap() -> None:
    values = [
        ["1", "A"],
        ["2", "B"],
        [],
        ["4", "D"],
    ]

    assert compute_next_empty_row_number(values, 2) == 4


def test_compute_next_empty_row_number_appends_after_last_used_row() -> None:
    values = [
        ["1", "A"],
        ["2", "B"],
        ["3", "C"],
    ]

    assert compute_next_empty_row_number(values, 2) == 5


def test_compute_next_empty_row_number_from_grid_rows_uses_first_blank_gap() -> None:
    row_data = [
        {"values": [{"formattedValue": "1"}, {"formattedValue": "A"}]},
        {},
        {"values": [{"formattedValue": "3"}, {"formattedValue": "C"}]},
    ]

    assert compute_next_empty_row_number_from_grid_rows(row_data, 2, total_data_rows=4) == 3


def test_metadata_cache_reuses_response_until_invalidated() -> None:
    class FakeExecute:
        def __init__(self, payload: dict[str, object], counter: dict[str, int]) -> None:
            self.payload = payload
            self.counter = counter

        def execute(self) -> dict[str, object]:
            self.counter["count"] += 1
            return self.payload

    class FakeSpreadsheets:
        def __init__(self, payload: dict[str, object], counter: dict[str, int]) -> None:
            self.payload = payload
            self.counter = counter

        def get(self, **_: object) -> FakeExecute:
            return FakeExecute(self.payload, self.counter)

    class FakeService:
        def __init__(self, payload: dict[str, object], counter: dict[str, int]) -> None:
            self.payload = payload
            self.counter = counter

        def spreadsheets(self) -> FakeSpreadsheets:
            return FakeSpreadsheets(self.payload, self.counter)

    settings = SimpleNamespace(
        google_service_account_json_base64="x",
        google_application_credentials="",
        max_sample_rows=5,
        google_sheets_spreadsheet_id="sheet-123",
    )
    client = GoogleSheetsClient(settings=settings, spreadsheet_id="sheet-123")
    counter = {"count": 0}
    client.__dict__["service"] = FakeService({"sheets": []}, counter)
    _SPREADSHEET_METADATA_CACHE.pop("sheet-123", None)

    client._metadata()
    client._metadata()
    client._invalidate_runtime_caches()
    client._metadata()

    assert counter["count"] == 2


def test_format_operation_error_handles_rate_limit_cleanly() -> None:
    message = format_operation_error(Exception("HttpError 429 quota exceeded"))

    assert "limit sementara" in message