Add desktop ready checks, smarter chat scrolling, and fight-night reactions
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user