otherinbox-capybara-webkit 0.12.0 → 0.12.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/GOALS +9 -0
  2. data/README.md +1 -1
  3. data/capybara-webkit.gemspec +1 -1
  4. data/lib/capybara/webkit.rb +11 -4
  5. data/lib/capybara/{driver/webkit → webkit}/browser.rb +27 -3
  6. data/lib/capybara/{driver/webkit → webkit}/connection.rb +45 -47
  7. data/lib/capybara/{driver/webkit → webkit}/cookie_jar.rb +1 -1
  8. data/lib/capybara/webkit/driver.rb +150 -0
  9. data/lib/capybara/webkit/errors.rb +10 -0
  10. data/lib/capybara/{driver/webkit → webkit}/node.rb +2 -2
  11. data/lib/capybara/{driver/webkit → webkit}/socket_debugger.rb +1 -1
  12. data/lib/capybara/{driver/webkit → webkit}/version.rb +1 -1
  13. data/lib/capybara_webkit_builder.rb +17 -3
  14. data/spec/browser_spec.rb +38 -25
  15. data/spec/connection_spec.rb +5 -5
  16. data/spec/cookie_jar_spec.rb +3 -3
  17. data/spec/driver_rendering_spec.rb +19 -26
  18. data/spec/driver_resize_window_spec.rb +3 -3
  19. data/spec/driver_spec.rb +907 -829
  20. data/spec/integration/driver_spec.rb +4 -3
  21. data/spec/spec_helper.rb +14 -6
  22. data/spec/support/app_runner.rb +91 -0
  23. data/src/Authenticate.cpp +18 -0
  24. data/src/Authenticate.h +12 -0
  25. data/src/Body.h +3 -5
  26. data/src/ClearCookies.cpp +3 -5
  27. data/src/ClearCookies.h +3 -5
  28. data/src/Command.cpp +4 -15
  29. data/src/Command.h +3 -14
  30. data/src/CommandFactory.cpp +10 -6
  31. data/src/CommandFactory.h +3 -2
  32. data/src/CommandParser.cpp +1 -1
  33. data/src/Connection.cpp +22 -11
  34. data/src/Connection.h +4 -2
  35. data/src/ConsoleMessages.cpp +2 -1
  36. data/src/ConsoleMessages.h +3 -5
  37. data/src/CurrentUrl.cpp +2 -1
  38. data/src/CurrentUrl.h +3 -5
  39. data/src/EnableLogging.cpp +10 -0
  40. data/src/EnableLogging.h +12 -0
  41. data/src/Evaluate.cpp +2 -1
  42. data/src/Evaluate.h +3 -5
  43. data/src/Execute.cpp +2 -1
  44. data/src/Execute.h +3 -5
  45. data/src/Find.cpp +3 -2
  46. data/src/Find.h +3 -5
  47. data/src/FrameFocus.cpp +3 -2
  48. data/src/FrameFocus.h +3 -4
  49. data/src/GetCookies.cpp +3 -4
  50. data/src/GetCookies.h +3 -5
  51. data/src/GetWindowHandle.cpp +11 -0
  52. data/src/GetWindowHandle.h +10 -0
  53. data/src/GetWindowHandles.cpp +20 -0
  54. data/src/GetWindowHandles.h +10 -0
  55. data/src/Header.cpp +2 -1
  56. data/src/Header.h +3 -5
  57. data/src/Headers.cpp +2 -1
  58. data/src/Headers.h +3 -5
  59. data/src/IgnoreSslErrors.cpp +4 -3
  60. data/src/IgnoreSslErrors.h +3 -5
  61. data/src/JavascriptInvocation.cpp +1 -1
  62. data/src/JavascriptInvocation.h +1 -1
  63. data/src/NetworkAccessManager.cpp +19 -1
  64. data/src/NetworkAccessManager.h +10 -0
  65. data/src/Node.cpp +6 -1
  66. data/src/Node.h +4 -5
  67. data/src/NullCommand.cpp +5 -2
  68. data/src/NullCommand.h +4 -3
  69. data/src/PageLoadingCommand.cpp +12 -7
  70. data/src/PageLoadingCommand.h +6 -9
  71. data/src/Render.cpp +2 -1
  72. data/src/Render.h +3 -5
  73. data/src/RequestedUrl.cpp +2 -1
  74. data/src/RequestedUrl.h +3 -5
  75. data/src/Reset.cpp +3 -17
  76. data/src/Reset.h +3 -8
  77. data/src/ResizeWindow.cpp +2 -1
  78. data/src/ResizeWindow.h +3 -5
  79. data/src/Server.cpp +2 -3
  80. data/src/Server.h +0 -2
  81. data/src/SetCookie.cpp +3 -4
  82. data/src/SetCookie.h +3 -5
  83. data/src/SetProxy.cpp +2 -1
  84. data/src/SetProxy.h +3 -5
  85. data/src/SetSkipImageLoading.cpp +3 -2
  86. data/src/SetSkipImageLoading.h +3 -5
  87. data/src/SocketCommand.cpp +21 -0
  88. data/src/SocketCommand.h +29 -0
  89. data/src/Source.cpp +2 -1
  90. data/src/Source.h +3 -4
  91. data/src/Status.cpp +2 -1
  92. data/src/Status.h +3 -5
  93. data/src/UnsupportedContentHandler.cpp +1 -1
  94. data/src/Url.cpp +2 -1
  95. data/src/Url.h +3 -5
  96. data/src/Visit.cpp +3 -2
  97. data/src/Visit.h +3 -5
  98. data/src/WebPage.cpp +86 -39
  99. data/src/WebPage.h +22 -8
  100. data/src/WebPageManager.cpp +117 -0
  101. data/src/WebPageManager.h +56 -0
  102. data/src/WindowFocus.cpp +32 -0
  103. data/src/WindowFocus.h +15 -0
  104. data/src/body.cpp +2 -1
  105. data/src/find_command.h +6 -2
  106. data/src/webkit_server.pro +14 -0
  107. data/templates/Command.cpp +2 -4
  108. data/templates/Command.h +3 -3
  109. metadata +29 -10
  110. data/lib/capybara/driver/webkit.rb +0 -135
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
- require 'capybara/driver/webkit'
2
+ require 'capybara/webkit/driver'
3
3
 
