"""Tests for the Airbnb calendar price automation module.""" from datetime import date from unittest.mock import MagicMock, call, patch import pytest from src.airbnb.calendar import ( update_price, _navigate_to_month, CALENDAR_URL, SELECTORS, _MAX_UPDATE_ATTEMPTS, ) class TestUpdatePrice: def _make_page(self, *, fail_on_click: bool = False) -> MagicMock: page = MagicMock() if fail_on_click: from playwright.sync_api import TimeoutError as PlaywrightTimeout page.click.side_effect = PlaywrightTimeout("timed out") return page def test_successful_price_update(self): page = self._make_page() result = update_price(page, date(2026, 5, 10), 180) assert result is True page.goto.assert_called_once() assert "2026-05-10" in str(page.click.call_args_list[0]) page.fill.assert_called_once() def test_navigates_to_calendar_url(self): page = self._make_page() update_price(page, date(2026, 5, 10), 180) page.goto.assert_called_once_with( CALENDAR_URL, wait_until="networkidle", timeout=30_000 ) def test_fills_correct_price(self): page = self._make_page() update_price(page, date(2026, 5, 10), 200) page.fill.assert_called_once_with( SELECTORS["price_input"], "200", timeout=5_000 ) def test_retries_on_timeout(self): from playwright.sync_api import TimeoutError as PlaywrightTimeout page = MagicMock() page.goto.side_effect = PlaywrightTimeout("timed out") with patch("src.airbnb.calendar.time.sleep"): result = update_price(page, date(2026, 5, 10), 180) assert result is False assert page.goto.call_count == _MAX_UPDATE_ATTEMPTS def test_retries_on_generic_exception(self): page = MagicMock() page.goto.side_effect = RuntimeError("unexpected") with patch("src.airbnb.calendar.time.sleep"): result = update_price(page, date(2026, 5, 10), 180) assert result is False assert page.goto.call_count == _MAX_UPDATE_ATTEMPTS def test_succeeds_on_second_attempt(self): from playwright.sync_api import TimeoutError as PlaywrightTimeout page = MagicMock() page.goto.side_effect = [PlaywrightTimeout("first fail"), None] with patch("src.airbnb.calendar.time.sleep"): result = update_price(page, date(2026, 5, 10), 180) assert result is True assert page.goto.call_count == 2 class TestNavigateToMonth: def test_stub_does_not_crash(self): page = MagicMock() _navigate_to_month(page, date(2026, 5, 10)) class TestSelectors: def test_date_cell_selector_uses_date_format(self): sel = SELECTORS["date_cell"].format(date_str="2026-05-10") assert "2026-05-10" in sel def test_all_selectors_defined(self): assert "date_cell" in SELECTORS assert "price_input" in SELECTORS assert "save_button" in SELECTORS