summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-20 01:20:17 +0000
committerkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-20 01:20:17 +0000
commitd898053263f96faf49c8367d12ff64a3ee2f76dd (patch)
treea84ada02f679c4fdc38479e79b2c88235ef2aab7 /chrome
parent33e73aa2d4e9be16871985f3a6433a5bdb6e44c6 (diff)
downloadchromium_src-d898053263f96faf49c8367d12ff64a3ee2f76dd.zip
chromium_src-d898053263f96faf49c8367d12ff64a3ee2f76dd.tar.gz
chromium_src-d898053263f96faf49c8367d12ff64a3ee2f76dd.tar.bz2
Implement several ChromeDriver commands based on the javascript atoms.
Added a "501 Not Implemented" callback to mongoose for the WebDriver commands that have not been implemented yet. This ensures tests that fail from unimplemented commands fail with a meaningful message. Patch by jleyba@chromium.org. Original review at http://codereview.chromium.org/6542032 BUG=none TEST=none Review URL: http://codereview.chromium.org/6542036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75511 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/test/webdriver/WEBDRIVER_TESTS59
-rw-r--r--chrome/test/webdriver/commands/target_locator_commands.cc20
-rw-r--r--chrome/test/webdriver/commands/target_locator_commands.h14
-rw-r--r--chrome/test/webdriver/commands/webelement_commands.cc389
-rw-r--r--chrome/test/webdriver/commands/webelement_commands.h199
-rw-r--r--chrome/test/webdriver/server.cc56
6 files changed, 715 insertions, 22 deletions
diff --git a/chrome/test/webdriver/WEBDRIVER_TESTS b/chrome/test/webdriver/WEBDRIVER_TESTS
index 2580d67..02d8574 100644
--- a/chrome/test/webdriver/WEBDRIVER_TESTS
+++ b/chrome/test/webdriver/WEBDRIVER_TESTS
@@ -24,29 +24,33 @@
{
'all': [
'children_finding_tests',
- '-children_finding_tests.ChildrenFindingTests.testShouldFindElementByClassName',
- '-children_finding_tests.ChildrenFindingTests.testShouldFindElementById',
- '-children_finding_tests.ChildrenFindingTests.testShouldFindElementByIdWhenMultipleMatchesExist',
- '-children_finding_tests.ChildrenFindingTests.testShouldFindElementByLinkText',
- '-children_finding_tests.ChildrenFindingTests.testShouldFindElementByName',
- '-children_finding_tests.ChildrenFindingTests.testShouldFindElementByTagName',
- '-children_finding_tests.ChildrenFindingTests.testShouldFindElementByXPath',
- '-children_finding_tests.ChildrenFindingTests.testShouldFindElementsByTagName',
- '-children_finding_tests.ChildrenFindingTests.testShouldFindElementsByXpath',
# 'cookie_tests',
# 'correct_event_firing_tests',
'driver_element_finding_test',
-# 'element_attribute_tests',
+ 'element_attribute_tests',
# 'executing_async_javascript_test',
'executing_javascript_test',
- # This test needs the tagname command.
- '-executing_javascript_test.ExecutingJavaScriptTests.testShouldBeAbleToExecuteSimpleJavascriptAndReturnAWebElement',
-# 'form_handling_tests',
+ 'form_handling_tests',
+ # The following require the click command.
+ '-form_handling_tests.FormHandlingTests.testClickingOnUnclickableElementsDoesNothing',
+ '-form_handling_tests.FormHandlingTests.testShouldBeAbleToClickImageButtons',
+ '-form_handling_tests.FormHandlingTests.testShouldBeAbleToSelectARadioButtonByClickingOnIt',
+ '-form_handling_tests.FormHandlingTests.testShouldClickOnSubmitInputElements',
+ # The following are all suppressed because the submit command currently does
+ # not wait for post-submit navigation events to complete.
+ '-form_handling_tests.FormHandlingTests.testShouldBeAbleToSubmitForms',
+ '-form_handling_tests.FormHandlingTests.testShouldSubmitAFormWhenAnyElementWihinThatFormIsSubmitted',
+ '-form_handling_tests.FormHandlingTests.testShouldSubmitAFormWhenAnyInputElementWithinThatFormIsSubmitted',
+ # Test fails from a bug in the WebDriver python bindings. This bug has been
+ # fixed in the WebDriver tree:
+ # http://code.google.com/p/selenium/source/detail?r=11480
+ '-form_handling_tests.FormHandlingTests.testShouldThrowAnExceptionWhenSelectingAnUnselectableElement',
'frame_switching_tests',
- # Next two frame switching tests are disabled because they depend on toggle.
- '-frame_switching_tests.FrameSwitchingTest.testThatWeCanSwitchFrameByName',
- '-frame_switching_tests.FrameSwitchingTest.testThatWeCanSwitchToFrameByIndex',
-# 'implicit_waits_tests',
+ 'implicit_waits_tests',
+ # Depends on click.
+ '-implicit_waits_tests.ImplicitWaitTest.testShouldImplicitlyWaitForASingleElement',
+ '-implicit_waits_tests.ImplicitWaitTest.testShouldImplicitlyWaitUntilAtLeastOneElementIsFoundWhenSearchingForMany',
+ '-implicit_waits_tests.ImplicitWaitTest.testShouldReturnAfterFirstAttemptToFindManyAfterDisablingImplicitWaits',
'page_loading_tests',
# testShouldReturnWhenGettingAUrlThatDoesNotResolve causes the test after
# to fail when run in xvfb: crbug.com/72027.
@@ -56,12 +60,25 @@
'-page_loading_tests.PageLoadingTests.testShouldBeAbleToNavigateForwardsInTheBrowserHistory',
# This test is flaky.
'-page_loading_tests.PageLoadingTests.testShouldWaitForDocumentToBeLoaded',
-# 'rendered_webelement_tests'
-# 'select_element_handling_tests',
-# 'stale_reference_tests',
+ 'rendered_webelement_tests',
+ # Test is flaky. Sometimes can't find an element.
+ '-rendered_webelement_tests.RenderedWebElementTests.testShouldCorrectlyIdentifyThatAnElementHasWidth',
+ # Test expects a color keyword, but a rgba tuple is returned.
+ '-rendered_webelement_tests.RenderedWebElementTests.testShouldAllowInheritedStylesToBeUsed',
+ # Test expects hex color, but a rgb tuple is returned.
+ '-rendered_webelement_tests.RenderedWebElementTests.testShouldPickUpStyleOfAnElement',
+ 'select_element_handling_tests',
+ 'stale_reference_tests',
+ # Test requires click command.
+ '-stale_reference_tests.StaleReferenceTests.testOldPage',
# 'text_handling_tests',
# 'typing_tests',
-# 'visibility_tests',
+ 'visibility_tests',
+ # Depends on click.
+ '-visibility_tests.VisibilityTests.testShouldModifyTheVisibilityOfAnElementDynamically',
+ '-visibility_tests.VisibilityTests.testShouldNotBeAbleToClickOnAnElementThatIsNotDisplayed',
+ # Bug in typing: element is not verified before typing.
+ '-visibility_tests.VisibilityTests.testShouldNotBeAbleToTypeAnElementThatIsNotDisplayed',
],
'win': [
diff --git a/chrome/test/webdriver/commands/target_locator_commands.cc b/chrome/test/webdriver/commands/target_locator_commands.cc
index 841173c..0dd3684 100644
--- a/chrome/test/webdriver/commands/target_locator_commands.cc
+++ b/chrome/test/webdriver/commands/target_locator_commands.cc
@@ -130,4 +130,24 @@ void SwitchFrameCommand::ExecutePost(Response* const response) {
response->SetStatus(kSuccess);
}
+ActiveElementCommand::ActiveElementCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebDriverCommand(path_segments, parameters) {}
+
+ActiveElementCommand::~ActiveElementCommand() {}
+
+bool ActiveElementCommand::DoesPost() {
+ return true;
+}
+
+void ActiveElementCommand::ExecutePost(Response* const response) {
+ ListValue args;
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(
+ "return document.activeElement || document.body", &args, &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
} // namespace webdriver
diff --git a/chrome/test/webdriver/commands/target_locator_commands.h b/chrome/test/webdriver/commands/target_locator_commands.h
index d9093cc..9294ab8 100644
--- a/chrome/test/webdriver/commands/target_locator_commands.h
+++ b/chrome/test/webdriver/commands/target_locator_commands.h
@@ -79,6 +79,20 @@ class SwitchFrameCommand : public WebDriverCommand {
DISALLOW_COPY_AND_ASSIGN(SwitchFrameCommand);
};
+// Retrieves the active element on the current page.
+class ActiveElementCommand : public WebDriverCommand {
+ public:
+ ActiveElementCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ActiveElementCommand();
+
+ virtual bool DoesPost();
+ virtual void ExecutePost(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ActiveElementCommand);
+};
+
} // namespace webdriver
#endif // CHROME_TEST_WEBDRIVER_COMMANDS_TARGET_LOCATOR_COMMANDS_H_
diff --git a/chrome/test/webdriver/commands/webelement_commands.cc b/chrome/test/webdriver/commands/webelement_commands.cc
index f240326..052ac39 100644
--- a/chrome/test/webdriver/commands/webelement_commands.cc
+++ b/chrome/test/webdriver/commands/webelement_commands.cc
@@ -15,6 +15,8 @@
namespace webdriver {
+///////////////////// WebElementCommand ////////////////////
+
WebElementCommand::WebElementCommand(
const std::vector<std::string>& path_segments,
const DictionaryValue* const parameters)
@@ -96,6 +98,391 @@ bool WebElementCommand::RequiresValidTab() {
return true;
}
+///////////////////// ElementAttributeCommand ////////////////////
+
+ElementAttributeCommand::ElementAttributeCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementAttributeCommand::~ElementAttributeCommand() {}
+
+bool ElementAttributeCommand::DoesGet() {
+ return true;
+}
+
+void ElementAttributeCommand::ExecuteGet(Response* const response) {
+ // There should be at least 7 segments to match
+ // "/session/$session/element/$id/attribute/$name"
+ if (path_segments_.size() < 7) {
+ SET_WEBDRIVER_ERROR(response, "Path segments is less than 7",
+ kBadRequest);
+ return;
+ }
+
+ std::string script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE);
+
+ scoped_ptr<ListValue> args(new ListValue);
+ args->Append(GetElementIdAsDictionaryValue(element_id));
+ args->Append(Value::CreateStringValue(path_segments_.at(6)));
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementClearCommand ////////////////////
+
+ElementClearCommand::ElementClearCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementClearCommand::~ElementClearCommand() {}
+
+bool ElementClearCommand::DoesPost() {
+ return true;
+}
+
+void ElementClearCommand::ExecutePost(Response* const response) {
+ scoped_ptr<ListValue> args(new ListValue);
+ args->Append(GetElementIdAsDictionaryValue(element_id));
+
+ std::string script = base::StringPrintf(
+ "(%s).apply(null, arguments);", atoms::CLEAR);
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementCssCommand ////////////////////
+
+ElementCssCommand::ElementCssCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementCssCommand::~ElementCssCommand() {}
+
+bool ElementCssCommand::DoesGet() {
+ return true;
+}
+
+void ElementCssCommand::ExecuteGet(Response* const response) {
+ // There should be at least 7 segments to match
+ // "/session/$session/element/$id/css/$propertyName"
+ if (path_segments_.size() < 7) {
+ SET_WEBDRIVER_ERROR(response, "Path segments is less than 7",
+ kBadRequest);
+ return;
+ }
+
+ std::string script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", atoms::GET_EFFECTIVE_STYLE);
+
+ scoped_ptr<ListValue> args(new ListValue);
+ args->Append(GetElementIdAsDictionaryValue(element_id));
+ args->Append(Value::CreateStringValue(path_segments_.at(6)));
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementDisplayedCommand ////////////////////
+
+ElementDisplayedCommand::ElementDisplayedCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementDisplayedCommand::~ElementDisplayedCommand() {}
+
+bool ElementDisplayedCommand::DoesGet() {
+ return true;
+}
+
+void ElementDisplayedCommand::ExecuteGet(Response* const response) {
+ scoped_ptr<ListValue> args(new ListValue);
+ args->Append(GetElementIdAsDictionaryValue(element_id));
+
+ std::string script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", atoms::IS_DISPLAYED);
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementEnabledCommand ////////////////////
+
+ElementEnabledCommand::ElementEnabledCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementEnabledCommand::~ElementEnabledCommand() {}
+
+bool ElementEnabledCommand::DoesGet() {
+ return true;
+}
+
+void ElementEnabledCommand::ExecuteGet(Response* const response) {
+ scoped_ptr<ListValue> args(new ListValue);
+ args->Append(GetElementIdAsDictionaryValue(element_id));
+
+ std::string script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", atoms::IS_ENABLED);
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementEqualsCommand ////////////////////
+
+ElementEqualsCommand::ElementEqualsCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementEqualsCommand::~ElementEqualsCommand() {}
+
+bool ElementEqualsCommand::DoesGet() {
+ return true;
+}
+
+void ElementEqualsCommand::ExecuteGet(Response* const response) {
+ // There should be at least 7 segments to match
+ // "/session/$session/element/$id/equals/$other"
+ if (path_segments_.size() < 7) {
+ SET_WEBDRIVER_ERROR(response, "Path segments is less than 7",
+ kBadRequest);
+ return;
+ }
+
+ std::string script = "return arguments[0] == arguments[1];";
+
+ scoped_ptr<ListValue> args(new ListValue);
+ args->Append(GetElementIdAsDictionaryValue(element_id));
+ args->Append(Value::CreateStringValue(path_segments_.at(6)));
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementLocationCommand ////////////////////
+
+ElementLocationCommand::ElementLocationCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementLocationCommand::~ElementLocationCommand() {}
+
+bool ElementLocationCommand::DoesGet() {
+ return true;
+}
+
+void ElementLocationCommand::ExecuteGet(Response* const response) {
+ std::string script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", atoms::GET_LOCATION);
+
+ ListValue args;
+ args.Append(GetElementIdAsDictionaryValue(element_id));
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, &args, &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementLocationInViewCommand ////////////////////
+
+ElementLocationInViewCommand::ElementLocationInViewCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementLocationInViewCommand::~ElementLocationInViewCommand() {}
+
+bool ElementLocationInViewCommand::DoesGet() {
+ return true;
+}
+
+void ElementLocationInViewCommand::ExecuteGet(Response* const response) {
+ std::string script = base::StringPrintf("arguments[0].scrollIntoView();"
+ "return (%s).apply(null, arguments);",
+ atoms::GET_LOCATION);
+ ListValue args;
+ args.Append(GetElementIdAsDictionaryValue(element_id));
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, &args, &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementNameCommand ////////////////////
+
+ElementNameCommand::ElementNameCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementNameCommand::~ElementNameCommand() {}
+
+bool ElementNameCommand::DoesGet() {
+ return true;
+}
+
+void ElementNameCommand::ExecuteGet(Response* const response) {
+ scoped_ptr<ListValue> args(new ListValue);
+ args->Append(GetElementIdAsDictionaryValue(element_id));
+
+ std::string script = "return arguments[0].tagName;";
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementSelectedCommand ////////////////////
+
+ElementSelectedCommand::ElementSelectedCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementSelectedCommand::~ElementSelectedCommand() {}
+
+bool ElementSelectedCommand::DoesGet() {
+ return true;
+}
+
+bool ElementSelectedCommand::DoesPost() {
+ return true;
+}
+
+void ElementSelectedCommand::ExecuteGet(Response* const response) {
+ scoped_ptr<ListValue> args(new ListValue);
+ args->Append(GetElementIdAsDictionaryValue(element_id));
+
+ std::string script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", atoms::IS_SELECTED);
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+void ElementSelectedCommand::ExecutePost(Response* const response) {
+ scoped_ptr<ListValue> args(new ListValue);
+ args->Append(GetElementIdAsDictionaryValue(element_id));
+ args->Append(Value::CreateBooleanValue(true));
+
+ std::string script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", atoms::SET_SELECTED);
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementSizeCommand ////////////////////
+
+ElementSizeCommand::ElementSizeCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementSizeCommand::~ElementSizeCommand() {}
+
+bool ElementSizeCommand::DoesGet() {
+ return true;
+}
+
+void ElementSizeCommand::ExecuteGet(Response* const response) {
+ std::string script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", atoms::GET_SIZE);
+
+ ListValue args;
+ args.Append(GetElementIdAsDictionaryValue(element_id));
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, &args, &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementSubmitCommand ////////////////////
+
+ElementSubmitCommand::ElementSubmitCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementSubmitCommand::~ElementSubmitCommand() {}
+
+bool ElementSubmitCommand::DoesPost() {
+ return true;
+}
+
+void ElementSubmitCommand::ExecutePost(Response* const response) {
+ // TODO(jleyba): We need to wait for any post-submit navigation events to
+ // complete before responding to the client.
+ std::string script = base::StringPrintf(
+ "(%s).apply(null, arguments);", atoms::SUBMIT);
+
+ ListValue args;
+ args.Append(GetElementIdAsDictionaryValue(element_id));
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, &args, &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementToggleCommand ////////////////////
+
+ElementToggleCommand::ElementToggleCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebElementCommand(path_segments, parameters) {}
+
+ElementToggleCommand::~ElementToggleCommand() {}
+
+bool ElementToggleCommand::DoesPost() {
+ return true;
+}
+
+void ElementToggleCommand::ExecutePost(Response* const response) {
+ std::string script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", atoms::TOGGLE);
+
+ ListValue args;
+ args.Append(GetElementIdAsDictionaryValue(element_id));
+
+ Value* result = NULL;
+ ErrorCode status = session_->ExecuteScript(script, &args, &result);
+ response->SetStatus(status);
+ response->SetValue(result);
+}
+
+///////////////////// ElementValueCommand ////////////////////
+
ElementValueCommand::ElementValueCommand(
const std::vector<std::string>& path_segments,
DictionaryValue* parameters)
@@ -170,6 +557,8 @@ void ElementValueCommand::ExecutePost(Response* const response) {
response->SetStatus(kSuccess);
}
+///////////////////// ElementTextCommand ////////////////////
+
ElementTextCommand::ElementTextCommand(
const std::vector<std::string>& path_segments,
DictionaryValue* parameters)
diff --git a/chrome/test/webdriver/commands/webelement_commands.h b/chrome/test/webdriver/commands/webelement_commands.h
index 0484742..8d1ce9f 100644
--- a/chrome/test/webdriver/commands/webelement_commands.h
+++ b/chrome/test/webdriver/commands/webelement_commands.h
@@ -39,6 +39,205 @@ class WebElementCommand : public WebDriverCommand {
DISALLOW_COPY_AND_ASSIGN(WebElementCommand);
};
+// Retrieves element attributes.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/attribute/:name
+class ElementAttributeCommand : public WebElementCommand {
+ public:
+ ElementAttributeCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementAttributeCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementAttributeCommand);
+};
+
+// Clears test input elements.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/clear
+class ElementClearCommand : public WebElementCommand {
+ public:
+ ElementClearCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementClearCommand();
+
+ virtual bool DoesPost();
+ virtual void ExecutePost(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementClearCommand);
+};
+
+// Retrieves element style properties.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/css/:propertyName
+class ElementCssCommand : public WebElementCommand {
+ public:
+ ElementCssCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementCssCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementCssCommand);
+};
+
+// Queries whether an element is currently displayed ot the user.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/displayed
+class ElementDisplayedCommand : public WebElementCommand {
+ public:
+ ElementDisplayedCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementDisplayedCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementDisplayedCommand);
+};
+
+// Queries whether an element is currently enabled.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/enabled
+class ElementEnabledCommand : public WebElementCommand {
+ public:
+ ElementEnabledCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementEnabledCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementEnabledCommand);
+};
+
+// Queries whether two elements are equal.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/equals/:other
+class ElementEqualsCommand : public WebElementCommand {
+ public:
+ ElementEqualsCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementEqualsCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementEqualsCommand);
+};
+
+// Retrieves the element's location on the page.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/location
+class ElementLocationCommand : public WebElementCommand {
+ public:
+ ElementLocationCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementLocationCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementLocationCommand);
+};
+
+// Retrieves the element's location on the page after ensuring it is visible in
+// the current viewport.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/location_in_view
+class ElementLocationInViewCommand : public WebElementCommand {
+ public:
+ ElementLocationInViewCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementLocationInViewCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementLocationInViewCommand);
+};
+
+// Queries for an element's tag name.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/name
+class ElementNameCommand : public WebElementCommand {
+ public:
+ ElementNameCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementNameCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementNameCommand);
+};
+
+// Handles selecting elements and querying whether they are currently selected.
+// Queries whether an element is currently enabled.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/selected
+class ElementSelectedCommand : public WebElementCommand {
+ public:
+ ElementSelectedCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementSelectedCommand();
+
+ virtual bool DoesGet();
+ virtual bool DoesPost();
+ virtual void ExecuteGet(Response* const response);
+ virtual void ExecutePost(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementSelectedCommand);
+};
+
+// Queries for an element's size.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/size
+class ElementSizeCommand : public WebElementCommand {
+ public:
+ ElementSizeCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementSizeCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementSizeCommand);
+};
+
+// Submit's the form containing the target element.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/submit
+class ElementSubmitCommand : public WebElementCommand {
+ public:
+ ElementSubmitCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementSubmitCommand();
+
+ virtual bool DoesPost();
+ virtual void ExecutePost(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementSubmitCommand);
+};
+
+// Toggle's whether an element is selected.
+// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/toggle
+class ElementToggleCommand : public WebElementCommand {
+ public:
+ ElementToggleCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~ElementToggleCommand();
+
+ virtual bool DoesPost();
+ virtual void ExecutePost(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ElementToggleCommand);
+};
+
// Sends keys to the specified web element. Also gets the value property of an
// element.
// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value
diff --git a/chrome/test/webdriver/server.cc b/chrome/test/webdriver/server.cc
index 274820a..9ec37be 100644
--- a/chrome/test/webdriver/server.cc
+++ b/chrome/test/webdriver/server.cc
@@ -16,17 +16,20 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/format_macros.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/scoped_ptr.h"
#include "base/string_split.h"
#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/webdriver/dispatch.h"
+#include "chrome/test/webdriver/error_codes.h"
#include "chrome/test/webdriver/session_manager.h"
#include "chrome/test/webdriver/utility_functions.h"
#include "chrome/test/webdriver/commands/cookie_commands.h"
@@ -71,11 +74,37 @@ void Shutdown(struct mg_connection* connection,
shutdown_event->Signal();
}
+void SendNotImplementedError(struct mg_connection* connection,
+ const struct mg_request_info* request_info,
+ void* user_data) {
+ // Send a well-formed WebDriver JSON error response to ensure clients
+ // handle it correctly.
+ std::string body = base::StringPrintf(
+ "{\"status\":%d,\"value\":{\"message\":"
+ "\"Command has not been implemented yet: %s %s\"}}",
+ kUnknownCommand, request_info->request_method, request_info->uri);
+
+ std::string header = base::StringPrintf(
+ "HTTP/1.1 501 Not Implemented\r\n"
+ "Content-Type:application/json\r\n"
+ "Content-Length:%" PRIuS "\r\n"
+ "\r\n", body.length());
+
+ LOG(ERROR) << header << body;
+ mg_write(connection, header.data(), header.length());
+ mg_write(connection, body.data(), body.length());
+}
+
+
template <typename CommandType>
void SetCallback(struct mg_context* ctx, const char* pattern) {
mg_set_uri_callback(ctx, pattern, &Dispatch<CommandType>, NULL);
}
+void SetNotImplemented(struct mg_context* ctx, const char* pattern) {
+ mg_set_uri_callback(ctx, pattern, &SendNotImplementedError, NULL);
+}
+
void InitCallbacks(struct mg_context* ctx,
base::WaitableEvent* shutdown_event) {
mg_set_uri_callback(ctx, "/shutdown", &Shutdown, shutdown_event);
@@ -102,10 +131,35 @@ void InitCallbacks(struct mg_context* ctx,
// WebElement commands
SetCallback<FindOneElementCommand>(ctx, "/session/*/element");
SetCallback<FindManyElementsCommand>(ctx, "/session/*/elements");
+ SetCallback<ActiveElementCommand>(ctx, "/session/*/element/active");
SetCallback<FindOneElementCommand>(ctx, "/session/*/element/*/element");
SetCallback<FindManyElementsCommand>(ctx, "/session/*/elements/*/elements");
- SetCallback<ElementValueCommand>(ctx, "/session/*/element/*/value");
+ SetCallback<ElementAttributeCommand>(ctx,
+ "/session/*/element/*/attribute/*");
+ SetCallback<ElementCssCommand>(ctx, "/session/*/element/*/css/*");
+ SetCallback<ElementClearCommand>(ctx, "/session/*/element/*/clear");
+ SetCallback<ElementDisplayedCommand>(ctx, "/session/*/element/*/displayed");
+ SetCallback<ElementEnabledCommand>(ctx, "/session/*/element/*/enabled");
+ SetCallback<ElementEqualsCommand>(ctx, "/session/*/element/*/equals/*");
+ SetCallback<ElementLocationCommand>(ctx, "/session/*/element/*/location");
+ SetCallback<ElementLocationInViewCommand>(ctx,
+ "/session/*/element/*/location_in_view");
+ SetCallback<ElementNameCommand>(ctx, "/session/*/element/*/name");
+ SetCallback<ElementSelectedCommand>(ctx, "/session/*/element/*/selected");
+ SetCallback<ElementSizeCommand>(ctx, "/session/*/element/*/size");
+ SetCallback<ElementSubmitCommand>(ctx, "/session/*/element/*/submit");
SetCallback<ElementTextCommand>(ctx, "/session/*/element/*/text");
+ SetCallback<ElementToggleCommand>(ctx, "/session/*/element/*/toggle");
+ SetCallback<ElementValueCommand>(ctx, "/session/*/element/*/value");
+
+ // Commands that have not been implemented yet. We list these out explicitly
+ // so that tests that attempt to use them fail with a meaningful error.
+ SetNotImplemented(ctx, "/session/*/element/*/click");
+ SetNotImplemented(ctx, "/session/*/element/*/drag");
+ SetNotImplemented(ctx, "/session/*/element/*/hover");
+ SetNotImplemented(ctx, "/session/*/execute_async");
+ SetNotImplemented(ctx, "/session/*/timeouts/async_script");
+ SetNotImplemented(ctx, "/session/*/screenshot");
// Since the /session/* is a wild card that would match the above URIs, this
// line MUST be the last registered URI with the server.