otherinbox-capybara-webkit 0.12.0 → 0.12.0.1

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.
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
+ }