#

API Docs for: v2.11.1
Show: Inherited Protected Private Deprecated

# File: packages/ember-testing/lib/ext/application.js

    import { Application as EmberApplication } from 'ember-application';
    import setupForTesting from '../setup_for_testing';
    import { helpers } from '../test/helpers';
    import TestPromise, {
      resolve,
      getLastPromise
    } from '../test/promise';
    import run from '../test/run';
    import { invokeInjectHelpersCallbacks } from '../test/on_inject_helpers';
    import {
      asyncStart,
      asyncEnd
    } from '../test/adapter';

    EmberApplication.reopen({
      /**
       This property contains the testing helpers for the current application. These
       are created once you call `injectTestHelpers` on your `Ember.Application`
       instance. The included helpers are also available on the `window` object by
       default, but can be used from this object on the individual application also.

        @property testHelpers
        @type {Object}
        @default {}
        @public
      */
      testHelpers: {},

      /**
       This property will contain the original methods that were registered
       on the `helperContainer` before `injectTestHelpers` is called.

       When `removeTestHelpers` is called, these methods are restored to the
       `helperContainer`.

        @property originalMethods
        @type {Object}
        @default {}
        @private
        @since 1.3.0
      */
      originalMethods: {},

      /**
      This property indicates whether or not this application is currently in
      testing mode. This is set when `setupForTesting` is called on the current
      application.

      @property testing
      @type {Boolean}
      @default false
      @since 1.3.0
      @public
      */
      testing: false,

      /**
        This hook defers the readiness of the application, so that you can start
        the app when your tests are ready to run. It also sets the router's
        location to 'none', so that the window's location will not be modified
        (preventing both accidental leaking of state between tests and interference
        with your testing framework).

        Example:

        ```
        App.setupForTesting();
        ```

        @method setupForTesting
        @public
      */
      setupForTesting() {
        setupForTesting();

        this.testing = true;

        this.Router.reopen({
          location: 'none'
        });
      },

      /**
        This will be used as the container to inject the test helpers into. By
        default the helpers are injected into `window`.

        @property helperContainer
        @type {Object} The object to be used for test helpers.
        @default window
        @since 1.2.0
        @private
      */
      helperContainer: null,

      /**
        This injects the test helpers into the `helperContainer` object. If an object is provided
        it will be used as the helperContainer. If `helperContainer` is not set it will default
        to `window`. If a function of the same name has already been defined it will be cached
        (so that it can be reset if the helper is removed with `unregisterHelper` or
        `removeTestHelpers`).

        Any callbacks registered with `onInjectHelpers` will be called once the
        helpers have been injected.

        Example:
        ```
        App.injectTestHelpers();
        ```

        @method injectTestHelpers
        @public
      */
      injectTestHelpers(helperContainer) {
        if (helperContainer) {
          this.helperContainer = helperContainer;
        } else {
          this.helperContainer = window;
        }

        this.reopen({
          willDestroy() {
            this._super(...arguments);
            this.removeTestHelpers();
          }
        });

        this.testHelpers = {};
        for (let name in helpers) {
          this.originalMethods[name] = this.helperContainer[name];
          this.testHelpers[name] = this.helperContainer[name] = helper(this, name);
          protoWrap(TestPromise.prototype, name, helper(this, name), helpers[name].meta.wait);
        }

        invokeInjectHelpersCallbacks(this);
      },

      /**
        This removes all helpers that have been registered, and resets and functions
        that were overridden by the helpers.

        Example:

        ```javascript
        App.removeTestHelpers();
        ```

        @public
        @method removeTestHelpers
      */
      removeTestHelpers() {
        if (!this.helperContainer) { return; }

        for (let name in helpers) {
          this.helperContainer[name] = this.originalMethods[name];
          delete TestPromise.prototype[name];
          delete this.testHelpers[name];
          delete this.originalMethods[name];
        }
      }
    });

    // This method is no longer needed
    // But still here for backwards compatibility
    // of helper chaining
    function protoWrap(proto, name, callback, isAsync) {
      proto[name] = function(...args) {
        if (isAsync) {
          return callback.apply(this, args);
        } else {
          return this.then(function() {
            return callback.apply(this, args);
          });
        }
      };
    }

    function helper(app, name) {
      let fn = helpers[name].method;
      let meta = helpers[name].meta;
      if (!meta.wait) {
        return (...args) => fn.apply(app, [app, ...args]);
      }

      return (...args) => {
        let lastPromise = run(() => resolve(getLastPromise()));

        // wait for last helper's promise to resolve and then
        // execute. To be safe, we need to tell the adapter we're going
        // asynchronous here, because fn may not be invoked before we
        // return.
        asyncStart();
        return lastPromise.then(() => fn.apply(app, [app, ...args])).finally(asyncEnd);
      };
    }