capybara-webkit 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Capybara::Webkit, 'compatibility with selenium' do
4
4
  include AppRunner
5
5
 
6
- it 'generates the same events as selenium when filling out forms' do
6
+ it 'generates the same events as selenium when filling out forms', selenium_compatibility: true do
7
7
  run_application_for_html(<<-HTML)
8
8
  <html><body>
9
9
  <form onsubmit="return false">
@@ -28,6 +28,7 @@ RSpec.configure do |c|
28
28
 
29
29
  c.filter_run_excluding :skip_on_windows => !(RbConfig::CONFIG['host_os'] =~ /mingw32/).nil?
30
30
  c.filter_run_excluding :skip_on_jruby => !defined?(::JRUBY_VERSION).nil?
31
+ c.filter_run_excluding :selenium_compatibility => (Capybara::VERSION =~ /^2\.4\./).nil?
31
32
 
32
33
  # We can't support outerWidth and outerHeight without a visible window.
33
34
  # We focus the next window instead of failing when closing windows.
@@ -0,0 +1,11 @@
1
+ #include "AcceptAlert.h"
2
+ #include "SocketCommand.h"
3
+ #include "WebPage.h"
4
+ #include "WebPageManager.h"
5
+
6
+ AcceptAlert::AcceptAlert(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
7
+ }
8
+
9
+ void AcceptAlert::start() {
10
+ finish(true, page()->acceptAlert(arguments()[0]));
11
+ }
@@ -0,0 +1,10 @@
1
+ #include "SocketCommand.h"
2
+
3
+ class AcceptAlert : public SocketCommand {
4
+ Q_OBJECT
5
+
6
+ public:
7
+ AcceptAlert(WebPageManager *, QStringList &arguments, QObject *parent = 0);
8
+ virtual void start();
9
+ };
10
+
@@ -46,6 +46,8 @@
46
46
  #include "WindowMaximize.h"
47
47
  #include "GoBack.h"
48
48
  #include "GoForward.h"
49
+ #include "AcceptAlert.h"
50
+ #include "FindModal.h"
49
51
 
