diff --git a/lib/capybara/webkit/node.rb b/lib/capybara/webkit/node.rb index 4dbf2f0..d30b5f2 100644 --- a/lib/capybara/webkit/node.rb +++ b/lib/capybara/webkit/node.rb @@ -56,7 +56,15 @@ module Capybara::Webkit end def click - invoke("click") + invoke("leftClick") + end + + def double_click + invoke("doubleClick") + end + + def right_click + invoke("rightClick") end def drag_to(element) diff --git a/spec/driver_spec.rb b/spec/driver_spec.rb index df07ec0..395bdc0 100644 --- a/spec/driver_spec.rb +++ b/spec/driver_spec.rb @@ -991,9 +991,12 @@ describe Capybara::Webkit::Driver do @@ -1011,9 +1016,23 @@ describe Capybara::Webkit::Driver do before { visit("/") } + let(:watch) { driver.find_xpath("//a").first } + let(:fired_events) { driver.find_xpath("//li").map(&:visible_text) } + it "triggers mouse events" do - driver.find_xpath("//a").first.click - driver.find_xpath("//li").map(&:visible_text).should == %w(mousedown mouseup click) + watch.click + fired_events.should == %w(mousedown mouseup click) + end + + it "triggers double click" do + # check event order at http://www.quirksmode.org/dom/events/click.html + watch.double_click + fired_events.should == %w(mousedown mouseup click mousedown mouseup click dblclick) + end + + it "triggers right click" do + watch.right_click + fired_events.should == %w(contextmenu) end end diff --git a/src/JavascriptInvocation.cpp b/src/JavascriptInvocation.cpp index 1ddd307..430404f 100644 --- a/src/JavascriptInvocation.cpp +++ b/src/JavascriptInvocation.cpp @@ -2,6 +2,7 @@ #include "WebPage.h" #include "InvocationResult.h" #include +#include JavascriptInvocation::JavascriptInvocation(const QString &functionName, const QStringList &arguments, WebPage *page, QObject *parent) : QObject(parent) { m_functionName = functionName; @@ -34,16 +35,30 @@ InvocationResult JavascriptInvocation::invoke(QWebFrame *frame) { return InvocationResult(result); } -void JavascriptInvocation::click(int x, int y) { +void JavascriptInvocation::leftClick(int x, int y) { QPoint mousePos(x, y); - QMouseEvent event(QEvent::MouseMove, mousePos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); - QApplication::sendEvent(m_page, &event); + JavascriptInvocation::mouseEvent(QEvent::MouseMove, mousePos, Qt::NoButton); + JavascriptInvocation::mouseEvent(QEvent::MouseButtonPress, mousePos, Qt::LeftButton); + JavascriptInvocation::mouseEvent(QEvent::MouseButtonRelease, mousePos, Qt::LeftButton); +} - event = QMouseEvent(QEvent::MouseButtonPress, mousePos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - QApplication::sendEvent(m_page, &event); +void JavascriptInvocation::rightClick(int x, int y) { + QPoint mousePos(x, y); - event = QMouseEvent(QEvent::MouseButtonRelease, mousePos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + JavascriptInvocation::mouseEvent(QEvent::MouseMove, mousePos, Qt::NoButton); + JavascriptInvocation::mouseEvent(QEvent::MouseButtonPress, mousePos, Qt::RightButton); +} + +void JavascriptInvocation::doubleClick(int x, int y) { + QPoint mousePos(x, y); + + JavascriptInvocation::mouseEvent(QEvent::MouseButtonDblClick, mousePos, Qt::LeftButton); + JavascriptInvocation::mouseEvent(QEvent::MouseButtonRelease, mousePos, Qt::LeftButton); +} + +void JavascriptInvocation::mouseEvent(QEvent::Type type, const QPoint &position, Qt::MouseButton button) { + QMouseEvent event(type, position, button, button, Qt::NoModifier); QApplication::sendEvent(m_page, &event); } diff --git a/src/JavascriptInvocation.h b/src/JavascriptInvocation.h index 5a091c4..c4e11db 100644 --- a/src/JavascriptInvocation.h +++ b/src/JavascriptInvocation.h @@ -1,6 +1,7 @@ #include #include #include +#include #include class WebPage; @@ -16,7 +17,9 @@ class JavascriptInvocation : public QObject { JavascriptInvocation(const QString &functionName, const QStringList &arguments, WebPage *page, QObject *parent = 0); QString &functionName(); QStringList &arguments(); - Q_INVOKABLE void click(int x, int y); + Q_INVOKABLE void leftClick(int x, int y); + Q_INVOKABLE void rightClick(int x, int y); + Q_INVOKABLE void doubleClick(int x, int y); Q_INVOKABLE bool clickTest(QWebElement element, int absoluteX, int absoluteY); Q_INVOKABLE QVariantMap clickPosition(QWebElement element, int left, int top, int width, int height); QVariant getError(); @@ -28,5 +31,6 @@ class JavascriptInvocation : public QObject { QStringList m_arguments; WebPage *m_page; QVariant m_error; + void mouseEvent(QEvent::Type type, const QPoint & position, Qt::MouseButton button); }; diff --git a/src/capybara.js b/src/capybara.js index e6e48ec..1ea7353 100644 --- a/src/capybara.js +++ b/src/capybara.js @@ -151,18 +151,31 @@ Capybara = { return CapybaraInvocation.clickPosition(node, rect.left, rect.top, rect.width, rect.height); }, - click: function (index) { + click: function (index, action) { var node = this.nodes[index]; node.scrollIntoViewIfNeeded(); var pos = this.clickPosition(node); if (pos && this.clickTest(node, pos)) - CapybaraInvocation.click(pos.absoluteX, pos.absoluteY); + action(pos.absoluteX, pos.absoluteY); else throw new Capybara.ClickFailed(this.path(index), pos); }, + leftClick: function (index) { + this.click(index, CapybaraInvocation.leftClick); + }, + + doubleClick: function(index) { + this.click(index, CapybaraInvocation.leftClick); + this.click(index, CapybaraInvocation.doubleClick); + }, + + rightClick: function(index) { + this.click(index, CapybaraInvocation.rightClick); + }, + trigger: function (index, eventName) { var eventObject = document.createEvent("HTMLEvents"); eventObject.initEvent(eventName, true, true); @@ -294,12 +307,12 @@ Capybara = { } else if (type === "checkbox" || type === "radio") { if (node.checked != (value === "true")) { - this.click(index); + this.leftClick(index); } } else if (type === "file") { this.attachedFiles = Array.prototype.slice.call(arguments, 1); - this.click(index); + this.leftClick(index); } else { node.value = value;