Fix Enter key press not working by adding text field to keyDown events (#972)
This PR fixes an issue where pressing the Enter key via the `press Enter` command had no effect on web pages, even though the command executed successfully without errors. ## Problem The Chrome DevTools Protocol `Input.dispatchKeyEvent` requires a `text` field in `keyDown` events for certain keys to trigger their default browser actions. Without this field, keys like Enter don't actually submit forms or perform their expected actions. ## Changes - Added new `key_text()` function that returns the appropriate text value for special keys: - Enter returns `"\r"` (carriage return) - Tab returns `"\t"` (tab character) - Space returns `" "` (space character) - Single printable characters return themselves - Non-printable keys (Escape, Arrow keys, etc.) return `None` - Modified `press_key_with_modifiers()` to populate both `text` and `unmodified_text` fields in the CDP keyDown event - Added comprehensive unit tests for the new functionality ## Implementation Details The fix ensures that when pressing Enter on a filled search box, the form actually submits as expected, matching the behavior of manually pressing the Enter key. Fixes #966
This commit is contained in:
@@ -282,6 +282,7 @@ pub async fn press_key_with_modifiers(
|
|||||||
modifiers: Option<i32>,
|
modifiers: Option<i32>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let (key_name, code, key_code) = named_key_info(key);
|
let (key_name, code, key_code) = named_key_info(key);
|
||||||
|
let text = key_text(&key_name);
|
||||||
|
|
||||||
client
|
client
|
||||||
.send_command_typed::<_, Value>(
|
.send_command_typed::<_, Value>(
|
||||||
@@ -290,8 +291,8 @@ pub async fn press_key_with_modifiers(
|
|||||||
event_type: "keyDown".to_string(),
|
event_type: "keyDown".to_string(),
|
||||||
key: Some(key_name.clone()),
|
key: Some(key_name.clone()),
|
||||||
code: Some(code.clone()),
|
code: Some(code.clone()),
|
||||||
text: None,
|
text: text.clone(),
|
||||||
unmodified_text: None,
|
unmodified_text: text.clone(),
|
||||||
windows_virtual_key_code: Some(key_code),
|
windows_virtual_key_code: Some(key_code),
|
||||||
native_virtual_key_code: Some(key_code),
|
native_virtual_key_code: Some(key_code),
|
||||||
modifiers,
|
modifiers,
|
||||||
@@ -1000,6 +1001,26 @@ fn punctuation_key_info(ch: char) -> (&'static str, i32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the `text` value that CDP `Input.dispatchKeyEvent` needs on the
|
||||||
|
/// `keyDown` event so that Chrome performs the default action for the key.
|
||||||
|
/// For example Enter needs `"\r"` to actually submit a form, and Tab needs
|
||||||
|
/// `"\t"` to move focus. Non-printable / navigation keys return `None`.
|
||||||
|
fn key_text(key_name: &str) -> Option<String> {
|
||||||
|
match key_name {
|
||||||
|
"Enter" => Some("\r".to_string()),
|
||||||
|
"Tab" => Some("\t".to_string()),
|
||||||
|
" " => Some(" ".to_string()),
|
||||||
|
_ => {
|
||||||
|
// Single printable characters carry themselves as text.
|
||||||
|
if key_name.len() == 1 {
|
||||||
|
Some(key_name.to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn named_key_info(key: &str) -> (String, String, i32) {
|
fn named_key_info(key: &str) -> (String, String, i32) {
|
||||||
match key.to_lowercase().as_str() {
|
match key.to_lowercase().as_str() {
|
||||||
"enter" | "return" => ("Enter".to_string(), "Enter".to_string(), 13),
|
"enter" | "return" => ("Enter".to_string(), "Enter".to_string(), 13),
|
||||||
@@ -1127,4 +1148,19 @@ mod tests {
|
|||||||
assert_eq!(key, ch.to_string());
|
assert_eq!(key, ch.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_key_text_returns_correct_text_for_special_keys() {
|
||||||
|
assert_eq!(key_text("Enter"), Some("\r".to_string()));
|
||||||
|
assert_eq!(key_text("Tab"), Some("\t".to_string()));
|
||||||
|
assert_eq!(key_text(" "), Some(" ".to_string()));
|
||||||
|
// Single printable characters carry themselves.
|
||||||
|
assert_eq!(key_text("a"), Some("a".to_string()));
|
||||||
|
assert_eq!(key_text("Z"), Some("Z".to_string()));
|
||||||
|
// Non-printable named keys return None.
|
||||||
|
assert_eq!(key_text("Escape"), None);
|
||||||
|
assert_eq!(key_text("ArrowUp"), None);
|
||||||
|
assert_eq!(key_text("Backspace"), None);
|
||||||
|
assert_eq!(key_text("Delete"), None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user