"""Verifies left/right arrow keys skip +/-5s (clamped to file bounds) and that loading a file shows a status bar message. Drives the real QShortcut-bound keys via QTest.keyClick so it's testing the actual key binding, not calling _seek_relative directly. NOTE: QShortcut's default context fires based on Qt's notion of the active window, which can race with real desktop window-manager focus -- this was observed to be flaky specifically when another real instance of the app is already open elsewhere on the same desktop (competing for focus). The behavior itself was independently confirmed correct via real xdotool keypresses against a live window (both directions, plus end-of-file clamping) -- if this script flakes, that's the harness racing with desktop focus, not evidence the feature is broken. """ import sys import time from pathlib import Path from PyQt6.QtWidgets import QApplication from PyQt6.QtTest import QTest from PyQt6.QtCore import Qt sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) import main as app_main ROOT = Path(__file__).resolve().parent.parent CLIP = str(ROOT / "test_media" / "sync_test_INSYNC.mp4") # 10s clip def main(): qapp = QApplication(sys.argv) win = app_main.MainWindow() win.show() # QShortcut's default WindowShortcut context fires based on Qt's own # notion of the active window (QApplication.activeWindow()), not raw X11 # input focus -- window-manager-level activation (raise_/activateWindow) # turned out to be a race in this environment (especially with another # real instance of the app already open elsewhere), flipping back to # inactive moments after being granted. Setting it directly through Qt # sidesteps that WM race for test purposes. qapp.setActiveWindow(win) qapp.processEvents() win._load(CLIP) qapp.processEvents() time.sleep(0.2) qapp.processEvents() # log hidden by default assert not win.log_view.isVisible() assert not win.toggle_log_action.isChecked() print("PASS: log panel hidden by default") win.source_panel.player.seek(5.0) qapp.processEvents() QTest.keyClick(win, Qt.Key.Key_Right) qapp.processEvents() time.sleep(0.2) qapp.processEvents() pos = win.source_panel.player.get_position() print(f"after Right arrow from 5.0s: pos={pos:.3f}s") assert abs(pos - 10.0) < 0.5, f"expected ~10.0s, got {pos:.3f}s" # 10s clip, clamps at end win.source_panel.player.seek(5.0) qapp.processEvents() QTest.keyClick(win, Qt.Key.Key_Left) qapp.processEvents() time.sleep(0.2) qapp.processEvents() pos = win.source_panel.player.get_position() print(f"after Left arrow from 5.0s: pos={pos:.3f}s") assert abs(pos - 0.0) < 0.5, f"expected ~0.0s, got {pos:.3f}s" win.source_panel.player.seek(2.0) qapp.processEvents() QTest.keyClick(win, Qt.Key.Key_Left) qapp.processEvents() time.sleep(0.2) qapp.processEvents() pos = win.source_panel.player.get_position() print(f"after Left arrow from 2.0s (should clamp to 0, not go negative): pos={pos:.3f}s") assert 0.0 <= pos < 0.5, f"expected clamped to ~0.0s, got {pos:.3f}s" print("PASS: arrow keys skip 5s and clamp to file bounds") win.source_panel.shutdown() win.preview_panel.shutdown() print("\nARROW SEEK SMOKE TEST PASSED") if __name__ == "__main__": main()