1
0
Fork 0
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:
Joe Ferris 2011-03-09 00:08:30 -05:00
parent 5965f8a5af
commit a8e64a5f10
6 changed files with 92 additions and 24 deletions

View file

@ -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

View file

@ -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());
} }

View file

@ -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;

View file

@ -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);
} }

View file

@ -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();
}

View file

@ -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;
}; };