Skip to content

Commit fe1e23e

Browse files
committed
WebDriver: most of the clear tests are failing
https://bugs.webkit.org/show_bug.cgi?id=180404 Reviewed by Brian Burg. Source/WebDriver: Implement the element clear command following the spec. https://w3c.github.io/webdriver/#element-clear * Session.cpp: (WebDriver::Session::elementIsEditable): Helper function to check if the element is editable. (WebDriver::Session::elementClear): Check if the element is editable and interactable before executing the clear atom. * Session.h: Source/WebKit: Update the FormElementClear atom to follow the spec. * UIProcess/Automation/atoms/FormElementClear.js: (isEditable): (isResettableElementEmpty): WebDriverTests: Remove expectations for tests that are now passing. * TestExpectations.json: Canonical link: https://commits.webkit.org/217994@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@253029 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent bd90385 commit fe1e23e

7 files changed

Lines changed: 177 additions & 161 deletions

File tree

Source/WebDriver/ChangeLog

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
2019-12-03 Carlos Garcia Campos <cgarcia@igalia.com>
2+
3+
WebDriver: most of the clear tests are failing
4+
https://bugs.webkit.org/show_bug.cgi?id=180404
5+
6+
Reviewed by Brian Burg.
7+
8+
Implement the element clear command following the spec.
9+
https://w3c.github.io/webdriver/#element-clear
10+
11+
* Session.cpp:
12+
(WebDriver::Session::elementIsEditable): Helper function to check if the element is editable.
13+
(WebDriver::Session::elementClear): Check if the element is editable and interactable before executing the clear atom.
14+
* Session.h:
15+
116
2019-11-22 Carlos Garcia Campos <cgarcia@igalia.com>
217

318
Unreviewed. Fix GTK/WPE debug build after r252770

Source/WebDriver/Session.cpp

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,53 @@ void Session::elementClick(const String& elementID, Function<void (CommandResult
15951595
});
15961596
}
15971597

