Files
openswarm/backend/tests/test_cases/browser/test_browser_validator.py
T
haikdcandGitHub 9c95342704 Haik/feat/test runner (#86)
* [haik]: ckpt, added in the test runner skelton i made in another repo -> still gotta make tweaks to fold it onto the current repo

* [haik]: restructure backend test layout: move 37 test files from backend/tests/ into backend/tests/test_cases/, add backend/tests/run.sh one-command launcher that auto-provisions both runner and test venvs with stamp-based caching, update runner config.json to point test_paths at test_cases/ and fix venv_python path, revise runner README with run.sh usage and clearer setup instructions, and gitignore the .runner-venv directory

* [haik]: refactor: reorganize backend/tests/test_cases from flat structure into domain subdirectories — moved 36 test files into auth/, browser/, labeling/, service/, settings/, and web_search/ for better discoverability and grouping

* [haik]: overhaul test picker UI and add post-run rerun loop: replace checkbox glyphs with fzf-style row recolouring (coral=full, lighter coral=partial) and a right-pinned selection dot, add config-driven icon tiers (nerd/emoji/unicode/ascii) with per-glyph graceful degradation, replace the modal -k keyword screen with an inline live-filtering search bar that prunes the tree on every keystroke, add warm Anthropic-dark coral theme, toolbar flag chips replacing the old status line, and a floating help badge overlay; add rerun_prompt.py with inline Textual pill prompt (rerun all/failed/passed/exit) shown after each TTY run, wire it into main.py as a post-run loop; change run_tests to return (exit_code, RunSummary) tracking collected/passed/failed node IDs via new Dashboard methods; add icons field to config.py and config.json (set to nerd), document icon tiers and Nerd Font setup in README, set Hack Nerd Font in .vscode/settings.json, add .runner-venv to linter excludes
2026-06-14 07:02:30 -07:00

65 lines
2.1 KiB
Python

"""Aux-LLM stuck-adjudication for the browser sub-agent."""
import asyncio
from backend.apps.agents.browser.browser_validator import adjudicate_stuck, p_extract_text # p-private-ignore: p_extract_text
class Block:
def __init__(self, type_, text=""):
self.type = type_
self.text = text
class Resp:
def __init__(self, blocks):
self.content = blocks
class FakeClient:
"""Minimal Anthropic-shaped client: client.messages.create(...)."""
def __init__(self, resp=None, raise_exc=None):
self.resp = resp
self.raise_exc = raise_exc
self.calls = []
self.messages = self
async def create(self, **kwargs):
self.calls.append(kwargs)
if self.raise_exc:
raise self.raise_exc
return self.resp
def test_returns_extracted_guidance_and_assembles_prompt():
fc = FakeClient(resp=Resp([Block("text", "Press Tab then Enter to focus the field.")]))
out = asyncio.run(adjudicate_stuck(fc, "cheap-model", "share the doc", "- click -> not found", "the page"))
assert out == "Press Tab then Enter to focus the field."
call = fc.calls[0]
assert call["model"] == "cheap-model"
assert call["max_tokens"] == 300
prompt = call["messages"][0]["content"]
assert "share the doc" in prompt
assert "not found" in prompt
def test_swallows_provider_error_and_returns_empty():
fc = FakeClient(raise_exc=RuntimeError("429 rate limited"))
out = asyncio.run(adjudicate_stuck(fc, "m", "g", "r", "p"))
assert out == ""
def test_extract_text_joins_text_blocks_and_ignores_others():
resp = Resp([Block("text", "First."), Block("tool_use"), Block("text", "Second.")])
assert p_extract_text(resp) == "First. Second."
def test_handles_empty_inputs_without_crashing():
fc = FakeClient(resp=Resp([Block("text", "ok")]))
out = asyncio.run(adjudicate_stuck(fc, "m", "", "", ""))
assert out == "ok"
# placeholders keep the prompt well-formed
prompt = fc.calls[0]["messages"][0]["content"]
assert "(unknown)" in prompt and "(none)" in prompt and "(empty)" in prompt