Repository navigation
Unit test integration settings UI sync #368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 12 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
b0eff25
Merge pull request #366 from ikostan/main
ikostan e10ab48
Update README with development status and contribution guide
ikostan 88cbd91
Unit Test Plan: 4. Integration: Settings + UI Sync #350
ikostan 2d59db0
Update test_integration_key_mapping.gd
ikostan 857a5a4
Update test_integration_key_mapping.gd
ikostan 3848dd4
Update test_integration_key_mapping.gd
ikostan e6a8cab
Update requirements.txt
ikostan db8a3ab
Update test/gut/test_integration_key_mapping.gd
ikostan 5411667
Remove the unused settings_inst assignment.
ikostan d12958c
Update test_integration_key_mapping.gd
ikostan 2e0f0dc
Update test_integration_key_mapping.gd
ikostan a93f419
[DOCUMENTATION] Milestone #10 README.md update #315
ikostan 26a6c27
Use an isolated test config path or implement backup/restore.
ikostan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| ## Copyright (C) 2025 Egor Kostan | ||
| ## SPDX-License-Identifier: GPL-3.0-or-later | ||
| ## test_integration_key_mapping.gd | ||
| ## GUT unit tests for integration of key mapping load, remap, persistence, and reset. | ||
| ## Covers INT-01 to INT-03 from test plan. | ||
| ## Test Plan: | ||
| ## https://github.com/ikostan/SkyLockAssault/issues/350 | ||
| ## References: test_key_mapping_menu.gd, test_input_remap_button.gd, input_remap_button.gd, key_mapping.gd | ||
| ## Assumes Settings.load_input_mappings() loads [input] section from config to InputMap. | ||
| ## Assumes Settings.save_input_mappings() saves InputMap events to [input] as arrays of strings (e.g., ["key:87"] for KEY_W). | ||
| ## Assumes Settings.reset_to_defaults(device_type) resets InputMap for that device and saves. | ||
| ## Uses test config path to isolate; focuses on keyboard for brevity (extend for gamepad if needed). | ||
| ## Uses "speed_up" as test action (from UI paths); assumes default keyboard is KEY_W ("W"). | ||
| ## Simulates remap via direct calls to private methods due to input event mocking complexity in GUT. | ||
|
|
||
| extends GutTest | ||
|
|
||
| const InputRemapButton: Script = preload("res://scripts/input_remap_button.gd") | ||
| const TEST_ACTION: String = "speed_up" # Example action from UI; adjust if needed. | ||
| const TEST_CONFIG_PATH: String = "user://settings.cfg" | ||
| const KEY_W_CODE: int = Key.KEY_W # 87, default assumed. | ||
| const KEY_Z_CODE: int = Key.KEY_Z # 90, custom for tests. | ||
|
|
||
| var menu: CanvasLayer = null | ||
|
|
||
|
|
||
| ## Per-test setup: Delete test config, reset InputMap for test action. | ||
| ## :rtype: void | ||
| func before_each() -> void: | ||
| if FileAccess.file_exists(TEST_CONFIG_PATH): | ||
| var err: Error = DirAccess.remove_absolute(TEST_CONFIG_PATH) | ||
| assert_eq(err, OK) | ||
| for action in Settings.ACTIONS: | ||
| if InputMap.has_action(action): | ||
| InputMap.action_erase_events(action) | ||
| else: | ||
| InputMap.add_action(action) | ||
| Settings.load_input_mappings() # Reload empty | ||
|
|
||
|
|
||
|
ikostan marked this conversation as resolved.
Resolved
|
||
| ## Per-test cleanup: Free menu, delete test config. | ||
| ## :rtype: void | ||
| func after_each() -> void: | ||
| if is_instance_valid(menu): | ||
| menu.queue_free() | ||
| if FileAccess.file_exists(TEST_CONFIG_PATH): | ||
| var err: Error = DirAccess.remove_absolute(TEST_CONFIG_PATH) | ||
| assert_eq(err, OK) | ||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
| await get_tree().process_frame | ||
|
|
||
|
|
||
| ## INT-01 | Load mappings → UI | Pre-saved config | UI shows correct mappings | Matches config file | ||
| ## :rtype: void | ||
| func test_int_01_load_to_ui() -> void: | ||
| gut.p("INT-01: Pre-saved config loads to InputMap and UI shows correct labels matching config.") | ||
| # Setup: Create config with custom keyboard mapping (e.g., "Z" instead of default "W") | ||
| var config: ConfigFile = ConfigFile.new() | ||
| config.set_value("input", TEST_ACTION, ["key:" + str(KEY_Z_CODE)]) # Assume string format "key:<code>" | ||
| config.save(TEST_CONFIG_PATH) | ||
| # Load mappings to InputMap | ||
| Settings.load_input_mappings() | ||
| # Verify InputMap loaded correctly | ||
| var events: Array[InputEvent] = InputMap.action_get_events(TEST_ACTION) | ||
| var key_events: Array[InputEventKey] = [] | ||
| for ev: InputEvent in events: | ||
| if ev is InputEventKey: | ||
| key_events.append(ev) | ||
| assert_eq(key_events.size(), 1, "Should have one keyboard event after load") | ||
| var key_ev: InputEventKey = key_events[0] | ||
| assert_eq(key_ev.physical_keycode, KEY_Z_CODE, "Loaded keycode should match config") | ||
| # Instantiate menu and add to tree (UI updates in _ready via update_button_text) | ||
| menu = load("res://scenes/key_mapping_menu.tscn").instantiate() | ||
| add_child(menu) | ||
| # Get specific remap button for test action (keyboard default) | ||
| var speed_up_btn: InputRemapButton = menu.get_node("Panel/Options/KeyMapContainer/PlayerKeyMap/KeyMappingSpeedUp/SpeedUpInputRemap") | ||
| assert_not_null(speed_up_btn, "SpeedUp remap button should exist") | ||
| # Validation: UI matches config/loaded mapping | ||
| assert_eq(speed_up_btn.text, "Z", "UI label should show loaded custom key 'Z'") | ||
| # Double-check config unchanged | ||
| config = ConfigFile.new() | ||
| config.load(TEST_CONFIG_PATH) | ||
| var saved_events: Array = config.get_value("input", TEST_ACTION, []) | ||
| assert_true(saved_events.any(func(s: String) -> bool: return s == "key:" + str(KEY_Z_CODE)), "Config should match") | ||
|
|
||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
|
|
||
| ## INT-02 | Remap + persist | Change action then save | Reload restores mapping | Disk & UI sync | ||
| ## :rtype: void | ||
| func test_int_02_remap_persist() -> void: | ||
| gut.p("INT-02: Remap updates InputMap/UI, saves to config; reload restores to disk/UI sync.") | ||
| # Setup: Default mapping (assume reset sets to "W"); instantiate menu | ||
| Settings.reset_to_defaults("keyboard") # Ensure defaults loaded | ||
| menu = load("res://scenes/key_mapping_menu.tscn").instantiate() | ||
| add_child(menu) | ||
| var speed_up_btn: InputRemapButton = menu.get_node("Panel/Options/KeyMapContainer/PlayerKeyMap/KeyMappingSpeedUp/SpeedUpInputRemap") | ||
| assert_eq(speed_up_btn.text, "W", "Should start with default 'W'") | ||
| # Simulate remap to "Z" (direct calls as in ref tests) | ||
| speed_up_btn.button_pressed = true | ||
| speed_up_btn._on_pressed() # Start listening | ||
| var temp_event := InputEventKey.new() | ||
| temp_event.physical_keycode = KEY_Z_CODE | ||
| temp_event.pressed = true | ||
| speed_up_btn._input(temp_event) # Triggers erase/add/save | ||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
| # Verify immediate UI/InputMap update | ||
| assert_eq(speed_up_btn.text, "Z", "UI label should update to new key 'Z'") | ||
| var events: Array[InputEvent] = InputMap.action_get_events(TEST_ACTION) | ||
| var key_events: Array[InputEventKey] = [] | ||
| for ev: InputEvent in events: | ||
| if ev is InputEventKey: | ||
| key_events.append(ev) | ||
| assert_eq(key_events.size(), 1, "Should have one keyboard event after remap") | ||
| var key_ev: InputEventKey = key_events[0] | ||
| assert_eq(key_ev.physical_keycode, KEY_Z_CODE, "InputMap should have new keycode") | ||
| # Verify saved to config (persist) | ||
| var config: ConfigFile = ConfigFile.new() | ||
| config.load(TEST_CONFIG_PATH) | ||
| assert_true(config.has_section("input"), "Config should have input section after save") | ||
| assert_true(config.has_section_key("input", TEST_ACTION), "Config should have key after save") | ||
| var saved_events: Array = config.get_value("input", TEST_ACTION, []) | ||
| assert_true(saved_events.any(func(s: String) -> bool: return s == "key:" + str(KEY_Z_CODE)), "Config should match new mapping") | ||
| # Simulate reload: Erase InputMap, load from config, update UI | ||
| InputMap.action_erase_events(TEST_ACTION) | ||
| Settings.load_input_mappings() | ||
| speed_up_btn.update_button_text() # Or reinstantiate, but update suffices | ||
| assert_eq(speed_up_btn.text, "Z", "UI should restore loaded mapping after reload") | ||
| events = InputMap.action_get_events(TEST_ACTION) | ||
| key_events = [] | ||
| for ev: InputEvent in events: | ||
| if ev is InputEventKey: | ||
| key_events.append(ev) | ||
| assert_eq(key_events.size(), 1, "Should have one keyboard event after reload") | ||
| key_ev = key_events[0] | ||
| assert_eq(key_ev.physical_keycode, KEY_Z_CODE, "InputMap restored from disk") | ||
|
|
||
|
|
||
| ## INT-03 | Reset via UI | Click reset | Mappings + config reset | Defaults in UI & file | ||
| ## :rtype: void | ||
| func test_int_03_reset_via_ui() -> void: | ||
| gut.p("INT-03: Reset button resets InputMap/config to defaults; UI/file show defaults.") | ||
| # Setup: Set custom mapping in config/InputMap, then instantiate menu | ||
| var config: ConfigFile = ConfigFile.new() | ||
| config.set_value("input", TEST_ACTION, ["key:" + str(KEY_Z_CODE)]) | ||
| config.save(TEST_CONFIG_PATH) | ||
| Settings.load_input_mappings() | ||
| menu = load("res://scenes/key_mapping_menu.tscn").instantiate() | ||
| add_child(menu) | ||
| var speed_up_btn: InputRemapButton = menu.get_node("Panel/Options/KeyMapContainer/PlayerKeyMap/KeyMappingSpeedUp/SpeedUpInputRemap") | ||
| assert_eq(speed_up_btn.text, "Z", "Should start with custom 'Z'") | ||
| # Get reset button | ||
| var reset_btn: Button = menu.get_node("Panel/Options/BtnContainer/ControlResetButton") | ||
| # Simulate reset (keyboard mode default) | ||
| reset_btn.pressed.emit() # Triggers _on_reset_pressed → Settings.reset_to_defaults("keyboard") → update_all_remap_buttons | ||
| # Verify UI/InputMap reset to default | ||
| assert_eq(speed_up_btn.text, "W", "UI label should reset to default 'W'") | ||
| var events: Array[InputEvent] = InputMap.action_get_events(TEST_ACTION) | ||
| var key_events: Array[InputEventKey] = [] | ||
| for ev: InputEvent in events: | ||
| if ev is InputEventKey: | ||
| key_events.append(ev) | ||
| assert_eq(key_events.size(), 1, "Should have one keyboard event after reset") | ||
| var key_ev: InputEventKey = key_events[0] | ||
| assert_eq(key_ev.physical_keycode, KEY_W_CODE, "InputMap should reset to default keycode") | ||
| # Verify config reset (assume reset saves defaults) | ||
| config = ConfigFile.new() | ||
| config.load(TEST_CONFIG_PATH) | ||
| var saved_events: Array = config.get_value("input", TEST_ACTION, []) | ||
| assert_true(saved_events.any(func(s: String) -> bool: return s == "key:" + str(KEY_W_CODE)), "Config should reset to default mapping") | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.