<!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>