1598+
void Session::elementIsEditable(const String& elementID, Function<void (CommandResult&&)>&& completionHandler)
1599+
{
1600+
RefPtr<JSON::Array> arguments = JSON::Array::create();
1601+
arguments->pushString(createElement(elementID)->toJSONString());
1602+
1603+
static const char isEditableScript[] =
1604+
"function(element) {"
1605+
" if (element.disabled || element.readOnly)"
1606+
" return false;"
1607+
" var tagName = element.tagName.toLowerCase();"
1608+
" if (tagName === 'textarea' || element.isContentEditable)"
1609+
" return true;"
1610+
" if (tagName != 'input')"
1611+
" return false;"
1612+
" switch (element.type) {"
1613+
" case 'color': case 'date': case 'datetime-local': case 'email': case 'file': case 'month': case 'number': "
1614+
" case 'password': case 'range': case 'search': case 'tel': case 'text': case 'time': case 'url': case 'week':"
1615+
" return true;"
1616+
" }"
1617+
" return false;"
1618+
"}";
1619+
1620+
RefPtr<JSON::Object> parameters = JSON::Object::create();
1621+
parameters->setString("browsingContextHandle"_s, m_toplevelBrowsingContext.value());
1622+
if (m_currentBrowsingContext)
1623+
parameters->setString("frameHandle"_s, m_currentBrowsingContext.value());
1624+
parameters->setString("function"_s, isEditableScript);
1625+
parameters->setArray("arguments"_s, WTFMove(arguments));
1626+
m_host->sendCommandToBackend("evaluateJavaScriptFunction"_s, WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
1627+
if (response.isError || !response.responseObject) {
1628+
completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
1629+
return;
1630+
}
1631+
String valueString;
1632+
if (!response.responseObject->getString("result"_s, valueString)) {
1633+
completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
1634+
return;
1635+
}
1636+
RefPtr<JSON::Value> resultValue;
1637+
if (!JSON::Value::parseJSON(valueString, resultValue)) {
1638+
completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
1639+
return;
1640+
}
1641+
completionHandler(CommandResult::success(WTFMove(resultValue)));
1642+
});
1643+
}
1644+
15981645
void Session::elementClear(const String& elementID, Function<void (CommandResult&&)>&& completionHandler)
15991646
{
16001647
if (!m_toplevelBrowsingContext) {
@@ -1608,21 +1655,45 @@ void Session::elementClear(const String& elementID, Function<void (CommandResult
16081655
return;
16091656
}
16101657

1611-
RefPtr<JSON::Array> arguments = JSON::Array::create();
1612-
arguments->pushString(createElement(elementID)->toJSONString());
1658+
elementIsEditable(elementID, [this, protectedThis = protectedThis.copyRef(), elementID, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
1659+
if (result.isError()) {
1660+
completionHandler(WTFMove(result));
1661+
return;
1662+
}
16131663

1614-
RefPtr<JSON::Object> parameters = JSON::Object::create();
1615-
parameters->setString("browsingContextHandle"_s, m_toplevelBrowsingContext.value());
1616-
if (m_currentBrowsingContext)
1617-
parameters->setString("frameHandle"_s, m_currentBrowsingContext.value());
1618-
parameters->setString("function"_s, String(FormElementClearJavaScript, sizeof(FormElementClearJavaScript)));
1619-
parameters->setArray("arguments"_s, WTFMove(arguments));
1620-
m_host->sendCommandToBackend("evaluateJavaScriptFunction"_s, WTFMove(parameters), [protectedThis = protectedThis.copyRef(), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
1621-
if (response.isError) {
1622-
completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
1664+
bool isEditable;
1665+
if (!result.result()->asBoolean(isEditable) || !isEditable) {
1666+
completionHandler(CommandResult::fail(CommandResult::ErrorCode::InvalidElementState));
16231667
return;
16241668
}
1625-
completionHandler(CommandResult::success());
1669+
1670+
OptionSet<ElementLayoutOption> options = { ElementLayoutOption::ScrollIntoViewIfNeeded };
1671+
computeElementLayout(elementID, options, [this, protectedThis = protectedThis.copyRef(), elementID, completionHandler = WTFMove(completionHandler)](Optional<Rect>&& rect, Optional<Point>&& inViewCenter, bool, RefPtr<JSON::Object>&& error) mutable {
1672+
if (!rect || error) {
1673+
completionHandler(CommandResult::fail(WTFMove(error)));
1674+
return;
1675+
}
1676+
if (!inViewCenter) {
1677+
completionHandler(CommandResult::fail(CommandResult::ErrorCode::ElementNotInteractable));
1678+
return;
1679+
}
1680+
RefPtr<JSON::Array> arguments = JSON::Array::create();
1681+
arguments->pushString(createElement(elementID)->toJSONString());
1682+
1683+
RefPtr<JSON::Object> parameters = JSON::Object::create();
1684+
parameters->setString("browsingContextHandle"_s, m_toplevelBrowsingContext.value());
1685+
if (m_currentBrowsingContext)
1686+
parameters->setString("frameHandle"_s, m_currentBrowsingContext.value());
1687+
parameters->setString("function"_s, String(FormElementClearJavaScript, sizeof(FormElementClearJavaScript)));
1688+
parameters->setArray("arguments"_s, WTFMove(arguments));
1689+
m_host->sendCommandToBackend("evaluateJavaScriptFunction"_s, WTFMove(parameters), [protectedThis = protectedThis.copyRef(), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) {
1690+
if (response.isError) {
1691+
completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
1692+
return;
1693+
}
1694+
completionHandler(CommandResult::success());
1695+
});
1696+
});
16261697
});
16271698
});
16281699
}

Source/WebDriver/Session.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class Session : public RefCounted<Session> {
146146
RefPtr<JSON::Object> extractElement(JSON::Value&);
147147
String extractElementID(JSON::Value&);
148148
RefPtr<JSON::Value> handleScriptResult(RefPtr<JSON::Value>&&);
149+
void elementIsEditable(const String& elementID, Function<void (CommandResult&&)>&&);
149150

150151
struct Point {
151152
int x { 0 };

Source/WebKit/ChangeLog

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
2019-12-03 Carlos Garcia Campos <cgarcia@igalia.com>
2+
3+
WebDriver: most of the clear tests are failing
4+
https://bugs.webkit.org/show_bug.cgi?id=180404
5+
6+
Reviewed by Brian Burg.
7+
8+
Update the FormElementClear atom to follow the spec.
9+
10+
* UIProcess/Automation/atoms/FormElementClear.js:
11+
(isEditable):
12+
(isResettableElementEmpty):
13+
114
2019-12-03 Carlos Garcia Campos <cgarcia@igalia.com>
215

316
[PSON] Tooltips from previous page shown on new page

Source/WebKit/UIProcess/Automation/atoms/FormElementClear.js

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,69 @@
2626
function(element) {
2727
"use strict";
2828

29-
if (element.disabled || element.readOnly)
30-
throw {name: "InvalidElementState", message: "Element must be user-editable in order to clear."};
29+
function isEditable(element) {
30+
if (element.disabled || element.readOnly)
31+
return false;
3132

32-
if (element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement) {
33-
element.value = "";
34-
return;
35-
}
33+
if (element instanceof HTMLTextAreaElement)
34+
return true;
3635

37-
if (element instanceof HTMLInputElement) {
38-
switch (element.type) {
39-
case "button":
40-
case "submit":
41-
case "reset":
42-
return;
36+
if (element.isContentEditable)
37+
return true;
4338

44-
case "radio":
45-
case "checkbox":
46-
element.checked = false;
47-
return;
39+
if (element.tagName.toUpperCase() != "INPUT")
40+
return false;
4841

49-
default:
50-
element.value = "";
51-
return;
42+
switch (element.type) {
43+
case "color":
44+
case "date":
45+
case "datetime-local":
46+
case "email":
47+
case "file":
48+
case "month":
49+
case "number":
50+
case "password":
51+
case "range":
52+
case "search":
53+
case "tel":
54+
case "text":
55+
case "time":
56+
case "url":
57+
case "week":
58+
return true;
5259
}
60+
61+
return false;
5362
}
5463

64+
if (!isEditable(element))
65+
throw {name: "InvalidElementState", message: "Element must be user-editable in order to clear."};
66+
67+
// Clear a content editable element.
5568
if (element.isContentEditable) {
69+
if (element.innerHTML === "")
70+
return;
71+
72+
element.focus();
5673
element.innerHTML = "";
74+
element.blur();
5775
return;
5876
}
77+
78+
// Clear a resettable element.
79+
function isResettableElementEmpty(element) {
80+
if (element instanceof HTMLInputElement && element.type == "file")
81+
return element.files.length == 0;
82+
return element.value === "";
83+
}
84+
85+
if (element.validity.valid && isResettableElementEmpty(element))
86+
return;
87+
88+
element.focus();
89+
element.value = "";
90+
var event = document.createEvent("Event");
91+
event.initEvent("change", true, true);
92+
element.dispatchEvent(event);
93+
element.blur();
5994
}

WebDriverTests/ChangeLog

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2019-12-03 Carlos Garcia Campos <cgarcia@igalia.com>
2+
3+
WebDriver: most of the clear tests are failing
4+
https://bugs.webkit.org/show_bug.cgi?id=180404
5+
6+
Reviewed by Brian Burg.
7+
8+
Remove expectations for tests that are now passing.
9+
10+
* TestExpectations.json:
11+
112
2019-11-13 Carlos Garcia Campos <cgarcia@igalia.com>
213

314
Unreviewed gardening. Skip imported/w3c/webdriver/tests/send_alert_text/send.py::test_alert_unsupported_operation.

WebDriverTests/TestExpectations.json

Lines changed: 0 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -595,136 +595,6 @@
595595
"imported/w3c/webdriver/tests/element_send_keys/content_editable.py": {
596596
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180403"}}
597597
},
598-
"imported/w3c/webdriver/tests/element_clear/clear.py": {
599-
"subtests": {
600-
"test_pointer_interactable": {
601-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
602-
},
603-
"test_input[number-42-]": {
604-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
605-
},
606-
"test_input[range-42-50]": {
607-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
608-
},
609-
"test_input[email-foo@example.com-]": {
610-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
611-
},
612-
"test_input[password-password-]": {
613-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
614-
},
615-
"test_input[search-search-]": {
616-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
617-
},
618-
"test_input[tel-999-]": {
619-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
620-
},
621-
"test_input[text-text-]": {
622-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
623-
},
624-
"test_input[url-https://example.com/-]": {
625-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
626-
},
627-
"test_input[color-#ff0000-#000000]": {
628-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
629-
},
630-
"test_input[date-2017-12-26-]": {
631-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
632-
},
633-
"test_input[datetime-2017-12-26T19:48-]": {
634-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
635-
},
636-
"test_input[datetime-local-2017-12-26T19:48-]": {
637-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
638-
},
639-
"test_input[time-19:48-]": {
640-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
641-
},
642-
"test_input[month-2017-11-]": {
643-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
644-
},
645-
"test_input[week-2017-W52-]": {
646-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
647-
},
648-
"test_textarea": {
649-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
650-
},
651-
"test_input_file": {
652-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
653-
},
654-
"test_input_file_multiple": {
655-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
656-
},
657-
"test_select": {
658-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
659-
},
660-
"test_button": {
661-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
662-
},
663-
"test_button_with_subtree": {
664-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
665-
},
666-
"test_contenteditable": {
667-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
668-
},
669-
"test_designmode": {
670-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
671-
},
672-
"test_resettable_element_does_not_satisfy_validation_constraints[number-foo]": {
673-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
674-
},
675-
"test_resettable_element_does_not_satisfy_validation_constraints[range-foo]": {
676-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
677-
},
678-
"test_resettable_element_does_not_satisfy_validation_constraints[email-foo]": {
679-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
680-
},
681-
"test_resettable_element_does_not_satisfy_validation_constraints[url-foo]": {
682-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
683-
},
684-
"test_resettable_element_does_not_satisfy_validation_constraints[color-foo]": {
685-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
686-
},
687-
"test_resettable_element_does_not_satisfy_validation_constraints[date-foo]": {
688-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
689-
},
690-
"test_resettable_element_does_not_satisfy_validation_constraints[datetime-foo]": {
691-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
692-
},
693-
"test_resettable_element_does_not_satisfy_validation_constraints[datetime-local-foo]": {
694-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
695-
},
696-
"test_resettable_element_does_not_satisfy_validation_constraints[time-foo]": {
697-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
698-
},
699-
"test_resettable_element_does_not_satisfy_validation_constraints[month-foo]": {
700-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
701-
},
702-
"test_resettable_element_does_not_satisfy_validation_constraints[week-foo]": {
703-
"expected": {"all": {"status": ["SKIP"], "bug": "webkit.org/b/180404"}}
704-
},
705-
"test_non_editable_inputs[checkbox]": {
706-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
707-
},
708-
"test_non_editable_inputs[radio]": {
709-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
710-
},
711-
"test_non_editable_inputs[hidden]": {
712-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
713-
},
714-
"test_non_editable_inputs[submit]": {
715-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
716-
},
717-
"test_non_editable_inputs[button]": {
718-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
719-
},
720-
"test_non_editable_inputs[image]": {
721-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
722-
},
723-
"test_scroll_into_view": {
724-
"expected": {"all": {"status": ["FAIL"], "bug": "webkit.org/b/180404"}}
725-
}
726-
}
727-
},
728598
"imported/w3c/webdriver/tests/get_current_url/get.py": {
729599
"subtests": {
730600
"test_set_malformed_url": {

0 commit comments

Comments
 (0)