Some checks failed
Release / semantic-release (push) Successful in 22s
tests / Unit tests (Linux, Python 3.11) (push) Failing after 5m16s
Release / build-linux (push) Failing after 7m10s
Release / build-windows (push) Has been cancelled
Release / build-macos (arm64, macos-latest) (push) Has been cancelled
Release / build-macos (x64, macos-15-intel) (push) Has been cancelled
Release / release-main (push) Has been cancelled
Release / release-develop (push) Has been cancelled
agents/llm.md promises "play the Nth video from the top", but browseAndPlay only ever clicked the first result. Add an optional 1-based index argument (default 1, backward-compatible) threaded to the Node helper, which now clicks the Nth a#video-title and clamps to the number of results returned so asking beyond the list plays the last available video instead of failing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
"""Tests for browseAndPlay's ``index`` argument (play the Nth search result).
|
|
|
|
Behaviour verified:
|
|
- default plays the first result (index 1) and stays backward-compatible,
|
|
- an explicit index is forwarded to the Node helper as the 4th argv,
|
|
- bad / sub-1 index values clamp to 1,
|
|
- the index is advertised in the tool schema.
|
|
"""
|
|
|
|
import json
|
|
from unittest.mock import Mock, patch
|
|
|
|
import pytest
|
|
|
|
from src.jarvis.tools.builtin.browse_and_play import BrowseAndPlayTool, _NODE_SCRIPT
|
|
|
|
|
|
def _ctx():
|
|
cfg = Mock()
|
|
cfg.stream_browser = True
|
|
return Mock(cfg=cfg, user_print=Mock())
|
|
|
|
|
|
def _run(args):
|
|
tool = BrowseAndPlayTool()
|
|
with patch("src.jarvis.tools.builtin.browse_and_play.subprocess.run") as mock_run:
|
|
mock_run.return_value = Mock(
|
|
stdout=json.dumps({"ok": True, "title": "Some Video"}),
|
|
stderr="",
|
|
)
|
|
result = tool.run(args, _ctx())
|
|
return mock_run, result
|
|
|
|
|
|
def _argv(mock_run):
|
|
return list(mock_run.call_args[0][0])
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_schema_exposes_index():
|
|
schema = BrowseAndPlayTool().inputSchema
|
|
assert "index" in schema["properties"]
|
|
assert schema["properties"]["index"]["type"] == "integer"
|
|
assert "query" in schema["required"]
|
|
assert "index" not in schema["required"] # optional
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_default_index_is_first():
|
|
mock_run, result = _run({"query": "IU Good Day"})
|
|
argv = _argv(mock_run)
|
|
assert argv[:4] == ["node", str(_NODE_SCRIPT), "IU Good Day", "youtube"]
|
|
assert argv[4] == "1"
|
|
assert result.success is True
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_explicit_index_forwarded():
|
|
mock_run, _ = _run({"query": "lofi", "index": 3})
|
|
assert _argv(mock_run)[4] == "3"
|
|
|
|
|
|
@pytest.mark.unit
|
|
@pytest.mark.parametrize("bad", [0, -2, "nope", None])
|
|
def test_bad_index_clamps_to_one(bad):
|
|
mock_run, _ = _run({"query": "lofi", "index": bad})
|
|
assert _argv(mock_run)[4] == "1"
|
|
|
|
|
|
@pytest.mark.unit
|
|
def test_voice_only_mode_does_not_play():
|
|
tool = BrowseAndPlayTool()
|
|
cfg = Mock()
|
|
cfg.stream_browser = False
|
|
ctx = Mock(cfg=cfg, user_print=Mock())
|
|
with patch("src.jarvis.tools.builtin.browse_and_play.subprocess.run") as mock_run:
|
|
result = tool.run({"query": "x", "index": 2}, ctx)
|
|
assert result.success is False
|
|
mock_run.assert_not_called()
|