capybara-webkit 0.14.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. data/.gitignore +2 -0
  2. data/.travis.yml +21 -0
  3. data/Appraisals +4 -4
  4. data/CONTRIBUTING.md +14 -3
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +27 -19
  7. data/NEWS.md +15 -0
  8. data/README.md +126 -76
  9. data/Vagrantfile +7 -0
  10. data/capybara-webkit.gemspec +3 -0
  11. data/gemfiles/2.0.gemfile +7 -0
  12. data/gemfiles/2.0.gemfile.lock +72 -0
  13. data/gemfiles/2.1.gemfile +7 -0
  14. data/gemfiles/2.1.gemfile.lock +71 -0
  15. data/lib/capybara/webkit/browser.rb +22 -22
  16. data/lib/capybara/webkit/connection.rb +9 -6
  17. data/lib/capybara/webkit/driver.rb +22 -6
  18. data/lib/capybara/webkit/errors.rb +25 -0
  19. data/lib/capybara/webkit/node.rb +36 -10
  20. data/lib/capybara/webkit/version.rb +1 -1
  21. data/spec/browser_spec.rb +16 -1
  22. data/spec/capybara_webkit_builder_spec.rb +9 -3
  23. data/spec/connection_spec.rb +19 -3
  24. data/spec/driver_spec.rb +324 -144
  25. data/spec/errors_spec.rb +11 -0
  26. data/spec/integration/session_spec.rb +244 -0
  27. data/spec/selenium_compatibility_spec.rb +3 -1
  28. data/spec/spec_helper.rb +1 -9
  29. data/src/Authenticate.cpp +3 -2
  30. data/src/ClearCookies.cpp +1 -1
  31. data/src/ClearPromptText.cpp +1 -1
  32. data/src/Command.cpp +8 -4
  33. data/src/Command.h +7 -4
  34. data/src/CommandFactory.cpp +4 -2
  35. data/src/CommandParser.cpp +1 -1
  36. data/src/Connection.cpp +4 -4
  37. data/src/ConsoleMessages.cpp +1 -1
  38. data/src/CurrentUrl.cpp +2 -2
  39. data/src/EnableLogging.cpp +1 -1
  40. data/src/ErrorMessage.cpp +26 -0
  41. data/src/ErrorMessage.h +21 -0
  42. data/src/Evaluate.cpp +1 -1
  43. data/src/Execute.cpp +3 -2
  44. data/src/FindCss.cpp +13 -0
  45. data/src/FindCss.h +11 -0
  46. data/src/FindXpath.cpp +13 -0
  47. data/src/FindXpath.h +11 -0
  48. data/src/FrameFocus.cpp +4 -3
  49. data/src/GetCookies.cpp +1 -1
  50. data/src/GetTimeout.cpp +1 -1
  51. data/src/GetWindowHandle.cpp +1 -1
  52. data/src/GetWindowHandles.cpp +1 -1
  53. data/src/Header.cpp +2 -2
  54. data/src/Headers.cpp +1 -6
  55. data/src/IgnoreSslErrors.cpp +1 -1
  56. data/src/InvocationResult.cpp +29 -0
  57. data/src/InvocationResult.h +16 -0
  58. data/src/JavascriptAlertMessages.cpp +1 -1
  59. data/src/JavascriptCommand.cpp +15 -0
  60. data/src/JavascriptCommand.h +20 -0
  61. data/src/JavascriptConfirmMessages.cpp +1 -1
  62. data/src/JavascriptInvocation.cpp +128 -1
  63. data/src/JavascriptInvocation.h +22 -1
  64. data/src/JavascriptPromptMessages.cpp +1 -1
  65. data/src/NetworkAccessManager.cpp +8 -16
  66. data/src/NetworkAccessManager.h +5 -11
  67. data/src/NetworkReplyProxy.cpp +91 -0
  68. data/src/NetworkReplyProxy.h +65 -0
  69. data/src/Node.cpp +4 -4
  70. data/src/Node.h +2 -2
  71. data/src/NullCommand.cpp +2 -1
  72. data/src/PageLoadingCommand.cpp +2 -1
  73. data/src/Render.cpp +1 -1
  74. data/src/Reset.cpp +1 -1
  75. data/src/ResizeWindow.cpp +1 -1
  76. data/src/Response.cpp +7 -0
  77. data/src/Response.h +8 -3
  78. data/src/SetConfirmAction.cpp +1 -1
  79. data/src/SetCookie.cpp +2 -2
  80. data/src/SetPromptAction.cpp +1 -1
  81. data/src/SetPromptText.cpp +1 -1
  82. data/src/SetProxy.cpp +2 -2
  83. data/src/SetSkipImageLoading.cpp +1 -1
  84. data/src/SetTimeout.cpp +3 -2
  85. data/src/SetUrlBlacklist.cpp +2 -2
  86. data/src/Status.cpp +1 -1
  87. data/src/TimeoutCommand.cpp +4 -2
  88. data/src/Title.cpp +11 -0
  89. data/src/Title.h +9 -0
  90. data/src/Version.cpp +13 -0
  91. data/src/Version.h +10 -0
  92. data/src/Visit.cpp +1 -1
  93. data/src/WebPage.cpp +49 -27
  94. data/src/WebPage.h +14 -7
  95. data/src/WebPageManager.cpp +10 -1
  96. data/src/WebPageManager.h +4 -1
  97. data/src/WindowFocus.cpp +3 -2
  98. data/src/body.cpp +3 -6
  99. data/src/capybara.js +103 -101
  100. data/src/find_command.h +4 -2
  101. data/src/main.cpp +1 -1
  102. data/src/stable.h +39 -0
  103. data/src/webkit_server.pro +26 -6
  104. data/vagrant_setup.sh +58 -0
  105. metadata +51 -78
  106. data/gemfiles/1.0.gemfile +0 -7
  107. data/gemfiles/1.0.gemfile.lock +0 -70
  108. data/gemfiles/1.1.gemfile +0 -7
  109. data/gemfiles/1.1.gemfile.lock +0 -70
  110. data/src/Find.cpp +0 -20
  111. data/src/Find.h +0 -11
