Agent-Reach/tests/test_twitter_channel.py
Panniantong 7ae0cd8c0a feat(twitter): migrate from xreach to bird CLI
- Replace xreach CLI with bird (@steipete/bird) as Twitter/X backend
- bird uses AUTH_TOKEN/CT0 env vars (simpler than xreach's session.json)
- Accept both 'bird' and 'birdx' binary names
- Remove version detection logic (bird v0.8.0 is the baseline)
- Write credentials.env to ~/.config/bird/ for easy sourcing
- Keep xfetch session.json sync for backward compatibility
- Update SKILL.md commands: bird search/read/user-tweets/thread
- Update install/uninstall to use npm @steipete/bird
- All 52 tests pass
2026-03-23 08:51:22 +01:00

70 lines
2.5 KiB
Python

# -*- coding: utf-8 -*-
from unittest.mock import patch, Mock
from agent_reach.channels.twitter import TwitterChannel
def _cp(stdout="", stderr="", returncode=0):
m = Mock()
m.stdout = stdout
m.stderr = stderr
m.returncode = returncode
return m
def test_check_bird_found_and_auth_ok():
"""bird found + bird check returns 0 → ok."""
channel = TwitterChannel()
with patch("shutil.which", side_effect=lambda name: "/usr/local/bin/bird" if name == "bird" else None), patch(
"subprocess.run",
return_value=_cp(stdout="Authenticated as @user\n", returncode=0),
):
status, message = channel.check()
assert status == "ok"
assert "完整可用" in message
def test_check_bird_found_auth_missing():
"""bird found + bird check returns 1 with 'Missing credentials' → warn about auth."""
channel = TwitterChannel()
with patch("shutil.which", side_effect=lambda name: "/usr/local/bin/bird" if name == "bird" else None), patch(
"subprocess.run",
return_value=_cp(stderr="Missing credentials: AUTH_TOKEN and CT0 required\n", returncode=1),
):
status, message = channel.check()
assert status == "warn"
assert "未配置认证" in message
def test_check_bird_not_found():
"""bird not found → warn with install hint for @steipete/bird."""
channel = TwitterChannel()
with patch("shutil.which", return_value=None):
status, message = channel.check()
assert status == "warn"
assert "@steipete/bird" in message
def test_check_birdx_binary_accepted():
"""birdx symlink is accepted as an alternative binary name."""
channel = TwitterChannel()
with patch("shutil.which", side_effect=lambda name: "/usr/local/bin/birdx" if name == "birdx" else None), patch(
"subprocess.run",
return_value=_cp(stdout="Authenticated as @user\n", returncode=0),
):
status, message = channel.check()
assert status == "ok"
assert "完整可用" in message
def test_check_bird_auth_failure_generic():
"""bird check returns 1 without 'Missing credentials' → generic auth failure warn."""
channel = TwitterChannel()
with patch("shutil.which", side_effect=lambda name: "/usr/local/bin/bird" if name == "bird" else None), patch(
"subprocess.run",
return_value=_cp(stderr="Error: token expired\n", returncode=1),
):
status, message = channel.check()
assert status == "warn"
assert "认证检查失败" in message