Add desktop ready checks, smarter chat scrolling, and fight-night reactions

This commit is contained in:
Peter Stockings
2026-10-05 15:46:55 +11:00
parent 19576de166
commit f3eeda71e6
13 changed files with 1228 additions and 10 deletions
+116
View File
@@ -17,6 +17,7 @@ class PlayerSignals(QObject):
def room(qtbot, monkeypatch):
player = Mock(signals=PlayerSignals())
monkeypatch.setattr(room_widget, 'VLCSyncPlayer', lambda frame: player)
monkeypatch.setattr(room_widget.RoomWidget, '_play_reaction_sound', Mock())
widget = room_widget.RoomWidget()
widget.username = 'Me'
qtbot.addWidget(widget)
@@ -101,3 +102,118 @@ def test_popout_focus_and_wrapping(room, qtbot, monkeypatch):
room.add_chat_message('Other', 'Background popout', 0)
assert room._unread_messages == 1
popout.close()
def test_scrolling_preserves_position_and_counts_unread(room, qtbot):
for i in range(30):
room.add_chat_message('Other', f'Message {i}: ' + 'wrapped words ' * 10, 0)
qtbot.wait(150)
bar = room.chat_messages.verticalScrollBar()
assert bar.value() == bar.maximum()
bar.setValue(100)
qtbot.wait(30)
position = bar.value()
room.add_chat_message('Other', 'First unread message', 0)
room.add_chat_message('Other', 'Second unread message', 0)
room.add_system_message('Someone paused')
qtbot.wait(150)
assert bar.value() == position
assert room._pending_chat_messages == 2
assert not room.chat_jump_btn.isHidden()
assert room._unread_divider is not None
room.chat_input.setFocus()
assert room._pending_chat_messages == 2
room.jump_to_latest()
qtbot.wait(150)
assert bar.value() == bar.maximum()
assert room.chat_jump_btn.isHidden()
room.add_chat_message('Other', 'Follow latest', 0)
qtbot.wait(150)
assert bar.value() == bar.maximum()
assert room._pending_chat_messages == 0
def test_scroll_back_to_bottom_clears_pending(room, qtbot):
for i in range(20):
room.add_chat_message('Other', 'Words ' * 30, 0)
qtbot.wait(150)
bar = room.chat_messages.verticalScrollBar()
bar.setValue(0)
room.add_chat_message('Other', 'Unread', 0)
qtbot.wait(100)
bar.setValue(bar.maximum())
assert room._pending_chat_messages == 0
assert room._follow_chat
assert room.chat_jump_btn.isHidden()
room.clear_chat()
assert room._unread_divider is None
assert room.chat_content_layout.count() == 0
def test_ready_command_and_controls(room, qtbot):
with qtbot.waitSignal(room.ready_action_requested) as signal:
room.chat_input.setText('/ready')
room.send_chat()
assert signal.args == [{'type': 'ready_check', 'action': 'begin'}]
assert room.chat_input.text() == ''
state = {'active': True, 'id': 'check-1', 'requestedBy': 'Me', 'participants': [
{'username': 'Me', 'ready': False, 'connected': True},
{'username': "<b>O'Brien</b>", 'ready': True, 'connected': True}]}
room.update_ready_check(state)
assert not room.ready_panel.isHidden()
assert not room.ready_start_btn.isEnabled()
assert "<b>O'Brien</b>" in room.ready_users.text()
with qtbot.waitSignal(room.ready_action_requested) as signal:
room.ready_btn.click()
assert signal.args[0] == {'type': 'ready_check', 'action': 'vote', 'id': 'check-1', 'ready': True}
state['participants'][0]['ready'] = True
room.update_ready_check(state)
assert room.ready_start_btn.isEnabled()
with qtbot.waitSignal(room.ready_action_requested) as signal:
room.ready_start_btn.click()
assert signal.args[0]['action'] == 'start'
state['participants'][1]['connected'] = False
room.update_ready_check(state)
assert not room.ready_start_btn.isEnabled()
assert 'Reconnecting' in room.ready_users.text()
state['requestedBy'] = 'Other'
room.update_ready_check(state)
assert room.ready_start_btn.isHidden()
room.update_ready_check({'active': False})
assert room.ready_panel.isHidden()
def test_ready_panel_buttons_fit_styled_chat(room, qtbot):
from main import VlcSyncApp
VlcSyncApp.apply_stylesheet(room)
room.splitter.setSizes([750, 300])
room.update_ready_check({'active': True, 'id': 'layout', 'requestedBy': 'Me', 'participants': [
{'username': 'Me', 'ready': True, 'connected': True}]})
qtbot.wait(100)
for button in (room.ready_btn, room.ready_start_btn, room.ready_cancel_btn):
assert button.width() >= button.fontMetrics().horizontalAdvance(button.text()) + 20
room.update_connection_status(False)
room.update_ready_check(room._ready_check)
assert not room.ready_start_btn.isEnabled()
assert not room.ready_btn.isEnabled()
def test_app_wires_commands_to_websocket_and_incoming_panels(room, qtbot, monkeypatch):
import main
from sync_client import SyncClientThread
client = SyncClientThread()
client.send_message = Mock()
monkeypatch.setattr(main, 'SyncClientThread', lambda url: client)
app = main.VlcSyncApp()
qtbot.addWidget(app)
for command, expected in [('/ready', {'type': 'ready_check', 'action': 'begin'}),
('/ko', {'type': 'reaction', 'kind': 'ko'}),
('/bell', {'type': 'reaction', 'kind': 'bell'})]:
app.room_widget.chat_input.setText(command)
app.room_widget.send_chat()
client.send_message.assert_called_with(expected)
state = {'type': 'ready_check', 'active': True, 'id': 'wired', 'requestedBy': 'Me',
'participants': [{'username': 'Me', 'ready': False, 'connected': True}]}
client._handle_message(state)
assert app.room_widget._ready_check['id'] == 'wired'
assert not app.room_widget.ready_panel.isHidden()