mirror of
https://github.com/thoughtbot/capybara-webkit
synced 2023-03-27 23:22:28 -04:00
Don't create a command until all arguments are received; don't start the next command if a page is still loading
This commit is contained in:
parent
5965f8a5af
commit
a8e64a5f10
6 changed files with 92 additions and 24 deletions
|
@ -309,4 +309,26 @@ describe Capybara::Driver::Webkit do
|
||||||
parent.find("./*[@class='find']").map(&:text).should == %w(Expected)
|
parent.find("./*[@class='find']").map(&:text).should == %w(Expected)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "slow app" do
|
||||||
|
let(:app) do
|
||||||
|
lambda do |env|
|
||||||
|
body = <<-HTML
|
||||||
|
<html><body>
|
||||||
|
<form action="/next"><input type="submit"/></form>
|
||||||
|
<p>#{env['PATH_INFO']}</p>
|
||||||
|
</body></html>
|
||||||
|
HTML
|
||||||
|
sleep(0.5)
|
||||||
|
[200,
|
||||||
|
{ 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
|
||||||
|
[body]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "waits for a request to load" do
|
||||||
|
subject.find("//input").first.click
|
||||||
|
subject.find("//p").first.text.should == "/next"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
|
#include "WebPage.h"
|
||||||
#include "Visit.h"
|
#include "Visit.h"
|
||||||
#include "Find.h"
|
#include "Find.h"
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
|
@ -54,33 +55,15 @@ void Connection::readDataBlock() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::processNext(const char *data) {
|
void Connection::processNext(const char *data) {
|
||||||
if (m_command) {
|
if (m_commandName.isNull()) {
|
||||||
continueCommand(data);
|
m_commandName = data;
|
||||||
} else {
|
|
||||||
m_command = createCommand(data);
|
|
||||||
if (m_command) {
|
|
||||||
startCommand();
|
|
||||||
} else {
|
|
||||||
QString failure = QString("Unknown command: ") + data + "\n";
|
|
||||||
writeResponse(false, failure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Command *Connection::createCommand(const char *name) {
|
|
||||||
#include "find_command.h"
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Connection::startCommand() {
|
|
||||||
m_argumentsExpected = -1;
|
m_argumentsExpected = -1;
|
||||||
connect(m_command,
|
} else {
|
||||||
SIGNAL(finished(bool, QString &)),
|
processArgument(data);
|
||||||
this,
|
}
|
||||||
SLOT(finishCommand(bool, QString &)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::continueCommand(const char *data) {
|
void Connection::processArgument(const char *data) {
|
||||||
if (m_argumentsExpected == -1) {
|
if (m_argumentsExpected == -1) {
|
||||||
m_argumentsExpected = QString(data).toInt();
|
m_argumentsExpected = QString(data).toInt();
|
||||||
} else if (m_expectingDataSize == -1) {
|
} else if (m_expectingDataSize == -1) {
|
||||||
|
@ -90,7 +73,40 @@ void Connection::continueCommand(const char *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_arguments.length() == m_argumentsExpected) {
|
if (m_arguments.length() == m_argumentsExpected) {
|
||||||
|
if (m_page->isLoading())
|
||||||
|
connect(m_page, SIGNAL(loadFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
|
||||||
|
else
|
||||||
|
startCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::startCommand() {
|
||||||
|
m_command = createCommand(m_commandName.toAscii().constData());
|
||||||
|
if (m_command) {
|
||||||
|
connect(m_command,
|
||||||
|
SIGNAL(finished(bool, QString &)),
|
||||||
|
this,
|
||||||
|
SLOT(finishCommand(bool, QString &)));
|
||||||
m_command->start(m_arguments);
|
m_command->start(m_arguments);
|
||||||
|
} else {
|
||||||
|
QString failure = QString("Unknown command: ") + m_commandName + "\n";
|
||||||
|
writeResponse(false, failure);
|
||||||
|
}
|
||||||
|
m_commandName = QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Command *Connection::createCommand(const char *name) {
|
||||||
|
#include "find_command.h"
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::pendingLoadFinished(bool success) {
|
||||||
|
m_page->disconnect(this, SLOT(pendingLoadFinished(bool)));
|
||||||
|
if (success) {
|
||||||
|
startCommand();
|
||||||
|
} else {
|
||||||
|
QString response = m_page->failureString();
|
||||||
|
finishCommand(false, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,3 +127,4 @@ void Connection::writeResponse(bool success, QString &response) {
|
||||||
m_socket->write(responseLength.toAscii());
|
m_socket->write(responseLength.toAscii());
|
||||||
m_socket->write(response.toAscii());
|
m_socket->write(response.toAscii());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,17 +14,19 @@ class Connection : public QObject {
|
||||||
public slots:
|
public slots:
|
||||||
void checkNext();
|
void checkNext();
|
||||||
void finishCommand(bool success, QString &response);
|
void finishCommand(bool success, QString &response);
|
||||||
|
void pendingLoadFinished(bool success);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void readLine();
|
void readLine();
|
||||||
void readDataBlock();
|
void readDataBlock();
|
||||||
void processNext(const char *line);
|
void processNext(const char *line);
|
||||||
Command *createCommand(const char *name);
|
Command *createCommand(const char *name);
|
||||||
|
void processArgument(const char *line);
|
||||||
void startCommand();
|
void startCommand();
|
||||||
void continueCommand(const char *line);
|
|
||||||
void writeResponse(bool success, QString &response);
|
void writeResponse(bool success, QString &response);
|
||||||
|
|
||||||
QTcpSocket *m_socket;
|
QTcpSocket *m_socket;
|
||||||
|
QString m_commandName;
|
||||||
Command *m_command;
|
Command *m_command;
|
||||||
QStringList m_arguments;
|
QStringList m_arguments;
|
||||||
int m_argumentsExpected;
|
int m_argumentsExpected;
|
||||||
|
|
|
@ -12,6 +12,9 @@ void Visit::start(QStringList &arguments) {
|
||||||
|
|
||||||
void Visit::loadFinished(bool success) {
|
void Visit::loadFinished(bool success) {
|
||||||
QString response;
|
QString response;
|
||||||
|
if (!success)
|
||||||
|
response = page()->failureString();
|
||||||
|
|
||||||
emit finished(success, response);
|
emit finished(success, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,9 @@ WebPage::WebPage(QObject *parent) : QWebPage(parent) {
|
||||||
strcpy(javascriptString, (const char *)javascript.data());
|
strcpy(javascriptString, (const char *)javascript.data());
|
||||||
javascriptString[javascript.size()] = 0;
|
javascriptString[javascript.size()] = 0;
|
||||||
m_capybaraJavascript = javascriptString;
|
m_capybaraJavascript = javascriptString;
|
||||||
|
m_loading = false;
|
||||||
|
connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
|
||||||
|
connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPage::injectJavascriptHelpers() {
|
void WebPage::injectJavascriptHelpers() {
|
||||||
|
@ -40,3 +43,19 @@ void WebPage::javaScriptConsoleMessage(const QString &message, int lineNumber, c
|
||||||
std::cout << qPrintable(message) << std::endl;
|
std::cout << qPrintable(message) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebPage::loadStarted() {
|
||||||
|
m_loading = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebPage::loadFinished(bool success) {
|
||||||
|
m_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebPage::isLoading() const {
|
||||||
|
return m_loading;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString WebPage::failureString() {
|
||||||
|
return QString("Unable to load URL: ") + mainFrame()->url().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,20 @@ class WebPage : public QWebPage {
|
||||||
WebPage(QObject *parent = 0);
|
WebPage(QObject *parent = 0);
|
||||||
QVariant invokeCapybaraFunction(const char *name, QStringList &arguments);
|
QVariant invokeCapybaraFunction(const char *name, QStringList &arguments);
|
||||||
QVariant invokeCapybaraFunction(QString &name, QStringList &arguments);
|
QVariant invokeCapybaraFunction(QString &name, QStringList &arguments);
|
||||||
|
QString failureString();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool shouldInterruptJavaScript();
|
bool shouldInterruptJavaScript();
|
||||||
void injectJavascriptHelpers();
|
void injectJavascriptHelpers();
|
||||||
|
void loadStarted();
|
||||||
|
void loadFinished(bool);
|
||||||
|
bool isLoading() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
|
virtual void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_capybaraJavascript;
|
QString m_capybaraJavascript;
|
||||||
|
bool m_loading;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue