Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions gui_agents/s1/aci/WindowsOSACI.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,9 @@ def hotkey(self, keys: List[str]):
Args:
keys:List[str] the keys to press in combination in a list format (e.g. ['shift', 'c'])
"""
# Ensure keys is a list - if a string is passed, wrap it
if isinstance(keys, str):
keys = [keys]
keys = [_normalize_key(k) for k in keys]
keys = [f"'{key}'" for key in keys]
command = f"import pyautogui; pyautogui.hotkey({', '.join(keys)}, interval=0.5)"
Expand Down
57 changes: 57 additions & 0 deletions tests/test_windows_aci.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import unittest
from gui_agents.s1.aci.WindowsOSACI import WindowsACI


class TestWindowsACIHotkey(unittest.TestCase):
def setUp(self):
"""Set up test fixtures"""
self.aci = WindowsACI(top_app_only=True, ocr=False)

Comment on lines +1 to +9
def test_hotkey_with_string_single_key(self):
"""Test that passing a string like 'enter' works correctly"""
result = self.aci.hotkey('enter')
expected = "import pyautogui; pyautogui.hotkey('enter', interval=0.5)"
self.assertEqual(result, expected)

def test_hotkey_with_list_single_key(self):
"""Test that passing a list with a single key works correctly"""
result = self.aci.hotkey(['enter'])
expected = "import pyautogui; pyautogui.hotkey('enter', interval=0.5)"
self.assertEqual(result, expected)

def test_hotkey_with_list_multiple_keys(self):
"""Test that passing a list with multiple keys works correctly"""
result = self.aci.hotkey(['alt', 'tab'])
expected = "import pyautogui; pyautogui.hotkey('alt', 'tab', interval=0.5)"
self.assertEqual(result, expected)

def test_hotkey_with_control_normalization(self):
"""Test that 'control' is normalized to 'ctrl'"""
result = self.aci.hotkey(['control', 'c'])
expected = "import pyautogui; pyautogui.hotkey('ctrl', 'c', interval=0.5)"
self.assertEqual(result, expected)

def test_hotkey_with_string_special_keys(self):
"""Test various special key strings"""
test_cases = [
('escape', "import pyautogui; pyautogui.hotkey('escape', interval=0.5)"),
('space', "import pyautogui; pyautogui.hotkey('space', interval=0.5)"),
('backspace', "import pyautogui; pyautogui.hotkey('backspace', interval=0.5)"),
('delete', "import pyautogui; pyautogui.hotkey('delete', interval=0.5)"),
]
for key, expected in test_cases:
with self.subTest(key=key):
result = self.aci.hotkey(key)
self.assertEqual(result, expected)

def test_hotkey_does_not_split_string(self):
"""Regression test: ensure 'enter' doesn't become 'e', 'n', 't', 'e', 'r'"""
result = self.aci.hotkey('enter')
# This should NOT contain individual characters
self.assertNotIn("'e', 'n', 't', 'e', 'r'", result)
# This SHOULD contain the full key name
self.assertIn("'enter'", result)


if __name__ == "__main__":
unittest.main()