From 2c47aea29fe612eef4876e5c5fd6a09efb5e0305 Mon Sep 17 00:00:00 2001 From: Matthew Horan Date: Sun, 13 Jan 2013 09:13:57 -0500 Subject: [PATCH] Raise error when iframe elements are unclickable --- spec/integration/session_spec.rb | 22 ++++++++++++++++++++++ src/JavascriptInvocation.cpp | 20 +++++++++++++------- src/JavascriptInvocation.h | 3 ++- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/spec/integration/session_spec.rb b/spec/integration/session_spec.rb index fd7bf4d..ba66ee5 100644 --- a/spec/integration/session_spec.rb +++ b/spec/integration/session_spec.rb @@ -293,6 +293,28 @@ describe Capybara::Session do end end end + + it 'raises an error if an element is obscured when clicked' do + subject.visit('/') + + subject.execute_script(<<-JS) + var div = document.createElement('div'); + div.style.position = 'absolute'; + div.style.left = '0px'; + div.style.top = '0px'; + div.style.width = '100%'; + div.style.height = '100%'; + document.body.appendChild(div); + JS + + subject.within_frame('a_frame') do + subject.within_frame('b_frame') do + lambda { + subject.click_button 'B Button' + }.should raise_error(Capybara::Webkit::ClickFailed) + end + end + end end context 'click tests' do diff --git a/src/JavascriptInvocation.cpp b/src/JavascriptInvocation.cpp index b78ab7c..7764036 100644 --- a/src/JavascriptInvocation.cpp +++ b/src/JavascriptInvocation.cpp @@ -16,20 +16,26 @@ QStringList &JavascriptInvocation::arguments() { return m_arguments; } -bool JavascriptInvocation::click(const QWebElement &element, int left, int top, int width, int height) { +bool JavascriptInvocation::click(QWebElement element, int left, int top, int width, int height) { QRect elementBox(left, top, width, height); + QRect viewport(QPoint(0, 0), m_page->viewportSize()); + QRect boundedBox = elementBox.intersected(viewport); + QPoint mousePos = boundedBox.center(); + + QString script = QString("Capybara.clickTest(this, %1, %2);").arg(mousePos.x()).arg(mousePos.y()); + bool ok = element.evaluateJavaScript(script).toBool(); + QWebFrame *parent = element.webFrame(); while (parent) { elementBox.translate(parent->geometry().topLeft()); parent = parent->parentFrame(); } - QRect viewport(QPoint(0, 0), m_page->viewportSize()); - QRect boundedBox = elementBox.intersected(viewport); - QPoint mousePos = boundedBox.center(); - QRect r = QRect(QPoint(left, top), boundedBox.size()); - QPoint p = r.center(); - bool ok = QWebElement(element).evaluateJavaScript(QString("Capybara.clickTest(this, %1, %2);").arg(p.x()).arg(p.y())).toBool(); + boundedBox = elementBox.intersected(viewport); + mousePos = boundedBox.center(); + + QWebHitTestResult res = m_page->mainFrame()->hitTestContent(mousePos); + ok = ok && res.frame() == element.webFrame(); if (ok) { execClick(mousePos); diff --git a/src/JavascriptInvocation.h b/src/JavascriptInvocation.h index e36f928..8cb3ca0 100644 --- a/src/JavascriptInvocation.h +++ b/src/JavascriptInvocation.h @@ -14,12 +14,13 @@ class JavascriptInvocation : public QObject { JavascriptInvocation(const QString &functionName, const QStringList &arguments, WebPage *page, QObject *parent = 0); QString &functionName(); QStringList &arguments(); - Q_INVOKABLE bool click(const QWebElement &element, int left, int top, int width, int height); + Q_INVOKABLE bool click(QWebElement element, int left, int top, int width, int height); private: QString m_functionName; QStringList m_arguments; WebPage *m_page; void execClick(QPoint mousePos); + };