121 lines
3.6 KiB
Python
121 lines
3.6 KiB
Python
"""Slave GUI chat: newest-first transcript and fullscreen chat mode (offscreen Qt)."""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
|
|
|
SLAVE_SRC = Path(__file__).resolve().parents[1] / "javis-slave" / "src"
|
|
if str(SLAVE_SRC) not in sys.path:
|
|
sys.path.insert(0, str(SLAVE_SRC))
|
|
|
|
QtWidgets = pytest.importorskip("PySide6.QtWidgets")
|
|
QtTest = pytest.importorskip("PySide6.QtTest")
|
|
|
|
from javis_slave import main_window # noqa: E402
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def qapp():
|
|
return QtWidgets.QApplication.instance() or QtWidgets.QApplication([])
|
|
|
|
|
|
@pytest.fixture
|
|
def screen(qapp):
|
|
scr = main_window.MainScreen()
|
|
scr.resize(900, 700)
|
|
scr.show()
|
|
yield scr
|
|
scr.close()
|
|
|
|
|
|
def _texts(scr) -> list[str]:
|
|
"""Bubble texts from the top of the transcript to the bottom."""
|
|
layout = scr.transcript_layout
|
|
out = []
|
|
for i in range(layout.count()):
|
|
row = layout.itemAt(i).widget()
|
|
if row is not None:
|
|
out.append(row.findChild(QtWidgets.QLabel).text())
|
|
return out
|
|
|
|
|
|
def test_newest_message_is_on_top(screen):
|
|
screen.set_turn("frage 1", "antwort 1")
|
|
screen.set_turn("frage 2", "antwort 2")
|
|
screen.show_error("kaputt")
|
|
assert _texts(screen) == [
|
|
"⚠ kaputt", "antwort 2", "frage 2", "antwort 1", "frage 1"]
|
|
|
|
|
|
def test_prune_drops_oldest_at_the_bottom(screen):
|
|
for i in range(30):
|
|
screen.set_turn(f"u{i}", f"a{i}")
|
|
texts = _texts(screen)
|
|
assert len(texts) == 40
|
|
assert texts[0] == "a29"
|
|
assert "u0" not in texts and "u29" in texts
|
|
|
|
|
|
def test_scrolls_to_top_on_new_message(screen):
|
|
for i in range(12):
|
|
screen.set_turn(f"u{i}", "x " * 200)
|
|
QtTest.QTest.qWait(150) # lets the layout settle (and the first auto-scroll fire)
|
|
vbar = screen.transcript_scroll.verticalScrollBar()
|
|
assert vbar.maximum() > 0
|
|
vbar.setValue(vbar.maximum())
|
|
screen.set_turn("neu", "neu")
|
|
QtTest.QTest.qWait(150) # the scroll is deferred by a 50 ms timer
|
|
assert vbar.value() == vbar.minimum()
|
|
|
|
|
|
def test_fullscreen_button_goes_fullscreen_and_keeps_orb_and_chat_visible(qapp):
|
|
win = main_window.SlaveWindow()
|
|
win.show_main()
|
|
win.show()
|
|
scr = win.main_screen
|
|
scr.set_turn("frage", "antwort")
|
|
try:
|
|
assert not win.isFullScreen()
|
|
assert scr.expand_btn.toolTip() == "Vollbild"
|
|
|
|
scr.expand_btn.click()
|
|
QtTest.QTest.qWait(50)
|
|
assert win.isFullScreen()
|
|
assert scr.orb.isVisible() and scr.transcript_scroll.isVisible()
|
|
assert scr.expand_btn.toolTip() == "Vollbild beenden"
|
|
|
|
scr.expand_btn.click()
|
|
QtTest.QTest.qWait(50)
|
|
assert not win.isFullScreen()
|
|
assert scr.orb.isVisible() and scr.transcript_scroll.isVisible()
|
|
assert scr.expand_btn.toolTip() == "Vollbild"
|
|
finally:
|
|
win.close()
|
|
|
|
|
|
def test_esc_and_f11_keep_button_in_sync(qapp):
|
|
win = main_window.SlaveWindow()
|
|
win.show_main()
|
|
win.show()
|
|
try:
|
|
win._toggle_fullscreen() # F11
|
|
QtTest.QTest.qWait(50)
|
|
assert win.isFullScreen() and win.main_screen.expand_btn.toolTip() == "Vollbild beenden"
|
|
|
|
win._leave_fullscreen() # Esc
|
|
QtTest.QTest.qWait(50)
|
|
assert not win.isFullScreen() and win.main_screen.expand_btn.toolTip() == "Vollbild"
|
|
finally:
|
|
win.close()
|
|
|
|
def test_expand_icons_render(qapp):
|
|
for kind in ("expand", "collapse"):
|
|
img = main_window._icon(kind, "#cccccc", 26).pixmap(26, 26).toImage()
|
|
assert any(img.pixelColor(x, y).alpha() > 0
|
|
for x in range(img.width()) for y in range(img.height()))
|