4
- describe Capybara::Driver::Webkit do
4
+ describe Capybara::Webkit::Driver do
5
5
  before do
6
- @driver = Capybara::Driver::Webkit.new(TestApp, :browser => $webkit_browser)
6
+ @driver = Capybara::Webkit::Driver.new(TestApp, :browser => $webkit_browser)
7
7
  end
8
8
 
9
9
  it_should_behave_like "driver"
@@ -12,6 +12,7 @@ describe Capybara::Driver::Webkit do
12
12
  it_should_behave_like "driver with header support"
13
13
  it_should_behave_like "driver with status code support"
14
14
  it_should_behave_like "driver with frame support"
15
+ it_should_behave_like "driver with support for window switching"
15
16
 
16
17
  it "returns the rack server port" do
17
18
  @driver.server_port.should eq(@driver.instance_variable_get(:@rack_server).port)
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'rspec'
2
2
  require 'rspec/autorun'
3
3
  require 'rbconfig'
4
+ require 'capybara'
4
5
 
5
6
  PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')).freeze
6
7
 
@@ -20,15 +21,22 @@ RSpec.configure do |c|
20
21
  c.filter_run_excluding :skip_on_windows => !(RbConfig::CONFIG['host_os'] =~ /mingw32/).nil?
21
22
  end
22
23
 
23
- require File.join(spec_dir, "spec_helper")
24
+ require 'capybara/webkit'
25
+ connection = Capybara::Webkit::Connection.new(:socket_class => TCPSocket, :stdout => nil)
26
+ $webkit_browser = Capybara::Webkit::Browser.new(connection)
27
+
28
+ if ENV['DEBUG']
29
+ $webkit_browser.enable_logging
30
+ end
24
31
 
25
- require 'capybara/driver/webkit/connection'
26
- require 'capybara/driver/webkit/browser'
27
- connection = Capybara::Driver::Webkit::Connection.new(:socket_class => TCPSocket, :stdout => nil)
28
- $webkit_browser = Capybara::Driver::Webkit::Browser.new(connection)
32
+ RSpec.configure do |config|
33
+ config.before { $webkit_browser.reset! }
34
+ end
35
+
36
+ require File.join(spec_dir, "spec_helper")
29
37
 
30
38
  Capybara.register_driver :reusable_webkit do |app|
31
- Capybara::Driver::Webkit.new(app, :browser => $webkit_browser)
39
+ Capybara::Webkit::Driver.new(app, :browser => $webkit_browser)
32
40
  end
33
41
 
34
42
  def with_env_vars(vars)
