from unittest.mock import MagicMock, AsyncMock import asyncio import pytest from theHarvester.discovery import githubcode from theHarvester.lib.core import Core class TestSearchGithubCodeProcess: @pytest.mark.asyncio async def test_process_stops_after_max_retries(self, monkeypatch): Core.github_key = MagicMock(return_value="test_key") # type: ignore[method-assign] inst = githubcode.SearchGithubCode(word="test", limit=10) # Speed up by avoiding actual sleeps monkeypatch.setattr(githubcode, "get_delay", lambda: 0, raising=False) monkeypatch.setattr(asyncio, "sleep", AsyncMock(return_value=None)) # Force RetryResult every time monkeypatch.setattr( inst, "handle_response", AsyncMock(return_value=githubcode.RetryResult(0)), ) monkeypatch.setattr( inst, "do_search", AsyncMock(return_value=("", {}, 403, {})), ) inst.max_retries = 2 await inst.process() assert inst.page == 0, "Process should stop after exceeding max retries" assert inst.retry_count == 3, "Retry count should exceed max_retries before stopping" @pytest.mark.asyncio async def test_process_stops_on_error_result(self, monkeypatch): Core.github_key = MagicMock(return_value="test_key") # type: ignore[method-assign] inst = githubcode.SearchGithubCode(word="test", limit=10) monkeypatch.setattr(githubcode, "get_delay", lambda: 0, raising=False) monkeypatch.setattr(asyncio, "sleep", AsyncMock(return_value=None)) # Force ErrorResult monkeypatch.setattr( inst, "handle_response", AsyncMock(return_value=githubcode.ErrorResult(500, "err")), ) monkeypatch.setattr( inst, "do_search", AsyncMock(return_value=("", {}, 500, {})), ) await inst.process() assert inst.page == 0, "Process should stop on error result to avoid infinite loop" @pytest.mark.asyncio async def test_process_breaks_on_same_page_pagination(self, monkeypatch): Core.github_key = MagicMock(return_value="test_key") # type: ignore[method-assign] inst = githubcode.SearchGithubCode(word="test", limit=10) monkeypatch.setattr(githubcode, "get_delay", lambda: 0, raising=False) monkeypatch.setattr(asyncio, "sleep", AsyncMock(return_value=None)) # Force SuccessResult that does not advance the page monkeypatch.setattr( inst, "handle_response", AsyncMock(return_value=githubcode.SuccessResult([], next_page=1, last_page=0)), ) monkeypatch.setattr( inst, "do_search", AsyncMock(return_value=("", {"items": []}, 200, {})), ) await inst.process() assert inst.page == 0, "Process should stop when pagination does not advance"