1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 tvcm.require('tvcm.raf');
9 tvcm.exportTo('tvcm.unittest', function() {
10 var realTvcmOnAnimationFrameError;
11 var realWindowOnError;
12 var realWindowHistoryPushState;
14 function installGlobalTestHooks(runner) {
15 realTvcmOnAnimationFrameError = tvcm.onAnimationFrameError;
16 tvcm.onAnimationFrameError = function(error) {
17 runner.results.addErrorForCurrentTest(error);
20 realWindowOnError = window.onerror;
21 window.onerror = function(errorMsg, url, lineNumber) {
22 runner.results.addErrorForCurrentTest(
23 errorMsg + ' at ' + url + ':' + lineNumber);
24 if (realWindowOnError)
25 return realWindowOnError(errorMsg, url, lineNumber);
29 realWindowHistoryPushState = window.history.pushState;
30 window.history.pushState = function() {
33 tvcm.unittest.addHTMLOutputForCurrentTest = function(element) {
34 runner.results.addHTMLOutputForCurrentTest(element);
37 global.sessionStorage.clear();
38 tvcm.Settings.setAlternativeStorageInstance(global.sessionStorage);
39 tvcm.KeyEventManager.resetInstanceForUnitTesting();
42 function uninstallGlobalTestHooks() {
43 window.onerror = realWindowOnError;
44 realWindowOnError = undefined;
46 tvcm.onAnimationFrameError = realTvcmOnAnimationFrameError;
47 realTvcmOnAnimationFrameError = undefined;
49 realWindowHistoryPushState = undefined;
50 window.history.pushState = realWindowHistoryPushState;
53 tvcm.unittest.addHTMLOutputForCurrentTest = undefined;
57 function TestRunner(results, testCases) {
58 this.results_ = results;
59 this.testCases_ = testCases;
60 this.pendingTestCases_ = [];
62 this.runOneTestCaseScheduled_ = false;
64 this.runCompletedPromise = undefined;
65 this.runCompletedResolver_ = undefined;
67 this.currentTestCase_ = undefined;
70 TestRunner.prototype = {
71 __proto__: Object.prototype,
73 beginRunning: function() {
74 if (this.pendingTestCases_.length)
75 throw new Error('Tests still running!');
77 this.runCompletedPromise = new tvcm.Promise(function(resolver) {
78 this.runCompletedResolver_ = resolver;
81 this.pendingTestCases_ = this.testCases_.slice(0);
83 this.scheduleRunOneTestCase_();
85 return this.runCompletedPromise;
88 beginToStopRunning: function() {
89 if (!this.runCompletedResolver_)
90 throw new Error('Still running');
91 this.pendingTestCases_ = [];
92 return this.runCompletedPromise;
96 return this.testCases_;
100 return this.results_;
103 scheduleRunOneTestCase_: function() {
104 if (this.runOneTestCaseScheduled_)
106 this.runOneTestCaseScheduled_ = true;
107 tvcm.requestIdleCallback(this.runOneTestCase_, this);
110 runOneTestCase_: function() {
111 this.runOneTestCaseScheduled_ = false;
113 if (this.pendingTestCases_.length == 0) {
114 this.didFinishRunningAllTests_();
118 this.currentTestCase_ = this.pendingTestCases_.splice(0, 1)[0];
120 this.results_.willRunTest(this.currentTestCase_);
121 if (!this.setUpCurrentTestCase_()) {
122 this.results_.didCurrentTestEnd();
123 this.currentTestCase_ = undefined;
124 this.scheduleRunOneTestCase_();
128 this.runCurrentTestCase_().then(
129 function pass(result) {
130 this.tearDownCurrentTestCase_(true);
132 this.results_.setReturnValueFromCurrentTest(result);
133 this.results_.didCurrentTestEnd();
134 this.currentTestCase_ = undefined;
135 this.scheduleRunOneTestCase_();
137 function fail(error) {
138 this.results_.addErrorForCurrentTest(error);
139 this.tearDownCurrentTestCase_(false);
140 this.results_.didCurrentTestEnd();
141 this.currentTestCase_ = undefined;
142 this.scheduleRunOneTestCase_();
146 setUpCurrentTestCase_: function() {
147 // Try setting it up. Return true if succeeded.
148 installGlobalTestHooks(this);
150 if (this.currentTestCase_.options_.setUp)
151 this.currentTestCase_.options_.setUp.call(this.currentTestCase_);
153 this.results_.addErrorForCurrentTest(error);
159 runCurrentTestCase_: function() {
160 return new Promise(function(runTestCaseResolver) {
162 var maybePromise = this.currentTestCase_.run();
164 runTestCaseResolver.reject(error);
168 if (maybePromise !== undefined && maybePromise.then) {
171 runTestCaseResolver.fulfill(result);
174 runTestCaseResolver.reject(error);
177 runTestCaseResolver.fulfill(maybePromise);
182 tearDownCurrentTestCase_: function() {
184 if (this.currentTestCase_.tearDown)
185 this.currentTestCase_.tearDown.call(this.currentTestCase_);
187 this.results_.addErrorForCurrentTest(error);
190 uninstallGlobalTestHooks();
193 didFinishRunningAllTests_: function() {
194 this.results.didRunTests();
195 this.runCompletedResolver_.resolve();
196 this.runCompletedResolver_ = undefined;
201 TestRunner: TestRunner