ensure a spec can't leave the page, causing a craaaazy loop

This commit is contained in:
John Bintz 2011-07-22 07:42:25 -04:00
parent fe18d2a3fd
commit 13bcd5226e
8 changed files with 88 additions and 5 deletions

View File

@ -35,6 +35,9 @@
class HeadlessSpecRunnerPage: public QWebPage class HeadlessSpecRunnerPage: public QWebPage
{ {
Q_OBJECT Q_OBJECT
public:
HeadlessSpecRunnerPage();
void oneFalseConfirm();
signals: signals:
void consoleLog(const QString &msg, int lineNumber, const QString &sourceID); void consoleLog(const QString &msg, int lineNumber, const QString &sourceID);
void internalLog(const QString &note, const QString &msg); void internalLog(const QString &note, const QString &msg);
@ -42,8 +45,17 @@ protected:
void javaScriptConsoleMessage(const QString & message, int lineNumber, const QString & sourceID); void javaScriptConsoleMessage(const QString & message, int lineNumber, const QString & sourceID);
bool javaScriptConfirm(QWebFrame *frame, const QString &msg); bool javaScriptConfirm(QWebFrame *frame, const QString &msg);
void javaScriptAlert(QWebFrame *frame, const QString &msg); void javaScriptAlert(QWebFrame *frame, const QString &msg);
private:
bool confirmResult;
}; };
HeadlessSpecRunnerPage::HeadlessSpecRunnerPage()
: QWebPage()
, confirmResult(true)
{
}
void HeadlessSpecRunnerPage::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID) void HeadlessSpecRunnerPage::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID)
{ {
emit consoleLog(message, lineNumber, sourceID); emit consoleLog(message, lineNumber, sourceID);
@ -51,8 +63,13 @@ void HeadlessSpecRunnerPage::javaScriptConsoleMessage(const QString &message, in
bool HeadlessSpecRunnerPage::javaScriptConfirm(QWebFrame *frame, const QString &msg) bool HeadlessSpecRunnerPage::javaScriptConfirm(QWebFrame *frame, const QString &msg)
{ {
if (confirmResult) {
emit internalLog("TODO", "jasmine-headless-webkit can't handle confirm() yet! You should mock window.confirm for now. Returning true."); emit internalLog("TODO", "jasmine-headless-webkit can't handle confirm() yet! You should mock window.confirm for now. Returning true.");
return true; return true;
} else {
confirmResult = true;
return false;
}
} }
void HeadlessSpecRunnerPage::javaScriptAlert(QWebFrame *frame, const QString &msg) void HeadlessSpecRunnerPage::javaScriptAlert(QWebFrame *frame, const QString &msg)
@ -60,6 +77,11 @@ void HeadlessSpecRunnerPage::javaScriptAlert(QWebFrame *frame, const QString &ms
emit internalLog("alert", msg); emit internalLog("alert", msg);
} }
void HeadlessSpecRunnerPage::oneFalseConfirm()
{
confirmResult = false;
}
class HeadlessSpecRunner: public QObject class HeadlessSpecRunner: public QObject
{ {
Q_OBJECT Q_OBJECT
@ -71,6 +93,7 @@ public:
void go(); void go();
public slots: public slots:
void log(const QString &msg); void log(const QString &msg);
void leavePageAttempt(const QString &msg);
void specPassed(); void specPassed();
void specFailed(const QString &specDetail); void specFailed(const QString &specDetail);
void printName(const QString &name); void printName(const QString &name);
@ -250,6 +273,16 @@ void HeadlessSpecRunner::log(const QString &msg)
std::cout << std::endl; std::cout << std::endl;
} }
void HeadlessSpecRunner::leavePageAttempt(const QString &msg)
{
red();
std::cout << "[error] ";
clear();
std::cout << qPrintable(msg) << std::endl;
m_page.oneFalseConfirm();
hasErrors = true;
}
void HeadlessSpecRunner::printName(const QString &name) void HeadlessSpecRunner::printName(const QString &name)
{ {
std::cout << std::endl << std::endl; std::cout << std::endl << std::endl;

View File

@ -50,7 +50,7 @@ jasmine.Spec.prototype.getSpecSplitName = ->
parts parts
class jasmine.HeadlessReporter class jasmine.HeadlessReporter
constructor: -> constructor: (@callback = null) ->
@results = [] @results = []
@failedCount = 0 @failedCount = 0
@length = 0 @length = 0
@ -59,6 +59,7 @@ class jasmine.HeadlessReporter
do (result) => do (result) =>
result.print() result.print()
this.callback() if @callback
JHW.finishSuite((new Date() - @startTime) / 1000.0, @length, @failedCount) JHW.finishSuite((new Date() - @startTime) / 1000.0, @length, @failedCount)
reportRunnerStarting: (runner) -> reportRunnerStarting: (runner) ->
@startTime = new Date() @startTime = new Date()

View File

@ -83,7 +83,8 @@
return parts; return parts;
}; };
jasmine.HeadlessReporter = (function() { jasmine.HeadlessReporter = (function() {
function HeadlessReporter() { function HeadlessReporter(callback) {
this.callback = callback != null ? callback : null;
this.results = []; this.results = [];
this.failedCount = 0; this.failedCount = 0;
this.length = 0; this.length = 0;
@ -98,6 +99,9 @@
result = _ref[_i]; result = _ref[_i];
_fn(result); _fn(result);
} }
if (this.callback) {
this.callback();
}
return JHW.finishSuite((new Date() - this.startTime) / 1000.0, this.length, this.failedCount); return JHW.finishSuite((new Date() - this.startTime) / 1000.0, this.length, this.failedCount);
}; };
HeadlessReporter.prototype.reportRunnerStarting = function(runner) { HeadlessReporter.prototype.reportRunnerStarting = function(runner) {

View File

@ -31,6 +31,16 @@ module Jasmine
}, pp: function(data) { }, pp: function(data) {
JHW.log(jasmine ? jasmine.pp(data) : JSON.stringify(data)); JHW.log(jasmine ? jasmine.pp(data) : JSON.stringify(data));
} }; } };
window.onbeforeunload = function(e) {
JHW.leavePageAttempt('The code tried to leave the test page. Check for unhandled form submits and link clicks.');
if (e = e || window.event) {
e.returnValue = "leaving";
}
return "leaving";
};
</script> </script>
#{files.join("\n")} #{files.join("\n")}
<script type="text/javascript"> <script type="text/javascript">
@ -40,7 +50,9 @@ HeadlessReporterResult.specLineNumbers = #{MultiJson.encode(spec_lines)};
<body> <body>
<script type="text/javascript"> <script type="text/javascript">
jasmine.getEnv().addReporter(new jasmine.HeadlessReporter()); jasmine.getEnv().addReporter(new jasmine.HeadlessReporter(function() {
window.onbeforeunload = null;
}));
jasmine.getEnv().execute(); jasmine.getEnv().execute();
</script> </script>

View File

@ -60,6 +60,15 @@ describe "jasmine-headless-webkit" do
end end
end end
describe 'tries to leave page' do
it "should not leave the page nor loop" do
system %{bin/jasmine-headless-webkit -j spec/jasmine/leave_page/leave_page.yml --report #{report}}
$?.exitstatus.should == 1
report.should be_a_report_containing(2, 0, false)
end
end
describe 'with filtered run' do describe 'with filtered run' do
context "don't run a full run, just the filtered run" do context "don't run a full run, just the filtered run" do
it "should succeed and run both" do it "should succeed and run both" do

View File

@ -0,0 +1,4 @@
function yes() {
document.location.href = 'http://www.google.com/'
}

View File

@ -0,0 +1,9 @@
src_files:
- spec/jasmine/leave_page/leave_page.js
spec_files:
- spec/jasmine/leave_page/leave_page_spec.js
src_dir: .
spec_dir: .

View File

@ -0,0 +1,11 @@
describe("something", function() {
it("should be true", function() {
yes();
expect(true).toEqual(true);
});
it("should so something else", function() {
expect(true).toEqual(true);
});
});