Files
javis_bot/tests/tools/builtin/test_screenshot.py
javis-bot c4abf63f38
Some checks failed
Release / semantic-release (push) Successful in 59s
tests / Unit tests (Linux, Python 3.11) (push) Successful in 13m45s
Release / build-linux (push) Failing after 7m47s
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
Add Discord-native hybrid front-end for Jarvis (bot + bridge)
Transform isair/jarvis into a Discord-controlled voice assistant running on
the Ubuntu VNC desktop, keeping the mature ~39k-line Python brain intact.

- bot/ (Node + bun, discord.js): /자비스 slash commands (ephemeral),
  voice channel join + voice receive/playback, pluggable VNC screen broadcast
  (selfbot live / noVNC / screenshot)
- bridge/ (Python, Flask): wraps jarvis STT + run_reply_engine + Piper TTS
  behind a thin localhost HTTP API
- .env.example, scripts/ (start_bridge/start_bot/dev), README rewrite,
  docs/language-comparison.md and docs/vnc-xfce-setup.md

Language decision: hybrid (Python brain + Node/bun Discord layer) because
Discord blocks bot video; native screen broadcast only works via a Node
selfbot library.
2026-06-09 14:51:05 +09:00

88 lines
3.2 KiB
Python

"""Tests for screenshot tool."""
import pytest
from unittest.mock import Mock, patch
import sys
from src.jarvis.tools.builtin.screenshot import ScreenshotTool
from src.jarvis.tools.base import ToolContext
from src.jarvis.tools.types import ToolExecutionResult
class TestScreenshotTool:
"""Test screenshot tool functionality."""
def setup_method(self):
"""Set up test fixtures."""
self.tool = ScreenshotTool()
self.context = Mock(spec=ToolContext)
self.context.user_print = Mock()
def test_tool_properties(self):
"""Test tool metadata properties."""
assert self.tool.name == "screenshot"
assert "capture" in self.tool.description.lower()
assert self.tool.inputSchema["type"] == "object"
assert self.tool.inputSchema["required"] == []
@patch('shutil.which')
@patch('subprocess.run')
def test_run_success(self, mock_run, mock_which):
"""Test successful screenshot capture with inlined OCR logic."""
# Lightweight stubs so dynamic imports succeed without heavy deps
class _StubImgCtx:
def __enter__(self):
return self
def __exit__(self, *a):
return False
class _StubImage:
@staticmethod
def open(*a, **k):
return _StubImgCtx()
sys.modules['pytesseract'] = type('StubTess', (), {
'image_to_string': staticmethod(lambda *a, **k: 'Sample OCR text')
})
sys.modules['PIL'] = type('StubPIL', (), {'Image': _StubImage})
sys.modules['PIL.Image'] = _StubImage
# Indicate tools exist
def which_side_effect(name):
return f"/usr/bin/{name}" if name in ("screencapture", "tesseract") else None
mock_which.side_effect = which_side_effect
mock_proc = Mock()
mock_proc.returncode = 0
mock_run.return_value = mock_proc
with patch('tempfile.mkdtemp', return_value='/tmp/jarvis_ocr_test'), \
patch('os.path.exists', return_value=True), \
patch('os.remove'), \
patch('os.rmdir'):
result = self.tool.run({}, self.context)
assert isinstance(result, ToolExecutionResult)
assert result.success is True
assert result.reply_text == 'Sample OCR text'
self.context.user_print.assert_called()
@patch('shutil.which')
@patch('subprocess.run')
def test_run_empty_ocr(self, mock_run, mock_which):
"""Test screenshot with empty OCR result (tesseract missing)."""
# screencapture present, tesseract missing
def which_side_effect(name):
if name == 'screencapture':
return '/usr/bin/screencapture'
return None
mock_which.side_effect = which_side_effect
mock_proc = Mock(); mock_proc.returncode = 0; mock_run.return_value = mock_proc
with patch('tempfile.mkdtemp') as mock_tmp, \
patch('os.path.exists') as mock_exists:
mock_tmp.return_value = '/tmp/jarvis_ocr_test'
mock_exists.return_value = True
result = self.tool.run({}, self.context)
assert isinstance(result, ToolExecutionResult)
assert result.success is True
assert result.reply_text == ''