summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/chrome_tests.gypi6
-rw-r--r--chrome/test/chromedriver/basic_types.cc40
-rw-r--r--chrome/test/chromedriver/basic_types.h43
-rw-r--r--chrome/test/chromedriver/chromedriver.py22
-rw-r--r--chrome/test/chromedriver/command_executor_impl.cc36
-rw-r--r--chrome/test/chromedriver/commands.cc132
-rw-r--r--chrome/test/chromedriver/commands.h30
-rw-r--r--chrome/test/chromedriver/element_util.cc63
-rw-r--r--chrome/test/chromedriver/element_util.h43
-rwxr-xr-xchrome/test/chromedriver/run_py_tests.py64
-rw-r--r--chrome/test/chromedriver/session.cc5
-rw-r--r--chrome/test/chromedriver/session.h2
12 files changed, 391 insertions, 95 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 2b9d0e5..ee432f6 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -706,6 +706,8 @@
'<(INTERMEDIATE_DIR)/chrome/test/chromedriver/js.h',
'../third_party/webdriver/atoms.cc',
'../third_party/webdriver/atoms.h',
+ 'test/chromedriver/basic_types.cc',
+ 'test/chromedriver/basic_types.h',
'test/chromedriver/chrome.h',
'test/chromedriver/chrome_finder.cc',
'test/chromedriver/chrome_finder.h',
@@ -729,10 +731,10 @@
'test/chromedriver/devtools_client_impl.cc',
'test/chromedriver/devtools_client_impl.h',
'test/chromedriver/devtools_event_listener.h',
- 'test/chromedriver/dom_tracker.h',
'test/chromedriver/dom_tracker.cc',
- 'test/chromedriver/element_util.h',
+ 'test/chromedriver/dom_tracker.h',
'test/chromedriver/element_util.cc',
+ 'test/chromedriver/element_util.h',
'test/chromedriver/net/net_util.cc',
'test/chromedriver/net/net_util.h',
'test/chromedriver/net/sync_websocket.h',
diff --git a/chrome/test/chromedriver/basic_types.cc b/chrome/test/chromedriver/basic_types.cc
new file mode 100644
index 0000000..ef6b2f3
--- /dev/null
+++ b/chrome/test/chromedriver/basic_types.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/test/chromedriver/basic_types.h"
+
+WebPoint::WebPoint() : x(0), y(0) {}
+
+WebPoint::WebPoint(int x, int y) : x(x), y(y) {}
+
+WebPoint::~WebPoint() {}
+
+void WebPoint::offset(int x_, int y_) {
+ x += x_;
+ y += y_;
+}
+
+WebSize::WebSize() : width(0), height(0) {}
+
+WebSize::WebSize(int width, int height) : width(width), height(height) {}
+
+WebSize::~WebSize() {}
+
+WebRect::WebRect() : origin(0, 0), size(0, 0) {}
+
+WebRect::WebRect(int x, int y, int width, int height)
+ : origin(x, y), size(width, height) {}
+
+WebRect::WebRect(const WebPoint& origin, const WebSize& size)
+ : origin(origin), size(size) {}
+
+WebRect::~WebRect() {}
+
+int WebRect::x() { return origin.x; }
+
+int WebRect::y() { return origin.y; }
+
+int WebRect::width() { return size.width; }
+
+int WebRect::height() { return size.height; }
diff --git a/chrome/test/chromedriver/basic_types.h b/chrome/test/chromedriver/basic_types.h
new file mode 100644
index 0000000..8a623c4
--- /dev/null
+++ b/chrome/test/chromedriver/basic_types.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_TEST_CHROMEDRIVER_BASIC_TYPES_H_
+#define CHROME_TEST_CHROMEDRIVER_BASIC_TYPES_H_
+
+struct WebPoint {
+ WebPoint();
+ WebPoint(int x, int y);
+ ~WebPoint();
+
+ void offset(int x_, int y_);
+
+ int x;
+ int y;
+};
+
+struct WebSize {
+ WebSize();
+ WebSize(int width, int height);
+ ~WebSize();
+
+ int width;
+ int height;
+};
+
+struct WebRect {
+ WebRect();
+ WebRect(int x, int y, int width, int height);
+ WebRect(const WebPoint& origin, const WebSize& size);
+ ~WebRect();
+
+ int x();
+ int y();
+ int width();
+ int height();
+
+ WebPoint origin;
+ WebSize size;
+};
+
+#endif // CHROME_TEST_CHROMEDRIVER_BASIC_TYPES_H_
diff --git a/chrome/test/chromedriver/chromedriver.py b/chrome/test/chromedriver/chromedriver.py
index 8b3766b..c125d05 100644
--- a/chrome/test/chromedriver/chromedriver.py
+++ b/chrome/test/chromedriver/chromedriver.py
@@ -158,6 +158,28 @@ class ChromeDriver(object):
def Refresh(self):
return self.ExecuteSessionCommand('refresh')
+ def MouseMoveTo(self, element=None, x_offset=None, y_offset=None):
+ params = {}
+ if element is not None:
+ params['element'] = element._id
+ if x_offset is not None:
+ params['xoffset'] = x_offset
+ if y_offset is not None:
+ params['yoffset'] = y_offset
+ self.ExecuteSessionCommand('mouseMoveTo', params)
+
+ def MouseClick(self, button=0):
+ self.ExecuteSessionCommand('mouseClick', {'button': button})
+
+ def MouseButtonDown(self, button=0):
+ self.ExecuteSessionCommand('mouseButtonDown', {'button': button})
+
+ def MouseButtonUp(self, button=0):
+ self.ExecuteSessionCommand('mouseButtonUp', {'button': button})
+
+ def MouseDoubleClick(self, button=0):
+ self.ExecuteSessionCommand('mouseDoubleClick', {'button': button})
+
def Quit(self):
"""Quits the browser and ends the session."""
self.ExecuteSessionCommand('quit')
diff --git a/chrome/test/chromedriver/command_executor_impl.cc b/chrome/test/chromedriver/command_executor_impl.cc
index 82261a6..7858d99 100644
--- a/chrome/test/chromedriver/command_executor_impl.cc
+++ b/chrome/test/chromedriver/command_executor_impl.cc
@@ -96,6 +96,22 @@ void CommandExecutorImpl::Init() {
command_map_.Set(
CommandNames::kRefresh,
base::Bind(execute_session_command, base::Bind(&ExecuteRefresh)));
+ command_map_.Set(
+ CommandNames::kMouseMoveTo,
+ base::Bind(execute_session_command, base::Bind(&ExecuteMouseMoveTo)));
+ command_map_.Set(
+ CommandNames::kMouseClick,
+ base::Bind(execute_session_command, base::Bind(&ExecuteMouseClick)));
+ command_map_.Set(
+ CommandNames::kMouseButtonDown,
+ base::Bind(execute_session_command, base::Bind(&ExecuteMouseButtonDown)));
+ command_map_.Set(
+ CommandNames::kMouseButtonUp,
+ base::Bind(execute_session_command, base::Bind(&ExecuteMouseButtonUp)));
+ command_map_.Set(
+ CommandNames::kMouseDoubleClick,
+ base::Bind(execute_session_command,
+ base::Bind(&ExecuteMouseDoubleClick)));
Command quit_command = base::Bind(execute_session_command,
base::Bind(&ExecuteQuit, &session_map_));
command_map_.Set(CommandNames::kQuit, quit_command);
@@ -104,28 +120,28 @@ void CommandExecutorImpl::Init() {
command_map_.Set(
CommandNames::kFindChildElement,
base::Bind(execute_session_command,
- base::Bind(&ExecuteElementCommand,
- base::Bind(&ExecuteFindChildElement, 50))));
+ base::Bind(&ExecuteElementCommand,
+ base::Bind(&ExecuteFindChildElement, 50))));
command_map_.Set(
CommandNames::kFindChildElements,
base::Bind(execute_session_command,
- base::Bind(&ExecuteElementCommand,
- base::Bind(&ExecuteFindChildElements, 50))));
+ base::Bind(&ExecuteElementCommand,
+ base::Bind(&ExecuteFindChildElements, 50))));
command_map_.Set(
CommandNames::kHoverOverElement,
base::Bind(execute_session_command,
- base::Bind(&ExecuteElementCommand,
- base::Bind(&ExecuteHoverOverElement))));
+ base::Bind(&ExecuteElementCommand,
+ base::Bind(&ExecuteHoverOverElement))));
command_map_.Set(
CommandNames::kClickElement,
base::Bind(execute_session_command,
- base::Bind(&ExecuteElementCommand,
- base::Bind(&ExecuteClickElement))));
+ base::Bind(&ExecuteElementCommand,
+ base::Bind(&ExecuteClickElement))));
command_map_.Set(
CommandNames::kClearElement,
base::Bind(execute_session_command,
- base::Bind(&ExecuteElementCommand,
- base::Bind(&ExecuteClearElement))));
+ base::Bind(&ExecuteElementCommand,
+ base::Bind(&ExecuteClearElement))));
// Non-session commands.
command_map_.Set(CommandNames::kStatus, base::Bind(&ExecuteGetStatus));
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc
index c5e7956..35814b0 100644
--- a/chrome/test/chromedriver/commands.cc
+++ b/chrome/test/chromedriver/commands.cc
@@ -13,6 +13,7 @@
#include "base/stringprintf.h"
#include "base/sys_info.h"
#include "base/values.h"
+#include "chrome/test/chromedriver/basic_types.h"
#include "chrome/test/chromedriver/chrome.h"
#include "chrome/test/chromedriver/chrome_launcher.h"
#include "chrome/test/chromedriver/element_util.h"
@@ -55,6 +56,19 @@ Status CheckChromeVersion(Chrome* chrome, std::string* chrome_version) {
return Status(kOk);
}
+Status GetMouseButton(const base::DictionaryValue& params,
+ MouseButton* button) {
+ int button_num;
+ if (!params.GetInteger("button", &button_num)) {
+ button_num = 0; // Default to left mouse button.
+ } else if (button_num < 0 || button_num > 2) {
+ return Status(kUnknownError,
+ base::StringPrintf("invalid button: %d", button_num));
+ }
+ *button = static_cast<MouseButton>(button_num);
+ return Status(kOk);
+}
+
} // namespace
Status ExecuteGetStatus(
@@ -285,7 +299,10 @@ Status ExecuteHoverOverElement(
kMovedMouseEventType, kNoneMouseButton, location.x, location.y, 0);
std::list<MouseEvent> events;
events.push_back(move_event);
- return session->chrome->DispatchMouseEvents(events);
+ status = session->chrome->DispatchMouseEvents(events);
+ if (status.IsOk())
+ session->mouse_position = location;
+ return status;
}
Status ExecuteClickElement(
@@ -326,7 +343,10 @@ Status ExecuteClickElement(
events.push_back(
MouseEvent(kReleasedMouseEventType, kLeftMouseButton,
location.x, location.y, 1));
- return session->chrome->DispatchMouseEvents(events);
+ status = session->chrome->DispatchMouseEvents(events);
+ if (status.IsOk())
+ session->mouse_position = location;
+ return status;
}
}
@@ -396,3 +416,111 @@ Status ExecuteRefresh(
scoped_ptr<base::Value>* value) {
return session->chrome->Reload();
}
+
+Status ExecuteMouseMoveTo(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value) {
+ std::string element_id;
+ bool has_element = params.GetString("element", &element_id);
+ int x_offset = 0;
+ int y_offset = 0;
+ bool has_offset = params.GetInteger("xoffset", &x_offset) &&
+ params.GetInteger("yoffset", &y_offset);
+ if (!has_element && !has_offset)
+ return Status(kUnknownError, "at least an element or offset should be set");
+
+ WebPoint location;
+ if (has_element) {
+ Status status = ScrollElementIntoView(session, element_id, &location);
+ if (status.IsError())
+ return status;
+ } else {
+ location = session->mouse_position;
+ }
+
+ if (has_offset) {
+ location.offset(x_offset, y_offset);
+ } else {
+ WebSize size;
+ Status status = GetElementSize(session, element_id, &size);
+ if (status.IsError())
+ return status;
+ location.offset(size.width / 2, size.height / 2);
+ }
+
+ std::list<MouseEvent> events;
+ events.push_back(
+ MouseEvent(kMovedMouseEventType, kNoneMouseButton,
+ location.x, location.y, 0));
+ Status status = session->chrome->DispatchMouseEvents(events);
+ if (status.IsOk())
+ session->mouse_position = location;
+ return status;
+}
+
+Status ExecuteMouseClick(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value) {
+ MouseButton button;
+ Status status = GetMouseButton(params, &button);
+ if (status.IsError())
+ return status;
+ std::list<MouseEvent> events;
+ events.push_back(
+ MouseEvent(kPressedMouseEventType, button,
+ session->mouse_position.x, session->mouse_position.y, 1));
+ events.push_back(
+ MouseEvent(kReleasedMouseEventType, button,
+ session->mouse_position.x, session->mouse_position.y, 1));
+ return session->chrome->DispatchMouseEvents(events);
+}
+
+Status ExecuteMouseButtonDown(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value) {
+ MouseButton button;
+ Status status = GetMouseButton(params, &button);
+ if (status.IsError())
+ return status;
+ std::list<MouseEvent> events;
+ events.push_back(
+ MouseEvent(kPressedMouseEventType, button,
+ session->mouse_position.x, session->mouse_position.y, 1));
+ return session->chrome->DispatchMouseEvents(events);
+}
+
+Status ExecuteMouseButtonUp(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value) {
+ MouseButton button;
+ Status status = GetMouseButton(params, &button);
+ if (status.IsError())
+ return status;
+ std::list<MouseEvent> events;
+ events.push_back(
+ MouseEvent(kReleasedMouseEventType, button,
+ session->mouse_position.x, session->mouse_position.y, 1));
+ return session->chrome->DispatchMouseEvents(events);
+}
+
+Status ExecuteMouseDoubleClick(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value) {
+ MouseButton button;
+ Status status = GetMouseButton(params, &button);
+ if (status.IsError())
+ return status;
+ std::list<MouseEvent> events;
+ events.push_back(
+ MouseEvent(kPressedMouseEventType, button,
+ session->mouse_position.x, session->mouse_position.y, 2));
+ events.push_back(
+ MouseEvent(kReleasedMouseEventType, button,
+ session->mouse_position.x, session->mouse_position.y, 2));
+ return session->chrome->DispatchMouseEvents(events);
+}
diff --git a/chrome/test/chromedriver/commands.h b/chrome/test/chromedriver/commands.h
index dc12c0e..30fffb5 100644
--- a/chrome/test/chromedriver/commands.h
+++ b/chrome/test/chromedriver/commands.h
@@ -159,4 +159,34 @@ Status ExecuteRefresh(
const base::DictionaryValue& params,
scoped_ptr<base::Value>* value);
+// Move the mouse by an offset of the specificed element.
+Status ExecuteMouseMoveTo(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value);
+
+// Click a mouse button at the coordinates set by the last moveto.
+Status ExecuteMouseClick(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value);
+
+// Click and hold a mouse button at the coordinates set by the last moveto.
+Status ExecuteMouseButtonDown(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value);
+
+// Releases the mouse button previously held (where the mouse is currently at).
+Status ExecuteMouseButtonUp(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value);
+
+// Double-clicks at the current mouse coordinates (set by last moveto).
+Status ExecuteMouseDoubleClick(
+ Session* session,
+ const base::DictionaryValue& params,
+ scoped_ptr<base::Value>* value);
+
#endif // CHROME_TEST_CHROMEDRIVER_COMMANDS_H_
diff --git a/chrome/test/chromedriver/element_util.cc b/chrome/test/chromedriver/element_util.cc
index 0437419..fc911a9 100644
--- a/chrome/test/chromedriver/element_util.cc
+++ b/chrome/test/chromedriver/element_util.cc
@@ -7,6 +7,7 @@
#include "base/threading/platform_thread.h"
#include "base/time.h"
#include "base/values.h"
+#include "chrome/test/chromedriver/basic_types.h"
#include "chrome/test/chromedriver/chrome.h"
#include "chrome/test/chromedriver/js.h"
#include "chrome/test/chromedriver/session.h"
@@ -30,7 +31,7 @@ bool ParseFromValue(base::Value* value, WebPoint* point) {
return true;
}
-base::Value* CreateValueFrom(WebPoint* point) {
+base::Value* CreateValueFrom(const WebPoint* point) {
base::DictionaryValue* dict = new base::DictionaryValue();
dict->SetInteger("x", point->x);
dict->SetInteger("y", point->y);
@@ -50,7 +51,7 @@ bool ParseFromValue(base::Value* value, WebSize* size) {
return true;
}
-base::Value* CreateValueFrom(WebSize* size) {
+base::Value* CreateValueFrom(const WebSize* size) {
base::DictionaryValue* dict = new base::DictionaryValue();
dict->SetInteger("width", size->width);
dict->SetInteger("height", size->height);
@@ -74,7 +75,7 @@ bool ParseFromValue(base::Value* value, WebRect* rect) {
return true;
}
-base::Value* CreateValueFrom(WebRect* rect) {
+base::Value* CreateValueFrom(const WebRect* rect) {
base::DictionaryValue* dict = new base::DictionaryValue();
dict->SetInteger("left", rect->origin.x);
dict->SetInteger("top", rect->origin.y);
@@ -95,42 +96,6 @@ Status CallAtomsJs(
} // namespace
-
-WebPoint::WebPoint() : x(0), y(0) {}
-
-WebPoint::WebPoint(int x, int y) : x(x), y(y) {}
-
-WebPoint::~WebPoint() {}
-
-void WebPoint::offset(int x_, int y_) {
- x += x_;
- y += y_;
-}
-
-WebSize::WebSize() : width(0), height(0) {}
-
-WebSize::WebSize(int width, int height) : width(width), height(height) {}
-
-WebSize::~WebSize() {}
-
-WebRect::WebRect() : origin(0, 0), size(0, 0) {}
-
-WebRect::WebRect(int x, int y, int width, int height)
- : origin(x, y), size(width, height) {}
-
-WebRect::WebRect(const WebPoint& origin, const WebSize& size)
- : origin(origin), size(size) {}
-
-WebRect::~WebRect() {}
-
-int WebRect::x() { return origin.x; }
-
-int WebRect::y() { return origin.y; }
-
-int WebRect::width() { return size.width; }
-
-int WebRect::height() { return size.height; }
-
base::DictionaryValue* CreateElement(const std::string& id) {
base::DictionaryValue* element = new base::DictionaryValue();
element->SetString(kElementKey, id);
@@ -223,7 +188,7 @@ Status GetElementClickableLocation(
return Status(kElementNotVisible);
status = ScrollElementRegionIntoView(
- session, element_id, &rect, true, location);
+ session, element_id, rect, true, location);
if (status.IsError())
return status;
location->offset(rect.width() / 2, rect.height() / 2);
@@ -384,17 +349,29 @@ Status ToggleOptionElement(
return SetOptionElementSelected(session, id, !is_selected);
}
+Status ScrollElementIntoView(
+ Session* session,
+ const std::string& id,
+ WebPoint* location) {
+ WebSize size;
+ Status status = GetElementSize(session, id, &size);
+ if (status.IsError())
+ return status;
+ return ScrollElementRegionIntoView(
+ session, id, WebRect(WebPoint(0, 0), size), false, location);
+}
+
Status ScrollElementRegionIntoView(
Session* session,
const std::string& id,
- WebRect* region,
+ const WebRect& region,
bool center,
WebPoint* location) {
- WebPoint region_offset = region->origin;
+ WebPoint region_offset = region.origin;
base::ListValue args;
args.Append(CreateElement(id));
args.AppendBoolean(center);
- args.Append(CreateValueFrom(region));
+ args.Append(CreateValueFrom(&region));
scoped_ptr<base::Value> result;
// TODO(chrisgao): Nested frame. See http://crbug.com/170998.
diff --git a/chrome/test/chromedriver/element_util.h b/chrome/test/chromedriver/element_util.h
index ad893e0..e0c1357 100644
--- a/chrome/test/chromedriver/element_util.h
+++ b/chrome/test/chromedriver/element_util.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/scoped_ptr.h"
+#include "chrome/test/chromedriver/basic_types.h"
namespace base {
class DictionaryValue;
@@ -18,41 +19,6 @@ class Value;
struct Session;
class Status;
-struct WebPoint {
- WebPoint();
- WebPoint(int x, int y);
- ~WebPoint();
-
- void offset(int x_, int y_);
-
- int x;
- int y;
-};
-
-struct WebSize {
- WebSize();
- WebSize(int width, int height);
- ~WebSize();
-
- int width;
- int height;
-};
-
-struct WebRect {
- WebRect();
- WebRect(int x, int y, int width, int height);
- WebRect(const WebPoint& origin, const WebSize& size);
- ~WebRect();
-
- int x();
- int y();
- int width();
- int height();
-
- WebPoint origin;
- WebSize size;
-};
-
base::DictionaryValue* CreateElement(const std::string& id);
// |id| could be null when no root element is given.
@@ -118,10 +84,15 @@ Status ToggleOptionElement(
Session* session,
const std::string& id);
+Status ScrollElementIntoView(
+ Session* session,
+ const std::string& id,
+ WebPoint* location);
+
Status ScrollElementRegionIntoView(
Session* session,
const std::string& id,
- WebRect* region,
+ const WebRect& region,
bool center,
WebPoint* location);
diff --git a/chrome/test/chromedriver/run_py_tests.py b/chrome/test/chromedriver/run_py_tests.py
index 74124a6..442e8e4 100755
--- a/chrome/test/chromedriver/run_py_tests.py
+++ b/chrome/test/chromedriver/run_py_tests.py
@@ -167,6 +167,70 @@ class ChromeDriverTest(unittest.TestCase):
self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
self._driver.Refresh()
+ def testMouseMoveTo(self):
+ div = self._driver.ExecuteScript(
+ 'document.body.innerHTML = "<div>old</div>";'
+ 'var div = document.getElementsByTagName("div")[0];'
+ 'div.style["width"] = "100px";'
+ 'div.style["height"] = "100px";'
+ 'div.addEventListener("mouseover", function() {'
+ ' var div = document.getElementsByTagName("div")[0];'
+ ' div.innerHTML="new<br>";'
+ '});'
+ 'return div;')
+ self._driver.MouseMoveTo(div, 10, 10)
+ self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
+
+ def testMouseClick(self):
+ div = self._driver.ExecuteScript(
+ 'document.body.innerHTML = "<div>old</div>";'
+ 'var div = document.getElementsByTagName("div")[0];'
+ 'div.style["width"] = "100px";'
+ 'div.style["height"] = "100px";'
+ 'div.addEventListener("click", function() {'
+ ' var div = document.getElementsByTagName("div")[0];'
+ ' div.innerHTML="new<br>";'
+ '});'
+ 'return div;')
+ self._driver.MouseMoveTo(div)
+ self._driver.MouseClick()
+ self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
+
+ def testMouseButtonDownAndUp(self):
+ self._driver.ExecuteScript(
+ 'document.body.innerHTML = "<div>old</div>";'
+ 'var div = document.getElementsByTagName("div")[0];'
+ 'div.style["width"] = "100px";'
+ 'div.style["height"] = "100px";'
+ 'div.addEventListener("mousedown", function() {'
+ ' var div = document.getElementsByTagName("div")[0];'
+ ' div.innerHTML="new1<br>";'
+ '});'
+ 'div.addEventListener("mouseup", function() {'
+ ' var div = document.getElementsByTagName("div")[0];'
+ ' div.innerHTML="new2<a></a>";'
+ '});')
+ self._driver.MouseMoveTo(None, 50, 50);
+ self._driver.MouseButtonDown();
+ self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
+ self._driver.MouseButtonUp();
+ self.assertEquals(1, len(self._driver.FindElements('tag name', 'a')))
+
+ def testMouseDoubleClick(self):
+ div = self._driver.ExecuteScript(
+ 'document.body.innerHTML = "<div>old</div>";'
+ 'var div = document.getElementsByTagName("div")[0];'
+ 'div.style["width"] = "100px";'
+ 'div.style["height"] = "100px";'
+ 'div.addEventListener("dblclick", function() {'
+ ' var div = document.getElementsByTagName("div")[0];'
+ ' div.innerHTML="new<br>";'
+ '});'
+ 'return div;')
+ self._driver.MouseMoveTo(div, 1, 1);
+ self._driver.MouseDoubleClick();
+ self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
+
if __name__ == '__main__':
parser = optparse.OptionParser()
parser.add_option(
diff --git a/chrome/test/chromedriver/session.cc b/chrome/test/chromedriver/session.cc
index 944574f..5313e51 100644
--- a/chrome/test/chromedriver/session.cc
+++ b/chrome/test/chromedriver/session.cc
@@ -7,10 +7,11 @@
#include "chrome/test/chromedriver/chrome.h"
Session::Session(const std::string& id)
- : id(id), implicit_wait(0), page_load_timeout(0), script_timeout(0) {}
+ : id(id), mouse_position(0, 0), implicit_wait(0), page_load_timeout(0),
+ script_timeout(0) {}
Session::Session(const std::string& id, scoped_ptr<Chrome> chrome)
- : id(id), chrome(chrome.Pass()), implicit_wait(0),
+ : id(id), chrome(chrome.Pass()), mouse_position(0, 0), implicit_wait(0),
page_load_timeout(0), script_timeout(0) {}
Session::~Session() {}
diff --git a/chrome/test/chromedriver/session.h b/chrome/test/chromedriver/session.h
index fdebfdd..1733641 100644
--- a/chrome/test/chromedriver/session.h
+++ b/chrome/test/chromedriver/session.h
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
+#include "chrome/test/chromedriver/basic_types.h"
class Chrome;
@@ -22,6 +23,7 @@ struct Session {
const std::string id;
scoped_ptr<Chrome> chrome;
std::string frame;
+ WebPoint mouse_position;
int implicit_wait;
int page_load_timeout;
int script_timeout;