Files
openswarm/backend/tests/test_browser_submit_click.py

75 lines
3.8 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Container-scoped submit tier: the middle rung between the below-composer index pick and the
by-name 'Send' last resort, plus the expression builder's escaping. The JS itself is proven live
(X modal resolves tweetButton, inline resolves tweetButtonInline at hop 20); these tests pin the
tier ORDER and the fail-safe parse."""
import pytest
from backend.apps.agents.browser import browser_send_script as ss
from backend.apps.agents.browser import browser_submit_click as sc
from backend.apps.agents.browser.browser_agent import send_submit_index_in_state
# Committed fill whose submit ranks OUT of the capped listing (the shape that starves the picker).
COMPOSER_FILLED_NO_SEND = '[1]<textbox "I\'m looking for…">\n[24]<textbox "Write a message" value="[test] hello world r9-os">'
COMPOSER_SENT = '[2]<textbox "Write a message">\n[9]<button "Attach">'
def make_exec(eval_result):
calls = {"clicks": []}
async def execute(tool, params, bid, tid):
if tool == "BrowserListInteractives":
return {"text": COMPOSER_SENT}
calls["clicks"].append((tool, params))
if tool == "BrowserEvaluate":
return eval_result
return {"ok": True}
return execute, calls
@pytest.mark.asyncio
async def test_container_submit_tier_between_index_and_by_name():
"""X's compose modal: covered feed rows behind the overlay eat the 60-row cap, so the modal's
own Post never reaches the picker (live 0/2 deliveries). The container tier resolves the
submit inside the composer's own container and clicks it with REAL input; by-name stays last."""
execute, calls = make_exec({"value": {"ok": True, "name": "post", "xPct": 61.0, "yPct": 33.0}})
r = await ss.complete_send("[test] hello world r9-os", COMPOSER_FILLED_NO_SEND,
"b1", "", execute, send_submit_index_in_state, composer_index=24)
assert r["clicked"] is True and r["sent"] is True
tools = [c[0] for c in calls["clicks"]]
assert "BrowserEvaluate" in tools and "BrowserClickByName" not in tools
point = [c for c in calls["clicks"] if c[0] == "BrowserClickPoint"]
assert point and point[0][1] == {"xPercent": 61.0, "yPercent": 33.0}
@pytest.mark.asyncio
async def test_container_submit_miss_falls_to_by_name():
execute, calls = make_exec({"value": {"ok": False, "why": "no submit control in the composer container"}})
r = await ss.complete_send("[test] hello world r9-os", COMPOSER_FILLED_NO_SEND,
"b1", "", execute, send_submit_index_in_state, composer_index=24)
assert r["clicked"] is True
tools = [c[0] for c in calls["clicks"]]
assert tools.index("BrowserEvaluate") < tools.index("BrowserClickByName")
def test_container_submit_expression_escapes_and_truncates():
expr = sc.container_submit_expression('he said "hi" ' + "x" * 60)
assert '\\"hi\\"' in expr # payload lands as a JS string literal, quotes escaped
assert "x" * 30 not in expr # truncated to the 24-char prefix the fill verifier uses
assert '"post"' in expr and '"send"' in expr
def test_clean_button_name_strips_shortcut_suffix_and_bidi():
# Gmail's real Send accessible name: 'Send (⌘Enter)'
assert sc.clean_button_name("Send (⌘Enter)") == "send"
assert sc.clean_button_name(" Post ") == "post"
assert sc.clean_button_name("Reply (Ctrl-Enter)") == "reply"
assert sc.clean_button_name("") == ""
def test_parse_eval_value_reads_value_text_and_garbage():
assert sc.parse_eval_value({"value": {"ok": True}}) == {"ok": True}
assert sc.parse_eval_value({"text": '{"ok": false, "why": "x"}'}) == {"ok": False, "why": "x"}
assert sc.parse_eval_value({"text": "not json"}) is None
assert sc.parse_eval_value({"error": "boom"}) is None
assert sc.parse_eval_value("weird") is None