Bug 1910352 - Ensure keyUp/keyDown value it one grapheme cluster, r=webdriver-reviewers,jdescottes

Return InvalidArgumentError if the action value for key actions is
not exactly one grapheme cluster long.

Supporting full grapheme clusters rather than just single codepoints
is marked as TODO in the spec, so add tentative tests for that.

Differential Revision: https://phabricator.services.mozilla.com/D217950
This commit is contained in:
James Graham 2024-08-07 12:20:02 +00:00
parent bff48bb6cb
commit 33081e4ed7
6 changed files with 83 additions and 24 deletions

View File

@ -766,17 +766,25 @@ class KeyAction extends Action {
static fromJSON(id, actionItem) { static fromJSON(id, actionItem) {
const { value } = 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( lazy.assert.string(
value, value,
'Expected "value" to be a string that represents single code point ' + 'Expected "value" to be a string that represents single code point ' +
lazy.pprint`or grapheme cluster, got ${value}` 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 }); return new this(id, { value });
} }
} }

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,4 @@
# META: timeout=long
import pytest import pytest
from webdriver.error import InvalidArgumentException 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") 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"]) @pytest.mark.parametrize("value", ["", "pointerDowns", "pointerMoves", "pointerUps"])
def test_pointer_action_subtype_invalid_value(session, value): def test_pointer_action_subtype_invalid_value(session, value):
if value == "pointerMoves": if value == "pointerMoves":

View File

@ -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

View File

@ -21,6 +21,8 @@ trojan-source:
- third_party/rust/error-chain/tests/tests.rs - third_party/rust/error-chain/tests/tests.rs
- third_party/rust/unicode-width/src/tests.rs - third_party/rust/unicode-width/src/tests.rs
- security/nss/gtests/mozpkix_gtest/pkixnames_tests.cpp - 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 - toolkit/components/uniffi-fixtures/rondpoint/tests/bindings/test_rondpoint.py
extensions: extensions:
- .c - .c