@@ -0,0 +1,91 @@
1
+ # Boots a single Capybara::Server for a Rack application that delegates to another, singleton Rack
2
+ # application that can be configured for each spec. Also configures Capybara to use that server.
3
+
4
+ require 'sinatra/base'
5
+
6
+ module AppRunner
7
+ class << self
8
+ attr_accessor :app, :app_host
9
+ end
10
+
11
+ def self.boot
12
+ app_container = lambda { |env| AppRunner.app.call(env) }
13
+ server = Capybara::Server.new(app_container)
14
+ server.boot
15
+ self.app_host = "http://127.0.0.1:#{server.port}"
16
+ end
17
+
18
+ def self.reset
19
+ self.app = lambda do |env|
20
+ [200, { 'Content-Type' => 'html', 'Content-Length' => 0 }, []]
21
+ end
22
+ end
23
+
24
+ def run_application(app)
25
+ AppRunner.app = app
26
+ end
27
+
28
+ def driver_for_app(&body)
29
+ app = Class.new(ExampleApp, &body)
30
+ run_application app
31
+ build_driver
32
+ end
33
+
34
+ def driver_for_html(html)
35
+ app = lambda do |env|
36
+ [200, { 'Content-Type' => 'text/html', 'Content-Length' => html.size.to_s }, [html]]
37
+ end
38
+ run_application app
39
+ build_driver
40
+ end
41
+
42
+ private
43
+
44
+ def build_driver
45
+ Capybara::Webkit::Driver.new(AppRunner.app, :browser => $webkit_browser)
46
+ end
47
+
48
+ def self.included(example_group)
49
+ example_group.class_eval do
50
+ before { AppRunner.reset }
51
+
52
+ around do |example|
53
+ Capybara.run_server = false
54
+ Capybara.app_host = AppRunner.app_host
55
+ begin
56
+ example.run
57
+ ensure
58
+ Capybara.run_server = true
59
+ Capybara.app_host = nil
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ class ExampleApp < Sinatra::Base
67
+ # Sinatra fixes invalid responses that would break QWebPage, so this middleware breaks them again
68
+ # for testing purposes.
69
+ class ResponseInvalidator
70
+ def initialize(app)
71
+ @app = app
72
+ end
73
+
74
+ def call(env)
75
+ response = @app.call(env)
76
+ if response.to_a[1]['X-Response-Invalid']
77
+ [404, {}, []]
78
+ else
79
+ response
80
+ end
81
+ end
82
+ end
83
+
84
+ use ResponseInvalidator
85
+
86
+ def invalid_response
87
+ [200, { 'X-Response-Invalid' => 'TRUE' }, []]
88
+ end
89
+ end
90
+
91
+ AppRunner.boot
@@ -0,0 +1,18 @@
1
+ #include "Authenticate.h"
2
+ #include "WebPage.h"
3
+ #include "NetworkAccessManager.h"
4
+
5
+ Authenticate::Authenticate(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
6
+ }
7
+
8
+ void Authenticate::start() {
9
+ QString username = arguments()[0];
10
+ QString password = arguments()[1];
11
+
12
+ NetworkAccessManager* networkAccessManager = qobject_cast<NetworkAccessManager*>(page()->networkAccessManager());
13
+ networkAccessManager->setUserName(username);
14
+ networkAccessManager->setPassword(password);
15
+
16
+ emit finished(new Response(true));
17
+ }
18
+
@@ -0,0 +1,12 @@
1
+ #include "SocketCommand.h"
2
+
3
+ class WebPage;
4
+
5
+ class Authenticate : public SocketCommand {
6
+ Q_OBJECT
7
+
8
+ public:
9
+ Authenticate(WebPageManager *manager, QStringList &arguments, QObject *parent = 0);
10
+ virtual void start();
11
+ };
12
+
data/src/Body.h CHANGED
@@ -1,12 +1,10 @@
1
- #include "Command.h"
1
+ #include "SocketCommand.h"
2
2
 
