"""Startpage rung: the second independent engine behind DuckDuckGo.
The fixture is the real markup shape captured live 2026-07-30: an inline
asyncio — Asynchronous I/O
The asyncio library, explained.
Unrelated footer blurb, belongs to no result.
"""
P_CHALLENGE_BODY = """
Making sure you are not a bot...
"""
def p_reply(status: int, text: str) -> HttpReply:
return HttpReply(status=status, text=text, content=text.encode(),
content_type="text/html", url="https://www.startpage.com/sp/search")
def p_answer(monkeypatch, reply: HttpReply, seen=None):
async def p_req(url, **kw):
if seen is not None:
seen.append((url, kw.get("method"), kw.get("params")))
return reply
monkeypatch.setattr(SP, "browser_request", p_req)
def test_parses_title_url_and_the_snippet_from_its_own_block():
out = parse_startpage_results(P_BODY, 5)
assert "[1] asyncio — Asynchronous I/O" in out
assert "https://docs.python.org/3/library/asyncio.html" in out
assert "The asyncio library, explained." in out
assert "[2] Real Python walkthrough" in out
assert "A hands-on tour." in out
def test_inline_style_never_becomes_the_title():
"""Tag-stripping alone would emit the anchor's own CSS as the result title."""
out = parse_startpage_results(P_BODY, 5)
assert "css-" not in out
assert "font-size" not in out
def test_an_orphan_snippet_is_not_attached_to_a_result():
out = parse_startpage_results(P_BODY, 5)
assert "Unrelated footer blurb" not in out
def test_respects_num_results():
out = parse_startpage_results(P_BODY, 1)
assert "[1]" in out and "[2]" not in out
@pytest.mark.asyncio
async def test_challenge_page_reads_as_refused_not_as_zero_hits(monkeypatch):
# Startpage answers its proof-of-work interstitial with a normal 200, so "parsed nothing" is the only honest signal.
p_answer(monkeypatch, p_reply(200, P_CHALLENGE_BODY))
answer = await search_startpage("q", 5)
assert answer.refused and not answer.results
@pytest.mark.asyncio
async def test_http_error_reads_as_refused(monkeypatch):
p_answer(monkeypatch, p_reply(503, "nope"))
assert (await search_startpage("q", 5)).refused
@pytest.mark.asyncio
async def test_must_post_or_startpage_serves_the_proof_of_work_wall(monkeypatch):
seen = []
p_answer(monkeypatch, p_reply(200, P_BODY), seen)
out = (await search_startpage("some query", 5)).results
assert out
url, method, params = seen[0]
assert url == "https://www.startpage.com/sp/search"
assert method == "POST"
assert params == {"query": "some query", "cat": "web"}
P_NO_RESULTS_BODY = """
Uh-oh, there are no results for this search.
Let's see, it could be due to:
"""
@pytest.mark.asyncio
async def test_startpages_own_no_results_page_is_an_answer_not_a_refusal(monkeypatch):
"""Nonsense queries must read as 'nothing matched', not as an engine that shut us out."""
p_answer(monkeypatch, p_reply(200, P_NO_RESULTS_BODY))
answer = await search_startpage("zxqvbnmklwertyuiopasdfg", 5)
assert not answer.refused
assert answer.results == ""
@pytest.mark.asyncio
async def test_unrecognised_markup_is_a_refusal_not_zero_hits(monkeypatch):
"""If Startpage redesigns, we must fail loudly rather than report the web as empty."""
p_answer(monkeypatch, p_reply(200, "redesigned
"))
assert (await search_startpage("python", 5)).refused