Commit f4a1aed8 authored by Maksim Sadym's avatar Maksim Sadym Committed by Commit Bot

GetComputedLabel

* Add `GetNodeIdByElement` to webView
* Add `ExecuteGetComputedLabel` to Element

Bug: chromedriver:3507
Change-Id: I53c558d73c57b588e27a8cc20c270619121d7fb7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2410392Reviewed-by: default avatarShengfa Lin <shengfa@google.com>
Reviewed-by: default avatarJohn Chen <johnchen@chromium.org>
Commit-Queue: Maksim Sadym <sadym@chromium.org>
Cr-Commit-Position: refs/heads/master@{#807931}
parent 226ee15a
......@@ -271,3 +271,9 @@ std::unique_ptr<base::Value> StubWebView::GetCastIssueMessage() {
}
void StubWebView::SetFrame(const std::string& new_frame_id) {}
Status StubWebView::GetNodeIdByElement(const std::string& frame,
const base::DictionaryValue& element,
int* node_id) {
return Status(kOk);
}
......@@ -129,6 +129,9 @@ class StubWebView : public WebView {
std::unique_ptr<base::Value> GetCastSinks() override;
std::unique_ptr<base::Value> GetCastIssueMessage() override;
void SetFrame(const std::string& new_frame_id) override;
Status GetNodeIdByElement(const std::string& frame,
const base::DictionaryValue& element,
int* node_id) override;
private:
std::string id_;
......
......@@ -270,6 +270,10 @@ class WebView {
virtual std::unique_ptr<base::Value> GetCastIssueMessage() = 0;
virtual void SetFrame(const std::string& new_frame_id) = 0;
virtual Status GetNodeIdByElement(const std::string& frame,
const base::DictionaryValue& element,
int* node_id) = 0;
};
#endif // CHROME_TEST_CHROMEDRIVER_CHROME_WEB_VIEW_H_
......@@ -925,6 +925,26 @@ Status WebViewImpl::PrintToPDF(const base::DictionaryValue& params,
return Status(kOk);
}
Status WebViewImpl::GetNodeIdByElement(const std::string& frame,
const base::DictionaryValue& element,
int* node_id) {
int context_id;
Status status = GetContextIdForFrame(this, frame, &context_id);
if (status.IsError())
return status;
base::ListValue args;
args.Append(element.CreateDeepCopy());
bool found_node;
status = internal::GetNodeIdFromFunction(
client_.get(), context_id, "function(element) { return element; }", args,
&found_node, node_id, w3c_compliant_);
if (status.IsError())
return status;
if (!found_node)
return Status(kNoSuchElement, "no node ID for given element");
return Status(kOk);
}
Status WebViewImpl::SetFileInputFiles(const std::string& frame,
const base::DictionaryValue& element,
const std::vector<base::FilePath>& files,
......@@ -937,21 +957,10 @@ Status WebViewImpl::SetFileInputFiles(const std::string& frame,
return target->SetFileInputFiles(frame, element, files, append);
}
int context_id;
Status status = GetContextIdForFrame(this, frame, &context_id);
if (status.IsError())
return status;
base::ListValue args;
args.Append(element.CreateDeepCopy());
bool found_node;
int node_id;
status = internal::GetNodeIdFromFunction(
client_.get(), context_id, "function(element) { return element; }",
args, &found_node, &node_id, w3c_compliant_);
Status status = GetNodeIdByElement(frame, element, &node_id);
if (status.IsError())
return status;
if (!found_node)
return Status(kUnknownError, "no node ID for file input");
base::ListValue file_list;
// if the append flag is true, we need to retrieve the files that
......
......@@ -165,6 +165,10 @@ class WebViewImpl : public WebView {
int y,
int xoffset,
int yoffset) override;
Status GetNodeIdByElement(const std::string& frame,
const base::DictionaryValue& element,
int* node_id) override;
bool IsNonBlocking() const override;
bool IsOOPIF(const std::string& frame_id) override;
FrameTracker* GetFrameTracker() const override;
......@@ -274,7 +278,6 @@ Status GetNodeIdFromFunction(DevToolsClient* client,
bool* found_node,
int* node_id,
bool w3c_compliant);
} // namespace internal
#endif // CHROME_TEST_CHROMEDRIVER_CHROME_WEB_VIEW_IMPL_H_
......@@ -79,6 +79,8 @@ class Command(object):
_Method.GET, '/session/:sessionId/element/:id/attribute/:name')
GET_ELEMENT_PROPERTY = (
_Method.GET, '/session/:sessionId/element/:id/property/:name')
GET_ELEMENT_COMPUTED_LABEL = (
_Method.GET, '/session/:sessionId/element/:id/computedlabel')
ELEMENT_EQUALS = (
_Method.GET, '/session/:sessionId/element/:id/equals/:other')
GET_COOKIES = (_Method.GET, '/session/:sessionId/cookie')
......
......@@ -34,6 +34,9 @@ class WebElement(object):
def GetProperty(self,name):
return self._Execute(Command.GET_ELEMENT_PROPERTY, {'name': name})
def GetComputedLabel(self):
return self._Execute(Command.GET_ELEMENT_COMPUTED_LABEL)
def Click(self):
self._Execute(Command.CLICK_ELEMENT)
......
......@@ -739,6 +739,61 @@ Status ExecuteIsElementEnabled(Session* session,
}
}
Status ExecuteGetComputedLabel(Session* session,
WebView* web_view,
const std::string& element_id,
const base::DictionaryValue& params,
std::unique_ptr<base::Value>* value) {
Status status = CheckElement(element_id);
if (status.IsError())
return status;
int node_id;
std::unique_ptr<base::DictionaryValue> element(CreateElement(element_id));
status = web_view->GetNodeIdByElement(session->GetCurrentFrameId(), *element,
&node_id);
if (status.IsError())
return status;
base::DictionaryValue body;
body.SetInteger("nodeId", node_id);
body.SetBoolean("fetchRelatives", false);
std::unique_ptr<base::Value> result;
status = web_view->SendCommandAndGetResult("Accessibility.getPartialAXTree",
body, &result);
if (status.IsError())
return status;
base::Optional<base::Value> nodes = result->ExtractKey("nodes");
if (!nodes)
return Status(kUnknownError, "No `nodes` found in CDP response");
base::Value::ListView nodesList = nodes->GetList();
if (nodesList.size() != 1)
return Status(kUnknownError, "`nodes` in CDP response is not a list");
base::Value* node = &nodesList[0];
// Computed label stores as `name` in the AXTree.
base::Optional<base::Value> name = node->ExtractKey("name");
if (!name) {
// No computed label found. Return empty string.
*value = std::make_unique<base::Value>("");
return Status(kOk);
}
base::Optional<base::Value> nameVal = name->ExtractKey("value");
if (!nameVal)
return Status(kUnknownError,
"No name value found in the node in CDP response");
*value = std::make_unique<base::Value>(std::move(*nameVal));
return Status(kOk);
}
Status ExecuteIsElementDisplayed(Session* session,
WebView* web_view,
const std::string& element_id,
......
......@@ -148,6 +148,12 @@ Status ExecuteIsElementEnabled(Session* session,
const base::DictionaryValue& params,
std::unique_ptr<base::Value>* value);
Status ExecuteGetComputedLabel(Session* session,
WebView* web_view,
const std::string& element_id,
const base::DictionaryValue& params,
std::unique_ptr<base::Value>* value);
Status ExecuteIsElementDisplayed(Session* session,
WebView* web_view,
const std::string& element_id,
......
......@@ -301,6 +301,9 @@ HttpHandler::HttpHandler(
kGet, "session/:sessionId/element/:id/enabled",
WrapToCommand("IsElementEnabled",
base::BindRepeating(&ExecuteIsElementEnabled))),
CommandMapping(kGet, "session/:sessionId/element/:id/computedlabel",
WrapToCommand("GetComputedLabel",
base::Bind(&ExecuteGetComputedLabel))),
CommandMapping(kPost, "session/:sessionId/element/:id/click",
WrapToCommand("ClickElement",
base::BindRepeating(&ExecuteClickElement))),
......
......@@ -538,6 +538,14 @@ class ChromeDriverTest(ChromeDriverBaseTestWithWebServer):
def testStartStop(self):
pass
def testGetComputedLabel(self):
self._driver.Load(self.GetHttpUrlForFile(
'/chromedriver/accessibility.html'))
element = self._driver.FindElement('css selector', '#first-header')
# print >> sys.stdout, "element.GetText: ", element.GetText()
computedLabel = element.GetComputedLabel()
self.assertEquals(computedLabel, 'header content')
def testLoadUrl(self):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
......
<!DOCTYPE html>
<title>Test</title>
<h1 id="first-header">header content</h1>
......@@ -40,6 +40,7 @@ Below is a list of all WebDriver commands and their current support in ChromeDri
| GET | /session/{session id}/element/{element id}/name | Get Element Tag Name | Complete |
| GET | /session/{session id}/element/{element id}/rect | Get Element Rect | Complete |
| GET | /session/{session id}/element/{element id}/enabled | Is Element Enabled | Complete |
| GET | /session/{session id}/element/{element id}/computedlabel | Get Computed Label | Complete |
| POST | /session/{session id}/element/{element id}/click | Element Click | Partially Complete | [1996](https://bugs.chromium.org/p/chromedriver/issues/detail?id=1996)
| POST | /session/{session id}/element/{element id}/clear | Element Clear | Complete |
| POST | /session/{session id}/element/{element id}/value | Element Send Keys | Partially Complete | [1999](https://bugs.chromium.org/p/chromedriver/issues/detail?id=1999)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment