// This is the first file included 
 
/**
 * @class ST
 * @singleton
 *
 * This is the root namespace for the Sencha Test API.
 */
var ST = ST || {};
 
// Create our sub-namespaces. 
ST.future = {};
ST.event = {};
ST.locator = {};
 
/**
 * @class ST.Gate
 * This class manages a counter-based notification queue. Gates start blocked and must
 * be released by calling `unblock`. If other processes must be injected before the Gate
 * should open, the `block` method is used to increment the internal counter. Each such
 * call to `block` must have a corresponding call to `unblock`.
 * @private
 * @since 1.0.2
 */
ST.Gate = function (name, delay) {
    if (delay != null) {
        this.delay = delay;
    }
 
    this.name = name;
 
    /**
     * @property {Number} blocks 
     * The number of blocks that must be released to open this Gate (see `unblock`).
     * @readonly
     * @private
     */
    this.blocks = 1;
 
    /**
     * @property {Function[]} callbacks
     * The array of notification handlers to call when the Gate is opened.
     * @readonly
     * @private
     */
    this.callbacks = [];
};
 
ST.Gate.prototype = {
    /**
     * @property {Number} delay 
     * The number of milliseconds to delay before calling the `callbacks` after the last
     * `unblock` call is made.
     * @readonly
     * @private
     */
    delay: null,
 
    /**
     * Registers a `callback` function to be called when this gate opens.
     * @param callback
     * @private
     */
    on: function (callback) {
        if (this.blocks) {
            this.callbacks.push(callback);
        } else {
            callback();
        }
    },
 
    /**
     * Increments the `blocks` counter by one, thereby preventing this gate from opening.
     * Each call to this method must have a corresponding call to `unblock` to decrement
     * the counter and eventually allow the gate to open.
     * @private
     */
    block: function () {
        ++this.blocks;
    },
 
    /**
     * Notifies all registered `callbacks` that this gate is open. This method is not
     * called directly, but rather when `unblock` has decremented `blocks` to 0.
     * @private
     */
    fire: function () {
        //console.log('fire', this.name); 
        var callbacks = this.callbacks,
            fn;
 
        while (callbacks.length && !this.blocks) {
            fn = callbacks.shift();
            fn();
        }
    },
 
    /**
     * Decrements the `blocks` counter by one, thereby allowing this gate to open. This
     * method should be called once for each call to `block`.
     * @private
     */
    unblock: function () {
        var me = this,
            delay = me.delay;
 
        if (--me.blocks < 1) {
            if (delay === null) {
                me.fire();
            } else {
                ST.defer(function () {
                    me.fire();
                }, delay);
            }
        }
    }
};
 
/**
 * @property {ST.Gate} ready
 * The `ready` gate is opened when the document is ready as well as Ext JS / Sencha Touch.
 * @readonly
 * @private
 * @since 1.0.2
 */
ST.ready = new ST.Gate('ready');
// The initial block count of 1 is decremented by afterFiles() 
 
/**
 * @property {ST.Gate} testsReady
 * The `testsReady` gate is opened when all tests are described and ready to run.
 * @readonly
 * @private
 * @since 1.0.2
 */
ST.testsReady = new ST.Gate('testsReady', 50);
 
// The ready gate opens first and signals that ST is ready and, if the app is using a 
// Sencha SDK, that it is ready. 
// 
// The testsReady gate must not open before ready, but can open immediately after. The 
// jasmine-orion adapter defers running top-level describe() calls until the ready gate 
// is open to ensure those test suites have access to application classes. To do this, 
// jasmine-orion blocks the testsReady gate and defers even running top-level describes() 
// until the ready gate is open. 
 
ST.ready.on(function () {
    // We start with 1 testsReady blockage so here we unblock it. We may have blocked 
    // testsReady to load tests but that does not make any difference since we must 
    // "balance out the books" for the initial block. 
    ST.testsReady.unblock();
});
 
/**
 * This method queues a function to be called when ST is ready to run.
 * @method onReady
 * @param {Function} fn 
 * @private
 */
ST.onReady = function (fn) {
    ST.ready.on(fn);
};
 
ST.now = function () {
    return +new Date();
}
 
/**
 * This object contains various test options.
 * @class ST.options
 * @singleton
 */
