2026-07-07 15:28:28 +02:00
# retoor <retoor@molodetz.nl>
from tests . conftest import run_async
from devplacepy . services . jobs . deepsearch import crawl as crawl_module
from devplacepy . services . jobs . deepsearch . crawl import (
CrawledPage ,
_interleave ,
_is_hostile ,
_snippet_page ,
crawl ,
)
async def _no_stop ( ) - > bool :
return False
def test_interleave_round_robins_and_dedupes ( ) :
buckets = [
[ { " url " : " a " } , { " url " : " b " } ] ,
[ { " url " : " c " } , { " url " : " a " } ] ,
[ { " url " : " d " } ] ,
]
assert [ item [ " url " ] for item in _interleave ( buckets ) ] == [ " a " , " c " , " d " , " b " ]
def test_is_hostile_matches_social_domains ( ) :
assert _is_hostile ( " https://x.com/user/status/1 " )
assert _is_hostile ( " https://www.youtube.com/watch?v=abc " )
assert _is_hostile ( " https://old.reddit.com/r/x " )
assert not _is_hostile ( " https://blog.example.com/post " )
def test_snippet_page_prefers_content_over_description ( ) :
candidate = {
" url " : " https://x.com/a/status/1 " ,
" title " : " Tweet " ,
" description " : " short " ,
" content " : " This is the full rsearch content, deliberately written long enough to clear the snippet minimum length floor so that it is kept as a real source easily. " ,
}
page = _snippet_page ( candidate , 0 )
assert page is not None
assert page . source == " search "
assert " full rsearch content " in page . text
def test_snippet_page_none_when_too_thin ( ) :
assert _snippet_page ( { " url " : " https://x.com/a " , " content " : " tiny " } , 0 ) is None
def test_crawl_uses_snippet_for_hostile_and_skips_fetch ( monkeypatch ) :
fetched = [ ]
Report every test failure in one pass and fix the whole suite
The suite ran with -x, so a run stopped at the first failure and finding N
failures cost N full runs. Move -rf into the pytest addopts so every run
lists each failure, and add the triage targets test-fast (unit + api, no
browser), test-failed (--last-failed), test-first-failure (the old -x),
test-slowest and test-cache-clean. A stale .pytest_cache holding node ids
from deleted files made --last-failed select everything; make clean and
test-cache-clean drop it.
Fix the fifteen failures this surfaced.
DeepSearch crawling raised AttributeError in its finally block on every run:
async_playwright().__aenter__() returns a Playwright, which has no __aexit__.
Use start()/stop() at both call sites.
Update the tests left behind by changed signatures: VectorStore is async now,
fetch_page takes a browser, _summary_payload takes dom_evidence, and the
messages/notifications page compounds take a user_uid.
Close four real flakes that fail-fast had been hiding, all of them late in
the run. Harvest assertions pinned crop.reward_coins while is_golden pays
five times on about five percent of harvests, so they now assert through
realizable_harvest_coins with the observed golden flag. Market saturation
fixtures assumed a single active farm and landed two tiers milder once the
api and e2e tiers had created farms, so they scale by active_farms(). The
primary-administrator container test raced the one second cross-worker cache
version window and now waits for the server to agree. The isslop tools test
matched the collapsed nav dropdown link instead of the tools grid card.
Stop burning ninety seconds waiting out server-side display caches:
DEVPLACE_RANKING_TTL and DEVPLACE_MARKET_SATURATION_TTL follow the existing
sitemap and home cache precedent and are zero for the suite, taking the
leaderboard test from 60.6s to 4.4s and the saturation test from 30.1s to
under a second.
2881 passed, 1 skipped in 15:13.
2026-07-26 16:02:36 +02:00
async def fake_fetch ( url , depth , browser = None ) :
2026-07-07 15:28:28 +02:00
fetched . append ( url )
return CrawledPage ( url = url , title = " T " , text = " x " * 200 , source = " httpx " , status = 200 , depth = depth )
monkeypatch . setattr ( crawl_module , " fetch_page " , fake_fetch )
candidates = [
{
" url " : " https://x.com/ThePrimeagen/status/1 " ,
" title " : " Prime " ,
" description " : " " ,
" content " : " The real tweet text returned by rsearch for this social post, well past the snippet minimum length threshold so it survives as a usable source here. " ,
}
]
outcome = run_async (
crawl ( candidates , 6 , lambda f : None , lambda u : False , _no_stop , query = " q " , depth = 1 )
)
assert fetched == [ ]
assert len ( outcome . pages ) == 1
assert outcome . pages [ 0 ] . source == " search "
def test_crawl_prefers_richer_crawl_over_snippet ( monkeypatch ) :
Report every test failure in one pass and fix the whole suite
The suite ran with -x, so a run stopped at the first failure and finding N
failures cost N full runs. Move -rf into the pytest addopts so every run
lists each failure, and add the triage targets test-fast (unit + api, no
browser), test-failed (--last-failed), test-first-failure (the old -x),
test-slowest and test-cache-clean. A stale .pytest_cache holding node ids
from deleted files made --last-failed select everything; make clean and
test-cache-clean drop it.
Fix the fifteen failures this surfaced.
DeepSearch crawling raised AttributeError in its finally block on every run:
async_playwright().__aenter__() returns a Playwright, which has no __aexit__.
Use start()/stop() at both call sites.
Update the tests left behind by changed signatures: VectorStore is async now,
fetch_page takes a browser, _summary_payload takes dom_evidence, and the
messages/notifications page compounds take a user_uid.
Close four real flakes that fail-fast had been hiding, all of them late in
the run. Harvest assertions pinned crop.reward_coins while is_golden pays
five times on about five percent of harvests, so they now assert through
realizable_harvest_coins with the observed golden flag. Market saturation
fixtures assumed a single active farm and landed two tiers milder once the
api and e2e tiers had created farms, so they scale by active_farms(). The
primary-administrator container test raced the one second cross-worker cache
version window and now waits for the server to agree. The isslop tools test
matched the collapsed nav dropdown link instead of the tools grid card.
Stop burning ninety seconds waiting out server-side display caches:
DEVPLACE_RANKING_TTL and DEVPLACE_MARKET_SATURATION_TTL follow the existing
sitemap and home cache precedent and are zero for the suite, taking the
leaderboard test from 60.6s to 4.4s and the saturation test from 30.1s to
under a second.
2881 passed, 1 skipped in 15:13.
2026-07-26 16:02:36 +02:00
async def fake_fetch ( url , depth , browser = None ) :
2026-07-07 15:28:28 +02:00
return CrawledPage ( url = url , title = " Article " , text = " Deep article body. " * 60 , source = " httpx " , status = 200 , depth = depth )
monkeypatch . setattr ( crawl_module , " fetch_page " , fake_fetch )
candidates = [
{
" url " : " https://blog.example.com/a " ,
" title " : " Blog " ,
" description " : " " ,
" content " : " A short snippet that is longer than the floor but shorter than the crawled article body itself. " ,
}
]
outcome = run_async (
crawl ( candidates , 6 , lambda f : None , lambda u : False , _no_stop , query = " q " , depth = 1 )
)
assert outcome . pages [ 0 ] . source == " httpx "
def test_crawl_falls_back_to_snippet_when_fetch_empty ( monkeypatch ) :
Report every test failure in one pass and fix the whole suite
The suite ran with -x, so a run stopped at the first failure and finding N
failures cost N full runs. Move -rf into the pytest addopts so every run
lists each failure, and add the triage targets test-fast (unit + api, no
browser), test-failed (--last-failed), test-first-failure (the old -x),
test-slowest and test-cache-clean. A stale .pytest_cache holding node ids
from deleted files made --last-failed select everything; make clean and
test-cache-clean drop it.
Fix the fifteen failures this surfaced.
DeepSearch crawling raised AttributeError in its finally block on every run:
async_playwright().__aenter__() returns a Playwright, which has no __aexit__.
Use start()/stop() at both call sites.
Update the tests left behind by changed signatures: VectorStore is async now,
fetch_page takes a browser, _summary_payload takes dom_evidence, and the
messages/notifications page compounds take a user_uid.
Close four real flakes that fail-fast had been hiding, all of them late in
the run. Harvest assertions pinned crop.reward_coins while is_golden pays
five times on about five percent of harvests, so they now assert through
realizable_harvest_coins with the observed golden flag. Market saturation
fixtures assumed a single active farm and landed two tiers milder once the
api and e2e tiers had created farms, so they scale by active_farms(). The
primary-administrator container test raced the one second cross-worker cache
version window and now waits for the server to agree. The isslop tools test
matched the collapsed nav dropdown link instead of the tools grid card.
Stop burning ninety seconds waiting out server-side display caches:
DEVPLACE_RANKING_TTL and DEVPLACE_MARKET_SATURATION_TTL follow the existing
sitemap and home cache precedent and are zero for the suite, taking the
leaderboard test from 60.6s to 4.4s and the saturation test from 30.1s to
under a second.
2881 passed, 1 skipped in 15:13.
2026-07-26 16:02:36 +02:00
async def fake_fetch ( url , depth , browser = None ) :
2026-07-07 15:28:28 +02:00
return None
monkeypatch . setattr ( crawl_module , " fetch_page " , fake_fetch )
candidates = [
{
" url " : " https://walled.example.com/a " ,
" title " : " Wall " ,
" description " : " " ,
" content " : " The search snippet holds the real content that the login-walled page refused to serve to the bot today, and it is comfortably past the snippet minimum length floor. " ,
}
]
outcome = run_async (
crawl ( candidates , 6 , lambda f : None , lambda u : False , _no_stop , query = " q " , depth = 1 )
)
assert len ( outcome . pages ) == 1
assert outcome . pages [ 0 ] . source == " search "
2026-07-26 19:05:21 +02:00
def test_crawl_degrades_to_httpx_when_the_playwright_driver_cannot_start ( monkeypatch ) :
import playwright . async_api as playwright_api
class FailingDriver :
async def start ( self ) :
raise RuntimeError ( " driver missing " )
monkeypatch . setattr ( playwright_api , " async_playwright " , lambda : FailingDriver ( ) )
async def fake_fetch ( url , depth , browser = None ) :
return CrawledPage (
url = url , title = " T " , text = " body " * 100 , source = " httpx " , status = 200 , depth = depth
)
monkeypatch . setattr ( crawl_module , " fetch_page " , fake_fetch )
candidates = [
{ " url " : " https://example.com/a " , " title " : " A " , " description " : " " , " content " : " " }
]
outcome = run_async (
crawl ( candidates , 6 , lambda f : None , lambda u : False , _no_stop , query = " q " , depth = 1 )
)
assert len ( outcome . pages ) == 1
assert outcome . pages [ 0 ] . source == " httpx "