Implement send keys to file input

Signed-off-by: PotatoCP <kenzieradityatirtarahardja18@gmail.com>
This commit is contained in:
PotatoCP 2025-06-02 16:33:51 +08:00
parent f710e2cab4
commit 9bf7c7849d
6 changed files with 66 additions and 54 deletions

View file

@ -2266,15 +2266,20 @@ impl ScriptThread {
can_gc, can_gc,
) )
}, },
WebDriverScriptCommand::FocusElement(element_id, reply) => { WebDriverScriptCommand::FocusElement(
webdriver_handlers::handle_focus_element( strict_file_interactability,
&documents, text,
pipeline_id, element_id,
element_id, reply,
reply, ) => webdriver_handlers::handle_focus_element(
can_gc, &documents,
) pipeline_id,
}, element_id,
text,
strict_file_interactability,
reply,
can_gc,
),
WebDriverScriptCommand::ElementClick(element_id, reply) => { WebDriverScriptCommand::ElementClick(element_id, reply) => {
webdriver_handlers::handle_element_click( webdriver_handlers::handle_element_click(
&documents, &documents,

View file

@ -838,20 +838,52 @@ pub(crate) fn handle_focus_element(
documents: &DocumentCollection, documents: &DocumentCollection,
pipeline: PipelineId, pipeline: PipelineId,
element_id: String, element_id: String,
reply: IpcSender<Result<(), ErrorStatus>>, text: String,
strict_file_interactability: bool,
reply: IpcSender<Result<bool, ErrorStatus>>,
can_gc: CanGc, can_gc: CanGc,
) { ) {
reply reply
.send( .send(
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| { find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| {
match node.downcast::<HTMLElement>() { let file_input = {
Some(element) => { if let Some(input_element) = node.downcast::<HTMLInputElement>() {
// Need a way to find if this actually succeeded if input_element.input_type() == InputType::File {
element.Focus(can_gc); Some(input_element)
Ok(()) } else {
}, None
None => Err(ErrorStatus::UnknownError), }
} else {
None
}
};
if file_input.is_none() || strict_file_interactability {
match node.downcast::<HTMLElement>() {
Some(element) => {
// Need a way to find if this actually succeeded
element.Focus(can_gc);
},
None => return Err(ErrorStatus::UnknownError),
}
} }
if let Some(file_input) = file_input {
let files: Vec<DOMString> = text.split("\n").map(|s| s.into()).collect();
if files.is_empty() {
return Err(ErrorStatus::InvalidArgument);
}
if !file_input.Multiple() && files.len() > 1 {
return Err(ErrorStatus::InvalidArgument);
}
// TODO: Should return invalid argument error if file doesn't exist
file_input.SelectFiles(files, can_gc);
return Ok(false);
}
// TODO: Check non-typeable form control
return Ok(true);
}), }),
) )
.unwrap(); .unwrap();

View file

@ -130,7 +130,7 @@ pub enum WebDriverScriptCommand {
IpcSender<Result<Vec<String>, ErrorStatus>>, IpcSender<Result<Vec<String>, ErrorStatus>>,
), ),
FindElementElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>), FindElementElementsTagName(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
FocusElement(String, IpcSender<Result<(), ErrorStatus>>), FocusElement(bool, String, String, IpcSender<Result<bool, ErrorStatus>>),
ElementClick(String, IpcSender<Result<Option<String>, ErrorStatus>>), ElementClick(String, IpcSender<Result<Option<String>, ErrorStatus>>),
GetActiveElement(IpcSender<Option<String>>), GetActiveElement(IpcSender<Option<String>>),
GetComputedRole(String, IpcSender<Result<Option<String>, ErrorStatus>>), GetComputedRole(String, IpcSender<Result<Option<String>, ErrorStatus>>),

View file

@ -1617,14 +1617,23 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
let cmd = WebDriverScriptCommand::FocusElement(element.to_string(), sender); let cmd = WebDriverScriptCommand::FocusElement(
self.session()?.strict_file_interactability,
keys.text.to_string(),
element.to_string(),
sender,
);
let cmd_msg = WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd); let cmd_msg = WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd);
self.constellation_chan self.constellation_chan
.send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg)) .send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg))
.unwrap(); .unwrap();
// TODO: distinguish the not found and not focusable cases // TODO: distinguish the not found and not focusable cases
wait_for_script_response(receiver)?.map_err(|error| WebDriverError::new(error, ""))?; // File input and non-typeable form control should have
// been handled in `webdriver_handler.rs`
if wait_for_script_response(receiver)?.map_err(|error| WebDriverError::new(error, ""))? {
return Ok(WebDriverResponse::Void);
}
let input_events = send_keys(&keys.text); let input_events = send_keys(&keys.text);

View file

@ -1,7 +1,4 @@
[events.py] [events.py]
[test_file_upload]
expected: FAIL
[test_form_control_send_text[input\]] [test_form_control_send_text[input\]]
expected: FAIL expected: FAIL

View file

@ -1,50 +1,19 @@
[file_upload.py] [file_upload.py]
expected: TIMEOUT
[test_empty_text] [test_empty_text]
expected: FAIL expected: FAIL
[test_multiple_files]
expected: FAIL
[test_multiple_files_last_path_not_found] [test_multiple_files_last_path_not_found]
expected: FAIL expected: FAIL
[test_multiple_files_without_multiple_attribute]
expected: FAIL
[test_multiple_files_send_twice] [test_multiple_files_send_twice]
expected: FAIL expected: FAIL
[test_multiple_files_reset_with_element_clear] [test_multiple_files_reset_with_element_clear]
expected: FAIL expected: FAIL
[test_single_file]
expected: FAIL
[test_single_file_replaces_without_multiple_attribute]
expected: FAIL
[test_single_file_appends_with_multiple_attribute] [test_single_file_appends_with_multiple_attribute]
expected: FAIL expected: FAIL
[test_transparent]
expected: FAIL
[test_obscured]
expected: FAIL
[test_outside_viewport]
expected: FAIL
[test_hidden]
expected: FAIL
[test_display_none]
expected: FAIL
[test_not_focused]
expected: FAIL
[test_focused] [test_focused]
expected: ERROR expected: ERROR