capybara-webkit 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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