Skip to content

Commit cd627d4

Browse files
committed
Add E2E integration test for macros - vjoy output actions only
1 parent 563e3fe commit cd627d4

2 files changed

Lines changed: 328 additions & 0 deletions

File tree

test/integration/test_e2e_macro.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# -*- coding: utf-8; -*-
2+
3+
# Copyright (C) 2015 - 2025 Lionel Ott
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
"""
18+
Integration tests with a profile with macros that have vJoy outputs.
19+
"""
20+
21+
import sys
22+
23+
sys.path.append(".")
24+
25+
import pytest
26+
27+
import dill
28+
from test.integration import app_tester
29+
from vjoy import vjoy
30+
31+
32+
@pytest.fixture(scope="module")
33+
def profile_name() -> str:
34+
"""Returns the name of the profile to be used for the macro test.
35+
36+
The profile maps button 1 press to vJoy actions of each type: button press,
37+
hat direction set, absolute axis set, and relative axis change.
38+
"""
39+
return "e2e_macros.xml"
40+
41+
42+
class TestMacro:
43+
"""Tests the vJoy actions of macro.py."""
44+
45+
def test_macro_sequence(
46+
self,
47+
subtests,
48+
tester: app_tester.GremlinAppTester,
49+
vjoy_control_device: vjoy.VJoy,
50+
vjoy_di_device: dill.DeviceSummary,
51+
):
52+
"""Verifies multiple macro executions triggered by a single button press."""
53+
input_button_id = 1
54+
vjoy_output = 1
55+
cached_value = True
56+
vjoy_control_device.button(index=input_button_id).is_pressed = True
57+
tester.assert_button_eventually_equals(
58+
vjoy_di_device.device_guid, input_button_id, vjoy_output
59+
)
60+
tester.assert_cached_button_eventually_equals(
61+
vjoy_di_device.device_guid.uuid, input_button_id, cached_value
62+
)
63+
64+
def assert_fixed_outputs(step: int):
65+
with subtests.test("hat northeast", step=step):
66+
tester.assert_hat_eventually_equals(vjoy_di_device.device_guid, 1, 4500)
67+
with subtests.test("hat west", step=step):
68+
tester.assert_hat_eventually_equals(
69+
vjoy_di_device.device_guid, 2, 27000
70+
)
71+
with subtests.test("button", step=step):
72+
tester.assert_button_eventually_equals(vjoy_di_device.device_guid, 3, 1)
73+
with subtests.test("axis absolute positive", step=step):
74+
tester.assert_axis_eventually_equals(
75+
vjoy_di_device.device_guid, 2, tester.AXIS_MAX_INT * 0.7
76+
)
77+
with subtests.test("axis absolute negative", step=step):
78+
tester.assert_axis_eventually_equals(
79+
vjoy_di_device.device_guid, 3, tester.AXIS_MAX_INT * -0.5
80+
)
81+
82+
assert_fixed_outputs(step=1)
83+
with subtests.test("axis relative positive", step=1):
84+
tester.assert_axis_eventually_equals(
85+
vjoy_di_device.device_guid, 5, tester.AXIS_MAX_INT * 0.2
86+
)
87+
with subtests.test("axis relative negative", step=1):
88+
tester.assert_axis_eventually_equals(
89+
vjoy_di_device.device_guid, 6, tester.AXIS_MAX_INT * -0.1
90+
)
91+
92+
vjoy_control_device.button(index=input_button_id).is_pressed = False
93+
assert_fixed_outputs(step=2)
94+
with subtests.test("axis relative positive", step=2):
95+
tester.assert_axis_eventually_equals(
96+
vjoy_di_device.device_guid, 5, tester.AXIS_MAX_INT * 0.2
97+
)
98+
with subtests.test("axis relative negative", step=2):
99+
tester.assert_axis_eventually_equals(
100+
vjoy_di_device.device_guid, 6, tester.AXIS_MAX_INT * -0.1
101+
)
102+
103+
vjoy_control_device.button(index=input_button_id).is_pressed = True
104+
assert_fixed_outputs(step=3)
105+
with subtests.test("axis relative positive", step=3):
106+
tester.assert_axis_eventually_equals(
107+
vjoy_di_device.device_guid, 5, tester.AXIS_MAX_INT * 0.2 * 2
108+
)
109+
with subtests.test("axis relative negative", step=3):
110+
tester.assert_axis_eventually_equals(
111+
vjoy_di_device.device_guid, 6, tester.AXIS_MAX_INT * -0.1 * 2
112+
)
113+
114+
vjoy_control_device.button(index=input_button_id).is_pressed = False
115+
assert_fixed_outputs(step=4)
116+
vjoy_control_device.button(index=input_button_id).is_pressed = True
117+
assert_fixed_outputs(step=5)
118+
with subtests.test("axis relative positive", step=5):
119+
tester.assert_axis_eventually_equals(
120+
vjoy_di_device.device_guid, 5, tester.AXIS_MAX_INT * 0.2 * 3
121+
)
122+
with subtests.test("axis relative negative", step=5):
123+
tester.assert_axis_eventually_equals(
124+
vjoy_di_device.device_guid, 6, tester.AXIS_MAX_INT * -0.1 * 3
125+
)
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
<?xml version="1.0" ?>
2+
<profile version="14">
3+
<inputs>
4+
<input>
5+
<device-id>97b77b40-07d8-11f0-8028-444553540000</device-id>
6+
<input-type>button</input-type>
7+
<mode>Default</mode>
8+
<input-id>1</input-id>
9+
<action-configuration>
10+
<root-action>7c55893e-ceff-4038-8223-0b8a5294b392</root-action>
11+
<behavior>button</behavior>
12+
</action-configuration>
13+
</input>
14+
</inputs>
15+
<logical-device/>
16+
<library>
17+
<action id="5daa1184-c5e9-4316-9a66-c4143c51a6b9" type="macro">
18+
<property type="bool">
19+
<name>is-exclusive</name>
20+
<value>False</value>
21+
</property>
22+
<property type="string">
23+
<name>repeat-mode</name>
24+
<value>Single</value>
25+
</property>
26+
<property type="int">
27+
<name>repeat-count</name>
28+
<value>3</value>
29+
</property>
30+
<property type="float">
31+
<name>repeat-delay</name>
32+
<value>0.8</value>
33+
</property>
34+
<macro-action type="vjoy">
35+
<property type="int">
36+
<name>vjoy-id</name>
37+
<value>1</value>
38+
</property>
39+
<property type="input_type">
40+
<name>input-type</name>
41+
<value>hat</value>
42+
</property>
43+
<property type="int">
44+
<name>input-id</name>
45+
<value>1</value>
46+
</property>
47+
<property type="hat_direction">
48+
<name>value</name>
49+
<value>north-east</value>
50+
</property>
51+
</macro-action>
52+
<macro-action type="vjoy">
53+
<property type="int">
54+
<name>vjoy-id</name>
55+
<value>1</value>
56+
</property>
57+
<property type="input_type">
58+
<name>input-type</name>
59+
<value>hat</value>
60+
</property>
61+
<property type="int">
62+
<name>input-id</name>
63+
<value>2</value>
64+
</property>
65+
<property type="hat_direction">
66+
<name>value</name>
67+
<value>west</value>
68+
</property>
69+
</macro-action>
70+
<macro-action type="vjoy">
71+
<property type="int">
72+
<name>vjoy-id</name>
73+
<value>1</value>
74+
</property>
75+
<property type="input_type">
76+
<name>input-type</name>
77+
<value>button</value>
78+
</property>
79+
<property type="int">
80+
<name>input-id</name>
81+
<value>3</value>
82+
</property>
83+
<property type="bool">
84+
<name>value</name>
85+
<value>True</value>
86+
</property>
87+
</macro-action>
88+
<macro-action type="vjoy">
89+
<property type="int">
90+
<name>vjoy-id</name>
91+
<value>1</value>
92+
</property>
93+
<property type="input_type">
94+
<name>input-type</name>
95+
<value>axis</value>
96+
</property>
97+
<property type="int">
98+
<name>input-id</name>
99+
<value>2</value>
100+
</property>
101+
<property type="float">
102+
<name>value</name>
103+
<value>0.7</value>
104+
</property>
105+
<property type="axis_mode">
106+
<name>axis-mode</name>
107+
<value>absolute</value>
108+
</property>
109+
</macro-action>
110+
<macro-action type="vjoy">
111+
<property type="int">
112+
<name>vjoy-id</name>
113+
<value>1</value>
114+
</property>
115+
<property type="input_type">
116+
<name>input-type</name>
117+
<value>axis</value>
118+
</property>
119+
<property type="int">
120+
<name>input-id</name>
121+
<value>3</value>
122+
</property>
123+
<property type="float">
124+
<name>value</name>
125+
<value>-0.5</value>
126+
</property>
127+
<property type="axis_mode">
128+
<name>axis-mode</name>
129+
<value>absolute</value>
130+
</property>
131+
</macro-action>
132+
<macro-action type="vjoy">
133+
<property type="int">
134+
<name>vjoy-id</name>
135+
<value>1</value>
136+
</property>
137+
<property type="input_type">
138+
<name>input-type</name>
139+
<value>axis</value>
140+
</property>
141+
<property type="int">
142+
<name>input-id</name>
143+
<value>5</value>
144+
</property>
145+
<property type="float">
146+
<name>value</name>
147+
<value>0.2</value>
148+
</property>
149+
<property type="axis_mode">
150+
<name>axis-mode</name>
151+
<value>relative</value>
152+
</property>
153+
</macro-action>
154+
<macro-action type="vjoy">
155+
<property type="int">
156+
<name>vjoy-id</name>
157+
<value>1</value>
158+
</property>
159+
<property type="input_type">
160+
<name>input-type</name>
161+
<value>axis</value>
162+
</property>
163+
<property type="int">
164+
<name>input-id</name>
165+
<value>6</value>
166+
</property>
167+
<property type="float">
168+
<name>value</name>
169+
<value>-0.1</value>
170+
</property>
171+
<property type="axis_mode">
172+
<name>axis-mode</name>
173+
<value>relative</value>
174+
</property>
175+
</macro-action>
176+
<property type="string">
177+
<name>action-label</name>
178+
<value>Macro</value>
179+
</property>
180+
<property type="activation-mode">
181+
<name>activation-mode</name>
182+
<value>press</value>
183+
</property>
184+
</action>
185+
<action id="7c55893e-ceff-4038-8223-0b8a5294b392" type="root">
186+
<actions>
187+
<action-id>5daa1184-c5e9-4316-9a66-c4143c51a6b9</action-id>
188+
</actions>
189+
<property type="string">
190+
<name>action-label</name>
191+
<value>Root</value>
192+
</property>
193+
<property type="activation-mode">
194+
<name>activation-mode</name>
195+
<value>disallowed</value>
196+
</property>
197+
</action>
198+
</library>
199+
<modes>
200+
<mode>Default</mode>
201+
</modes>
202+
<scripts/>
203+
</profile>

0 commit comments

Comments
 (0)