test: verify and document desktop ui
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
||||
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
from javis.core.provider_router import ApprovalChoice
|
||||
from javis.providers.base import ChatMessage
|
||||
from javis.security.privacy import CloudPolicy, PrivacyDecision
|
||||
from javis.ui.main_window import MainWindow
|
||||
from javis.ui.models import DesktopStatus, GenerationState
|
||||
from javis.ui.workers import ApprovalBridge
|
||||
|
||||
|
||||
class _Controller:
|
||||
def __init__(self) -> None:
|
||||
self.active_session_id = None
|
||||
self.state = GenerationState.READY
|
||||
self.session = SimpleNamespace(
|
||||
id="session-one",
|
||||
title="Desktop-Test",
|
||||
last_provider="ollama",
|
||||
message_count=2,
|
||||
updated_at="2026-07-30T20:00:00+00:00",
|
||||
)
|
||||
|
||||
def list_sessions(self, search: str = ""):
|
||||
return [self.session] if not search or search in self.session.title else []
|
||||
|
||||
def load_session(self, session_id: str):
|
||||
self.active_session_id = session_id
|
||||
return SimpleNamespace(
|
||||
session=self.session,
|
||||
messages=[
|
||||
ChatMessage("user", "Hallo"),
|
||||
ChatMessage("assistant", "Guten Tag"),
|
||||
],
|
||||
)
|
||||
|
||||
def new_session(self):
|
||||
self.active_session_id = self.session.id
|
||||
return self.session
|
||||
|
||||
def rename_active_session(self, title: str):
|
||||
self.session.title = title
|
||||
return self.session
|
||||
|
||||
def set_mode(self, _mode: str) -> None:
|
||||
return
|
||||
|
||||
def status(self) -> DesktopStatus:
|
||||
return DesktopStatus(
|
||||
state=self.state,
|
||||
mode="Lokal",
|
||||
provider="ollama",
|
||||
ollama_reachable=True,
|
||||
local_model="test-model",
|
||||
privacy_policy="never",
|
||||
cloud_requests_today=0,
|
||||
local_fallback=False,
|
||||
data_dir="D:\\Testdaten",
|
||||
)
|
||||
|
||||
|
||||
class _MessageBox:
|
||||
Question = object()
|
||||
AcceptRole = object()
|
||||
RejectRole = object()
|
||||
DestructiveRole = object()
|
||||
selected_label = ""
|
||||
|
||||
def __init__(self, _parent) -> None:
|
||||
self.buttons: dict[str, object] = {}
|
||||
|
||||
def setWindowTitle(self, _text: str) -> None:
|
||||
return
|
||||
|
||||
def setIcon(self, _icon: object) -> None:
|
||||
return
|
||||
|
||||
def setText(self, _text: str) -> None:
|
||||
return
|
||||
|
||||
def setInformativeText(self, _text: str) -> None:
|
||||
return
|
||||
|
||||
def addButton(self, label: str, _role: object) -> object:
|
||||
button = object()
|
||||
self.buttons[label] = button
|
||||
return button
|
||||
|
||||
def exec(self) -> None:
|
||||
return
|
||||
|
||||
def clickedButton(self) -> object | None:
|
||||
return self.buttons.get(type(self).selected_label)
|
||||
|
||||
|
||||
class DesktopGuiTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
cls.application = QApplication.instance() or QApplication([])
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.bridge = ApprovalBridge()
|
||||
self.window = MainWindow(_Controller(), self.bridge)
|
||||
self.window.show()
|
||||
self.application.processEvents()
|
||||
|
||||
def tearDown(self) -> None:
|
||||
self.window.close()
|
||||
self.application.processEvents()
|
||||
|
||||
def test_offscreen_window_loads_session_and_core_widgets(self) -> None:
|
||||
self.assertEqual(self.window.windowTitle(), "Javis Desktop")
|
||||
self.assertEqual(self.window.session_list.count(), 1)
|
||||
self.assertIn("Hallo", self.window.chat_view.toPlainText())
|
||||
self.assertTrue(self.window.send_button.isEnabled())
|
||||
self.assertFalse(self.window.stop_button.isEnabled())
|
||||
self.assertEqual(self.window.status_labels["provider"].text(), "ollama")
|
||||
|
||||
def test_approval_dialog_maps_all_three_choices(self) -> None:
|
||||
decision = PrivacyDecision(CloudPolicy.ASK, "persönliche Information")
|
||||
self.bridge.resolve = Mock()
|
||||
expected = {
|
||||
"Einmal erlauben": ApprovalChoice.ALLOW,
|
||||
"Lokal beantworten": ApprovalChoice.LOCAL,
|
||||
"Abbrechen": ApprovalChoice.CANCEL,
|
||||
}
|
||||
|
||||
with patch("javis.ui.main_window.QMessageBox", _MessageBox):
|
||||
for label, choice in expected.items():
|
||||
with self.subTest(label=label):
|
||||
_MessageBox.selected_label = label
|
||||
self.window._show_approval(decision)
|
||||
self.bridge.resolve.assert_called_with(choice)
|
||||
Reference in New Issue
Block a user