mirror of
https://github.com/thoughtbot/capybara-webkit
synced 2023-03-27 23:22:28 -04:00
Revert "Revert "Add configurable timeouts to commands.""
This reverts commit b1b3a4c390
.
This commit is contained in:
parent
b1b3a4c390
commit
cbb58d05f1
15 changed files with 271 additions and 11 deletions
|
@ -165,6 +165,14 @@ module Capybara::Webkit
|
||||||
command "Render", path, width, height
|
command "Render", path, width, height
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def timeout=(timeout_in_seconds)
|
||||||
|
command "SetTimeout", timeout_in_seconds
|
||||||
|
end
|
||||||
|
|
||||||
|
def timeout
|
||||||
|
command("GetTimeout").to_i
|
||||||
|
end
|
||||||
|
|
||||||
def set_cookie(cookie)
|
def set_cookie(cookie)
|
||||||
command "SetCookie", cookie
|
command "SetCookie", cookie
|
||||||
end
|
end
|
||||||
|
@ -199,12 +207,26 @@ module Capybara::Webkit
|
||||||
if result.nil?
|
if result.nil?
|
||||||
raise NoResponseError, "No response received from the server."
|
raise NoResponseError, "No response received from the server."
|
||||||
elsif result != 'ok'
|
elsif result != 'ok'
|
||||||
raise InvalidResponseError, read_response
|
case response = read_response
|
||||||
|
when "timeout"
|
||||||
|
raise Capybara::TimeoutError, "Request timed out after #{timeout_seconds}"
|
||||||
|
else
|
||||||
|
raise InvalidResponseError, response
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def timeout_seconds
|
||||||
|
seconds = timeout
|
||||||
|
if seconds > 1
|
||||||
|
"#{seconds} seconds"
|
||||||
|
else
|
||||||
|
"1 second"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def read_response
|
def read_response
|
||||||
response_length = @connection.gets.to_i
|
response_length = @connection.gets.to_i
|
||||||
if response_length > 0
|
if response_length > 0
|
||||||
|
|
|
@ -1825,6 +1825,78 @@ describe Capybara::Webkit::Driver do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "timeout for long requests" do
|
||||||
|
let(:driver) do
|
||||||
|
driver_for_app do
|
||||||
|
html = <<-HTML
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<form action="/form" method="post">
|
||||||
|
<input type="submit" value="Submit"/>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
get "/" do
|
||||||
|
sleep(2)
|
||||||
|
html
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/form" do
|
||||||
|
sleep(4)
|
||||||
|
html
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not raise a timeout error when zero" do
|
||||||
|
driver.browser.timeout = 0
|
||||||
|
lambda { driver.visit("/") }.should_not raise_error(Capybara::TimeoutError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should raise a timeout error" do
|
||||||
|
driver.browser.timeout = 1
|
||||||
|
lambda { driver.visit("/") }.should raise_error(Capybara::TimeoutError, "Request timed out after 1 second")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not raise an error when the timeout is high enough" do
|
||||||
|
driver.browser.timeout = 10
|
||||||
|
lambda { driver.visit("/") }.should_not raise_error(Capybara::TimeoutError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should set the timeout for each request" do
|
||||||
|
driver.browser.timeout = 10
|
||||||
|
lambda { driver.visit("/") }.should_not raise_error(Capybara::TimeoutError)
|
||||||
|
driver.browser.timeout = 1
|
||||||
|
lambda { driver.visit("/") }.should raise_error(Capybara::TimeoutError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should set the timeout for each request" do
|
||||||
|
driver.browser.timeout = 1
|
||||||
|
lambda { driver.visit("/") }.should raise_error(Capybara::TimeoutError)
|
||||||
|
driver.reset!
|
||||||
|
driver.browser.timeout = 10
|
||||||
|
lambda { driver.visit("/") }.should_not raise_error(Capybara::TimeoutError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should raise a timeout on a slow form" do
|
||||||
|
driver.browser.timeout = 3
|
||||||
|
driver.visit("/")
|
||||||
|
driver.status_code.should == 200
|
||||||
|
driver.browser.timeout = 1
|
||||||
|
driver.find("//input").first.click
|
||||||
|
lambda { driver.status_code }.should raise_error(Capybara::TimeoutError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "get timeout" do
|
||||||
|
driver.browser.timeout = 10
|
||||||
|
driver.browser.timeout.should == 10
|
||||||
|
driver.browser.timeout = 3
|
||||||
|
driver.browser.timeout.should == 3
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "logger app" do
|
describe "logger app" do
|
||||||
it "logs nothing before turning on the logger" do
|
it "logs nothing before turning on the logger" do
|
||||||
driver.visit("/")
|
driver.visit("/")
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include "ConsoleMessages.h"
|
#include "ConsoleMessages.h"
|
||||||
#include "RequestedUrl.h"
|
#include "RequestedUrl.h"
|
||||||
#include "CurrentUrl.h"
|
#include "CurrentUrl.h"
|
||||||
|
#include "SetTimeout.h"
|
||||||
|
#include "GetTimeout.h"
|
||||||
#include "ResizeWindow.h"
|
#include "ResizeWindow.h"
|
||||||
#include "IgnoreSslErrors.h"
|
#include "IgnoreSslErrors.h"
|
||||||
#include "SetSkipImageLoading.h"
|
#include "SetSkipImageLoading.h"
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "CommandParser.h"
|
#include "CommandParser.h"
|
||||||
#include "CommandFactory.h"
|
#include "CommandFactory.h"
|
||||||
#include "PageLoadingCommand.h"
|
#include "PageLoadingCommand.h"
|
||||||
|
#include "TimeoutCommand.h"
|
||||||
#include "SocketCommand.h"
|
#include "SocketCommand.h"
|
||||||
|
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
|
@ -24,18 +25,14 @@ Connection::Connection(QTcpSocket *socket, WebPageManager *manager, QObject *par
|
||||||
void Connection::commandReady(Command *command) {
|
void Connection::commandReady(Command *command) {
|
||||||
m_queuedCommand = command;
|
m_queuedCommand = command;
|
||||||
m_manager->logger() << "Received" << command->toString();
|
m_manager->logger() << "Received" << command->toString();
|
||||||
if (m_manager->isLoading()) {
|
|
||||||
m_manager->logger() << command->toString() << "waiting for load to finish";
|
|
||||||
m_commandWaiting = true;
|
|
||||||
} else {
|
|
||||||
startCommand();
|
startCommand();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::startCommand() {
|
void Connection::startCommand() {
|
||||||
m_commandWaiting = false;
|
m_commandWaiting = false;
|
||||||
if (m_pageSuccess) {
|
if (m_pageSuccess) {
|
||||||
m_runningCommand = new PageLoadingCommand(m_queuedCommand, m_manager, this);
|
m_runningCommand = new PageLoadingCommand(m_queuedCommand, m_manager, this);
|
||||||
|
m_runningCommand = new TimeoutCommand(m_runningCommand, m_manager, this);
|
||||||
connect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
|
connect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
|
||||||
m_runningCommand->start();
|
m_runningCommand->start();
|
||||||
} else {
|
} else {
|
||||||
|
@ -45,9 +42,6 @@ void Connection::startCommand() {
|
||||||
|
|
||||||
void Connection::pendingLoadFinished(bool success) {
|
void Connection::pendingLoadFinished(bool success) {
|
||||||
m_pageSuccess = m_pageSuccess && success;
|
m_pageSuccess = m_pageSuccess && success;
|
||||||
if (m_commandWaiting) {
|
|
||||||
startCommand();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::writePageLoadFailure() {
|
void Connection::writePageLoadFailure() {
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Connection : public QObject {
|
||||||
WebPageManager *m_manager;
|
WebPageManager *m_manager;
|
||||||
CommandParser *m_commandParser;
|
CommandParser *m_commandParser;
|
||||||
CommandFactory *m_commandFactory;
|
CommandFactory *m_commandFactory;
|
||||||
PageLoadingCommand *m_runningCommand;
|
Command *m_runningCommand;
|
||||||
bool m_pageSuccess;
|
bool m_pageSuccess;
|
||||||
bool m_commandWaiting;
|
bool m_commandWaiting;
|
||||||
WebPage *currentPage();
|
WebPage *currentPage();
|
||||||
|
|
9
src/GetTimeout.cpp
Normal file
9
src/GetTimeout.cpp
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include "GetTimeout.h"
|
||||||
|
#include "WebPageManager.h"
|
||||||
|
|
||||||
|
GetTimeout::GetTimeout(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetTimeout::start() {
|
||||||
|
emit finished(new Response(true, QString::number(manager()->getTimeout())));
|
||||||
|
}
|
11
src/GetTimeout.h
Normal file
11
src/GetTimeout.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "SocketCommand.h"
|
||||||
|
|
||||||
|
class WebPageManager;
|
||||||
|
|
||||||
|
class GetTimeout : public SocketCommand {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GetTimeout(WebPageManager *page, QStringList &arguments, QObject *parent = 0);
|
||||||
|
virtual void start();
|
||||||
|
};
|
19
src/SetTimeout.cpp
Normal file
19
src/SetTimeout.cpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include "SetTimeout.h"
|
||||||
|
#include "WebPageManager.h"
|
||||||
|
|
||||||
|
SetTimeout::SetTimeout(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTimeout::start() {
|
||||||
|
QString timeoutString = arguments()[0];
|
||||||
|
bool ok;
|
||||||
|
int timeout = timeoutString.toInt(&ok);
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
manager()->setTimeout(timeout);
|
||||||
|
emit finished(new Response(true));
|
||||||
|
} else {
|
||||||
|
emit finished(new Response(false, QString("Invalid value for timeout")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
src/SetTimeout.h
Normal file
9
src/SetTimeout.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include "SocketCommand.h"
|
||||||
|
|
||||||
|
class SetTimeout : public SocketCommand {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SetTimeout(WebPageManager *manager, QStringList &arguments, QObject *parent = 0);
|
||||||
|
virtual void start();
|
||||||
|
};
|
59
src/TimeoutCommand.cpp
Normal file
59
src/TimeoutCommand.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include "TimeoutCommand.h"
|
||||||
|
#include "Command.h"
|
||||||
|
#include "WebPageManager.h"
|
||||||
|
#include "WebPage.h"
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
TimeoutCommand::TimeoutCommand(Command *command, WebPageManager *manager, QObject *parent) : Command(parent) {
|
||||||
|
m_command = command;
|
||||||
|
m_manager = manager;
|
||||||
|
m_timer = new QTimer(this);
|
||||||
|
m_timer->setSingleShot(true);
|
||||||
|
connect(m_timer, SIGNAL(timeout()), this, SLOT(commandTimeout()));
|
||||||
|
connect(m_manager, SIGNAL(loadStarted()), this, SLOT(pageLoadingFromCommand()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeoutCommand::start() {
|
||||||
|
if (m_manager->isLoading()) {
|
||||||
|
connect(m_manager, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
|
||||||
|
startTimeout();
|
||||||
|
} else {
|
||||||
|
startCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeoutCommand::startCommand() {
|
||||||
|
connect(m_command, SIGNAL(finished(Response *)), this, SLOT(commandFinished(Response *)));
|
||||||
|
m_command->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeoutCommand::startTimeout() {
|
||||||
|
int timeout = m_manager->getTimeout();
|
||||||
|
if (timeout > 0) {
|
||||||
|
m_timer->start(timeout * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeoutCommand::pendingLoadFinished(bool success) {
|
||||||
|
if (success) {
|
||||||
|
startCommand();
|
||||||
|
} else {
|
||||||
|
emit finished(new Response(false, m_manager->currentPage()->failureString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeoutCommand::pageLoadingFromCommand() {
|
||||||
|
startTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeoutCommand::commandTimeout() {
|
||||||
|
m_manager->currentPage()->triggerAction(QWebPage::Stop);
|
||||||
|
m_command->deleteLater();
|
||||||
|
emit finished(new Response(false, QString("timeout")));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeoutCommand::commandFinished(Response *response) {
|
||||||
|
m_command->deleteLater();
|
||||||
|
emit finished(response);
|
||||||
|
}
|
||||||
|
|
41
src/TimeoutCommand.h
Normal file
41
src/TimeoutCommand.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#include "Command.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
class Response;
|
||||||
|
class WebPageManager;
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
/* Decorates a command with a timeout.
|
||||||
|
*
|
||||||
|
* If the timeout, using a QTimer is reached before
|
||||||
|
* the command is finished, the load page load will
|
||||||
|
* be stopped and failure response will be issued.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class TimeoutCommand : public Command {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TimeoutCommand(Command *command, WebPageManager *page, QObject *parent = 0);
|
||||||
|
virtual void start();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void commandTimeout();
|
||||||
|
void commandFinished(Response *response);
|
||||||
|
void pageLoadingFromCommand();
|
||||||
|
void pendingLoadFinished(bool);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished(Response *response);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void startCommand();
|
||||||
|
void startTimeout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebPageManager *m_manager;
|
||||||
|
QTimer *m_timer;
|
||||||
|
Command *m_command;
|
||||||
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@ WebPageManager::WebPageManager(QObject *parent) : QObject(parent) {
|
||||||
m_success = true;
|
m_success = true;
|
||||||
m_loggingEnabled = false;
|
m_loggingEnabled = false;
|
||||||
m_ignoredOutput = new QString();
|
m_ignoredOutput = new QString();
|
||||||
|
m_timeout = -1;
|
||||||
createPage(this)->setFocus();
|
createPage(this)->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +86,16 @@ bool WebPageManager::ignoreSslErrors() {
|
||||||
return m_ignoreSslErrors;
|
return m_ignoreSslErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WebPageManager::getTimeout() {
|
||||||
|
return m_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebPageManager::setTimeout(int timeout) {
|
||||||
|
m_timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
void WebPageManager::reset() {
|
void WebPageManager::reset() {
|
||||||
|
m_timeout = -1;
|
||||||
m_cookieJar->clearCookies();
|
m_cookieJar->clearCookies();
|
||||||
m_pages.first()->deleteLater();
|
m_pages.first()->deleteLater();
|
||||||
m_pages.clear();
|
m_pages.clear();
|
||||||
|
|
|
@ -22,6 +22,8 @@ class WebPageManager : public QObject {
|
||||||
WebPage *createPage(QObject *parent);
|
WebPage *createPage(QObject *parent);
|
||||||
void setIgnoreSslErrors(bool);
|
void setIgnoreSslErrors(bool);
|
||||||
bool ignoreSslErrors();
|
bool ignoreSslErrors();
|
||||||
|
void setTimeout(int);
|
||||||
|
int getTimeout();
|
||||||
void reset();
|
void reset();
|
||||||
NetworkCookieJar *cookieJar();
|
NetworkCookieJar *cookieJar();
|
||||||
bool isLoading() const;
|
bool isLoading() const;
|
||||||
|
@ -50,6 +52,7 @@ class WebPageManager : public QObject {
|
||||||
bool m_success;
|
bool m_success;
|
||||||
bool m_loggingEnabled;
|
bool m_loggingEnabled;
|
||||||
QString *m_ignoredOutput;
|
QString *m_ignoredOutput;
|
||||||
|
int m_timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WEBPAGEMANAGER_H
|
#endif // _WEBPAGEMANAGER_H
|
||||||
|
|
|
@ -39,3 +39,6 @@ CHECK_COMMAND(ClearPromptText)
|
||||||
CHECK_COMMAND(JavascriptAlertMessages)
|
CHECK_COMMAND(JavascriptAlertMessages)
|
||||||
CHECK_COMMAND(JavascriptConfirmMessages)
|
CHECK_COMMAND(JavascriptConfirmMessages)
|
||||||
CHECK_COMMAND(JavascriptPromptMessages)
|
CHECK_COMMAND(JavascriptPromptMessages)
|
||||||
|
CHECK_COMMAND(GetTimeout)
|
||||||
|
CHECK_COMMAND(SetTimeout)
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,9 @@ HEADERS = \
|
||||||
WindowFocus.h \
|
WindowFocus.h \
|
||||||
GetWindowHandles.h \
|
GetWindowHandles.h \
|
||||||
GetWindowHandle.h \
|
GetWindowHandle.h \
|
||||||
|
GetTimeout.h \
|
||||||
|
SetTimeout.h \
|
||||||
|
TimeoutCommand.h \
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
EnableLogging.cpp \
|
EnableLogging.cpp \
|
||||||
|
@ -102,11 +105,14 @@ SOURCES = \
|
||||||
SetProxy.cpp \
|
SetProxy.cpp \
|
||||||
NullCommand.cpp \
|
NullCommand.cpp \
|
||||||
PageLoadingCommand.cpp \
|
PageLoadingCommand.cpp \
|
||||||
|
SetTimeout.cpp \
|
||||||
|
GetTimeout.cpp \
|
||||||
SetSkipImageLoading.cpp \
|
SetSkipImageLoading.cpp \
|
||||||
WebPageManager.cpp \
|
WebPageManager.cpp \
|
||||||
WindowFocus.cpp \
|
WindowFocus.cpp \
|
||||||
GetWindowHandles.cpp \
|
GetWindowHandles.cpp \
|
||||||
GetWindowHandle.cpp \
|
GetWindowHandle.cpp \
|
||||||
|
TimeoutCommand.cpp \
|
||||||
|
|
||||||
RESOURCES = webkit_server.qrc
|
RESOURCES = webkit_server.qrc
|
||||||
QT += network webkit
|
QT += network webkit
|
||||||
|
|
Loading…
Reference in a new issue