halfway in the middle of the reporting change
This commit is contained in:
parent
68a2888d35
commit
e5510f13d0
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,3 +11,4 @@ moc_*.*
|
||||
.DS_Store
|
||||
hydra-runner.log
|
||||
jhw-test
|
||||
.jhw-cache/
|
||||
|
@ -26,7 +26,8 @@ guard 'jasmine-headless-webkit', :all_on_start => false do
|
||||
end
|
||||
|
||||
def compile
|
||||
system %{cd ext/jasmine-webkit-specrunner && ruby test.rb && ruby extconf.rb}
|
||||
#system %{cd ext/jasmine-webkit-specrunner && ruby test.rb && ruby extconf.rb}
|
||||
system %{cd ext/jasmine-webkit-specrunner && ruby extconf.rb}
|
||||
end
|
||||
|
||||
compile
|
||||
|
@ -1,10 +1,54 @@
|
||||
#include "ReportFileOutput.h"
|
||||
|
||||
ReportFileOutput::ReportFileOutput() : QObject() {
|
||||
using namespace std;
|
||||
|
||||
ReportFileOutput::ReportFileOutput() : QObject() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void ReportFileOutput::reset() {
|
||||
buffer = new stringstream();
|
||||
|
||||
outputIO = buffer;
|
||||
}
|
||||
|
||||
void ReportFileOutput::passed(const QString &specDetail) {
|
||||
*outputIO << "PASS||" << qPrintable(specDetail) << std::endl;
|
||||
successes.push(specDetail);
|
||||
}
|
||||
|
||||
void ReportFileOutput::failed(const QString &specDetail) {
|
||||
*outputIO << "FAIL||" << qPrintable(specDetail) << std::endl;
|
||||
failures.push(specDetail);
|
||||
}
|
||||
|
||||
void ReportFileOutput::errorLog(const QString &msg, int lineNumber, const QString &sourceID) {
|
||||
*outputIO << "ERROR||" << qPrintable(msg) << "||" << qPrintable(sourceID) << ":" << lineNumber << std::endl;
|
||||
}
|
||||
|
||||
void ReportFileOutput::consoleLog(const QString &msg) {
|
||||
*outputIO << "CONSOLE||" << qPrintable(msg) << std::endl;
|
||||
}
|
||||
|
||||
void ReportFileOutput::internalLog(const QString &, const QString &) {}
|
||||
void ReportFileOutput::logSpecFilename(const QString &) {}
|
||||
void ReportFileOutput::logSpecResult(const QString &) {}
|
||||
|
||||
void ReportFileOutput::reportFailure(const QString &totalTests, const QString &failedTests, const QString &duration) {
|
||||
reportTotals(totalTests, failedTests, duration, false);
|
||||
}
|
||||
|
||||
void ReportFileOutput::reportSuccess(const QString &totalTests, const QString &failedTests, const QString &duration) {
|
||||
reportTotals(totalTests, failedTests, duration, false);
|
||||
}
|
||||
|
||||
void ReportFileOutput::reportSuccessWithJSErrors(const QString &totalTests, const QString &failedTests, const QString &duration) {
|
||||
reportTotals(totalTests, failedTests, duration, true);
|
||||
}
|
||||
|
||||
void ReportFileOutput::reportTotals(const QString &totalTests, const QString &failedTests, const QString &duration, bool hasJavaScriptError) {
|
||||
*outputIO << "TOTAL||" << qPrintable(totalTests) << "||" << qPrintable(failedTests) << "||" << qPrintable(duration) << "||";
|
||||
*outputIO << (hasJavaScriptError ? "T" : "F");
|
||||
*outputIO << std::endl;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,9 @@
|
||||
#include <QObject>
|
||||
#include <iostream>
|
||||
#include <QStack>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class ReportFileOutput : public QObject {
|
||||
public:
|
||||
@ -21,9 +24,14 @@ class ReportFileOutput : public QObject {
|
||||
void reportSuccess(const QString &totalTests, const QString &failedTests, const QString &duration);
|
||||
void reportSuccessWithJSErrors(const QString &totalTests, const QString &failedTests, const QString &duration);
|
||||
|
||||
std::ostream *outputIO;
|
||||
void reset();
|
||||
|
||||
stringstream *buffer;
|
||||
stringstream *outputIO;
|
||||
QStack<QString> successes;
|
||||
QStack<QString> failures;
|
||||
private:
|
||||
void reportTotals(const QString &totalTests, const QString &failedTests, const QString &duration, bool hasJavaScriptError);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -23,11 +23,66 @@ void ReportFileOutputTest::testFailed() {
|
||||
ReportFileOutput output;
|
||||
|
||||
output.outputIO = &buffer;
|
||||
output.passed("test||done||file.js:23");
|
||||
output.failed("test||done||file.js:23");
|
||||
QVERIFY(buffer.str() == "FAIL||test||done||file.js:23\n");
|
||||
QVERIFY(output.successes.size() == 0);
|
||||
QVERIFY(output.failures.size() == 1);
|
||||
}
|
||||
|
||||
void ReportFileOutputTest::testErrorLog() {
|
||||
stringstream buffer;
|
||||
ReportFileOutput output;
|
||||
|
||||
output.outputIO = &buffer;
|
||||
output.errorLog("JS Error", 23, "file.js");
|
||||
QVERIFY(buffer.str() == "ERROR||JS Error||file.js:23\n");
|
||||
}
|
||||
|
||||
void ReportFileOutputTest::testConsoleLog() {
|
||||
stringstream buffer;
|
||||
ReportFileOutput output;
|
||||
|
||||
output.outputIO = &buffer;
|
||||
output.consoleLog("Console");
|
||||
QVERIFY(buffer.str() == "CONSOLE||Console\n");
|
||||
}
|
||||
|
||||
void ReportFileOutputTest::testStubMethods() {
|
||||
stringstream buffer;
|
||||
ReportFileOutput output;
|
||||
|
||||
output.outputIO = &buffer;
|
||||
output.internalLog("Internal", "Log");
|
||||
output.logSpecFilename("Filename");
|
||||
output.logSpecResult("REsult");
|
||||
}
|
||||
|
||||
void ReportFileOutputTest::testReportFailure() {
|
||||
stringstream buffer;
|
||||
ReportFileOutput output;
|
||||
|
||||
output.outputIO = &buffer;
|
||||
output.reportFailure("5", "2", "1.5");
|
||||
QVERIFY(buffer.str() == "TOTAL||5||2||1.5||F\n");
|
||||
}
|
||||
|
||||
void ReportFileOutputTest::testReportSuccess() {
|
||||
stringstream buffer;
|
||||
ReportFileOutput output;
|
||||
|
||||
output.outputIO = &buffer;
|
||||
output.reportSuccess("5", "0", "1.5");
|
||||
QVERIFY(buffer.str() == "TOTAL||5||0||1.5||F\n");
|
||||
}
|
||||
|
||||
void ReportFileOutputTest::testReportSuccessWithJSErrors() {
|
||||
stringstream buffer;
|
||||
ReportFileOutput output;
|
||||
|
||||
output.outputIO = &buffer;
|
||||
output.reportSuccessWithJSErrors("5", "0", "1.5");
|
||||
QVERIFY(buffer.str() == "TOTAL||5||0||1.5||T\n");
|
||||
}
|
||||
|
||||
QTEST_MAIN(ReportFileOutputTest);
|
||||
|
||||
|
@ -15,6 +15,12 @@ class ReportFileOutputTest : public QObject {
|
||||
private slots:
|
||||
void testPassed();
|
||||
void testFailed();
|
||||
void testErrorLog();
|
||||
void testConsoleLog();
|
||||
void testStubMethods();
|
||||
void testReportFailure();
|
||||
void testReportSuccess();
|
||||
void testReportSuccessWithJSErrors();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -7,197 +7,195 @@
|
||||
|
||||
#include "Runner.h"
|
||||
|
||||
Runner::Runner() : QObject()
|
||||
, m_runs(0)
|
||||
, hasErrors(false)
|
||||
, usedConsole(false)
|
||||
, isFinished(false)
|
||||
, didFail(false) {
|
||||
m_page.settings()->enablePersistentStorage();
|
||||
connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(watch(bool)));
|
||||
connect(&m_page, SIGNAL(consoleLog(QString, int, QString)), this, SLOT(errorLog(QString, int, QString)));
|
||||
connect(&m_page, SIGNAL(internalLog(QString, QString)), this, SLOT(internalLog(QString, QString)));
|
||||
connect(m_page.mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(addJHW()));
|
||||
using namespace std;
|
||||
|
||||
Runner::Runner() : QObject()
|
||||
, m_runs(0)
|
||||
, hasErrors(false)
|
||||
, usedConsole(false)
|
||||
, isFinished(false)
|
||||
, didFail(false) {
|
||||
m_page.settings()->enablePersistentStorage();
|
||||
connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(watch(bool)));
|
||||
connect(&m_page, SIGNAL(consoleLog(QString, int, QString)), this, SLOT(errorLog(QString, int, QString)));
|
||||
connect(&m_page, SIGNAL(internalLog(QString, QString)), this, SLOT(internalLog(QString, QString)));
|
||||
connect(m_page.mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(addJHW()));
|
||||
}
|
||||
|
||||
void Runner::addFile(const QString &spec) {
|
||||
runnerFiles.enqueue(spec);
|
||||
}
|
||||
|
||||
void Runner::go()
|
||||
{
|
||||
m_ticker.stop();
|
||||
m_page.setPreferredContentsSize(QSize(1024, 600));
|
||||
addJHW();
|
||||
loadSpec();
|
||||
}
|
||||
void Runner::addJHW()
|
||||
{
|
||||
m_page.mainFrame()->addToJavaScriptWindowObject("JHW", this);
|
||||
}
|
||||
|
||||
void Runner::loadSpec()
|
||||
{
|
||||
m_page.mainFrame()->load(runnerFiles.dequeue());
|
||||
m_ticker.start(200, this);
|
||||
}
|
||||
|
||||
void Runner::watch(bool ok)
|
||||
{
|
||||
if (!ok) {
|
||||
std::cerr << "Can't load " << qPrintable(m_page.mainFrame()->url().toString()) << ", the file may be broken." << std::endl;
|
||||
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;
|
||||
}
|
||||
|
||||
void Runner::addFile(const QString &spec) {
|
||||
runnerFiles.enqueue(spec);
|
||||
}
|
||||
m_ticker.start(200, this);
|
||||
}
|
||||
|
||||
void Runner::go()
|
||||
{
|
||||
m_ticker.stop();
|
||||
m_page.setPreferredContentsSize(QSize(1024, 600));
|
||||
addJHW();
|
||||
loadSpec();
|
||||
}
|
||||
void Runner::addJHW()
|
||||
{
|
||||
m_page.mainFrame()->addToJavaScriptWindowObject("JHW", this);
|
||||
}
|
||||
bool Runner::hasElement(const char *select)
|
||||
{
|
||||
return !m_page.mainFrame()->findFirstElement(select).isNull();
|
||||
}
|
||||
|
||||
void Runner::loadSpec()
|
||||
{
|
||||
m_page.mainFrame()->load(runnerFiles.dequeue());
|
||||
m_ticker.start(200, this);
|
||||
}
|
||||
void Runner::setColors(bool colors) {
|
||||
consoleOutput.showColors = colors;
|
||||
}
|
||||
|
||||
void Runner::watch(bool ok)
|
||||
{
|
||||
if (!ok) {
|
||||
std::cerr << "Can't load " << qPrintable(m_page.mainFrame()->url().toString()) << ", the file may be broken." << std::endl;
|
||||
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;
|
||||
}
|
||||
void Runner::reportFile(const QString &file) {
|
||||
reportFileName = file;
|
||||
}
|
||||
|
||||
m_ticker.start(200, this);
|
||||
}
|
||||
bool Runner::hasError() {
|
||||
return hasErrors;
|
||||
}
|
||||
|
||||
bool Runner::hasElement(const char *select)
|
||||
{
|
||||
return !m_page.mainFrame()->findFirstElement(select).isNull();
|
||||
}
|
||||
void Runner::specPassed(const QString &specDetail) {
|
||||
consoleOutput.passed(specDetail);
|
||||
reportFileOutput.passed(specDetail);
|
||||
}
|
||||
|
||||
void Runner::setColors(bool colors)
|
||||
{
|
||||
consoleOutput.showColors = colors;
|
||||
}
|
||||
void Runner::specFailed(const QString &specDetail) {
|
||||
consoleOutput.failed(specDetail);
|
||||
reportFileOutput.failed(specDetail);
|
||||
|
||||
void Runner::reportFile(const QString &file)
|
||||
{
|
||||
reportFilename = file;
|
||||
}
|
||||
didFail = true;
|
||||
failedSpecs.push(specDetail);
|
||||
}
|
||||
|
||||
bool Runner::hasError() {
|
||||
return hasErrors;
|
||||
}
|
||||
void Runner::errorLog(const QString &msg, int lineNumber, const QString &sourceID)
|
||||
{
|
||||
consoleOutput.errorLog(msg, lineNumber, sourceID);
|
||||
reportFileOutput.errorLog(msg, lineNumber, sourceID);
|
||||
|
||||
void Runner::specPassed()
|
||||
{
|
||||
consoleOutput.passed("");
|
||||
}
|
||||
hasErrors = true;
|
||||
m_runs = 0;
|
||||
m_ticker.start(200, this);
|
||||
}
|
||||
|
||||
void Runner::specFailed(const QString &specDetail)
|
||||
{
|
||||
consoleOutput.failed("");
|
||||
didFail = true;
|
||||
failedSpecs.push(specDetail);
|
||||
}
|
||||
void Runner::internalLog(const QString ¬e, const QString &msg) {
|
||||
consoleOutput.internalLog(note, msg);
|
||||
reportFileOutput.internalLog(note, msg);
|
||||
}
|
||||
|
||||
void Runner::errorLog(const QString &msg, int lineNumber, const QString &sourceID)
|
||||
{
|
||||
consoleOutput.errorLog(msg, lineNumber, sourceID);
|
||||
void Runner::log(const QString &msg)
|
||||
{
|
||||
usedConsole = true;
|
||||
consoleOutput.consoleLog(msg);
|
||||
reportFileOutput.consoleLog(msg);
|
||||
}
|
||||
|
||||
hasErrors = true;
|
||||
m_runs = 0;
|
||||
m_ticker.start(200, this);
|
||||
}
|
||||
void Runner::leavePageAttempt(const QString &msg)
|
||||
{
|
||||
consoleOutput.internalLog("error", msg);
|
||||
m_page.oneFalseConfirm();
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
void Runner::internalLog(const QString ¬e, const QString &msg) {
|
||||
consoleOutput.internalLog(note, msg);
|
||||
}
|
||||
void Runner::printName(const QString &name)
|
||||
{
|
||||
consoleOutput.logSpecFilename(name);
|
||||
}
|
||||
|
||||
void Runner::log(const QString &msg)
|
||||
{
|
||||
usedConsole = true;
|
||||
consoleOutput.consoleLog(msg);
|
||||
}
|
||||
void Runner::printResult(const QString &result)
|
||||
{
|
||||
consoleOutput.logSpecResult(result);
|
||||
}
|
||||
|
||||
void Runner::leavePageAttempt(const QString &msg)
|
||||
{
|
||||
consoleOutput.internalLog("error", msg);
|
||||
m_page.oneFalseConfirm();
|
||||
hasErrors = true;
|
||||
}
|
||||
|
||||
void Runner::printName(const QString &name)
|
||||
{
|
||||
consoleOutput.logSpecFilename(name);
|
||||
}
|
||||
|
||||
void Runner::printResult(const QString &result)
|
||||
{
|
||||
consoleOutput.logSpecResult(result);
|
||||
}
|
||||
|
||||
void Runner::finishSuite(const QString &duration, const QString &total, const QString& failed)
|
||||
{
|
||||
if (didFail) {
|
||||
consoleOutput.reportFailure(total, failed, duration);
|
||||
void Runner::finishSuite(const QString &duration, const QString &total, const QString& failed)
|
||||
{
|
||||
if (didFail) {
|
||||
consoleOutput.reportFailure(total, failed, duration);
|
||||
reportFileOutput.reportFailure(total, failed, duration);
|
||||
} else {
|
||||
if (hasErrors) {
|
||||
consoleOutput.reportSuccessWithJSErrors(total, failed, duration);
|
||||
reportFileOutput.reportSuccessWithJSErrors(total, failed, duration);
|
||||
} else {
|
||||
if (hasErrors) {
|
||||
consoleOutput.reportSuccessWithJSErrors(total, failed, duration);
|
||||
} else {
|
||||
consoleOutput.reportSuccess(total, failed, duration);
|
||||
}
|
||||
consoleOutput.reportSuccess(total, failed, duration);
|
||||
reportFileOutput.reportSuccess(total, failed, duration);
|
||||
}
|
||||
|
||||
if (!reportFilename.isEmpty()) {
|
||||
QFile reportFH(reportFilename);
|
||||
|
||||
if (reportFH.open(QFile::WriteOnly)) {
|
||||
QTextStream report(&reportFH);
|
||||
report << qPrintable(total) << "/" << qPrintable(failed) << "/";
|
||||
report << (usedConsole ? "T" : "F");
|
||||
report << "/" << qPrintable(duration) << "\n";
|
||||
|
||||
QString failedSpec;
|
||||
|
||||
while (!failedSpecs.isEmpty()) {
|
||||
failedSpec = failedSpecs.pop();
|
||||
report << qPrintable(failedSpec) << "\n";
|
||||
}
|
||||
|
||||
reportFH.close();
|
||||
}
|
||||
}
|
||||
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
void Runner::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
++m_runs;
|
||||
if (!reportFileName.isEmpty()) {
|
||||
QFile outputFile(reportFileName);
|
||||
outputFile.open(QIODevice::WriteOnly);
|
||||
|
||||
if (event->timerId() != m_ticker.timerId())
|
||||
return;
|
||||
QTextStream ts(&outputFile);
|
||||
|
||||
if (hasErrors && m_runs > 2)
|
||||
QApplication::instance()->exit(1);
|
||||
ts << reportFileOutput.outputIO->str().c_str();
|
||||
|
||||
if (isFinished) {
|
||||
int exitCode = 0;
|
||||
if (didFail || hasErrors) {
|
||||
exitCode = 1;
|
||||
} else {
|
||||
if (usedConsole) {
|
||||
exitCode = 2;
|
||||
}
|
||||
outputFile.close();
|
||||
}
|
||||
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
void Runner::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
++m_runs;
|
||||
|
||||
if (event->timerId() != m_ticker.timerId())
|
||||
return;
|
||||
|
||||
if (hasErrors && m_runs > 2)
|
||||
QApplication::instance()->exit(1);
|
||||
|
||||
if (isFinished) {
|
||||
int exitCode = 0;
|
||||
if (didFail || hasErrors) {
|
||||
exitCode = 1;
|
||||
} else {
|
||||
if (usedConsole) {
|
||||
exitCode = 2;
|
||||
}
|
||||
}
|
||||
|
||||
bool runAgain = true;
|
||||
bool runAgain = true;
|
||||
|
||||
if (runnerFiles.count() == 0) {
|
||||
if (runnerFiles.count() == 0) {
|
||||
runAgain = false;
|
||||
} else {
|
||||
if (exitCode == 1) {
|
||||
runAgain = false;
|
||||
} else {
|
||||
if (exitCode == 1) {
|
||||
runAgain = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (runAgain) {
|
||||
isFinished = false;
|
||||
loadSpec();
|
||||
} else {
|
||||
QApplication::instance()->exit(exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_runs > 30) {
|
||||
std::cout << "WARNING: too many runs and the test is still not finished!" << std::endl;
|
||||
QApplication::instance()->exit(1);
|
||||
if (runAgain) {
|
||||
isFinished = false;
|
||||
loadSpec();
|
||||
} else {
|
||||
QApplication::instance()->exit(exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_runs > 30) {
|
||||
std::cout << "WARNING: too many runs and the test is still not finished!" << std::endl;
|
||||
QApplication::instance()->exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,53 +6,57 @@
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <QQueue>
|
||||
|
||||
#include "Page.h"
|
||||
#include "ConsoleOutput.h"
|
||||
#include "ReportFileOutput.h"
|
||||
|
||||
class Runner: public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Runner();
|
||||
void setColors(bool colors);
|
||||
void reportFile(const QString &file);
|
||||
void addFile(const QString &spec);
|
||||
void go();
|
||||
using namespace std;
|
||||
|
||||
class Runner: public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Runner();
|
||||
void setColors(bool colors);
|
||||
void reportFile(const QString &file);
|
||||
void addFile(const QString &spec);
|
||||
void go();
|
||||
public slots:
|
||||
void log(const QString &msg);
|
||||
bool hasError();
|
||||
void leavePageAttempt(const QString &msg);
|
||||
void specPassed();
|
||||
void specFailed(const QString &specDetail);
|
||||
void printName(const QString &name);
|
||||
void printResult(const QString &result);
|
||||
void finishSuite(const QString &duration, const QString &total, const QString& failed);
|
||||
bool hasError();
|
||||
void leavePageAttempt(const QString &msg);
|
||||
void specPassed(const QString &specDetail);
|
||||
void specFailed(const QString &specDetail);
|
||||
void printName(const QString &name);
|
||||
void printResult(const QString &result);
|
||||
void finishSuite(const QString &duration, const QString &total, const QString& failed);
|
||||
private slots:
|
||||
void watch(bool ok);
|
||||
void errorLog(const QString &msg, int lineNumber, const QString &sourceID);
|
||||
void internalLog(const QString ¬e, const QString &msg);
|
||||
void addJHW();
|
||||
protected:
|
||||
bool hasElement(const char *select);
|
||||
void timerEvent(QTimerEvent *event);
|
||||
private:
|
||||
Page m_page;
|
||||
QBasicTimer m_ticker;
|
||||
int m_runs;
|
||||
bool hasErrors;
|
||||
bool usedConsole;
|
||||
bool isFinished;
|
||||
bool didFail;
|
||||
QQueue<QString> runnerFiles;
|
||||
QString reportFilename;
|
||||
QStack<QString> failedSpecs;
|
||||
void errorLog(const QString &msg, int lineNumber, const QString &sourceID);
|
||||
void internalLog(const QString ¬e, const QString &msg);
|
||||
void addJHW();
|
||||
protected:
|
||||
bool hasElement(const char *select);
|
||||
void timerEvent(QTimerEvent *event);
|
||||
private:
|
||||
Page m_page;
|
||||
QBasicTimer m_ticker;
|
||||
int m_runs;
|
||||
bool hasErrors;
|
||||
bool usedConsole;
|
||||
bool isFinished;
|
||||
bool didFail;
|
||||
QQueue<QString> runnerFiles;
|
||||
QStack<QString> failedSpecs;
|
||||
|
||||
ConsoleOutput consoleOutput;
|
||||
ReportFileOutput reportFileOutput;
|
||||
ConsoleOutput consoleOutput;
|
||||
ReportFileOutput reportFileOutput;
|
||||
|
||||
void loadSpec();
|
||||
};
|
||||
QString reportFileName;
|
||||
|
||||
void loadSpec();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -56,11 +56,13 @@ int main(int argc, char** argv)
|
||||
app.setApplicationName("jasmine-headless-webkit");
|
||||
Runner runner;
|
||||
runner.setColors(showColors);
|
||||
|
||||
runner.reportFile(reporter);
|
||||
|
||||
for (index = optind; index < argc; index++) {
|
||||
runner.addFile(QString::fromLocal8Bit(argv[index]));
|
||||
}
|
||||
|
||||
runner.go();
|
||||
|
||||
return app.exec();
|
||||
|
@ -8,19 +8,19 @@ class window.HeadlessReporterResult
|
||||
@results.push(message)
|
||||
print: ->
|
||||
output = @name
|
||||
bestChoice = this._findSpecLine()
|
||||
bestChoice = HeadlessReporterResult.findSpecLine(@splitName)
|
||||
output += " (#{bestChoice.file}:#{bestChoice.lineNumber})" if bestChoice.file
|
||||
|
||||
JHW.printName(output)
|
||||
for result in @results
|
||||
JHW.printResult(result)
|
||||
_findSpecLine: ->
|
||||
@findSpecLine: (splitName) ->
|
||||
bestChoice = { accuracy: 0, file: null, lineNumber: null }
|
||||
|
||||
for file, lines of HeadlessReporterResult.specLineNumbers
|
||||
index = 0
|
||||
lineNumber = 0
|
||||
while newLineNumberInfo = lines[@splitName[index]]
|
||||
while newLineNumberInfo = lines[splitName[index]]
|
||||
if newLineNumberInfo.length == 0
|
||||
lineNumber = newLineNumberInfo[0]
|
||||
else
|
||||
@ -40,14 +40,20 @@ class window.HeadlessReporterResult
|
||||
|
||||
jasmine.Suite.prototype.getSuiteSplitName = ->
|
||||
parts = if @parentSuite then @parentSuite.getSuiteSplitName() else []
|
||||
parts.push(@description)
|
||||
parts.push(String(@description).replace(/[\n\r]/g, ' '))
|
||||
parts
|
||||
|
||||
jasmine.Spec.prototype.getSpecSplitName = ->
|
||||
parts = @suite.getSuiteSplitName()
|
||||
parts.push(@description)
|
||||
parts.push(String(@description).replace(/[\n\r]/g, ' '))
|
||||
parts
|
||||
|
||||
jasmine.Spec.prototype.getJHWSpecInformation = ->
|
||||
parts = this.getSpecSplitName()
|
||||
specLineInfo = HeadlessReporterResult.findSpecLine(parts)
|
||||
parts.push("#{specLineInfo.file}:#{specLineInfo.lineNumber}")
|
||||
parts.join("||")
|
||||
|
||||
class jasmine.HeadlessReporter
|
||||
constructor: (@callback = null) ->
|
||||
@results = []
|
||||
@ -61,27 +67,31 @@ class jasmine.HeadlessReporter
|
||||
|
||||
this.callback() if @callback
|
||||
JHW.finishSuite((new Date() - @startTime) / 1000.0, @length, @failedCount)
|
||||
|
||||
reportRunnerStarting: (runner) ->
|
||||
@startTime = new Date()
|
||||
|
||||
reportSpecResults: (spec) ->
|
||||
return if this.hasError()
|
||||
|
||||
results = spec.results()
|
||||
@length++
|
||||
if results.passed()
|
||||
JHW.specPassed()
|
||||
JHW.specPassed(spec.getJHWSpecInformation())
|
||||
else
|
||||
JHW.specFailed(spec.getSpecSplitName().join('||'))
|
||||
JHW.specFailed(spec.getJHWSpecInformation())
|
||||
@failedCount++
|
||||
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName())
|
||||
for result in results.getItems()
|
||||
if result.type == 'expect' and !result.passed_
|
||||
failureResult.addResult(result.message)
|
||||
@results.push(failureResult)
|
||||
|
||||
reportSpecStarting: (spec) ->
|
||||
if this.hasError()
|
||||
spec.finish()
|
||||
spec.suite.finish()
|
||||
|
||||
reportSuiteResults: (suite) ->
|
||||
hasError: ->
|
||||
JHW.hasError()
|
||||
|
@ -14,7 +14,7 @@
|
||||
HeadlessReporterResult.prototype.print = function() {
|
||||
var bestChoice, output, result, _i, _len, _ref, _results;
|
||||
output = this.name;
|
||||
bestChoice = this._findSpecLine();
|
||||
bestChoice = HeadlessReporterResult.findSpecLine(this.splitName);
|
||||
if (bestChoice.file) {
|
||||
output += " (" + bestChoice.file + ":" + bestChoice.lineNumber + ")";
|
||||
}
|
||||
@ -27,7 +27,7 @@
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
HeadlessReporterResult.prototype._findSpecLine = function() {
|
||||
HeadlessReporterResult.findSpecLine = function(splitName) {
|
||||
var bestChoice, file, index, lastLine, line, lineNumber, lines, newLineNumberInfo, _i, _len, _ref;
|
||||
bestChoice = {
|
||||
accuracy: 0,
|
||||
@ -39,7 +39,7 @@
|
||||
lines = _ref[file];
|
||||
index = 0;
|
||||
lineNumber = 0;
|
||||
while (newLineNumberInfo = lines[this.splitName[index]]) {
|
||||
while (newLineNumberInfo = lines[splitName[index]]) {
|
||||
if (newLineNumberInfo.length === 0) {
|
||||
lineNumber = newLineNumberInfo[0];
|
||||
} else {
|
||||
@ -70,15 +70,22 @@
|
||||
jasmine.Suite.prototype.getSuiteSplitName = function() {
|
||||
var parts;
|
||||
parts = this.parentSuite ? this.parentSuite.getSuiteSplitName() : [];
|
||||
parts.push(this.description);
|
||||
parts.push(String(this.description).replace(/[\n\r]/g, ' '));
|
||||
return parts;
|
||||
};
|
||||
jasmine.Spec.prototype.getSpecSplitName = function() {
|
||||
var parts;
|
||||
parts = this.suite.getSuiteSplitName();
|
||||
parts.push(this.description);
|
||||
parts.push(String(this.description).replace(/[\n\r]/g, ' '));
|
||||
return parts;
|
||||
};
|
||||
jasmine.Spec.prototype.getJHWSpecInformation = function() {
|
||||
var parts, specLineInfo;
|
||||
parts = this.getSpecSplitName();
|
||||
specLineInfo = HeadlessReporterResult.findSpecLine(parts);
|
||||
parts.push("" + specLineInfo.file + ":" + specLineInfo.lineNumber);
|
||||
return parts.join("||");
|
||||
};
|
||||
jasmine.HeadlessReporter = (function() {
|
||||
function HeadlessReporter(callback) {
|
||||
this.callback = callback != null ? callback : null;
|
||||
@ -112,9 +119,9 @@
|
||||
results = spec.results();
|
||||
this.length++;
|
||||
if (results.passed()) {
|
||||
return JHW.specPassed();
|
||||
return JHW.specPassed(spec.getJHWSpecInformation());
|
||||
} else {
|
||||
JHW.specFailed(spec.getSpecSplitName().join('||'));
|
||||
JHW.specFailed(spec.getJHWSpecInformation());
|
||||
this.failedCount++;
|
||||
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName());
|
||||
_ref = results.getItems();
|
||||
|
@ -9,11 +9,8 @@ describe 'HeadlessReporterResult', ->
|
||||
}
|
||||
}
|
||||
it 'should find the best spec lines', ->
|
||||
result = new HeadlessReporterResult('test', [ 'name', 'of', 'test' ])
|
||||
expect(result._findSpecLine().lineNumber).toEqual(3)
|
||||
|
||||
result = new HeadlessReporterResult('test', [ 'other', 'of', 'test' ])
|
||||
expect(result._findSpecLine().lineNumber).toEqual(10)
|
||||
expect(HeadlessReporterResult.findSpecLine([ 'name', 'of', 'test' ]).lineNumber).toEqual(3)
|
||||
expect(HeadlessReporterResult.findSpecLine([ 'other', 'of', 'test' ]).lineNumber).toEqual(10)
|
||||
|
||||
describe 'jasmine.HeadlessReporter', ->
|
||||
reporter = null
|
||||
@ -36,3 +33,31 @@ describe 'jasmine.HeadlessReporter', ->
|
||||
expect(spec.finish).toHaveBeenCalled()
|
||||
expect(suite.finish).toHaveBeenCalled()
|
||||
|
||||
describe 'jasmine.Suite.prototype.getSuiteSplitName', ->
|
||||
it 'should flatten the description', ->
|
||||
suite = new jasmine.Suite({});
|
||||
suite.description = "hello\ngoodbye\n";
|
||||
expect(suite.getSuiteSplitName()).toEqual([ "hello goodbye " ])
|
||||
|
||||
it 'should not fail on missing description', ->
|
||||
suite = new jasmine.Suite({});
|
||||
suite.description = 1;
|
||||
expect(suite.getSuiteSplitName()).toEqual([ "1" ])
|
||||
|
||||
describe 'jasmine.Spec.prototype.getSuiteSplitName', ->
|
||||
it 'should flatten the description', ->
|
||||
spec = new jasmine.Spec({}, {});
|
||||
spec.suite = {
|
||||
getSuiteSplitName: -> []
|
||||
}
|
||||
spec.description = "hello\ngoodbye\n";
|
||||
expect(spec.getSpecSplitName()).toEqual([ "hello goodbye " ])
|
||||
|
||||
it 'should not fail on missing description', ->
|
||||
spec = new jasmine.Spec({}, {});
|
||||
spec.suite = {
|
||||
getSuiteSplitName: -> []
|
||||
}
|
||||
spec.description = 1
|
||||
expect(spec.getSpecSplitName()).toEqual([ "1" ])
|
||||
|
||||
|
18
spec/lib/jasmine/headless/report_spec.rb
Normal file
18
spec/lib/jasmine/headless/report_spec.rb
Normal file
@ -0,0 +1,18 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Jasmine::Headless::Report do
|
||||
include FakeFS::SpecHelpers
|
||||
|
||||
describe '.load' do
|
||||
context 'no file' do
|
||||
it 'should raise an exception' do
|
||||
expect { described_class.load(file) }.to raise_error(Errno::ENOENT)
|
||||
end
|
||||
end
|
||||
|
||||
context 'file' do
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user