123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- // Copyright 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.
- /**
- * @fileoverview
- * Integration module for QUnit tests running in browser tests.
- * Specifically it:
- * - Sets QUnit.autostart to false, so that the browser test can hook the test
- * results callback before the test starts.
- * - Implements a text-based test reporter to report test results back to the
- * browser test.
- */
- (function(QUnit, automationController, exports) {
- 'use strict';
- var TEST_TIMEOUT_IN_MS = 5000;
- var TestReporter = function() {
- this.errorMessage_ = '';
- this.failedTestsCount_ = 0;
- this.failedAssertions_ = [];
- };
- TestReporter.prototype.init = function(qunit) {
- qunit.testStart(this.onTestStart_.bind(this));
- qunit.testDone(this.onTestDone_.bind(this));
- qunit.log(this.onAssertion_.bind(this));
- };
- /**
- * @param {{ module:string, name: string }} details
- */
- TestReporter.prototype.onTestStart_ = function(details) {};
- /**
- * @param {{ module:string, name: string }} details
- */
- TestReporter.prototype.onTestDone_ = function(details) {
- if (this.failedAssertions_.length > 0) {
- this.errorMessage_ += ' ' + details.module + '.' + details.name + '\n';
- this.errorMessage_ += this.failedAssertions_.map(
- function(assertion, index){
- return ' ' + (index + 1) + '. ' + assertion.message + '\n' +
- ' ' + assertion.source;
- }).join('\n') + '\n';
- this.failedAssertions_ = [];
- this.failedTestsCount_++;
- }
- };
- TestReporter.prototype.onAssertion_ = function(details) {
- if (!details.result) {
- this.failedAssertions_.push(details);
- }
- };
- TestReporter.prototype.getErrorMessage = function(){
- var errorMessage = '';
- if (this.failedTestsCount_ > 0) {
- var test = (this.failedTestsCount_ > 1) ? 'tests' : 'test';
- errorMessage = this.failedTestsCount_ + ' ' + test + ' failed:\n';
- errorMessage += this.errorMessage_;
- }
- return errorMessage;
- };
- var BrowserTestHarness = function(qunit, domAutomationController, reporter) {
- this.qunit_ = qunit;
- this.automationController_ = domAutomationController;
- this.reporter_ = reporter;
- };
- BrowserTestHarness.prototype.init = function() {
- this.qunit_.config.autostart = false;
- };
- BrowserTestHarness.prototype.run = function() {
- this.reporter_.init(this.qunit_);
- this.qunit_.start();
- this.qunit_.done(function(details){
- this.automationController_.send(JSON.stringify({
- passed: details.passed == details.total,
- errorMessage: this.reporter_.getErrorMessage()
- }));
- }.bind(this));
- };
- // The browser test runs chrome with the flag --dom-automation, which creates
- // the window.domAutomationController object. This allows the test suite to
- // JS-encoded data back to the browser test.
- if (automationController) {
- if (!QUnit) {
- console.error('browser_test_harness.js must be included after QUnit.js.');
- return;
- }
- var testHarness = new BrowserTestHarness(
- QUnit,
- automationController,
- new TestReporter());
- testHarness.init();
- exports.browserTestHarness = testHarness;
- }
- var qunitTest = QUnit.test;
- var reasonTimeout = {};
- /**
- * Returns a promise that resolves after |delay| along with a timerId
- * for cancellation.
- *
- * @return {promise: !Promise, timerId: number}
- */
- BrowserTestHarness.timeout = function(delay) {
- var timerId = 0;
- var promise = new Promise(function(resolve) {
- timerId = window.setTimeout(function() {
- resolve();
- }, delay);
- });
- return {
- timerId: timerId,
- promise: promise
- };
- };
- QUnit.config.urlConfig.push({
- id: "disableTestTimeout",
- label: "disable test timeout",
- tooltip: "Check this when debugging locally to disable test timeout.",
- });
- /**
- * Forces the test to fail after |TEST_TIMEOUT_IN_MS|.
- *
- * @param {function(QUnit.Assert)} testCallback
- */
- BrowserTestHarness.test = function(testCallback) {
- return function() {
- var args = Array.prototype.slice.call(arguments);
- var timeout = BrowserTestHarness.timeout(TEST_TIMEOUT_IN_MS);
- var testPromise = Promise.resolve(testCallback.apply(this, args))
- .then(function() {
- window.clearTimeout(timeout.timerId);
- });
- var asserts = args[0];
- var timeoutPromise = timeout.promise.then(function(){
- asserts.ok(false, 'Test timed out after ' + TEST_TIMEOUT_IN_MS + ' ms')
- })
- return Promise.race([testPromise, timeoutPromise]);
- };
- };
- if (!QUnit.urlParams.disableTestTimeout) {
- QUnit.test = function(name, expected, testCallback, async) {
- qunitTest(name, expected, BrowserTestHarness.test(testCallback), async);
- };
- }
- })(window.QUnit, window.domAutomationController, window);
|