# SPDX-License-Identifier: MIT # Copyright (c) 2026 Rug Munch Media LLC # # Part of Pry — https://git.rugmunch.io/RugMunchMedia/pryscraper # Licensed under MIT. See LICENSE. """Tests for page structure monitor.""" from unittest.mock import AsyncMock, patch import pytest from structure_monitor import ( check_selectors, get_structure_history, monitor_page_structure, ) @pytest.fixture def temp_db(monkeypatch, tmp_path): import db as db_module db_path = tmp_path / "test.db" monkeypatch.setenv("PRY_DATABASE_URL", f"sqlite:///{db_path}") monkeypatch.setenv("PRY_DATA_DIR", str(tmp_path)) db_module._engine = None db_module._SessionLocal = None db_module.get_engine() yield db_module._engine = None db_module._SessionLocal = None @pytest.mark.asyncio async def test_check_selectors_empty(): result = await check_selectors("https://example.com", []) assert "selectors" in result assert result["all_matched"] is True @pytest.mark.asyncio async def test_get_structure_history_no_history(temp_db): result = await get_structure_history("https://nonexistent-page-test-123.com") assert result["has_history"] is False @pytest.mark.asyncio async def test_monitor_page_structure_creates_history(temp_db): mock_client = AsyncMock() mock_client.get.return_value.is_success = True mock_client.get.return_value.text = "

Title

" with patch("structure_monitor.get_client", return_value=mock_client): result = await monitor_page_structure( "https://example.com", [{"name": "title", "selector": "h1", "type": "css"}], ) assert "selectors" in result assert "changes" in result assert result["all_matched"] is True assert result["has_changes"] is False @pytest.mark.asyncio async def test_get_structure_history_with_data(temp_db): mock_client = AsyncMock() mock_client.get.return_value.is_success = True mock_client.get.return_value.text = "

Title

" with patch("structure_monitor.get_client", return_value=mock_client): await monitor_page_structure( "https://example.com", [{"name": "title", "selector": "h1", "type": "css"}], ) result = await get_structure_history("https://example.com") assert result["has_history"] is True assert "last_checked" in result assert "last_selectors" in result @pytest.mark.asyncio async def test_monitor_page_structure_with_template_id(temp_db): mock_client = AsyncMock() mock_client.get.return_value.is_success = True mock_client.get.return_value.text = "

Title

" with patch("structure_monitor.get_client", return_value=mock_client): result = await monitor_page_structure( "https://example.com", [{"name": "title", "selector": "h1", "type": "css"}], template_id="template-1", ) assert result["template_id"] == "template-1" by_url = await get_structure_history("https://example.com") assert by_url["has_history"] is True by_template = await get_structure_history("https://example.com", template_id="template-1") assert by_template["has_history"] is True @pytest.mark.asyncio async def test_monitor_page_structure_detects_change(temp_db): mock_client = AsyncMock() mock_client.get.return_value.is_success = True mock_client.get.return_value.text = "

Title

" with patch("structure_monitor.get_client", return_value=mock_client): await monitor_page_structure( "https://example.com", [{"name": "title", "selector": "h1", "type": "css"}], ) mock_client.get.return_value.text = "

New Title

" with patch("structure_monitor.get_client", return_value=mock_client): result = await monitor_page_structure( "https://example.com", [{"name": "title", "selector": "h2", "type": "css"}], ) assert "changes" in result @pytest.mark.asyncio async def test_structure_page_http_error(temp_db): mock_client = AsyncMock() mock_client.get.return_value.is_success = False mock_client.get.return_value.status_code = 404 with patch("structure_monitor.get_client", return_value=mock_client): result = await monitor_page_structure( "https://example.com/404", [{"name": "title", "selector": "h1", "type": "css"}], ) assert "error" in result