Skip to content

Commit e8bbc2e

Browse files
authored
appium: key (#367)
1 parent b1a092f commit e8bbc2e

13 files changed

Lines changed: 136 additions & 56 deletions

File tree

appium/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
from typing import Generator
99

1010
import pytest
11-
from appium import webdriver
1211
from appium.options.mac import Mac2Options
1312
from appium.webdriver.webdriver import WebDriver
1413

14+
from appium import webdriver
1515

1616
APPIUM_SERVER = "http://127.0.0.1:4723"
1717
BUNDLE_ID = "org.fcitx.FcitxTestApp"

appium/test_boolean.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from appium.webdriver.webdriver import WebDriver
22
from util.boolean import get_switch_state
3-
from util.button import get_undo_redo, is_enabled
3+
from util.button import get_undo_redo
44
from util.config import read_global_config
55
from util.message import (
66
BUTTON_SHOULD_BE_DISABLED,
@@ -26,18 +26,18 @@ def read_config_value() -> str:
2626
is_on = get_switch_state(switch)
2727
switch.click()
2828
assert get_switch_state(switch) != is_on, UI_NOT_UPDATED
29-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
30-
assert is_enabled(redo) is False, BUTTON_SHOULD_BE_DISABLED
29+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
30+
assert redo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
3131
assert read_config_value() == str(not is_on), CHANGE_NOT_SAVED
3232

3333
undo.click()
3434
assert get_switch_state(switch) == is_on, UI_NOT_UPDATED
35-
assert is_enabled(undo) is False, BUTTON_SHOULD_BE_DISABLED
36-
assert is_enabled(redo) is True, BUTTON_SHOULD_BE_ENABLED
35+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
36+
assert redo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
3737
assert read_config_value() == str(is_on), CHANGE_NOT_SAVED
3838

3939
redo.click()
4040
assert get_switch_state(switch) != is_on, UI_NOT_UPDATED
41-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
42-
assert is_enabled(redo) is False, BUTTON_SHOULD_BE_DISABLED
41+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
42+
assert redo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
4343
assert read_config_value() == str(not is_on), CHANGE_NOT_SAVED

appium/test_color.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
from appium.webdriver.webdriver import WebDriver
2-
3-
from util.config import read_theme_config
4-
from util.button import get_undo_redo, is_enabled
2+
from util.button import get_undo_redo
53
from util.color import get_color_value, set_color_value
4+
from util.config import read_theme_config
65
from util.message import (
76
BUTTON_SHOULD_BE_DISABLED,
87
BUTTON_SHOULD_BE_ENABLED,
@@ -11,7 +10,6 @@
1110
)
1211
from util.window import find_element_by_id, open_theme_config
1312

14-
1513
LIGHT_SECTION = "LightMode"
1614
COLOR_ID = "HighlightColor"
1715

@@ -31,10 +29,10 @@ def read_config_value() -> str:
3129

3230
set_color_value(field, new_value)
3331
assert get_color_value(field) == new_value, UI_NOT_UPDATED
34-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
32+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
3533
assert read_config_value() == new_value, CHANGE_NOT_SAVED
3634

3735
undo.click()
3836
assert get_color_value(field) == initial_value, UI_NOT_UPDATED
39-
assert is_enabled(undo) is False, BUTTON_SHOULD_BE_DISABLED
37+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
4038
assert read_config_value() == initial_value, CHANGE_NOT_SAVED

appium/test_enum.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
22
from appium.webdriver.webdriver import WebDriver
3-
from util.button import get_undo_redo, is_enabled
3+
from util.button import get_undo_redo
44
from util.config import read_config
55
from util.enum import get_enum_value, select_enum_option
66
from util.message import (
@@ -50,24 +50,24 @@ def read_config_value() -> str:
5050

5151
assert get_enum_value(picker) == target_value, UI_NOT_UPDATED
5252
assert read_config_value() == target_config_value, CHANGE_NOT_SAVED
53-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
54-
assert is_enabled(redo) is False, BUTTON_SHOULD_BE_DISABLED
53+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
54+
assert redo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
5555

5656
undo.click()
5757
assert get_enum_value(picker) == initial_value, UI_NOT_UPDATED
5858
assert read_config_value() == initial_config_value, CHANGE_NOT_SAVED
59-
assert is_enabled(undo) is False, BUTTON_SHOULD_BE_DISABLED
60-
assert is_enabled(redo) is True, BUTTON_SHOULD_BE_ENABLED
59+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
60+
assert redo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
6161

6262
# Re-select current value
6363
select_enum_option(picker, initial_value)
6464
assert get_enum_value(picker) == initial_value, UI_WRONGLY_UPDATED
6565
assert read_config_value() == initial_config_value, CHANGE_WRONGLY_SAVED
66-
assert is_enabled(undo) is False, BUTTON_SHOULD_BE_DISABLED
67-
assert is_enabled(redo) is True, BUTTON_SHOULD_BE_ENABLED
66+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
67+
assert redo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
6868

6969
redo.click()
7070
assert get_enum_value(picker) == target_value, UI_NOT_UPDATED
7171
assert read_config_value() == target_config_value, CHANGE_NOT_SAVED
72-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
73-
assert is_enabled(redo) is False, BUTTON_SHOULD_BE_DISABLED
72+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
73+
assert redo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED

appium/test_integer.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from appium.webdriver.webdriver import WebDriver
2-
from util.button import get_undo_redo, is_enabled
2+
from util.button import get_undo_redo
33
from util.config import read_global_config
44
from util.integer import (
55
click_stepper_decrement,
@@ -36,24 +36,24 @@ def read_config_value() -> str:
3636

3737
new_value = get_integer_value(field)
3838
assert new_value == initial_value + 1, UI_NOT_UPDATED
39-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
40-
assert is_enabled(redo) is False, BUTTON_SHOULD_BE_DISABLED
39+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
40+
assert redo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
4141

4242
assert read_config_value() == str(new_value), CHANGE_NOT_SAVED
4343

4444
undo.click()
4545
undo_value = get_integer_value(field)
4646
assert undo_value == initial_value, UI_NOT_UPDATED
47-
assert is_enabled(undo) is False, BUTTON_SHOULD_BE_DISABLED
48-
assert is_enabled(redo) is True, BUTTON_SHOULD_BE_ENABLED
47+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
48+
assert redo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
4949

5050
assert read_config_value() == str(initial_value), CHANGE_NOT_SAVED
5151

5252
redo.click()
5353
redo_value = get_integer_value(field)
5454
assert redo_value == initial_value + 1, UI_NOT_UPDATED
55-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
56-
assert is_enabled(redo) is False, BUTTON_SHOULD_BE_DISABLED
55+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
56+
assert redo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
5757
assert read_config_value() == str(redo_value), CHANGE_NOT_SAVED
5858

5959
click_stepper_decrement(driver, stepper)

appium/test_key.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from appium.webdriver.webdriver import WebDriver
2+
from selenium.webdriver.common.keys import Keys
3+
from util.button import get_undo_redo
4+
from util.config import read_global_config
5+
from util.key import get_label, press
6+
from util.message import (
7+
BUTTON_SHOULD_BE_DISABLED,
8+
BUTTON_SHOULD_BE_ENABLED,
9+
CHANGE_NOT_SAVED,
10+
UI_NOT_UPDATED,
11+
)
12+
from util.window import find_element_by_id, find_elements_by_id, open_global_config
13+
14+
KEY_ID = "TriggerKeys"
15+
INDEX = 0
16+
# XXX: [Keys.CONTROL, Keys.RIGHT_SHIFT] is recognized as Ctrl+LSHIFT.
17+
KEYS = [Keys.CONTROL, Keys.SHIFT, "A"]
18+
KEYS_LABEL = "⌃⇧A"
19+
KEYS_VALUE = "Control+Shift+A"
20+
21+
22+
def test_record_shortcut(driver: WebDriver, app: str):
23+
open_global_config(driver)
24+
25+
def read_config_value() -> str:
26+
cfg = read_global_config(app)
27+
return cfg[f"Hotkey/{KEY_ID}"][str(INDEX)]
28+
29+
button = find_elements_by_id(driver, KEY_ID)[INDEX]
30+
initial_label = get_label(button)
31+
undo, _ = get_undo_redo(driver)
32+
33+
def update():
34+
button.click()
35+
press(driver, KEYS)
36+
assert (
37+
find_element_by_id(driver, f"{KEY_ID}_key").get_attribute("value")
38+
== KEYS_LABEL
39+
), UI_NOT_UPDATED
40+
41+
update()
42+
find_element_by_id(driver, f"{KEY_ID}_cancel").click()
43+
assert get_label(button) == initial_label
44+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
45+
46+
update()
47+
find_element_by_id(driver, f"{KEY_ID}_ok").click()
48+
button = find_elements_by_id(driver, KEY_ID)[0]
49+
assert get_label(button) == KEYS_LABEL
50+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
51+
assert read_config_value() == KEYS_VALUE, CHANGE_NOT_SAVED
52+
53+
undo.click()
54+
button = find_elements_by_id(driver, KEY_ID)[0]
55+
assert get_label(button) == initial_label
56+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
57+
assert read_config_value() != KEYS_VALUE, CHANGE_NOT_SAVED

appium/test_string.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from appium.webdriver.webdriver import WebDriver
2-
from util.button import get_undo_redo, is_enabled
2+
from selenium.webdriver.common.keys import Keys
3+
from util.button import get_undo_redo
34
from util.config import read_theme_config
45
from util.key import press
56
from util.message import (
@@ -34,36 +35,36 @@ def update():
3435

3536
update()
3637
undo, _ = get_undo_redo(driver)
37-
assert is_enabled(undo) is False, BUTTON_SHOULD_BE_DISABLED
38+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
3839

39-
press(driver, "\n")
40+
press(driver, [Keys.ENTER])
4041
assert get_string_value(field) == new_value, UI_NOT_UPDATED
41-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
42+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
4243
assert read_config_value() == new_value, CHANGE_NOT_SAVED
4344

4445
undo.click()
45-
assert is_enabled(undo) is False, BUTTON_SHOULD_BE_DISABLED
46+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
4647
assert get_string_value(field) == initial_value, UI_NOT_UPDATED
4748
assert read_config_value() == initial_value, CHANGE_NOT_SAVED
4849

4950
update()
50-
press(driver, "\t")
51+
press(driver, [Keys.TAB])
5152
assert get_string_value(field) == new_value, UI_NOT_UPDATED
52-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
53+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
5354
assert read_config_value() == new_value, CHANGE_NOT_SAVED
5455

5556
undo.click()
56-
assert is_enabled(undo) is False, BUTTON_SHOULD_BE_DISABLED
57+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
5758
assert get_string_value(field) == initial_value, UI_NOT_UPDATED
5859
assert read_config_value() == initial_value, CHANGE_NOT_SAVED
5960

6061
update()
6162
find_element_by_id(driver, "checkmark").click()
6263
assert get_string_value(field) == new_value, UI_NOT_UPDATED
63-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
64+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
6465
assert read_config_value() == new_value, CHANGE_NOT_SAVED
6566

6667
reset_option(driver, STRING_ID)
67-
assert is_enabled(undo) is True, BUTTON_SHOULD_BE_ENABLED
68+
assert undo.is_enabled() is True, BUTTON_SHOULD_BE_ENABLED
6869
assert get_string_value(field) == initial_value, UI_NOT_UPDATED
6970
assert read_config_value() == initial_value, CHANGE_NOT_SAVED

appium/util/button.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,9 @@
77
def get_undo_redo(driver: WebDriver) -> tuple[WebElement, WebElement]:
88
"""Get undo and redo buttons, asserting they are initially disabled."""
99
undo = find_element_by_id(driver, "arrow.uturn.left")
10-
assert is_enabled(undo) is False, BUTTON_SHOULD_BE_DISABLED
10+
assert undo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
1111

1212
redo = find_element_by_id(driver, "arrow.uturn.right")
13-
assert is_enabled(redo) is False, BUTTON_SHOULD_BE_DISABLED
13+
assert redo.is_enabled() is False, BUTTON_SHOULD_BE_DISABLED
1414

1515
return undo, redo
16-
17-
18-
def is_enabled(element: WebElement) -> bool:
19-
"""Check if an element is enabled."""
20-
return element.get_attribute("enabled") == "true"

appium/util/color.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
from selenium.webdriver.remote.webelement import WebElement
21
from appium.webdriver.common.appiumby import AppiumBy
2+
from selenium.webdriver.common.keys import Keys
3+
from selenium.webdriver.remote.webelement import WebElement
34
from util.key import press
45
from util.window import find_element_by_id
56

@@ -31,7 +32,9 @@ def set_color_value(element: WebElement, value: str):
3132
# Type hex
3233
hex_field = find_element_by_id(driver, "hex")
3334
hex_field.send_keys(value)
34-
press(driver, "\n") # Without it, below may throw StaleElementReferenceException.
35+
press(
36+
driver, [Keys.ENTER]
37+
) # Without it, below may throw StaleElementReferenceException.
3538

3639
# Close
3740
buttons = driver.find_elements(AppiumBy.CLASS_NAME, "XCUIElementTypeButton")

appium/util/key.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
from appium.webdriver.webdriver import WebDriver
2+
from selenium.webdriver.common.actions.action_builder import ActionBuilder
3+
from selenium.webdriver.remote.webelement import WebElement
24

35

4-
def press(driver: WebDriver, key: str):
5-
driver.execute_script("macos: keys", {"keys": [key]})
6+
def press(driver: WebDriver, keys: list[str]):
7+
action = ActionBuilder(driver)
8+
for key in keys:
9+
action.key_action.key_down(key)
10+
for key in reversed(keys):
11+
action.key_action.key_up(key)
12+
action.perform()
13+
14+
15+
def get_label(button: WebElement) -> str:
16+
return button.get_attribute("label")

0 commit comments

Comments
 (0)