aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/testing/continuationtestcase.js
diff options
context:
space:
mode:
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/testing/continuationtestcase.js')
-rw-r--r--contexts/data/lib/closure-library/closure/goog/testing/continuationtestcase.js689
1 files changed, 0 insertions, 689 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/testing/continuationtestcase.js b/contexts/data/lib/closure-library/closure/goog/testing/continuationtestcase.js
deleted file mode 100644
index 1fb57df..0000000
--- a/contexts/data/lib/closure-library/closure/goog/testing/continuationtestcase.js
+++ /dev/null
@@ -1,689 +0,0 @@
-// Copyright 2009 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Defines test classes for tests that can wait for conditions.
- *
- * Normal unit tests must complete their test logic within a single function
- * execution. This is ideal for most tests, but makes it difficult to test
- * routines that require real time to complete. The tests and TestCase in this
- * file allow for tests that can wait until a condition is true before
- * continuing execution.
- *
- * Each test has the typical three phases of execution: setUp, the test itself,
- * and tearDown. During each phase, the test function may add wait conditions,
- * which result in new test steps being added for that phase. All steps in a
- * given phase must complete before moving on to the next phase. An error in
- * any phase will stop that test and report the error to the test runner.
- *
- * This class should not be used where adequate mocks exist. Time-based routines
- * should use the MockClock, which runs much faster and provides equivalent
- * results. Continuation tests should be used for testing code that depends on
- * browser behaviors that are difficult to mock. For example, testing code that
- * relies on Iframe load events, event or layout code that requires a setTimeout
- * to become valid, and other browser-dependent native object interactions for
- * which mocks are insufficient.
- *
- * Sample usage:
- *
- * <pre>
- * var testCase = new goog.testing.ContinuationTestCase();
- * testCase.autoDiscoverTests();
- *
- * if (typeof G_testRunner != 'undefined') {
- * G_testRunner.initialize(testCase);
- * }
- *
- * function testWaiting() {
- * var someVar = true;
- * waitForTimeout(function() {
- * assertTrue(someVar)
- * }, 500);
- * }
- *
- * function testWaitForEvent() {
- * var et = goog.events.EventTarget();
- * waitForEvent(et, 'test', function() {
- * // Test step runs after the event fires.
- * })
- * et.dispatchEvent(et, 'test');
- * }
- *
- * function testWaitForCondition() {
- * var counter = 0;
- *
- * waitForCondition(function() {
- * // This function is evaluated periodically until it returns true, or it
- * // times out.
- * return ++counter >= 3;
- * }, function() {
- * // This test step is run once the condition becomes true.
- * assertEquals(3, counter);
- * });
- * }
- * </pre>
- *
- * @author brenneman@google.com (Shawn Brenneman)
- */
-
-
-goog.provide('goog.testing.ContinuationTestCase');
-goog.provide('goog.testing.ContinuationTestCase.Step');
-goog.provide('goog.testing.ContinuationTestCase.Test');
-
-goog.require('goog.array');
-goog.require('goog.events.EventHandler');
-goog.require('goog.testing.TestCase');
-goog.require('goog.testing.TestCase.Test');
-goog.require('goog.testing.asserts');
-
-
-
-/**
- * Constructs a test case that supports tests with continuations. Test functions
- * may issue "wait" commands that suspend the test temporarily and continue once
- * the wait condition is met.
- *
- * @param {string=} opt_name Optional name for the test case.
- * @constructor
- * @extends {goog.testing.TestCase}
- */
-goog.testing.ContinuationTestCase = function(opt_name) {
- goog.testing.TestCase.call(this, opt_name);
-
- /**
- * An event handler for waiting on Closure or browser events during tests.
- * @type {goog.events.EventHandler}
- * @private
- */
- this.handler_ = new goog.events.EventHandler(this);
-};
-goog.inherits(goog.testing.ContinuationTestCase, goog.testing.TestCase);
-
-
-/**
- * The default maximum time to wait for a single test step in milliseconds.
- * @type {number}
- */
-goog.testing.ContinuationTestCase.MAX_TIMEOUT = 1000;
-
-
-/**
- * Lock used to prevent multiple test steps from running recursively.
- * @type {boolean}
- * @private
- */
-goog.testing.ContinuationTestCase.locked_ = false;
-
-
-/**
- * The current test being run.
- * @type {goog.testing.ContinuationTestCase.Test}
- * @private
- */
-goog.testing.ContinuationTestCase.prototype.currentTest_ = null;
-
-
-/**
- * Enables or disables the wait functions in the global scope.
- * @param {boolean} enable Whether the wait functions should be exported.
- * @private
- */
-goog.testing.ContinuationTestCase.prototype.enableWaitFunctions_ =
- function(enable) {
- if (enable) {
- goog.exportSymbol('waitForCondition',
- goog.bind(this.waitForCondition, this));
- goog.exportSymbol('waitForEvent', goog.bind(this.waitForEvent, this));
- goog.exportSymbol('waitForTimeout', goog.bind(this.waitForTimeout, this));
- } else {
- // Internet Explorer doesn't allow deletion of properties on the window.
- goog.global['waitForCondition'] = undefined;
- goog.global['waitForEvent'] = undefined;
- goog.global['waitForTimeout'] = undefined;
- }
-};
-
-
-/** @override */
-goog.testing.ContinuationTestCase.prototype.runTests = function() {
- this.enableWaitFunctions_(true);
- goog.testing.ContinuationTestCase.superClass_.runTests.call(this);
-};
-
-
-/** @override */
-goog.testing.ContinuationTestCase.prototype.finalize = function() {
- this.enableWaitFunctions_(false);
- goog.testing.ContinuationTestCase.superClass_.finalize.call(this);
-};
-
-
-/** @override */
-goog.testing.ContinuationTestCase.prototype.cycleTests = function() {
- // Get the next test in the queue.
- if (!this.currentTest_) {
- this.currentTest_ = this.createNextTest_();
- }
-
- // Run the next step of the current test, or exit if all tests are complete.
- if (this.currentTest_) {
- this.runNextStep_();
- } else {
- this.finalize();
- }
-};
-
-
-/**
- * Creates the next test in the queue.
- * @return {goog.testing.ContinuationTestCase.Test} The next test to execute, or
- * null if no pending tests remain.
- * @private
- */
-goog.testing.ContinuationTestCase.prototype.createNextTest_ = function() {
- var test = this.next();
- if (!test) {
- return null;
- }
-
-
- var name = test.name;
- goog.testing.TestCase.currentTestName = name;
- this.result_.runCount++;
- this.log('Running test: ' + name);
-
- return new goog.testing.ContinuationTestCase.Test(
- new goog.testing.TestCase.Test(name, this.setUp, this),
- test,
- new goog.testing.TestCase.Test(name, this.tearDown, this));
-};
-
-
-/**
- * Cleans up a finished test and cycles to the next test.
- * @private
- */
-goog.testing.ContinuationTestCase.prototype.finishTest_ = function() {
- var err = this.currentTest_.getError();
- if (err) {
- this.doError(this.currentTest_, err);
- } else {
- this.doSuccess(this.currentTest_);
- }
-
- goog.testing.TestCase.currentTestName = null;
- this.currentTest_ = null;
- this.locked_ = false;
- this.handler_.removeAll();
-
- this.timeout(goog.bind(this.cycleTests, this), 0);
-};
-
-
-/**
- * Executes the next step in the current phase, advancing through each phase as
- * all steps are completed.
- * @private
- */
-goog.testing.ContinuationTestCase.prototype.runNextStep_ = function() {
- if (this.locked_) {
- // Attempting to run a step before the previous step has finished. Try again
- // after that step has released the lock.
- return;
- }
-
- var phase = this.currentTest_.getCurrentPhase();
-
- if (!phase || !phase.length) {
- // No more steps for this test.
- this.finishTest_();
- return;
- }
-
- // Find the next step that is not in a wait state.
- var stepIndex = goog.array.findIndex(phase, function(step) {
- return !step.waiting;
- });
-
- if (stepIndex < 0) {
- // All active steps are currently waiting. Return until one wakes up.
- return;
- }
-
- this.locked_ = true;
- var step = phase[stepIndex];
-
- try {
- step.execute();
- // Remove the successfully completed step. If an error is thrown, all steps
- // will be removed for this phase.
- goog.array.removeAt(phase, stepIndex);
-
- } catch (e) {
- this.currentTest_.setError(e);
-
- // An assertion has failed, or an exception was raised. Clear the current
- // phase, whether it is setUp, test, or tearDown.
- this.currentTest_.cancelCurrentPhase();
-
- // Cancel the setUp and test phase no matter where the error occurred. The
- // tearDown phase will still run if it has pending steps.
- this.currentTest_.cancelTestPhase();
- }
-
- this.locked_ = false;
- this.runNextStep_();
-};
-
-
-/**
- * Creates a new test step that will run after a user-specified
- * timeout. No guarantee is made on the execution order of the
- * continuation, except for those provided by each browser's
- * window.setTimeout. In particular, if two continuations are
- * registered at the same time with very small delta for their
- * durations, this class can not guarantee that the continuation with
- * the smaller duration will be executed first.
- * @param {Function} continuation The test function to invoke after the timeout.
- * @param {number=} opt_duration The length of the timeout in milliseconds.
- */
-goog.testing.ContinuationTestCase.prototype.waitForTimeout =
- function(continuation, opt_duration) {
- var step = this.addStep_(continuation);
- step.setTimeout(goog.bind(this.handleComplete_, this, step),
- opt_duration || 0);
-};
-
-
-/**
- * Creates a new test step that will run after an event has fired. If the event
- * does not fire within a reasonable timeout, the test will fail.
- * @param {goog.events.EventTarget|EventTarget} eventTarget The target that will
- * fire the event.
- * @param {string} eventType The type of event to listen for.
- * @param {Function} continuation The test function to invoke after the event
- * fires.
- */
-goog.testing.ContinuationTestCase.prototype.waitForEvent = function(
- eventTarget,
- eventType,
- continuation) {
-
- var step = this.addStep_(continuation);
-
- var duration = goog.testing.ContinuationTestCase.MAX_TIMEOUT;
- step.setTimeout(goog.bind(this.handleTimeout_, this, step, duration),
- duration);
-
- this.handler_.listenOnce(eventTarget,
- eventType,
- goog.bind(this.handleComplete_, this, step));
-};
-
-
-/**
- * Creates a new test step which will run once a condition becomes true. The
- * condition will be polled at a user-specified interval until it becomes true,
- * or until a maximum timeout is reached.
- * @param {Function} condition The condition to poll.
- * @param {Function} continuation The test code to evaluate once the condition
- * becomes true.
- * @param {number=} opt_interval The polling interval in milliseconds.
- * @param {number=} opt_maxTimeout The maximum amount of time to wait for the
- * condition in milliseconds (defaults to 1000).
- */
-goog.testing.ContinuationTestCase.prototype.waitForCondition = function(
- condition,
- continuation,
- opt_interval,
- opt_maxTimeout) {
-
- var interval = opt_interval || 100;
- var timeout = opt_maxTimeout || goog.testing.ContinuationTestCase.MAX_TIMEOUT;
-
- var step = this.addStep_(continuation);
- this.testCondition_(step, condition, goog.now(), interval, timeout);
-};
-
-
-/**
- * Creates a new asynchronous test step which will be added to the current test
- * phase.
- * @param {Function} func The test function that will be executed for this step.
- * @return {goog.testing.ContinuationTestCase.Step} A new test step.
- * @private
- */
-goog.testing.ContinuationTestCase.prototype.addStep_ = function(func) {
- if (!this.currentTest_) {
- throw Error('Cannot add test steps outside of a running test.');
- }
-
- var step = new goog.testing.ContinuationTestCase.Step(
- this.currentTest_.name,
- func,
- this.currentTest_.scope);
- this.currentTest_.addStep(step);
- return step;
-};
-
-
-/**
- * Handles completion of a step's wait condition. Advances the test, allowing
- * the step's test method to run.
- * @param {goog.testing.ContinuationTestCase.Step} step The step that has
- * finished waiting.
- * @private
- */
-goog.testing.ContinuationTestCase.prototype.handleComplete_ = function(step) {
- step.clearTimeout();
- step.waiting = false;
- this.runNextStep_();
-};
-
-
-/**
- * Handles the timeout event for a step that has exceeded the maximum time. This
- * causes the current test to fail.
- * @param {goog.testing.ContinuationTestCase.Step} step The timed-out step.
- * @param {number} duration The length of the timeout in milliseconds.
- * @private
- */
-goog.testing.ContinuationTestCase.prototype.handleTimeout_ =
- function(step, duration) {
- step.ref = function() {
- fail('Continuation timed out after ' + duration + 'ms.');
- };
-
- // Since the test is failing, cancel any other pending event listeners.
- this.handler_.removeAll();
- this.handleComplete_(step);
-};
-
-
-/**
- * Tests a wait condition and executes the associated test step once the
- * condition is true.
- *
- * If the condition does not become true before the maximum duration, the
- * interval will stop and the test step will fail in the kill timer.
- *
- * @param {goog.testing.ContinuationTestCase.Step} step The waiting test step.
- * @param {Function} condition The test condition.
- * @param {number} startTime Time when the test step began waiting.
- * @param {number} interval The duration in milliseconds to wait between tests.
- * @param {number} timeout The maximum amount of time to wait for the condition
- * to become true. Measured from the startTime in milliseconds.
- * @private
- */
-goog.testing.ContinuationTestCase.prototype.testCondition_ = function(
- step,
- condition,
- startTime,
- interval,
- timeout) {
-
- var duration = goog.now() - startTime;
-
- if (condition()) {
- this.handleComplete_(step);
- } else if (duration < timeout) {
- step.setTimeout(goog.bind(this.testCondition_,
- this,
- step,
- condition,
- startTime,
- interval,
- timeout),
- interval);
- } else {
- this.handleTimeout_(step, duration);
- }
-};
-
-
-
-/**
- * Creates a continuation test case, which consists of multiple test steps that
- * occur in several phases.
- *
- * The steps are distributed between setUp, test, and tearDown phases. During
- * the execution of each step, 0 or more steps may be added to the current
- * phase. Once all steps in a phase have completed, the next phase will be
- * executed.
- *
- * If any errors occur (such as an assertion failure), the setUp and Test phases
- * will be cancelled immediately. The tearDown phase will always start, but may
- * be cancelled as well if it raises an error.
- *
- * @param {goog.testing.TestCase.Test} setUp A setUp test method to run before
- * the main test phase.
- * @param {goog.testing.TestCase.Test} test A test method to run.
- * @param {goog.testing.TestCase.Test} tearDown A tearDown test method to run
- * after the test method completes or fails.
- * @constructor
- * @extends {goog.testing.TestCase.Test}
- */
-goog.testing.ContinuationTestCase.Test = function(setUp, test, tearDown) {
- // This test container has a name, but no evaluation function or scope.
- goog.testing.TestCase.Test.call(this, test.name, null, null);
-
- /**
- * The list of test steps to run during setUp.
- * @type {Array.<goog.testing.TestCase.Test>}
- * @private
- */
- this.setUp_ = [setUp];
-
- /**
- * The list of test steps to run for the actual test.
- * @type {Array.<goog.testing.TestCase.Test>}
- * @private
- */
- this.test_ = [test];
-
- /**
- * The list of test steps to run during the tearDown phase.
- * @type {Array.<goog.testing.TestCase.Test>}
- * @private
- */
- this.tearDown_ = [tearDown];
-};
-goog.inherits(goog.testing.ContinuationTestCase.Test,
- goog.testing.TestCase.Test);
-
-
-/**
- * The first error encountered during the test run, if any.
- * @type {Error}
- * @private
- */
-goog.testing.ContinuationTestCase.Test.prototype.error_ = null;
-
-
-/**
- * @return {Error} The first error to be raised during the test run or null if
- * no errors occurred.
- */
-goog.testing.ContinuationTestCase.Test.prototype.getError = function() {
- return this.error_;
-};
-
-
-/**
- * Sets an error for the test so it can be reported. Only the first error set
- * during a test will be reported. Additional errors that occur in later test
- * phases will be discarded.
- * @param {Error} e An error.
- */
-goog.testing.ContinuationTestCase.Test.prototype.setError = function(e) {
- this.error_ = this.error_ || e;
-};
-
-
-/**
- * @return {Array.<goog.testing.TestCase.Test>} The current phase of steps
- * being processed. Returns null if all steps have been completed.
- */
-goog.testing.ContinuationTestCase.Test.prototype.getCurrentPhase = function() {
- if (this.setUp_.length) {
- return this.setUp_;
- }
-
- if (this.test_.length) {
- return this.test_;
- }
-
- if (this.tearDown_.length) {
- return this.tearDown_;
- }
-
- return null;
-};
-
-
-/**
- * Adds a new test step to the end of the current phase. The new step will wait
- * for a condition to be met before running, or will fail after a timeout.
- * @param {goog.testing.ContinuationTestCase.Step} step The test step to add.
- */
-goog.testing.ContinuationTestCase.Test.prototype.addStep = function(step) {
- var phase = this.getCurrentPhase();
- if (phase) {
- phase.push(step);
- } else {
- throw Error('Attempted to add a step to a completed test.');
- }
-};
-
-
-/**
- * Cancels all remaining steps in the current phase. Called after an error in
- * any phase occurs.
- */
-goog.testing.ContinuationTestCase.Test.prototype.cancelCurrentPhase =
- function() {
- this.cancelPhase_(this.getCurrentPhase());
-};
-
-
-/**
- * Skips the rest of the setUp and test phases, but leaves the tearDown phase to
- * clean up.
- */
-goog.testing.ContinuationTestCase.Test.prototype.cancelTestPhase = function() {
- this.cancelPhase_(this.setUp_);
- this.cancelPhase_(this.test_);
-};
-
-
-/**
- * Clears a test phase and cancels any pending steps found.
- * @param {Array.<goog.testing.TestCase.Test>} phase A list of test steps.
- * @private
- */
-goog.testing.ContinuationTestCase.Test.prototype.cancelPhase_ =
- function(phase) {
- while (phase && phase.length) {
- var step = phase.pop();
- if (step instanceof goog.testing.ContinuationTestCase.Step) {
- step.clearTimeout();
- }
- }
-};
-
-
-
-/**
- * Constructs a single step in a larger continuation test. Each step is similar
- * to a typical TestCase test, except it may wait for an event or timeout to
- * occur before running the test function.
- *
- * @param {string} name The test name.
- * @param {Function} ref The test function to run.
- * @param {Object=} opt_scope The object context to run the test in.
- * @constructor
- * @extends {goog.testing.TestCase.Test}
- */
-goog.testing.ContinuationTestCase.Step = function(name, ref, opt_scope) {
- goog.testing.TestCase.Test.call(this, name, ref, opt_scope);
-};
-goog.inherits(goog.testing.ContinuationTestCase.Step,
- goog.testing.TestCase.Test);
-
-
-/**
- * Whether the step is currently waiting for a condition to continue. All new
- * steps begin in wait state.
- * @type {boolean}
- */
-goog.testing.ContinuationTestCase.Step.prototype.waiting = true;
-
-
-/**
- * A saved reference to window.clearTimeout so that MockClock or other overrides
- * don't affect continuation timeouts.
- * @type {Function}
- * @private
- */
-goog.testing.ContinuationTestCase.Step.protectedClearTimeout_ =
- window.clearTimeout;
-
-
-/**
- * A saved reference to window.setTimeout so that MockClock or other overrides
- * don't affect continuation timeouts.
- * @type {Function}
- * @private
- */
-goog.testing.ContinuationTestCase.Step.protectedSetTimeout_ = window.setTimeout;
-
-
-/**
- * Key to this step's timeout. If the step is waiting for an event, the timeout
- * will be used as a kill timer. If the step is waiting
- * @type {number}
- * @private
- */
-goog.testing.ContinuationTestCase.Step.prototype.timeout_;
-
-
-/**
- * Starts a timeout for this step. Each step may have only one timeout active at
- * a time.
- * @param {Function} func The function to call after the timeout.
- * @param {number} duration The number of milliseconds to wait before invoking
- * the function.
- */
-goog.testing.ContinuationTestCase.Step.prototype.setTimeout =
- function(func, duration) {
-
- this.clearTimeout();
-
- var setTimeout = goog.testing.ContinuationTestCase.Step.protectedSetTimeout_;
- this.timeout_ = setTimeout(func, duration);
-};
-
-
-/**
- * Clears the current timeout if it is active.
- */
-goog.testing.ContinuationTestCase.Step.prototype.clearTimeout = function() {
- if (this.timeout_) {
- var clear = goog.testing.ContinuationTestCase.Step.protectedClearTimeout_;
-
- clear(this.timeout_);
- delete this.timeout_;
- }
-};