50
52
  CommandFactory::CommandFactory(WebPageManager *manager, QObject *parent) : QObject(parent) {
51
53
  m_manager = manager;
@@ -17,6 +17,7 @@ Connection::Connection(QTcpSocket *socket, WebPageManager *manager, QObject *par
17
17
  m_commandFactory = new CommandFactory(m_manager, this);
18
18
  m_commandParser = new CommandParser(socket, m_commandFactory, this);
19
19
  m_pageSuccess = true;
20
+ m_pendingCommand = NULL;
20
21
  connect(m_socket, SIGNAL(readyRead()), m_commandParser, SLOT(checkNext()));
21
22
  connect(m_commandParser, SIGNAL(commandReady(Command *)), this, SLOT(commandReady(Command *)));
22
23
  connect(m_manager, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
@@ -28,10 +29,13 @@ void Connection::commandReady(Command *command) {
28
29
  }
29
30
 
30
31
  void Connection::startCommand(Command *command) {
32
+ if (m_pendingCommand) {
33
+ m_pendingCommand->deleteLater();
34
+ }
31
35
  if (m_pageSuccess) {
32
- command = new TimeoutCommand(new PageLoadingCommand(command, m_manager, this), m_manager, this);
33
- connect(command, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
34
- command->start();
36
+ m_pendingCommand = new TimeoutCommand(new PageLoadingCommand(command, m_manager, this), m_manager, this);
37
+ connect(m_pendingCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
38
+ m_pendingCommand->start();
35
39
  } else {
36
40
  writePageLoadFailure();
37
41
  }
@@ -52,6 +56,7 @@ void Connection::finishCommand(Response *response) {
52
56
  m_pageSuccess = true;
53
57
  writeResponse(response);
54
58
  sender()->deleteLater();
59
+ m_pendingCommand = NULL;
55
60
  }
56
61
 
57
62
  void Connection::writeResponse(Response *response) {
@@ -32,5 +32,6 @@ class Connection : public QObject {
32
32
  CommandFactory *m_commandFactory;
33
33
  bool m_pageSuccess;
34
34
  WebPage *currentPage();
35
+ Command *m_pendingCommand;
35
36
  };
36
37
 
@@ -0,0 +1,29 @@
1
+ #include "FindModal.h"
2
+ #include "SocketCommand.h"
3
+ #include "WebPage.h"
4
+ #include "WebPageManager.h"
5
+ #include "ErrorMessage.h"
6
+
7
+ FindModal::FindModal(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
8
+ m_modalId = 0;
9
+ }
10
+
11
+ void FindModal::start() {
12
+ m_modalId = arguments()[0].toInt();
13
+ if (page()->modalCount() < m_modalId) {
14
+ connect(page(), SIGNAL(modalReady(int)), SLOT(handleModalReady(int)));
15
+ } else {
16
+ handleModalReady(m_modalId);
17
+ }
18
+ }
19
+
20
+ void FindModal::handleModalReady(int modalId) {
21
+ if (modalId == m_modalId) {
22
+ sender()->disconnect(SIGNAL(modalReady(int)), this, SLOT(handleModalReady(int)));
23
+ if (page()->modalMessage(m_modalId).isNull()) {
24
+ finish(false, new ErrorMessage("ModalNotFound", ""));
25
+ } else {
26
+ finish(true, page()->modalMessage(m_modalId));
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,16 @@
1
+ #include "SocketCommand.h"
2
+
3
+ class FindModal : public SocketCommand {
4
+ Q_OBJECT
5
+
6
+ public:
7
+ FindModal(WebPageManager *, QStringList &arguments, QObject *parent = 0);
8
+ virtual void start();
9
+
10
+ public slots:
11
+ void handleModalReady(int);
12
+
13
+ private:
14
+ int m_modalId;
15
+ };
16
+
@@ -74,19 +74,19 @@ void NetworkAccessManager::setUrlBlacklist(QStringList urlBlacklist) {
74
74
 
75
75
  QStringListIterator iter(urlBlacklist);
76
76
  while (iter.hasNext()) {
77
- m_urlBlacklist << QUrl(iter.next());
77
+ m_urlBlacklist << iter.next();
78
78
  }
79
79
  };
80
80
 
81
81
  bool NetworkAccessManager::isBlacklisted(QUrl url) {
82
- QListIterator<QUrl> iter(m_urlBlacklist);
82
+ QString urlString = url.toString();
83
+ QStringListIterator iter(m_urlBlacklist);
83
84
 
84
85
  while (iter.hasNext()) {
85
- QUrl blacklisted = iter.next();
86
+ QRegExp blacklisted = QRegExp(iter.next());
87
+ blacklisted.setPatternSyntax(QRegExp::Wildcard);
86
88
 
87
- if (blacklisted == url) {
88
- return true;
89
- } else if (blacklisted.path().isEmpty() && blacklisted.isParentOf(url)) {
89
+ if(urlString.contains(blacklisted)) {
90
90
  return true;
91
91
  }
92
92
  }
@@ -21,7 +21,7 @@ class NetworkAccessManager : public QNetworkAccessManager {
21
21
  QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice * outgoingData);
22
22
  QString m_userName;
23
23
  QString m_password;
24
- QList<QUrl> m_urlBlacklist;
24
+ QStringList m_urlBlacklist;
25
25
 
26
26
  private:
27
27
  void disableKeyChainLookup();
@@ -6,6 +6,14 @@ SetConfirmAction::SetConfirmAction(WebPageManager *manager, QStringList &argumen
6
6
 
7
7
  void SetConfirmAction::start()
8
8
  {
9
- page()->setConfirmAction(arguments()[0]);
10
- finish(true);
9
+ QString index;
10
+ switch (arguments().length()) {
11
+ case 2:
12
+ index = page()->setConfirmAction(arguments()[0], arguments()[1]);
13
+ break;
14
+ default:
15
+ page()->setConfirmAction(arguments()[0]);
16
+ }
17
+
18
+ finish(true, index);
11
19
  }
@@ -6,6 +6,17 @@ SetPromptAction::SetPromptAction(WebPageManager *manager, QStringList &arguments
6
6
 
7
7
  void SetPromptAction::start()
8
8
  {
9
- page()->setPromptAction(arguments()[0]);
10
- finish(true);
9
+ QString index;
10
+ switch (arguments().length()) {
11
+ case 3:
12
+ index = page()->setPromptAction(arguments()[0], arguments()[1], arguments()[2]);
13
+ break;
14
+ case 2:
15
+ index = page()->setPromptAction(arguments()[0], arguments()[1]);
16
+ break;
17
+ default:
18
+ page()->setPromptAction(arguments()[0]);
19
+ }
20
+
21
+ finish(true, index);
11
22
  }
@@ -19,14 +19,13 @@ WebPage::WebPage(WebPageManager *manager, QObject *parent) : QWebPage(parent) {
19
19
  m_failed = false;
20
20
  m_manager = manager;
21
21
  m_uuid = QUuid::createUuid().toString();
22
+ m_confirmAction = true;
23
+ m_promptAction = false;
22
24
 
23
25
  setForwardUnsupportedContent(true);
24
26
  loadJavascript();
25
27
  setUserStylesheet();
26
28
 
27
- m_confirm = true;
28
- m_prompt = false;
29
- m_prompt_text = QString();
30
29
  this->setCustomNetworkAccessManager();
31
30
 
32
31
  connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
@@ -41,6 +40,11 @@ WebPage::WebPage(WebPageManager *manager, QObject *parent) : QWebPage(parent) {
41
40
  settings()->setAttribute(QWebSettings::JavascriptCanCloseWindows, true);
42
41
  settings()->setAttribute(QWebSettings::LocalStorageDatabaseEnabled, true);
43
42
 
43
+ if(QFileInfo("tmp").isDir()) {
44
+ settings()->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, true);
45
+ settings()->setOfflineWebApplicationCachePath("tmp");
46
+ }
47
+
44
48
  createWindow();
45
49
  }
46
50
 
@@ -180,26 +184,71 @@ void WebPage::javaScriptConsoleMessage(const QString &message, int lineNumber, c
180
184
  void WebPage::javaScriptAlert(QWebFrame *frame, const QString &message) {
181
185
  Q_UNUSED(frame);
182
186
  m_alertMessages.append(message);
187
+
188
+ if (m_modalResponses.isEmpty()) {
189
+ m_modalMessages << QString();
190
+ } else {
191
+ QVariantMap alertResponse = m_modalResponses.takeLast();
192
+ bool expectedType = alertResponse["type"].toString() == "alert";
193
+ QRegExp expectedMessage = alertResponse["message"].toRegExp();
194
+
195
+ addModalMessage(expectedType, message, expectedMessage);
196
+ }
197
+
183
198
  m_manager->logger() << "ALERT:" << qPrintable(message);
184
199
  }
185
200
 
186
201
  bool WebPage::javaScriptConfirm(QWebFrame *frame, const QString &message) {
187
202
  Q_UNUSED(frame);
188
203
  m_confirmMessages.append(message);
189
- return m_confirm;
204
+
205
+ if (m_modalResponses.isEmpty()) {
206
+ m_modalMessages << QString();
207
+ return m_confirmAction;
208
+ } else {
209
+ QVariantMap confirmResponse = m_modalResponses.takeLast();
210
+ bool expectedType = confirmResponse["type"].toString() == "confirm";
211
+ QRegExp expectedMessage = confirmResponse["message"].toRegExp();
212
+
213
+ addModalMessage(expectedType, message, expectedMessage);
214
+ return expectedType &&
215
+ confirmResponse["action"].toBool() &&
216
+ message.contains(expectedMessage);
217
+ }
190
218
  }
191
219
 
192
220
  bool WebPage::javaScriptPrompt(QWebFrame *frame, const QString &message, const QString &defaultValue, QString *result) {
193
221
  Q_UNUSED(frame)
194
222
  m_promptMessages.append(message);
195
- if (m_prompt) {
196
- if (m_prompt_text.isNull()) {
223
+
224
+ bool action = false;
225
+ QString response;
226
+
227
+ if (m_modalResponses.isEmpty()) {
228
+ action = m_promptAction;
229
+ response = m_prompt_text;
230
+ m_modalMessages << QString();
231
+ } else {
232
+ QVariantMap promptResponse = m_modalResponses.takeLast();
233
+ bool expectedType = promptResponse["type"].toString() == "prompt";
234
+ QRegExp expectedMessage = promptResponse["message"].toRegExp();
235
+
236
+ action = expectedType &&
237
+ promptResponse["action"].toBool() &&
238
+ message.contains(expectedMessage);
239
+ response = promptResponse["response"].toString();
240
+ addModalMessage(expectedType, message, expectedMessage);
241
+ }
242
+
243
+ if (action) {
244
+ if (response.isNull()) {
197
245
  *result = defaultValue;
198
246
  } else {
199
- *result = m_prompt_text;
247
+ *result = response;
200
248
  }
201
249
  }
202
- return m_prompt;
250
+
251
+ return action;
203
252
  }
204
253
 
205
254
  void WebPage::loadStarted() {
@@ -376,15 +425,61 @@ void WebPage::remove() {
376
425
  m_manager->removePage(this);
377
426
  }
378
427
 
428
+ QString WebPage::setConfirmAction(QString action, QString message) {
429
+ QVariantMap confirmResponse;
430
+ confirmResponse["type"] = "confirm";
431
+ confirmResponse["action"] = (action=="Yes");
432
+ confirmResponse["message"] = QRegExp(message);
433
+ m_modalResponses << confirmResponse;
434
+ return QString::number(m_modalResponses.length());
435
+ }
436
+
379
437
  void WebPage::setConfirmAction(QString action) {
380
- m_confirm = (action == "Yes");
438
+ m_confirmAction = (action == "Yes");
439
+ }
440
+
441
+ QString WebPage::setPromptAction(QString action, QString message, QString response) {
442
+ QVariantMap promptResponse;
443
+ promptResponse["type"] = "prompt";
444
+ promptResponse["action"] = (action == "Yes");
445
+ promptResponse["message"] = QRegExp(message);
446
+ promptResponse["response"] = response;
447
+ m_modalResponses << promptResponse;
448
+ return QString::number(m_modalResponses.length());
449
+ }
450
+
451
+ QString WebPage::setPromptAction(QString action, QString message) {
452
+ return setPromptAction(action, message, QString());
381
453
  }
382
454
 
383
455
  void WebPage::setPromptAction(QString action) {
384
- m_prompt = (action == "Yes");
456
+ m_promptAction = (action == "Yes");
385
457
  }
386
458
 
387
459
  void WebPage::setPromptText(QString text) {
388
460
  m_prompt_text = text;
389
461
  }
390
462
 
463
+ QString WebPage::acceptAlert(QString message) {
464
+ QVariantMap alertResponse;
465
+ alertResponse["type"] = "alert";
466
+ alertResponse["message"] = QRegExp(message);
467
+ m_modalResponses << alertResponse;
468
+ return QString::number(m_modalResponses.length());
469
+ }
470
+
471
+ int WebPage::modalCount() {
472
+ return m_modalMessages.length();
473
+ }
474
+
475
+ QString WebPage::modalMessage(int id) {
476
+ return m_modalMessages[id - 1];
477
+ }
478
+
479
+ void WebPage::addModalMessage(bool expectedType, const QString &message, const QRegExp &expectedMessage) {
480
+ if (expectedType && message.contains(expectedMessage))
481
+ m_modalMessages << message;
482
+ else
483
+ m_modalMessages << QString();
484
+ emit modalReady(m_modalMessages.length());
485
+ }
@@ -23,8 +23,12 @@ class WebPage : public QWebPage {
23
23
  QString userAgentForUrl(const QUrl &url ) const;
24
24
  void setUserAgent(QString userAgent);
25
25
  void setConfirmAction(QString action);
26
+ QString setConfirmAction(QString action, QString message);
27
+ QString setPromptAction(QString action, QString message, QString response);
28
+ QString setPromptAction(QString action, QString message);
26
29
  void setPromptAction(QString action);
27
30
  void setPromptText(QString action);
31
+ QString acceptAlert(QString);
28
32
  int getLastStatus();
29
33
  void setCustomNetworkAccessManager();
30
34
  bool render(const QString &fileName, const QSize &minimumSize);
@@ -48,6 +52,8 @@ class WebPage : public QWebPage {
48
52
  void mouseEvent(QEvent::Type type, const QPoint &position, Qt::MouseButton button);
49
53
  bool clickTest(QWebElement element, int absoluteX, int absoluteY);
50
54
  void resize(int, int);
55
+ int modalCount();
56
+ QString modalMessage(int);
51
57
 
52
58
  public slots:
53
59
  bool shouldInterruptJavaScript();
@@ -65,6 +71,7 @@ class WebPage : public QWebPage {
65
71
  void pageFinished(bool);
66
72
  void requestCreated(QByteArray &url, QNetworkReply *reply);
67
73
  void replyFinished(QNetworkReply *reply);
74
+ void modalReady(int);
68
75
 
69
76
  protected:
70
77
  virtual void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
@@ -82,8 +89,8 @@ class WebPage : public QWebPage {
82
89
  QStringList getAttachedFileNames();
83
90
  void loadJavascript();
84
91
  void setUserStylesheet();
85
- bool m_confirm;
86
- bool m_prompt;
92
+ bool m_confirmAction;
93
+ bool m_promptAction;
87
94
  QVariantList m_consoleMessages;
88
95
  QVariantList m_alertMessages;
89
96
  QVariantList m_confirmMessages;
@@ -94,6 +101,9 @@ class WebPage : public QWebPage {
94
101
  QString m_errorPageMessage;
95
102
  void setFrameProperties(QWebFrame *, QUrl &, NetworkReplyProxy *);
96
103
  QPoint m_mousePosition;
104
+ QList<QVariantMap> m_modalResponses;
105
+ QStringList m_modalMessages;
106
+ void addModalMessage(bool, const QString &, const QRegExp &);
97
107
  };
98
108
 
99
109
  #endif //_WEBPAGE_H
@@ -124,6 +124,12 @@ void WebPageManager::reset() {
124
124
  WebPage *page = m_pages.takeFirst();
125
125
  page->deleteLater();
126
126
  }
127
+
128
+ qint64 size = QWebSettings::offlineWebApplicationCacheQuota();
129
+ // No public function was found to wrap the empty() call to
130
+ // WebCore::cacheStorage().empty()
131
+ QWebSettings::setOfflineWebApplicationCacheQuota(size);
132
+
127
133
  createPage()->setFocus();
128
134
  }
129
135