diff --git a/config/app_config.json b/config/app_config.json index 12b7a51..a9e7832 100644 --- a/config/app_config.json +++ b/config/app_config.json @@ -1,7 +1,7 @@ { - "server_ip": "192.168.0.108", - "port": "8080", - "screen_name": "WINDOWS-PC", + "server_ip": "192.168.0.110", + "port": "80", + "screen_name": "DESKTOP-NJLBQKH", "quickconnect_key": "8887779", "orientation": "Landscape", "touch": "True", diff --git a/src/signage_player.kv b/src/signage_player.kv index 878feba..0ff0b77 100644 --- a/src/signage_player.kv +++ b/src/signage_player.kv @@ -386,6 +386,7 @@ size_hint_x: 0.7 multiline: False font_size: sp(13) + hint_text: 'e.g. 192.168.0.110' write_tab: False on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None @@ -432,6 +433,7 @@ size_hint_x: 0.7 multiline: False font_size: sp(13) + hint_text: 'player name registered on the server' write_tab: False on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None @@ -454,6 +456,7 @@ size_hint_x: 0.7 multiline: False font_size: sp(13) + hint_text: 'e.g. 8887779' write_tab: False on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None diff --git a/windows/test_first_run_setup.py b/windows/test_first_run_setup.py new file mode 100644 index 0000000..6c7bb1c --- /dev/null +++ b/windows/test_first_run_setup.py @@ -0,0 +1,111 @@ +"""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())