data/src/Connection.cpp CHANGED
@@ -6,6 +6,7 @@
6
6
  #include "PageLoadingCommand.h"
7
7
  #include "TimeoutCommand.h"
8
8
  #include "SocketCommand.h"
9
+ #include "ErrorMessage.h"
9
10
 
10
11
  #include <QTcpSocket>
11
12
 
@@ -43,9 +44,8 @@ void Connection::pendingLoadFinished(bool success) {
43
44
  void Connection::writePageLoadFailure() {
44
45
  m_pageSuccess = true;
45
46
  QString message = currentPage()->failureString();
46
- Response *response = new Response(false, message, this);
47
- writeResponse(response);
48
- delete response;
47
+ Response response(false, new ErrorMessage(message));
48
+ writeResponse(&response);
49
49
  }
50
50
 
51
51
  void Connection::finishCommand(Response *response) {
@@ -64,7 +64,7 @@ void Connection::writeResponse(Response *response) {
64
64
 
65
65
  QByteArray messageUtf8 = response->message();
66
66
  QString messageLength = QString::number(messageUtf8.size()) + "\n";
67
- m_socket->write(messageLength.toAscii());
67
+ m_socket->write(messageLength.toLatin1());
68
68
  m_socket->write(messageUtf8);
69
69
  }
70
70
 
@@ -9,6 +9,6 @@ ConsoleMessages::ConsoleMessages(WebPageManager *manager, QStringList &arguments
9
9
  void ConsoleMessages::start() {
10
10
  JsonSerializer serializer;
11
11
  QByteArray json = serializer.serialize(page()->consoleMessages());
12
- emitFinished(true, json);
12
+ finish(true, json);
13
13
  }
14
14
 
data/src/CurrentUrl.cpp CHANGED
@@ -7,8 +7,8 @@ CurrentUrl::CurrentUrl(WebPageManager *manager, QStringList &arguments, QObject
7
7
 
8
8
  void CurrentUrl::start() {
9
9
  QStringList arguments;
10
- QVariant result = page()->invokeCapybaraFunction("currentUrl", arguments);
10
+ QVariant result = page()->currentFrame()->evaluateJavaScript("window.location.toString()");
11
11
  QString url = result.toString();
12
- emitFinished(true, url);
12
+ finish(true, url);
13
13
  }
14
14
 
@@ -6,5 +6,5 @@ EnableLogging::EnableLogging(WebPageManager *manager, QStringList &arguments, QO
6
6
 
7
7
  void EnableLogging::start() {
8
8
  manager()->enableLogging();
9
- emitFinished(true);
9
+ finish(true);
10
10
  }
@@ -0,0 +1,26 @@
1
+ #include "ErrorMessage.h"
2
+ #include "JsonSerializer.h"
3
+
4
+ ErrorMessage::ErrorMessage(QString message, QObject *parent) : QObject(parent) {
5
+ m_message = message;
6
+ }
7
+
8
+ ErrorMessage::ErrorMessage(QString type, QString message, QObject *parent) : QObject(parent) {
9
+ m_type = type;
10
+ m_message = message;
11
+ }
12
+
13
+ QByteArray ErrorMessage::toString() {
14
+ JsonSerializer serializer;
15
+
16
+ QVariantMap map;
17
+
18
+ if (m_type.isNull())
19
+ map["class"] = "InvalidResponseError";
20
+ else
21
+ map["class"] = m_type;
22
+
23
+ map["message"] = m_message;
24
+
25
+ return serializer.serialize(map);
26
+ }
@@ -0,0 +1,21 @@
1
+ #ifndef __ERROR_MESSAGE_H
2
+ #define __ERROR_MESSAGE_H
3
+
4
+ #include <QObject>
5
+ #include <QString>
6
+ #include <QByteArray>
7
+
8
+ class ErrorMessage : public QObject {
9
+ Q_OBJECT
10
+
11
+ public:
12
+ ErrorMessage(QString message, QObject *parent = 0);
13
+ ErrorMessage(QString type, QString message, QObject *parent = 0);
14
+ QByteArray toString();
15
+
16
+ private:
17
+ QString m_type;
18
+ QString m_message;
19
+ };
20
+
21
+ #endif
data/src/Evaluate.cpp CHANGED
@@ -10,5 +10,5 @@ Evaluate::Evaluate(WebPageManager *manager, QStringList &arguments, QObject *par
10
10
  void Evaluate::start() {
11
11
  QVariant result = page()->currentFrame()->evaluateJavaScript(arguments()[0]);
12
12
  JsonSerializer serializer;
13
- emitFinished(true, serializer.serialize(result));
13
+ finish(true, serializer.serialize(result));
14
14
  }
data/src/Execute.cpp CHANGED
@@ -1,6 +1,7 @@
1
1
  #include "Execute.h"
2
2
  #include "WebPage.h"
3
3
  #include "WebPageManager.h"
4
+ #include "ErrorMessage.h"
4
5
 
5
6
  Execute::Execute(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
6
7
  }
@@ -9,9 +10,9 @@ void Execute::start() {
9
10
  QString script = arguments()[0] + QString("; 'success'");
10
11
  QVariant result = page()->currentFrame()->evaluateJavaScript(script);
11
12
  if (result.isValid()) {
12
- emitFinished(true);
13
+ finish(true);
13
14
  } else {
14
- emitFinished(false, QString("Javascript failed to execute"));
15
+ finish(false, new ErrorMessage("Javascript failed to execute"));
15
16
  }
16
17
  }
17
18
 
data/src/FindCss.cpp ADDED
@@ -0,0 +1,13 @@
1
+ #include "FindCss.h"
2
+ #include "WebPage.h"
3
+ #include "WebPageManager.h"
4
+ #include "InvocationResult.h"
5
+
6
+ FindCss::FindCss(WebPageManager *manager, QStringList &arguments, QObject *parent) : JavascriptCommand(manager, arguments, parent) {
7
+ }
8
+
9
+ void FindCss::start() {
10
+ InvocationResult result = page()->invokeCapybaraFunction("findCss", arguments());
11
+ finish(&result);
12
+ }
13
+
data/src/FindCss.h ADDED
@@ -0,0 +1,11 @@
1
+ #include "JavascriptCommand.h"
2
+
3
+ class FindCss : public JavascriptCommand {
4
+ Q_OBJECT
5
+
6
+ public:
7
+ FindCss(WebPageManager *, QStringList &arguments, QObject *parent = 0);
8
+ virtual void start();
9
+ };
10
+
11
+
data/src/FindXpath.cpp ADDED
@@ -0,0 +1,13 @@
1
+ #include "FindXpath.h"
2
+ #include "WebPage.h"
3
+ #include "WebPageManager.h"
4
+ #include "InvocationResult.h"
5
+
6
+ FindXpath::FindXpath(WebPageManager *manager, QStringList &arguments, QObject *parent) : JavascriptCommand(manager, arguments, parent) {
7
+ }
8
+
9
+ void FindXpath::start() {
10
+ InvocationResult result = page()->invokeCapybaraFunction("findXpath", arguments());
11
+ finish(&result);
12
+ }
13
+
data/src/FindXpath.h ADDED
@@ -0,0 +1,11 @@
1
+ #include "JavascriptCommand.h"
2
+
3
+ class FindXpath : public JavascriptCommand {
4
+ Q_OBJECT
5
+
6
+ public:
7
+ FindXpath(WebPageManager *, QStringList &arguments, QObject *parent = 0);
8
+ virtual void start();
9
+ };
10
+
11
+
data/src/FrameFocus.cpp CHANGED
@@ -2,6 +2,7 @@
2
2
  #include "SocketCommand.h"
3
3
  #include "WebPage.h"
4
4
  #include "WebPageManager.h"
5
+ #include "ErrorMessage.h"
5
6
 
6
7
  FrameFocus::FrameFocus(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
7
8
  }
@@ -51,7 +52,7 @@ void FrameFocus::focusId(QString name) {
51
52
 
52
53
  void FrameFocus::focusParent() {
53
54
  if (page()->currentFrame()->parentFrame() == 0) {
54
- emitFinished(false, QString("Already at parent frame."));
55
+ finish(false, new ErrorMessage("Already at parent frame."));
55
56
  } else {
56
57
  page()->currentFrame()->parentFrame()->setFocus();
57
58
  success();
@@ -59,9 +60,9 @@ void FrameFocus::focusParent() {
59
60
  }
60
61
 
61
62
  void FrameFocus::frameNotFound() {
62
- emitFinished(false, QString("Unable to locate frame. "));
63
+ finish(false, new ErrorMessage("Unable to locate frame."));
63
64
  }
64
65
 
65
66
  void FrameFocus::success() {
66
- emitFinished(true);
67
+ finish(true);
67
68
  }
data/src/GetCookies.cpp CHANGED
@@ -15,5 +15,5 @@ void GetCookies::start()
15
15
  m_buffer.append(cookie.toRawForm());
16
16
  m_buffer.append("\n");
17
17
  }
18
- emitFinished(true, m_buffer);
18
+ finish(true, m_buffer);
19
19
  }
data/src/GetTimeout.cpp CHANGED
@@ -5,5 +5,5 @@ GetTimeout::GetTimeout(WebPageManager *manager, QStringList &arguments, QObject
5
5
  }
6
6
 
7
7
  void GetTimeout::start() {
8
- emitFinished(true, QString::number(manager()->getTimeout()));
8
+ finish(true, QString::number(manager()->getTimeout()));
9
9
  }
@@ -7,5 +7,5 @@ GetWindowHandle::GetWindowHandle(WebPageManager *manager, QStringList &arguments
7
7
  }
8
8
 
9
9
  void GetWindowHandle::start() {
10
- emitFinished(true, page()->uuid());
10
+ finish(true, page()->uuid());
11
11
  }
@@ -17,5 +17,5 @@ void GetWindowHandles::start() {
17
17
  JsonSerializer serializer;
18
18
  QByteArray json = serializer.serialize(handles);
19
19
 
20
- emitFinished(true, json);
20
+ finish(true, json);
21
21
  }
data/src/Header.cpp CHANGED
@@ -9,11 +9,11 @@ Header::Header(WebPageManager *manager, QStringList &arguments, QObject *parent)
9
9
  void Header::start() {
10
10
  QString key = arguments()[0];
11
11
  QString value = arguments()[1];
12
- NetworkAccessManager* networkAccessManager = page()->networkAccessManager();
12
+ NetworkAccessManager* networkAccessManager = manager()->networkAccessManager();
13
13
  if (key.toLower().replace("-", "_") == "user_agent") {
14
14
  page()->setUserAgent(value);
15
15
  } else {
16
16
  networkAccessManager->addHeader(key, value);
17
17
  }
18
- emitFinished(true);
18
+ finish(true);
19
19
  }
data/src/Headers.cpp CHANGED
@@ -6,11 +6,6 @@ Headers::Headers(WebPageManager *manager, QStringList &arguments, QObject *paren
6
6
  }
7
7
 
8
8
  void Headers::start() {
9
- QStringList headers;
10
-
11
- foreach(QNetworkReply::RawHeaderPair header, page()->pageHeaders())
12
- headers << header.first+": "+header.second;
13
-
14
- emitFinished(true, headers.join("\n"));
9
+ finish(true, page()->pageHeaders().join("\n"));
15
10
  }
16
11
 
@@ -8,6 +8,6 @@ IgnoreSslErrors::IgnoreSslErrors(WebPageManager *manager, QStringList &arguments
8
8
 
9
9
  void IgnoreSslErrors::start() {
10
10
  manager()->setIgnoreSslErrors(true);
11
- emitFinished(true);
11
+ finish(true);
12
12
  }
13
13
 
@@ -0,0 +1,29 @@
1
+ #include "InvocationResult.h"
2
+ #include "ErrorMessage.h"
3
+
4
+ InvocationResult::InvocationResult(QVariant result, bool error) {
5
+ m_result = result;
6
+ m_error = error;
7
+ }
8
+
9
+ const QVariant &InvocationResult::result() const {
10
+ return m_result;
11
+ }
12
+
13
+ bool InvocationResult::hasError() {
14
+ return m_error;
15
+ }
16
+
17
+ ErrorMessage *InvocationResult::errorMessage() {
18
+ if (!m_result.canConvert<QVariantMap>())
19
+ return new ErrorMessage(m_result.toString());
20
+
21
+ QVariantMap error = m_result.toMap();
22
+
23
+ QString message = error["message"].toString();
24
+
25
+ if (error["name"] == "Capybara.ClickFailed")
26
+ return new ErrorMessage("ClickFailed", message);
27
+ else
28
+ return new ErrorMessage(message);
29
+ }
@@ -0,0 +1,16 @@
1
+ #include <QVariant>
2
+
3
+ class ErrorMessage;
4
+
5
+ class InvocationResult {
6
+ public:
7
+ InvocationResult(QVariant result, bool error = false);
8
+ const QVariant &result() const;
9
+ bool hasError();
10
+ ErrorMessage *errorMessage();
11
+
12
+ private:
13
+ QVariant m_result;
14
+ bool m_error;
15
+ };
16
+
@@ -9,5 +9,5 @@ void JavascriptAlertMessages::start()
9
9
  {
10
10
  JsonSerializer serializer;
11
11
  QByteArray json = serializer.serialize(page()->alertMessages());
12
- emitFinished(true, json);
12
+ finish(true, json);
13
13
  }
@@ -0,0 +1,15 @@
1
+ #include "JavascriptCommand.h"
2
+ #include "WebPageManager.h"
3
+ #include "InvocationResult.h"
4
+
5
+ JavascriptCommand::JavascriptCommand(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
6
+ }
7
+
8
+ void JavascriptCommand::finish(InvocationResult *result) {
9
+ if (result->hasError())
10
+ SocketCommand::finish(false, result->errorMessage());
11
+ else {
12
+ QString message = result->result().toString();
13
+ SocketCommand::finish(true, message);
14
+ }
15
+ }
@@ -0,0 +1,20 @@
1
+ #ifndef JAVASCRIPT_COMMAND_H
2
+ #define JAVASCRIPT_COMMAND_H
3
+
4
+ #include <QObject>
5
+ #include <QStringList>
6
+ #include "SocketCommand.h"
7
+
8
+ class WebPage;
9
+ class WebPageManager;
10
+ class InvocationResult;
11
+
12
+ class JavascriptCommand : public SocketCommand {
13
+ Q_OBJECT
14
+
15
+ public:
16
+ JavascriptCommand(WebPageManager *, QStringList &arguments, QObject *parent = 0);
17
+ void finish(InvocationResult *result);
18
+ };
19
+
20
+ #endif
@@ -9,5 +9,5 @@ void JavascriptConfirmMessages::start()
9
9
  {
10
10
  JsonSerializer serializer;
11
11
  QByteArray json = serializer.serialize(page()->confirmMessages());
12
- emitFinished(true, json);
12
+ finish(true, json);
13
13
  }
@@ -1,8 +1,14 @@
1
1
  #include "JavascriptInvocation.h"
2
+ #include "WebPage.h"
3
+ #include "InvocationResult.h"
4
+ #include <QApplication>
5
+ #include <QEvent>
6
+ #include <QContextMenuEvent>
2
7
 
3
- JavascriptInvocation::JavascriptInvocation(const QString &functionName, const QStringList &arguments, QObject *parent) : QObject(parent) {
8
+ JavascriptInvocation::JavascriptInvocation(const QString &functionName, const QStringList &arguments, WebPage *page, QObject *parent) : QObject(parent) {
4
9
  m_functionName = functionName;
5
10
  m_arguments = arguments;
11
+ m_page = page;
6
12
  }
7
13
 
8
14
  QString &JavascriptInvocation::functionName() {
@@ -12,3 +18,124 @@ QString &JavascriptInvocation::functionName() {
12
18
  QStringList &JavascriptInvocation::arguments() {
13
19
  return m_arguments;
14
20
  }
21
+
22
+ QVariant JavascriptInvocation::getError() {
23
+ return m_error;
24
+ }
25
+
26
+ void JavascriptInvocation::setError(QVariant error) {
27
+ m_error = error;
28
+ }
29
+
30
+ InvocationResult JavascriptInvocation::invoke(QWebFrame *frame) {
31
+ frame->addToJavaScriptWindowObject("CapybaraInvocation", this);
32
+ QVariant result = frame->evaluateJavaScript("Capybara.invoke()");
33
+ if (getError().isValid())
34
+ return InvocationResult(getError(), true);
35
+ else
36
+ return InvocationResult(result);
37
+ }
38
+
39
+ void JavascriptInvocation::leftClick(int x, int y) {
40
+ QPoint mousePos(x, y);
41
+
42
+ hover(mousePos);
43
+ JavascriptInvocation::mouseEvent(QEvent::MouseButtonPress, mousePos, Qt::LeftButton);
44
+ JavascriptInvocation::mouseEvent(QEvent::MouseButtonRelease, mousePos, Qt::LeftButton);
45
+ }
46
+
47
+ void JavascriptInvocation::rightClick(int x, int y) {
48
+ QPoint mousePos(x, y);
49
+
50
+ hover(mousePos);
51
+ JavascriptInvocation::mouseEvent(QEvent::MouseButtonPress, mousePos, Qt::RightButton);
52
+
53
+ // swallowContextMenuEvent tries to fire contextmenu event in html page
54
+ QContextMenuEvent *event = new QContextMenuEvent(QContextMenuEvent::Mouse, mousePos);
55
+ m_page->swallowContextMenuEvent(event);
56
+
57
+ JavascriptInvocation::mouseEvent(QEvent::MouseButtonRelease, mousePos, Qt::RightButton);
58
+ }
59
+
60
+ void JavascriptInvocation::doubleClick(int x, int y) {
61
+ QPoint mousePos(x, y);
62
+
63
+ JavascriptInvocation::mouseEvent(QEvent::MouseButtonDblClick, mousePos, Qt::LeftButton);
64
+ JavascriptInvocation::mouseEvent(QEvent::MouseButtonRelease, mousePos, Qt::LeftButton);
65
+ }
66
+
67
+ void JavascriptInvocation::mouseEvent(QEvent::Type type, const QPoint &position, Qt::MouseButton button) {
68
+ QMouseEvent event(type, position, button, button, Qt::NoModifier);
69
+ QApplication::sendEvent(m_page, &event);
70
+ }
71
+
72
+ bool JavascriptInvocation::clickTest(QWebElement element, int absoluteX, int absoluteY) {
73
+ QPoint mousePos(absoluteX, absoluteY);
74
+ QWebHitTestResult res = m_page->mainFrame()->hitTestContent(mousePos);
75
+ return res.frame() == element.webFrame();
76
+ }
77
+
78
+ QVariantMap JavascriptInvocation::clickPosition(QWebElement element, int left, int top, int width, int height) {
79
+ QRect elementBox(left, top, width, height);
80
+ QRect viewport(QPoint(0, 0), m_page->viewportSize());
81
+ QRect boundedBox = elementBox.intersected(viewport);
82
+ QPoint mousePos = boundedBox.center();
83
+
84
+ QVariantMap m;
85
+ m["relativeX"] = mousePos.x();
86
+ m["relativeY"] = mousePos.y();
87
+
88
+ QWebFrame *parent = element.webFrame();
89
+ while (parent) {
90
+ elementBox.translate(parent->geometry().topLeft());
91
+ parent = parent->parentFrame();
92
+ }
93
+
94
+ boundedBox = elementBox.intersected(viewport);
95
+ mousePos = boundedBox.center();
96
+
97
+ m["absoluteX"] = mousePos.x();
98
+ m["absoluteY"] = mousePos.y();
99
+
100
+ return m;
101
+ }
102
+
103
+ void JavascriptInvocation::hover(int absoluteX, int absoluteY) {
104
+ QPoint mousePos(absoluteX, absoluteY);
105
+ hover(mousePos);
106
+ }
107
+
108
+ void JavascriptInvocation::hover(const QPoint &mousePos) {
109
+ mouseEvent(QEvent::MouseMove, mousePos, Qt::NoButton);
110
+ }
111
+
112
+ int JavascriptInvocation::keyCodeFor(const QChar &key) {
113
+ switch(key.unicode()) {
114
+ case 0x18:
115
+ return Qt::Key_Cancel;
116
+ case 0x08:
117
+ return Qt::Key_Backspace;
118
+ case 0x09:
119
+ return Qt::Key_Tab;
120
+ case 0x0A:
121
+ return Qt::Key_Return;
122
+ case 0x1B:
123
+ return Qt::Key_Escape;
124
+ case 0x7F:
125
+ return Qt::Key_Delete;
126
+ default:
127
+ int keyCode = key.toUpper().toLatin1();
128
+ if (keyCode >= Qt::Key_Space || keyCode <= Qt::Key_AsciiTilde)
129
+ return keyCode;
130
+ else
131
+ return Qt::Key_unknown;
132
+ }
133
+ }
134
+
135
+ void JavascriptInvocation::keypress(QChar key) {
136
+ int keyCode = keyCodeFor(key);
137
+ QKeyEvent event(QKeyEvent::KeyPress, keyCode, Qt::NoModifier, key);
138
+ QApplication::sendEvent(m_page, &event);
139
+ event = QKeyEvent(QKeyEvent::KeyRelease, keyCode, Qt::NoModifier, key);
140
+ QApplication::sendEvent(m_page, &event);
141
+ }