From 334848e9e213651e52ac5c3bf4744012d1d0f96d Mon Sep 17 00:00:00 2001 From: Rob <5183487+Rexeh@users.noreply.github.com> Date: Fri, 8 Mar 2024 18:08:01 +0000 Subject: [PATCH] Add export tests, fixed bug with template replacement for modifiers --- joystick_diagrams/template.py | 6 +- tests/test_export.py | 243 ++++++++++++++++++++++++++++++++++ tests/test_template.py | 6 +- 3 files changed, 248 insertions(+), 7 deletions(-) create mode 100644 tests/test_export.py diff --git a/joystick_diagrams/template.py b/joystick_diagrams/template.py index 985324c..3bceaae 100644 --- a/joystick_diagrams/template.py +++ b/joystick_diagrams/template.py @@ -19,11 +19,11 @@ class Template: # Modifiers MODIFIER_KEYS = [ # All Modifiers Key - re.compile(r"\b[a-zA-Z]+_\d+_Modifiers", flags=re.IGNORECASE), + re.compile(r"\b[a-zA-Z]+_\w+_Modifiers\b", flags=re.IGNORECASE), # Handles Modifier_X - re.compile(r"\b[a-zA-Z]+_\d+_Modifier_\d+", flags=re.IGNORECASE), + re.compile(r"\b[a-zA-Z]+_\w+_Modifier_\d+\b", flags=re.IGNORECASE), # Handles Specific Keys Modifier_X_Item - re.compile(r"\b[a-zA-Z]+_\d+_Modifier_\d+_[a-zA-Z]+", flags=re.IGNORECASE), + re.compile(r"\b[a-zA-Z]+_\w+_Modifier_\d+_[a-zA-Z]+\b", flags=re.IGNORECASE), ] HAT_KEY = re.compile(r"\bPOV_\d+_[URDL]+\b", flags=re.IGNORECASE) diff --git a/tests/test_export.py b/tests/test_export.py new file mode 100644 index 0000000..1cc96c6 --- /dev/null +++ b/tests/test_export.py @@ -0,0 +1,243 @@ +from dataclasses import dataclass +from datetime import datetime + +import pytest + +from build.lib.input.device import Device_ +from joystick_diagrams.export import ( + TEMPLATE_DATING_KEY, + TEMPLATE_NAMING_KEY, + populate_template, + replace_input_modifier_id_key, + replace_input_modifiers_string, + replace_input_string, + replace_template_date_string, + replace_template_name_string, + replace_unused_keys, + sanitize_string_for_svg, +) +from joystick_diagrams.input.axis import Axis, AxisDirection +from joystick_diagrams.input.button import Button +from joystick_diagrams.input.hat import Hat, HatDirection +from joystick_diagrams.input.modifier import Modifier + +# Unit Tests + + +def test_replacement_of_name_string(): + test_string = 'STRING="ABC">{}' + test_data = test_string.format(TEMPLATE_NAMING_KEY) + replacement = "Profile 123 - Name" + + rep = replace_template_name_string(replacement, test_data) + + assert rep == test_string.format(replacement) + + +def test_replacement_of_date_string(): + test_string = 'STRING="ABC">{}' + test_data = test_string.format(TEMPLATE_DATING_KEY) + + rep = replace_template_date_string(test_data) + + assert rep == test_string.format(datetime.now().strftime("%d/%m/%Y")) + + +def test_unused_keys_cleanup_buttons(): + test_string = 'STRING="ABC">{}' + controls = ["BUTTON_1", "BUTTON_4", "BUTTON_120"] + test_data = test_string.format("|".join(controls)) + + rep = replace_unused_keys(test_data) + + assert rep == test_string.format("|" * (len(controls) - 1)) + + +def test_unused_keys_cleanup_axis(): + test_string = 'STRING="ABC">{}' + controls = ["AXIS_X", "AXIS_Y", "AXIS_RZ", "AXIS_SLIDER_1"] + test_data = test_string.format("|".join(controls)) + + rep = replace_unused_keys(test_data) + + assert rep == test_string.format("|" * (len(controls) - 1)) + + +def test_unused_keys_cleanup_hats(): + test_string = 'STRING="ABC">{}' + controls = ["POV_1_U", "POV_1_UR", "POV_4_DR"] + test_data = test_string.format("|".join(controls)) + + rep = replace_unused_keys(test_data) + + assert rep == test_string.format("|" * (len(controls) - 1)) + + +def test_unused_keys_cleanup_modifiers(): + test_string = 'STRING="ABC">{}' + controls = [ + # Buttons + "BUTTON_1_MODIFIERS", + "BUTTON_1_MODIFIER_1", + "BUTTON_1_MODIFIER_1_KEY", + "BUTTON_1_MODIFIER_1_COMMAND", + # Normal AXIS + "AXIS_X_MODIFIERS", + "AXIS_X_MODIFIER_1", + "AXIS_X_MODIFIER_1_KEY", + "AXIS_X_MODIFIER_1_COMMAND", + # Slider AXIS + "AXIS_SLIDER_1_MODIFIERS", + "AXIS_SLIDER_1_MODIFIER_1", + "AXIS_SLIDER_1_MODIFIER_1_KEY", + "AXIS_SLIDER_1_MODIFIER_1_COMMAND", + # HATS + "POV_1_U_MODIFIERS", + "POV_1_U_MODIFIER_1", + "POV_1_UR_MODIFIER_1_KEY", + "POV_1_UR_MODIFIER_1_COMMAND", + ] + test_data = test_string.format(" | ".join(controls)) + + rep = replace_unused_keys(test_data) + + assert rep == test_string.format(" | " * (len(controls) - 1)) + + +def test_replace_basic_key_input_string(): + test_string = 'STRING="ABC">{}' + controls = [ + ("BUTTON_1", "One"), + ("AXIS_X", "Two"), + ("AXIS_SLIDER_1", "Three"), + ("POV_1_U", "Four"), + ("POV_1_UR", "Five"), + ] + # TODO add scenarios for sanitised values + + for control, string in controls: + test_data = test_string.format(control) + rep = replace_input_string(control, string, test_data) + assert rep == test_string.format(string) + + +def test_replace_specific_modifier_identifier(): + controls = [ + ("BUTTON_1", 1, Modifier({"ctrl"}, "Modifier 1")), + ("AXIS_X", 2, Modifier({"ctrl"}, "Modifier 2")), + ("AXIS_SLIDER_1", 3, Modifier({"ctrl"}, "Modifier 3")), + ("POV_1_U", 4, Modifier({"ctrl"}, "Modifier 4")), + ("POV_1_UR", 5, Modifier({"ctrl"}, "Modifier 5")), + ] + + for control, mod_id, modifier in controls: + test_case = [ + ( + f"{control}_modifier_{mod_id}", + f"{modifier.modifiers} - {modifier.command}", + ), + (f"{control}_modifier_{mod_id}_key", f"{modifier.modifiers}"), + (f"{control}_modifier_{mod_id}_action", f"{modifier.command}"), + ] + + for case, expected in test_case: + test_string = f'STRING="ABC">{case}' + expected_string = f'STRING="ABC">{expected}' + rep = replace_input_modifier_id_key(control, mod_id, modifier, test_string) + assert rep == expected_string + + +def test_replace_input_all_modifiers(): + controls = [ + ( + "BUTTON_1", + [Modifier({"ctrl"}, "Modifier 1"), Modifier({"alt"}, "Modifier 2")], + ), + ("AXIS_X", [Modifier({"ctrl"}, "Modifier 1"), Modifier({"alt"}, "Modifier 2")]), + ( + "AXIS_SLIDER_1", + [Modifier({"ctrl"}, "Modifier 1"), Modifier({"alt"}, "Modifier 2")], + ), + ( + "POV_1_U", + [Modifier({"ctrl"}, "Modifier 1"), Modifier({"alt"}, "Modifier 2")], + ), + ( + "POV_1_UR", + [Modifier({"ctrl"}, "Modifier 1"), Modifier({"alt"}, "Modifier 2")], + ), + ] + + for control, modifiers in controls: + test_string = f'STRING="ABC">{control}_Modifiers' + rep = replace_input_modifiers_string(control, modifiers, test_string) + + def build_string(modifiers: list[Modifier]): + mod_string = "" + for idx, mod in enumerate(modifiers, 1): + mod_string = mod_string + f"{str(mod)}" + if idx != len(modifiers): + mod_string = mod_string + " | " + return mod_string + + expected_string = f'STRING="ABC">{build_string(modifiers)}' + assert rep == expected_string + + +def test_svg_sanitization(): + tests = [("test", "test")] + # TODO create test scenarios from DCS data + + for test_value, expected_return in tests: + assert sanitize_string_for_svg(test_value) == expected_return + + +@pytest.fixture() +def mock_export_device(): + # Quick dirty object to meet the test, rather than creating a fully valid ExportDevice + + @dataclass + class MockExportDevice: + template: "MockTemplate" + profile_wrapper: "MockWrapper" + + @dataclass + class MockTemplate: + raw_data: object + + @dataclass + class MockWrapper: + profile_name: str + + obj = MockExportDevice( + MockTemplate( + "BUTTON_1 | BUTTON_2 | BUTTON_3 | AXIS_X | POV_1_D | POV_1_U | BUTTON_1_Modifiers" + ), + MockWrapper("profile_1"), + ) + + dev = Device_("666ec0a0-556b-11ee-8002-444553540000", "Test Device") + + inputs = [ + (Button(1), "Button Action 1"), + (Button(2), "Button Action 2"), + (Axis(AxisDirection.X), "AXIS Control 1"), + (Hat(1, HatDirection.D), "Hat Control Action 1"), + ] + for control, command in inputs: + dev.create_input(control, command) + + dev.add_modifier_to_input(Button(1), {"ctrl"}, "Modifier 1") + + obj.device = dev + + return obj + + +def test_template_populate(mock_export_device): + modified_template = populate_template(mock_export_device) + + assert ( + modified_template + == "Button Action 1 | Button Action 2 | | AXIS Control 1 | Hat Control Action 1 | | Modifier 1 - ctrl" + ) diff --git a/tests/test_template.py b/tests/test_template.py index 25f5100..63d48a5 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -60,18 +60,16 @@ def test_template_button_property(get_template_path_valid): def test_template_modifiers_property(get_template_path_valid): expected_modifiers = { - "button_1_modifier_1", - "button_2_modifiers", "button_1_modifiers", - "button_1_modifier_2", "button_1_modifier_1_key", "button_1_modifier_1_action", "button_1_modifier_2_key", "button_1_modifier_2_action", + "button_2_modifiers", } setup_template = Template(get_template_path_valid) - assert setup_template.modifier_count == 8 + assert setup_template.modifier_count == 6 assert setup_template.get_template_modifiers() == expected_modifiers