diff --git a/remote/shared/webdriver/Actions.sys.mjs b/remote/shared/webdriver/Actions.sys.mjs index 7c87e5b11f2c..9d3e793541c6 100644 --- a/remote/shared/webdriver/Actions.sys.mjs +++ b/remote/shared/webdriver/Actions.sys.mjs @@ -766,17 +766,25 @@ class KeyAction extends Action { static fromJSON(id, actionItem) { const { value } = actionItem; - // TODO countGraphemes - // TODO key.value could be a single code point like "\uE012" - // (see rawKey) or "grapheme cluster" - // https://bugzilla.mozilla.org/show_bug.cgi?id=1496323 - lazy.assert.string( value, 'Expected "value" to be a string that represents single code point ' + lazy.pprint`or grapheme cluster, got ${value}` ); + let segmenter = new Intl.Segmenter(); + lazy.assert.that(v => { + let graphemeIterator = segmenter.segment(v)[Symbol.iterator](); + // We should have exactly one grapheme cluster, so the first iterator + // value must be defined, but the second one must be undefined + return ( + graphemeIterator.next().value !== undefined && + graphemeIterator.next().value === undefined + ); + }, `Expected "value" to be a string that represents single code point or grapheme cluster, got "${value}"`)( + value + ); + return new this(id, { value }); } } diff --git a/testing/web-platform/meta/webdriver/tests/bidi/input/perform_actions/invalid.py.ini b/testing/web-platform/meta/webdriver/tests/bidi/input/perform_actions/invalid.py.ini deleted file mode 100644 index 344db3f7113f..000000000000 --- a/testing/web-platform/meta/webdriver/tests/bidi/input/perform_actions/invalid.py.ini +++ /dev/null @@ -1,19 +0,0 @@ -[invalid.py] - expected: - if (os == "linux") and not debug and not asan and not tsan: [OK, TIMEOUT] - if (os == "win") and not debug: [OK, TIMEOUT] - [test_params_key_action_value_invalid_multiple_codepoints[fa\]] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1826808 - expected: FAIL - - [test_params_key_action_value_invalid_multiple_codepoints[\\u0ba8\\u0bbfb\]] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1826808 - expected: FAIL - - [test_params_key_action_value_invalid_multiple_codepoints[\\u0ba8\\u0bbf\\u0ba8\]] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1826808 - expected: FAIL - - [test_params_key_action_value_invalid_multiple_codepoints[\\u1100\\u1161\\u11a8c\]] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1826808 - expected: FAIL diff --git a/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/key_tentative.py b/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/key_tentative.py new file mode 100644 index 000000000000..1f7053c24997 --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/key_tentative.py @@ -0,0 +1,30 @@ +import pytest + +from webdriver.bidi.error import NoSuchFrameException +from webdriver.bidi.modules.input import Actions +from webdriver.bidi.modules.script import ContextTarget + +from tests.support.keys import Keys +from .. import get_keys_value +from . import get_shadow_root_from_test_page + +pytestmark = pytest.mark.asyncio + +@pytest.mark.parametrize( + "value", + [ + ("\u0e01\u0e33"), + ("🤷🏽‍♀️"), + ], +) +async def test_grapheme_cluster( + bidi_session, top_context, setup_key_test, value +): + actions = Actions() + (actions.add_key().key_down(value).key_up(value)) + await bidi_session.input.perform_actions( + actions=actions, context=top_context["context"] + ) + # events sent by major browsers are inconsistent so only check key value + keys_value = await get_keys_value(bidi_session, top_context["context"]) + assert keys_value == value diff --git a/testing/web-platform/tests/webdriver/tests/classic/perform_actions/invalid.py b/testing/web-platform/tests/webdriver/tests/classic/perform_actions/invalid.py index f000477376e7..d83285abbe07 100644 --- a/testing/web-platform/tests/webdriver/tests/classic/perform_actions/invalid.py +++ b/testing/web-platform/tests/webdriver/tests/classic/perform_actions/invalid.py @@ -1,3 +1,4 @@ +# META: timeout=long import pytest from webdriver.error import InvalidArgumentException @@ -304,6 +305,28 @@ def test_key_action_value_invalid_type(session, key_action, value): assert_error(response, "invalid argument") +@pytest.mark.parametrize("action_type", ["keyDown", "keyUp"]) +@pytest.mark.parametrize( + "value", + ["fa", "\u0BA8\u0BBFb", "\u0BA8\u0BBF\u0BA8", "\u1100\u1161\u11A8c"], +) +def test_key_action_invalid_value(session, action_type, value): + actions = [ + { + "type": "key", + "id": "foo", + "actions": [ + { + "type": action_type, + "value": value, + } + ], + } + ] + response = perform_actions(session, actions) + assert_error(response, "invalid argument") + + @pytest.mark.parametrize("value", ["", "pointerDowns", "pointerMoves", "pointerUps"]) def test_pointer_action_subtype_invalid_value(session, value): if value == "pointerMoves": diff --git a/testing/web-platform/tests/webdriver/tests/classic/perform_actions/key_tentative.py b/testing/web-platform/tests/webdriver/tests/classic/perform_actions/key_tentative.py new file mode 100644 index 000000000000..62f380da0ec0 --- /dev/null +++ b/testing/web-platform/tests/webdriver/tests/classic/perform_actions/key_tentative.py @@ -0,0 +1,15 @@ +import pytest + +from tests.classic.perform_actions.support.refine import get_keys + +@pytest.mark.parametrize("value", + [ + ("\u0e01\u0e33"), + ("🤷🏽‍♀️"), + ]) +def test_grapheme_cluster(session, key_reporter, key_chain, value): + key_chain \ + .key_down(value) \ + .key_up(value) \ + .perform() + assert get_keys(key_reporter) == value diff --git a/tools/lint/trojan-source.yml b/tools/lint/trojan-source.yml index 4f4263fc20c2..1238a6874dbb 100644 --- a/tools/lint/trojan-source.yml +++ b/tools/lint/trojan-source.yml @@ -21,6 +21,8 @@ trojan-source: - third_party/rust/error-chain/tests/tests.rs - third_party/rust/unicode-width/src/tests.rs - security/nss/gtests/mozpkix_gtest/pkixnames_tests.cpp + - testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/key_tentative.py + - testing/web-platform/tests/webdriver/tests/classic/perform_actions/key_tentative.py - toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.py extensions: - .c