2011-08-01 17:09:08 +00:00
|
|
|
#include <QtGui>
|
|
|
|
#include <QtWebKit>
|
|
|
|
#include <QFile>
|
|
|
|
#include <QTextStream>
|
|
|
|
#include <iostream>
|
2011-10-25 19:41:22 +00:00
|
|
|
#include <sstream>
|
2011-08-01 17:09:08 +00:00
|
|
|
#include <QQueue>
|
|
|
|
|
|
|
|
#include "Runner.h"
|
2011-10-25 19:41:22 +00:00
|
|
|
#include "Page.h"
|
2011-08-01 17:09:08 +00:00
|
|
|
|
2011-09-02 19:52:19 +00:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
Runner::Runner() : QObject()
|
2011-10-26 02:22:29 +00:00
|
|
|
, runs(0)
|
2011-09-02 19:52:19 +00:00
|
|
|
, hasErrors(false)
|
2011-11-05 18:19:41 +00:00
|
|
|
, _hasSpecFailure(false)
|
2011-09-02 19:52:19 +00:00
|
|
|
, usedConsole(false)
|
|
|
|
, isFinished(false)
|
2011-10-25 19:41:22 +00:00
|
|
|
, useColors(false)
|
2011-09-06 15:37:29 +00:00
|
|
|
{
|
2011-10-26 02:22:29 +00:00
|
|
|
page.settings()->enablePersistentStorage();
|
|
|
|
ticker.setInterval(TIMER_TICK);
|
2011-09-06 15:37:29 +00:00
|
|
|
|
2011-10-26 02:22:29 +00:00
|
|
|
connect(&ticker, SIGNAL(timeout()), this, SLOT(timerEvent()));
|
|
|
|
connect(&page, SIGNAL(loadFinished(bool)), this, SLOT(watch(bool)));
|
|
|
|
connect(&page, SIGNAL(handleError(const QString &, int, const QString &)), this, SLOT(handleError(const QString &, int, const QString &)));
|
|
|
|
connect(page.mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(addJHW()));
|
2011-09-02 19:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Runner::addFile(const QString &spec) {
|
|
|
|
runnerFiles.enqueue(spec);
|
|
|
|
}
|
|
|
|
|
2011-10-25 19:41:22 +00:00
|
|
|
void Runner::go() {
|
2011-10-26 02:22:29 +00:00
|
|
|
ticker.stop();
|
|
|
|
page.setPreferredContentsSize(QSize(1024, 600));
|
2011-09-02 19:52:19 +00:00
|
|
|
addJHW();
|
2011-10-24 20:40:08 +00:00
|
|
|
|
2011-09-02 19:52:19 +00:00
|
|
|
loadSpec();
|
|
|
|
}
|
2011-10-25 19:41:22 +00:00
|
|
|
void Runner::addJHW() {
|
2011-10-26 02:22:29 +00:00
|
|
|
page.mainFrame()->addToJavaScriptWindowObject("JHW", this);
|
2011-09-02 19:52:19 +00:00
|
|
|
}
|
|
|
|
|
2011-10-25 19:41:22 +00:00
|
|
|
void Runner::handleError(const QString &message, int lineNumber, const QString &sourceID) {
|
|
|
|
QString messageEscaped = QString(message);
|
|
|
|
QString sourceIDEscaped = QString(sourceID);
|
|
|
|
|
|
|
|
messageEscaped.replace(QString("\""), QString("\\\""));
|
|
|
|
sourceIDEscaped.replace(QString("\""), QString("\\\""));
|
|
|
|
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << lineNumber;
|
|
|
|
|
|
|
|
QString command("JHW._handleError(\"" + messageEscaped + "\", " + QString(ss.str().c_str()) + ", \"" + sourceIDEscaped + "\"); false;");
|
|
|
|
|
2011-10-26 02:22:29 +00:00
|
|
|
page.mainFrame()->evaluateJavaScript(command);
|
2011-10-25 19:41:22 +00:00
|
|
|
|
|
|
|
hasErrors = true;
|
|
|
|
}
|
|
|
|
|
2011-09-02 19:52:19 +00:00
|
|
|
void Runner::loadSpec()
|
|
|
|
{
|
2011-12-29 23:37:23 +00:00
|
|
|
QVectorIterator<QString> iterator(reportFiles);
|
|
|
|
|
|
|
|
while (iterator.hasNext()) {
|
|
|
|
QFile *outputFile = new QFile(iterator.next());
|
2011-10-24 20:40:08 +00:00
|
|
|
outputFile->open(QIODevice::WriteOnly);
|
2011-12-12 19:54:53 +00:00
|
|
|
outputFiles.enqueue(outputFile);
|
2011-10-24 20:40:08 +00:00
|
|
|
}
|
|
|
|
|
2011-10-26 02:22:29 +00:00
|
|
|
page.mainFrame()->load(runnerFiles.dequeue());
|
|
|
|
ticker.start();
|
2011-09-02 19:52:19 +00:00
|
|
|
}
|
|
|
|
|
2011-10-25 19:41:22 +00:00
|
|
|
void Runner::watch(bool ok) {
|
2011-09-02 19:52:19 +00:00
|
|
|
if (!ok) {
|
2011-10-26 02:22:29 +00:00
|
|
|
std::cerr << "Can't load " << qPrintable(page.mainFrame()->url().toString()) << ", the file may be broken." << std::endl;
|
2011-09-02 19:52:19 +00:00
|
|
|
std::cerr << "Out of curiosity, did your tests try to submit a form and you haven't prevented that?" << std::endl;
|
|
|
|
std::cerr << "Try running your tests in your browser with the Jasmine server and see what happens." << std::endl;
|
|
|
|
QApplication::instance()->exit(1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-26 02:22:29 +00:00
|
|
|
page.mainFrame()->evaluateJavaScript(QString("JHW._setColors(") + (useColors ? QString("true") : QString("false")) + QString("); false;"));
|
2011-09-02 19:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Runner::setColors(bool colors) {
|
2011-10-25 19:41:22 +00:00
|
|
|
useColors = colors;
|
2011-09-02 19:52:19 +00:00
|
|
|
}
|
|
|
|
|
2011-10-25 20:15:52 +00:00
|
|
|
void Runner::hasUsedConsole() {
|
|
|
|
usedConsole = true;
|
|
|
|
}
|
|
|
|
|
2011-10-26 02:22:29 +00:00
|
|
|
void Runner::hasError() {
|
|
|
|
hasErrors = true;
|
|
|
|
}
|
|
|
|
|
2011-11-05 18:19:41 +00:00
|
|
|
void Runner::hasSpecFailure() {
|
|
|
|
_hasSpecFailure = true;
|
|
|
|
}
|
|
|
|
|
2011-12-29 23:37:23 +00:00
|
|
|
void Runner::setReportFiles(QStack<QString> &files) {
|
|
|
|
reportFiles = files;
|
2011-09-02 19:52:19 +00:00
|
|
|
}
|
|
|
|
|
2011-09-06 15:37:29 +00:00
|
|
|
void Runner::timerPause() {
|
2011-10-26 02:22:29 +00:00
|
|
|
ticker.stop();
|
2011-09-06 15:37:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Runner::timerDone() {
|
2011-10-26 02:22:29 +00:00
|
|
|
ticker.start();
|
2011-09-06 15:37:29 +00:00
|
|
|
}
|
|
|
|
|
2011-11-10 18:52:42 +00:00
|
|
|
void Runner::ping() {
|
|
|
|
runs = 0;
|
|
|
|
}
|
|
|
|
|
2011-12-29 23:37:23 +00:00
|
|
|
void Runner::setSeed(QString s) {
|
|
|
|
seed = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Runner::getSeed() {
|
|
|
|
return seed;
|
|
|
|
}
|
|
|
|
|
2011-10-24 20:40:08 +00:00
|
|
|
void Runner::print(const QString &fh, const QString &content) {
|
|
|
|
if (fh == "stdout") {
|
|
|
|
std::cout << qPrintable(content);
|
|
|
|
std::cout.flush();
|
|
|
|
}
|
2011-09-02 19:52:19 +00:00
|
|
|
|
2011-10-24 20:40:08 +00:00
|
|
|
if (fh == "stderr") {
|
|
|
|
std::cerr << qPrintable(content);
|
|
|
|
std::cerr.flush();
|
|
|
|
}
|
2011-09-02 19:52:19 +00:00
|
|
|
|
2011-12-29 23:37:23 +00:00
|
|
|
if (fh.contains("report")) {
|
|
|
|
int index = (int)fh.split(":").last().toUInt();
|
2011-12-12 19:54:53 +00:00
|
|
|
|
2011-12-29 23:37:23 +00:00
|
|
|
QTextStream ts(outputFiles.at(index));
|
|
|
|
ts << qPrintable(content);
|
|
|
|
ts.flush();
|
2011-10-24 20:40:08 +00:00
|
|
|
}
|
2011-09-02 19:52:19 +00:00
|
|
|
}
|
|
|
|
|
2011-10-24 20:40:08 +00:00
|
|
|
void Runner::finishSuite() {
|
2011-09-02 19:52:19 +00:00
|
|
|
isFinished = true;
|
2011-12-12 17:22:32 +00:00
|
|
|
runs = 0;
|
2011-09-02 19:52:19 +00:00
|
|
|
}
|
2011-08-01 17:09:08 +00:00
|
|
|
|
2011-10-24 20:40:08 +00:00
|
|
|
void Runner::timerEvent() {
|
2011-10-26 02:22:29 +00:00
|
|
|
++runs;
|
2011-08-01 17:09:08 +00:00
|
|
|
|
2011-10-26 02:22:29 +00:00
|
|
|
if (hasErrors && runs > 2)
|
2011-09-02 19:52:19 +00:00
|
|
|
QApplication::instance()->exit(1);
|
2011-08-01 17:09:08 +00:00
|
|
|
|
2011-12-12 17:22:32 +00:00
|
|
|
if (isFinished && runs > 2) {
|
2011-12-29 23:37:23 +00:00
|
|
|
while (!outputFiles.isEmpty()) {
|
|
|
|
outputFiles.dequeue()->close();
|
2011-10-25 19:41:22 +00:00
|
|
|
}
|
2011-10-24 20:40:08 +00:00
|
|
|
|
2011-09-02 19:52:19 +00:00
|
|
|
int exitCode = 0;
|
2011-11-05 18:19:41 +00:00
|
|
|
if (_hasSpecFailure || hasErrors) {
|
2011-09-02 19:52:19 +00:00
|
|
|
exitCode = 1;
|
2011-08-01 17:09:08 +00:00
|
|
|
} else {
|
2011-09-02 19:52:19 +00:00
|
|
|
if (usedConsole) {
|
|
|
|
exitCode = 2;
|
2011-08-01 17:09:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-02 19:52:19 +00:00
|
|
|
bool runAgain = true;
|
2011-08-01 17:09:08 +00:00
|
|
|
|
2011-09-02 19:52:19 +00:00
|
|
|
if (runnerFiles.count() == 0) {
|
|
|
|
runAgain = false;
|
|
|
|
} else {
|
|
|
|
if (exitCode == 1) {
|
2011-08-01 17:09:08 +00:00
|
|
|
runAgain = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-02 19:52:19 +00:00
|
|
|
if (runAgain) {
|
|
|
|
isFinished = false;
|
|
|
|
loadSpec();
|
|
|
|
} else {
|
|
|
|
QApplication::instance()->exit(exitCode);
|
2011-08-01 17:09:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-26 02:22:29 +00:00
|
|
|
if (runs > MAX_LOOPS) {
|
|
|
|
std::cerr << "WARNING: too many runs and the test is still not finished!" << std::endl;
|
2011-09-02 19:52:19 +00:00
|
|
|
QApplication::instance()->exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|