"""Tests the first-run setup decision logic in src/main.py. The rule that matters: a player is "configured" only when it has REAL server settings. A missing file, an empty file, unparseable JSON, missing keys, and leftover placeholder values must ALL count as unconfigured, so the app shows the setup notice instead of silently trying to reach "localhost". Run: windows\\venv\\Scripts\\python.exe windows\\test_first_run_setup.py Exit code 0 = PASS. """ import sys from pathlib import Path SRC = Path(__file__).resolve().parent.parent / 'src' sys.path.insert(0, str(SRC)) import main as app # noqa: E402 def main(): print('=' * 68) print(' First-run setup detection test') print('=' * 68) must_be_unconfigured = { 'None': None, 'empty dict': {}, 'empty config file': {}, 'placeholder defaults': { 'server_ip': 'localhost', 'screen_name': 'kivy-player', 'quickconnect_key': '1234567', }, 'all blank': { 'server_ip': '', 'screen_name': '', 'quickconnect_key': '', }, 'missing keys': {'server_ip': '192.168.0.110'}, 'whitespace only': { 'server_ip': ' ', 'screen_name': '\t', 'quickconnect_key': ' ', }, 'loopback': { 'server_ip': '127.0.0.1', 'screen_name': 'PC', 'quickconnect_key': '9', }, 'placeholder screen name': { 'server_ip': '192.168.0.110', 'screen_name': 'kivy-player', 'quickconnect_key': '8887779', }, } must_be_configured = { 'real settings': { 'server_ip': '192.168.0.110', 'screen_name': 'DESKTOP-NJLBQKH', 'quickconnect_key': '8887779', }, 'hostname as ip': { 'server_ip': 'digi-signage.local', 'screen_name': 'Player1', 'quickconnect_key': '0123456', }, 'extra keys ignored': { 'server_ip': '10.0.0.5', 'screen_name': 'Sign1', 'quickconnect_key': '424242', 'weblink': {'engine': 'auto'}, }, } ok = True for label, value in must_be_unconfigured.items(): got = app.config_is_configured(value) flag = 'ok ' if got is False else 'FAIL' if got is not False: ok = False print(f' [{flag}] unconfigured: {label:24} -> {got}') print() for label, value in must_be_configured.items(): got = app.config_is_configured(value) flag = 'ok ' if got is True else 'FAIL' if got is not True: ok = False print(f' [{flag}] configured: {label:24} -> {got}') # The defaults the app starts from must themselves be "unconfigured", # otherwise a fresh install would look ready to sync. print() default_ok = app.config_is_configured(app.DEFAULT_CONFIG) is False print(f' [{"ok " if default_ok else "FAIL"}] DEFAULT_CONFIG is unconfigured ' f'-> {app.config_is_configured(app.DEFAULT_CONFIG)}') if not default_ok: ok = False # Required keys must actually be the ones enforced. print(f'\n required keys: {app.CONFIG_REQUIRED_KEYS}') print(f' notice delay : {app.SETUP_NOTICE_SECONDS}s before Settings opens') # The notice must wait a few seconds (the user asked for 5). if app.SETUP_NOTICE_SECONDS != 5: print(f' FAIL: expected a 5s notice, got {app.SETUP_NOTICE_SECONDS}') ok = False print('=' * 68) print(' RESULT:', 'PASS' if ok else 'FAIL') print('=' * 68) return 0 if ok else 1 if __name__ == '__main__': sys.exit(main())