blob: e72431ad60c5aa7d14672ce5f48c946e24be2a93 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/base/raf.html">
<script>
'use strict';
tr.exportTo('tr.b.unittest', function() {
var realTvOnAnimationFrameError;
var realWindowOnError;
var realWindowHistoryPushState;
function installGlobalTestHooks(runner) {
realTvOnAnimationFrameError = tr.b.onAnimationFrameError;
tr.b.onAnimationFrameError = function(error) {
runner.results.addErrorForCurrentTest(error);
}
realWindowOnError = window.onerror;
window.onerror = function(errorMsg, url, lineNumber) {
runner.results.addErrorForCurrentTest(
errorMsg + ' at ' + url + ':' + lineNumber);
if (realWindowOnError)
return realWindowOnError(errorMsg, url, lineNumber);
return false;
}
realWindowHistoryPushState = window.history.pushState;
window.history.pushState = function() {
};
tr.b.unittest.addHTMLOutputForCurrentTest = function(element) {
runner.results.addHTMLOutputForCurrentTest(element);
}
global.sessionStorage.clear();
var e = new Event('tr-unittest-will-run');
document.head.dispatchEvent(e);
}
function uninstallGlobalTestHooks() {
window.onerror = realWindowOnError;
realWindowOnError = undefined;
tr.b.onAnimationFrameError = realTvOnAnimationFrameError;
realTvOnAnimationFrameError = undefined;
window.history.pushState = realWindowHistoryPushState;
realWindowHistoryPushState = undefined;
tr.b.unittest.addHTMLOutputForCurrentTest = undefined;
}
function TestRunner(results, testCases) {
this.results_ = results;
this.testCases_ = testCases;
this.pendingTestCases_ = [];
this.runOneTestCaseScheduled_ = false;
this.runCompletedPromise = undefined;
this.runCompletedResolver_ = undefined;
this.currentTestCase_ = undefined;
}
TestRunner.prototype = {
__proto__: Object.prototype,
beginRunning: function() {
if (this.pendingTestCases_.length)
throw new Error('Tests still running!');
this.runCompletedPromise = new Promise(function(resolve, reject) {
this.runCompletedResolver_ = {
resolve: resolve,
reject: reject
};
}.bind(this));
this.pendingTestCases_ = this.testCases_.slice(0);
this.scheduleRunOneTestCase_();
return this.runCompletedPromise;
},
beginToStopRunning: function() {
if (!this.runCompletedResolver_)
throw new Error('Still running');
this.pendingTestCases_ = [];
return this.runCompletedPromise;
},
get testCases() {
return this.testCases_;
},
get results() {
return this.results_;
},
scheduleRunOneTestCase_: function() {
if (this.runOneTestCaseScheduled_)
return;
this.runOneTestCaseScheduled_ = true;
tr.b.requestIdleCallback(this.runOneTestCase_, this);
},
runOneTestCase_: function() {
this.runOneTestCaseScheduled_ = false;
if (this.pendingTestCases_.length == 0) {
this.didFinishRunningAllTests_();
return;
}
this.currentTestCase_ = this.pendingTestCases_.splice(0, 1)[0];
this.results_.willRunTest(this.currentTestCase_);
if (!this.setUpCurrentTestCase_()) {
this.results_.didCurrentTestEnd();
this.currentTestCase_ = undefined;
this.scheduleRunOneTestCase_();
return;
}
this.runCurrentTestCase_().then(
function pass(result) {
this.tearDownCurrentTestCase_(true);
if (result)
this.results_.setReturnValueFromCurrentTest(result);
this.results_.didCurrentTestEnd();
this.currentTestCase_ = undefined;
this.scheduleRunOneTestCase_();
}.bind(this),
function fail(error) {
this.results_.addErrorForCurrentTest(error);
this.tearDownCurrentTestCase_(false);
this.results_.didCurrentTestEnd();
this.currentTestCase_ = undefined;
this.scheduleRunOneTestCase_();
}.bind(this));
},
setUpCurrentTestCase_: function() {
// Try setting it up. Return true if succeeded.
installGlobalTestHooks(this);
try {
this.currentTestCase_.setUp();
} catch (error) {
this.results_.addErrorForCurrentTest(error);
return false;
}
return true;
},
runCurrentTestCase_: function() {
return new Promise(function(resolve, reject) {
try {
var maybePromise = this.currentTestCase_.run();
} catch (error) {
reject(error);
return;
}
if (maybePromise !== undefined && maybePromise.then) {
maybePromise.then(
function(result) {
resolve(result);
},
function(error) {
reject(error);
});
} else {
resolve(maybePromise);
}
}.bind(this));
},
tearDownCurrentTestCase_: function() {
try {
this.currentTestCase_.tearDown();
} catch (error) {
this.results_.addErrorForCurrentTest(error);
}
uninstallGlobalTestHooks();
},
didFinishRunningAllTests_: function() {
this.results.didRunTests();
this.runCompletedResolver_.resolve();
this.runCompletedResolver_ = undefined;
}
};
return {
TestRunner: TestRunner
};
});
</script>