ST.options = {
    /**
     * @cfg {Boolean} breakOnFailure 
     * Specify `true` to trigger a `debugger` statement when a test fails.
     */
    breakOnFailure: false,
 
    /**
     * @cfg {Boolean} evaluateTestsOnReady 
     * Specify `false` to evaluate tests immediately instead of scheduling them for
     * after the page achieves `ready` state.
     */
    evaluateTestsOnReady: true,
 
    /**
     * @cfg {Number} eventDelay 
     * The milliseconds to delay between events in `ST.play` calls.
     */
    eventDelay: 500,
 
    /**
     * @cfg {Boolean} eventTranslation 
     * `false` to disable event translation.  If `false` events that are not supported by
     * the browser's event APIs will simply be skipped.
     */
    eventTranslation: true,
 
    /**
     * @cfg {Boolean} failOnMultipleMatches 
     * Specify `false` to suppress errors when locators produce multiple results.
     */
    failOnMultipleMatches: true,
 
    /**
     * @property {Object} globals 
     * An object holding as property keys the names of allowed global variables. Any
     * other global variables created by a test will be reported as failures due to
     * global variable leakage. Use {@link ST#addGlobals} to add allowable globals.
     * Normally, allowed globals are configured in the test project and/or scenario.
     */
    globals: {},
 
    /**
     * @cfg {Boolean} handleExceptions 
     * Set to `false` to disable internal `try`/`catch` wrappers. Disabling these
     * wrappers can make it easier to catch problems as they happen in the debugger
     * but will prevent test execution from continuing beyond them.
     */
    handleExceptions: true,
 
    /**
     * @cfg {number} [screenshotTimeout=60000]
     * The default timeout value (in milliseconds) for screenshots.
     */
    screenshotTimeout: 60000,
 
    /**
     * @cfg {number} timeout 
     * The default timeout value (in milliseconds). Specify `0` to disable timeouts
     * by default. This can be useful when debugging since it allows time to
     * manipulate the environment during test execution.
     */
    timeout: 5000,
 
    /**
     * @cfg {Number} typingDelay 
     * The milliseconds to delay between keyboard events in `ST.play` calls when playing
     * back `type` events.
     */
    typingDelay: 100,
 
    /**
     * @cfg {Boolean} visualFeedback 
     * `false` to disable visual feedback during event playback (mouse cursor, and "gesture"
     * indicator)
     */
    visualFeedback: true
};
 
(function () {
    var scripts = document.getElementsByTagName('script'),
        n = scripts.length,
        cookie = 'ext-cache=1; expires=',
        src;
 
    while (n-- > 0) {
        src = scripts[n].src;
 
        // Pick up the "_dc=" query parameter on our init.js file to see if the 
        // cacheBuster is enabled. Based on that we set or remove the "ext-cache" 
        // cookie. This cookie has been checked by Ext JS since 4.1.x era as a 
        // way to control the cacheBuster w/o resorting to URL hacks. 
        // 
        if (src && src.indexOf('~orion/files/init.js') > 0) {
            cookie += (src.indexOf('_dc') < 0) ? 0 : 'Thu, 01 Jan 1970 00:00:00 GMT';
            cookie += '; path=/';
            document.cookie = cookie;
            break;
        }
    }
}());
 
//----------------------------------------------------------------------- 
// Ext._beforereadyhandler is called very early on Ext JS initialization, 
// so we use it to block ST immediately in case the framework is 
// present and unblock it once it's ready. But that's not the end of the 
// story - see orion.js afterFiles(). 
 
var Ext = Ext || {};
Ext._beforereadyhandler = function() {
    ST.Ext = Ext; // feature detector for Ext JS (since we created the global) 
    
    if (Ext.getVersion) {
        ST.isModern = Ext.isModern;
        ST.isTouch = !!Ext.versions.touch;
        ST.isClassic = !ST.isModern && !ST.isTouch;
        ST.sdkVersion = new ST.Version(Ext.getVersion().version);
    }
 
    ST.ready.block();
 
    Ext.onReady(function () {
        ST.defer(function() {
            // Slightly delayed to ensure that this runs after any user onReady 
            // handlers.  This approach is preferred over using the priority option 
            // because it works with all versions of the framework. 
            ST.ready.unblock();
        }, 100);
    });
};