3
- class WebPage;
4
-
5
- class Body : public Command {
3
+ class Body : public SocketCommand {
6
4
  Q_OBJECT
7
5
 
8
6
  public:
9
- Body(WebPage *page, QStringList &arguments, QObject *parent = 0);
7
+ Body(WebPageManager *, QStringList &arguments, QObject *parent = 0);
10
8
  virtual void start();
11
9
  };
12
10
 
data/src/ClearCookies.cpp CHANGED
@@ -1,15 +1,13 @@
1
1
  #include "ClearCookies.h"
2
2
  #include "WebPage.h"
3
+ #include "WebPageManager.h"
3
4
  #include "NetworkCookieJar.h"
4
5
  #include <QNetworkCookie>
5
6
 
6
- ClearCookies::ClearCookies(WebPage *page, QStringList &arguments, QObject *parent) : Command(page, arguments, parent) {}
7
+ ClearCookies::ClearCookies(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {}
7
8
 
8
9
  void ClearCookies::start()
9
10
  {
10
- NetworkCookieJar *jar = qobject_cast<NetworkCookieJar*>(page()
11
- ->networkAccessManager()
12
- ->cookieJar());
13
- jar->clearCookies();
11
+ manager()->cookieJar()->clearCookies();
14
12
  emit finished(new Response(true));
15
13
  }
data/src/ClearCookies.h CHANGED
@@ -1,11 +1,9 @@
1
- #include "Command.h"
1
+ #include "SocketCommand.h"
2
2
 
3
- class WebPage;
4
-
5
- class ClearCookies : public Command {
3
+ class ClearCookies : public SocketCommand {
6
4
  Q_OBJECT;
7
5
 
8
6
  public:
9
- ClearCookies(WebPage *page, QStringList &arguments, QObject *parent = 0);
7
+ ClearCookies(WebPageManager *, QStringList &arguments, QObject *parent = 0);
10
8
  virtual void start();
11
9
  };
data/src/Command.cpp CHANGED
@@ -1,19 +1,8 @@
1
- #include "Command.h"
2
- #include "WebPage.h"
1
+ #include "SocketCommand.h"
3
2
 
4
- Command::Command(WebPage *page, QStringList &arguments, QObject *parent) : QObject(parent) {
5
- m_page = page;
6
- m_arguments = arguments;
3
+ Command::Command(QObject *parent) : QObject(parent) {
7
4
  }
8
5
 
9
- void Command::start() {
6
+ QString Command::toString() const {
7
+ return metaObject()->className();
10
8
  }
11
-
12
- WebPage *Command::page() {
13
- return m_page;
14
- }
15
-
16
- QStringList &Command::arguments() {
17
- return m_arguments;
18
- }
19
-
data/src/Command.h CHANGED
@@ -2,29 +2,18 @@
2
2
  #define COMMAND_H
3
3
 
4
4
  #include <QObject>
5
- #include <QStringList>
6
5
  #include "Response.h"
7
6
 
8
- class WebPage;
9
-
10
7
  class Command : public QObject {
11
8
  Q_OBJECT
12
9
 
13
10
  public:
14
- Command(WebPage *page, QStringList &arguments, QObject *parent = 0);
15
- virtual void start();
11
+ Command(QObject *parent = 0);
12
+ virtual void start() = 0;
13
+ virtual QString toString() const;
16
14
 
17
15
  signals:
18
16
  void finished(Response *response);
19
-
20
- protected:
21
- WebPage *page();
22
- QStringList &arguments();
23
-
24
- private:
25
- WebPage *m_page;
26
- QStringList m_arguments;
27
-
28
17
  };
29
18
 
30
19
  #endif
@@ -1,8 +1,8 @@
1
1
  #include "CommandFactory.h"
2
2
  #include "NullCommand.h"
3
+ #include "SocketCommand.h"
3
4
  #include "Visit.h"
4
5
  #include "Find.h"
5
- #include "Command.h"
6
6
  #include "Reset.h"
7
7
  #include "Node.h"
8
8
  #include "Url.h"
@@ -25,14 +25,18 @@
25
25
  #include "ResizeWindow.h"
26
26
  #include "IgnoreSslErrors.h"
27
27
  #include "SetSkipImageLoading.h"
28
+ #include "WindowFocus.h"
29
+ #include "GetWindowHandles.h"
30
+ #include "GetWindowHandle.h"
31
+ #include "WebPageManager.h"
32
+ #include "Authenticate.h"
33
+ #include "EnableLogging.h"
28
34
 
29
- CommandFactory::CommandFactory(WebPage *page, QObject *parent) : QObject(parent) {
30
- m_page = page;
35
+ CommandFactory::CommandFactory(WebPageManager *manager, QObject *parent) : QObject(parent) {
36
+ m_manager = manager;
31
37
  }
32
38
 
33
39
  Command *CommandFactory::createCommand(const char *name, QStringList &arguments) {
34
40
  #include "find_command.h"
35
- arguments.clear();
36
- arguments.append(QString(name));
37
- return new NullCommand(m_page, arguments);
41
+ return new NullCommand(QString(name));
38
42
  }
data/src/CommandFactory.h CHANGED
@@ -2,15 +2,16 @@
2
2
 
3
3
  class Command;
4
4
  class WebPage;
5
+ class WebPageManager;
5
6
 
6
7
  class CommandFactory : public QObject {
7
8
  Q_OBJECT
8
9
 
9
10
  public:
10
- CommandFactory(WebPage *page, QObject *parent = 0);
11
+ CommandFactory(WebPageManager *, QObject *parent = 0);
11
12
  Command *createCommand(const char *name, QStringList &arguments);
12
13
 
13
14
  private:
14
- WebPage *m_page;
15
+ WebPageManager *m_manager;
15
16
  };
16
17
 
@@ -1,6 +1,6 @@
1
1
  #include "CommandParser.h"
2
2
  #include "CommandFactory.h"
3
- #include "Command.h"
3
+ #include "SocketCommand.h"
4
4
 
5
5
  #include <QIODevice>
6
6
 
data/src/Connection.cpp CHANGED
@@ -1,37 +1,41 @@
1
1
  #include "Connection.h"
2
2
  #include "WebPage.h"
3
+ #include "WebPageManager.h"
3
4
  #include "CommandParser.h"
4
5
  #include "CommandFactory.h"
5
6
  #include "PageLoadingCommand.h"
6
- #include "Command.h"
7
+ #include "SocketCommand.h"
7
8
 
8
9
  #include <QTcpSocket>
9
10
 
10
- Connection::Connection(QTcpSocket *socket, WebPage *page, QObject *parent) :
11
+ Connection::Connection(QTcpSocket *socket, WebPageManager *manager, QObject *parent) :
11
12
  QObject(parent) {
12
13
  m_socket = socket;
13
- m_page = page;
14
- m_commandFactory = new CommandFactory(page, this);
14
+ m_manager = manager;
15
+ m_commandFactory = new CommandFactory(m_manager, this);
15
16
  m_commandParser = new CommandParser(socket, m_commandFactory, this);
16
17
  m_pageSuccess = true;
17
18
  m_commandWaiting = false;
18
19
  connect(m_socket, SIGNAL(readyRead()), m_commandParser, SLOT(checkNext()));
19
20
  connect(m_commandParser, SIGNAL(commandReady(Command *)), this, SLOT(commandReady(Command *)));
20
- connect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
21
+ connect(m_manager, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
21
22
  }
22
23
 
23
24
  void Connection::commandReady(Command *command) {
24
25
  m_queuedCommand = command;
25
- if (m_page->isLoading())
26
+ m_manager->logger() << "Received" << command->toString();
27
+ if (m_manager->isLoading()) {
28
+ m_manager->logger() << command->toString() << "waiting for load to finish";
26
29
  m_commandWaiting = true;
27
- else
30
+ } else {
28
31
  startCommand();
32
+ }
29
33
  }
30
34
 
31
35
  void Connection::startCommand() {
32
36
  m_commandWaiting = false;
33
37
  if (m_pageSuccess) {
34
- m_runningCommand = new PageLoadingCommand(m_queuedCommand, m_page, this);
38
+ m_runningCommand = new PageLoadingCommand(m_queuedCommand, m_manager, this);
35
39
  connect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
36
40
  m_runningCommand->start();
37
41
  } else {
@@ -40,18 +44,20 @@ void Connection::startCommand() {
40
44
  }
41
45
 
42
46
  void Connection::pendingLoadFinished(bool success) {
43
- m_pageSuccess = success;
44
- if (m_commandWaiting)
47
+ m_pageSuccess = m_pageSuccess && success;
48
+ if (m_commandWaiting) {
45
49
  startCommand();
50
+ }
46
51
  }
47
52
 
48
53
  void Connection::writePageLoadFailure() {
49
54
  m_pageSuccess = true;
50
- QString message = m_page->failureString();
55
+ QString message = currentPage()->failureString();
51
56
  writeResponse(new Response(false, message));
52
57
  }
53
58
 
54
59
  void Connection::finishCommand(Response *response) {
60
+ m_pageSuccess = true;
55
61
  m_runningCommand->deleteLater();
56
62
  writeResponse(response);
57
63
  }
@@ -62,6 +68,8 @@ void Connection::writeResponse(Response *response) {
62
68
  else
63
69
  m_socket->write("failure\n");
64
70
 
71
+ m_manager->logger() << "Wrote response" << response->isSuccess() << response->message();
72
+
65
73
  QByteArray messageUtf8 = response->message();
66
74
  QString messageLength = QString::number(messageUtf8.size()) + "\n";
67
75
  m_socket->write(messageLength.toAscii());
@@ -69,3 +77,6 @@ void Connection::writeResponse(Response *response) {
69
77
  delete response;
70
78
  }
71
79
 
80
+ WebPage *Connection::currentPage() {
81
+ return m_manager->currentPage();
82
+ }