1. #1
    Sencha User willf1976's Avatar
    Join Date
    May 2009
    Location
    carpinteria, ca
    Posts
    84
    Vote Rating
    0
    willf1976 is on a distinguished road

      0  

    Default Durable "selids" for selenium intregration tests

    Durable "selids" for selenium intregration tests


    Hi All

    I have been going through the classes we have developed over the last few years and sharing back with the community some of them that I think will be useful to others. These components have been tested extensively in ext-3.2.1.

    When we were writing tests utilizing selenium / sauce rc we found it very difficult to reference ext elements in the dom. The order in which elements appeared could not be guaranteed and there for the ids generated by ext could not be predicted. We built some tools to create a dom element property for ext components (as well as grid cells/rows and tree nodes) that would be more durable. These "selid" dom attributes helped us out alot and saved us alot of time and head ache in writing our integration tests. This code also includes some tools to allow for wait methods that depend on the number of ajax requests that are still outstanding.


    Here are the Ext components we used to accomplish these goals, then below are the selenium / sauce rc components.

    Ext.Rtb.SeleniumOverrides.js
    Code:
    /**
     * @author Will Ferrer, Ethan Brooks
     * @copyright (c) 2012, Intellectual Property Private Equity Group
     * @licensee 2012 developed under license for Switchsoft LLC http://www.switchsoft.com a "Direct response telephony company" as part of it's "VOIP Call distribution, ROI analysis platform, call recording, and IVR for inbound and outbound sales" and Run the Business Systems LLC a "Technology development investment group" as part of it's "PHP, Javascript rapid application development framework and MySQL analysis tools"
     * @license licensed under the terms of
     * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
     * that the code/component(s) do NOT become part of another Open Source or Commercially
     * licensed development library or toolkit without explicit permission.
     * <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
     * target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
    * We are pretty nice just ask. We want to meet our licensees
    */
    /*
     * date: 01/24/11
     * Overrides Ext components to have a createSelid method and a setUpSelid method (etc). Called by listeners created in Ext.ux.SeleniumPrep.
     */
     
     
    Ext.override(Ext.Component, {
        /**
         * Sets up the listeners that creates the selid ids 
         */
        setUpSelid : function () {
            this.on('afterrender', this.createSelid, this);
            this.on('show', this.createSelid, this);
        },
        /**
         * Creates the selid and uses the Ext.ux.SeleniumPrep.applySelid method to apply it to the dom. There is an order of priority in what property of the component will be used as the base of the selid. id is only considered if the id does not end in a -[a-z]*[0-9]+$. Further more if the code resorts to using the class of the dom element it will tag the dom element with a property of isdomclassselid -- certain locators will ignor dom elements with this property since its not a great way of identifying elements. Also what dom element the selid will be applied to based on what properties are available on the component.
         */
        createSelid : function () {
            var nameValueSeperator = Ext.ux.SeleniumPrep.nameValueSeperator,
                domElemn, selidIdBase, selid, extra = {};
                /*domElemn = this.btnEl,
                domElemn = (Ext.isEmpty(domElemn))?this.el:domElemn,
                domElemn = (Ext.isEmpty(domElemn))?this.dom:domElemn,
                domElemn = (Ext.isEmpty(domElemn))?this.body:domElemn,
                selidIdBase = (!Ext.isEmpty(this.selid))?this.selid:null,
                selidIdBase = (!Ext.isEmpty(this.name) && Ext.isEmpty(selidIdBase))?'name'+nameValueSeperator+this.name:selidIdBase,
                selidIdBase = (!Ext.isEmpty(this.title) && Ext.isEmpty(selidIdBase))?'title'+nameValueSeperator+this.title:selidIdBase,
                selidIdBase = (!Ext.isEmpty(this.fieldLabel) && Ext.isEmpty(selidIdBase))?'fieldLabel'+nameValueSeperator+this.fieldLabel:selidIdBase,
                selidIdBase = (!Ext.isEmpty(this.label) && Ext.isEmpty(selidIdBase))?'label'+nameValueSeperator+this.label:selidIdBase,
                selidIdBase = (!Ext.isEmpty(this.text) && Ext.isEmpty(selidIdBase))?'text'+nameValueSeperator+this.text:selidIdBase,
                selidIdBase = (!Ext.isEmpty(this.id) && !/\-[0-9]+$/.test(this.id) && Ext.isEmpty(selidIdBase))?'id'+nameValueSeperator+this.id:selidIdBase,
                selidIdBase = (!Ext.isEmpty(this.cls) && Ext.isEmpty(selidIdBase))?'cls'+nameValueSeperator+this.cls:selidIdBase,
                selidIdBase = (!Ext.isEmpty(domElemn.getAttribute('class')) && Ext.isEmpty(selidIdBase))?'dom_class'+nameValueSeperator+domElemn.getAttribute('class'):selidIdBase,
                selid;*/
                
            if (!Ext.isEmpty(this.btnEl)) {
                domElemn = this.btnEl
            } else if (!Ext.isEmpty(this.el)) {
                domElemn = this.el;
            } else if (!Ext.isEmpty(this.dom)) {
                domElemn = this.dom;
            } else if (!Ext.isEmpty(this.body)) {
                domElemn = this.body;
            }
    
            if (!Ext.isEmpty(this.selid)) {
                selidIdBase = this.selid;
            } else if (!Ext.isEmpty(this.id) && !/\-[a-z]*[0-9]+$/.test(this.id)) {
                selidIdBase = 'id'+nameValueSeperator+this.id;
            } else if (!Ext.isEmpty(this.name)) {
                selidIdBase = 'name'+nameValueSeperator+this.name;
            } else if (!Ext.isEmpty(this.title)) {
                selidIdBase = 'title'+nameValueSeperator+this.title;
            } else if (!Ext.isEmpty(this.fieldLabel)) {
                selidIdBase = 'fieldLabel'+nameValueSeperator+this.fieldLabel;
            } else if (!Ext.isEmpty(this.label)) {
                selidIdBase = 'label'+nameValueSeperator+this.label;
            } else if (!Ext.isEmpty(this.text)) {
                selidIdBase = 'text'+nameValueSeperator+this.text;
            } else if (!Ext.isEmpty(this.cls)) {
                selidIdBase = 'cls'+nameValueSeperator+this.cls;
            } else if (!Ext.isEmpty(domElemn.getAttribute('class'))) {
                selidIdBase = 'dom_class'+nameValueSeperator+domElemn.getAttribute('class');
                extra['isdomclassselid'] = true;
            }
            
            if (!Ext.isEmpty(selidIdBase) && !Ext.isEmpty(domElemn)) {
                selid = Ext.ux.SeleniumPrep.applySelid(selidIdBase, domElemn, this, extra);
                if (!Ext.isEmpty(selid)) {
                    this.selid = selid;
                }
            }
            
            if (!Ext.isEmpty(this.iframe) && !Ext.isEmpty(selidIdBase)) {
                Ext.ux.SeleniumPrep.applySelid(selidIdBase + '-iframe', Ext.fly(this.iframe), this);
            }
        }
    });
    
    
    
    Ext.override(Ext.grid.GridPanel, {
        /**
         * Sets up the listeners that creates the selid ids. Also sets up listeners on the grid view to put selids on rows 
         */
        setUpSelid : function () {
            this.on('viewready', this.setUpRowSelid, this);
            Ext.grid.GridPanel.superclass.setUpSelid.call(this);
        },
        /**
         * Sets up the listeners that creates the selid ids. Also sets up listeners on the grid view to put selids on rows 
         */
        setUpRowSelid : function () {
            this.view.on('refresh', this.createRowSelid, this.view);
            this.view.on('rowsinserted', this.createRowSelid, this.view);
            //this.view.on('rowremoved', this.createRowSelid, this);
            //this.view.on('rowupdated', this.createRowSelid, this);
        },
        /**
         * Creates the selid and uses the Ext.ux.SeleniumPrep.applySelid method to apply it to the dom of each row. The selid based on the selid of the grid + '-' either the selid of the row (if one is provided in the store) or an encoded version of the rows data or an encoded version of just the properties of the row listed in the cleanedAttributes property of the grid.
         */
        createRowSelid : function () {
            var store = this.grid.getStore(),
                view = this.grid.getView(),
                parentSelid = (!Ext.isEmpty(this.grid.selid))?this.grid.selid:'',
                n, record, recordIndex, row, selidIdBase, keyAttributes, curAttribute, obj;
            for(n=0;n<store.data.items.length;n++) {
                record = store.data.items[n];
                recordIndex = store.indexOf(record);
                domElemn = Ext.fly(view.getRow(recordIndex));
                if (domElemn) {
                    if (!Ext.isEmpty(record.data['selid']) && record.data['selid'] !== false) {
                        selidIdBase = Ext.ux.SeleniumPrep.prefixParentSelid + parentSelid + Ext.ux.SeleniumPrep.selidElementSeperator + record.get('selid');
                    } else if (!Ext.isEmpty(this.grid.selidIDAttributes)) {
                        for(n=0; n<this.grid.selidIDAttributes.length; n++) {
                            curAttribute = this.grid.selidIDAttributes[n];
                            if (!Ext.isObject(record.data[curAttribute])) {
                                keyAttributes[curAttribute] = record.data[curAttribute];
                            }
                        }
                        selidIdBase = Ext.ux.SeleniumPrep.prefixParentSelid + parentSelid + Ext.ux.SeleniumPrep.selidElementSeperator + Ext.encode(keyAttributes);
                    } else {
                        selidIdBase = '';
                        for (obj in record.data) {
                            if (!Ext.isEmpty(record.data[obj])) {
                                selidIdBase += obj + ':' + record.data[obj].substr(0, 64) + ',';
                            } else {
                                selidIdBase = obj;
                            }
                        }
                        
                        selidIdBase = Ext.ux.SeleniumPrep.prefixParentSelid + parentSelid + Ext.ux.SeleniumPrep.selidElementSeperator + selidIdBase
                        //selidIdBase = parentSelid + '-' +  Ext.encode(record.data);
                    }
                    Ext.ux.SeleniumPrep.applySelid(selidIdBase, domElemn, this);
                }
            }
        }
    });
    
    
    
    Ext.override(Ext.tree.TreePanel, {
        /**
         * Sets up the listeners that creates the selid ids. Also sets up listeners on the treepanel to apply selid ids to the nodes.
         */
        setUpSelid : function () {
            this.on('afterrender', this.createNodeSelids, this);
            this.on('append', this.createNodeSelids, this);
            this.on('expandnode', this.createNodeSelids, this);
            this.on('insert', this.createNodeSelids, this);
            Ext.tree.TreePanel.superclass.setUpSelid.call(this);
        },
        /**
         * Creates the selid and uses the Ext.ux.SeleniumPrep.applySelid method to apply it to the dom of each node. The selid based on the selid of the treepanel + '-' either the selid of the node if one is provided in the store) and all its parent nodes or an encoded version of the nodes attributes or just the attributes listed in the selidIDAttributes Property of the tree. Nodes that are not visible in the tree are ignored until they are made visible. You may make all nodes receive selids by setting a property of: makeAllSelids : true on the tree.
         * @param {Object} A node to apply the selids to the children of
         */
        createNodeSelids : function (node) {
            var parentSelid = (!Ext.isEmpty(this.selid))?this.selid:'',
                node = (Ext.isEmpty(node))?this.getRootNode():node, 
                cleanedAttributes = {},
                domElemn, n, appliedSelid, curNode, curAttribute;
            if (((!Ext.isEmpty(node.rendered) && node.rendered) && (Ext.isEmpty(node.hidden) || !node.hidden) && !Ext.isEmpty(node.attributes)) || (!Ext.isEmpty(this.makeAllSelids) && this.makeAllSelids)) {
                if (!Ext.isEmpty(node.ui) && !Ext.isEmpty(node.ui.getEl)) {
                    domElemn = Ext.fly(node.ui.getEl());
                    if (domElemn && !domElemn.dom.hasAttribute('selid')) {
                        if (!Ext.isEmpty(node.attributes['selid'])) {
                            selidIdBase = node.attributes['selid'];
                        } else if (!Ext.isEmpty(this.selidIDAttributes)) {
                            for(n=0; n<this.selidIDAttributes.length; n++) {
                                curAttribute = this.selidIDAttributes[n];
                                if (!Ext.isEmpty(node.attributes[curAttribute]) && !Ext.isObject(node.attributes[curAttribute])) {
                                    cleanedAttributes[curAttribute] = node.attributes[curAttribute];
                                }
                            }
                            selidIdBase = Ext.encode(cleanedAttributes);
                            
                        } else {
                            for(obj in node.attributes) {
                                if (!Ext.isObject(node.attributes[obj])) {
                                    cleanedAttributes[obj] = node.attributes[obj];
                                }
                            }
                            selidIdBase = Ext.encode(cleanedAttributes);
                        }
                        
                        curNode = node;
                        while (!Ext.isEmpty(curNode.parentNode) && !Ext.isEmpty(curNode.parentNode.attributes['selid'])) {
                            selidIdBase += Ext.ux.SeleniumPrep.selidElementSeperator + curNode.parentNode.attributes['selid'];
                            curNode = curNode.parentNode;
                        }
                        selidIdBase = Ext.ux.SeleniumPrep.prefixParentSelid + parentSelid + Ext.ux.SeleniumPrep.selidElementSeperator + selidIdBase;
                        appliedSelid = Ext.ux.SeleniumPrep.applySelid(selidIdBase, domElemn, this);
                        node['selid'] = appliedSelid;
                    }
                    
                }
    
                if (!Ext.isEmpty(node.eachChild)) {
                    node.eachChild(this.createNodeSelids, this);
                }
            }
        }
    });
    
    
    
    
    Ext.override(Ext.form.ComboBox, {
        /**
         * Sets up the listeners that creates the selid ids. Also sets up listeners on the combobox to apply selid ids to its rows.
         */
        setUpSelid : function () {
            this.on('expand', this.createComboRowSelids, this);
            this.on('afterrender', this.createComboRowSelids, this);
            this.on('afterrender', this.setUpStoreListener, this);
            Ext.form.ComboBox.superclass.setUpSelid.call(this);
        },
        /**
         * Sets up the listeners that creates the selid ids on the store.
         */
        setUpStoreListener : function () {
            this.store.on('load', this.createComboRowSelids, this);
        },
        /**
         * Creates the selid and uses the Ext.ux.SeleniumPrep.applySelid method to apply it to the dom of each combobox row. The selid based on the selid of the combobox + '-' either the selid of the store row (if one is provided in the store) or an encoded version of the store rows data, or if none is found the innerHtml of the dom of the combobox.
         * @param {Object} A node to apply the selids to the children of
         */
        createComboRowSelids : function () {
            var parentSelid = (!Ext.isEmpty(this.selid))?this.selid:'',
                n, n2, domElem, selidIdBase, record, keyAttributes={};
                
            if (!Ext.isEmpty(this.view)) {
                for (n=0; n<this.view.all.elements.length; n++) {
                    domElemn = Ext.fly(this.view.all.elements[n]);
                    if (!Ext.isEmpty(this.store) && !Ext.isEmpty(this.store.data) && !Ext.isEmpty(this.store.data) && !Ext.isEmpty(this.store.data.items) && !Ext.isEmpty(this.store.data.items[n])) {
                        record = this.store.data.items[n];
                        if (record.get('selid')) {
                            selidIdBase = Ext.ux.SeleniumPrep.prefixParentSelid + parentSelid + Ext.ux.SeleniumPrep.selidElementSeperator + record.get('selid');
                        } else if (!Ext.isEmpty(this.selidIDAttributes)) {
                            for(n2=0; n2<this.selidIDAttributes.length; n2++) {
                                curAttribute = this.selidIDAttributes[n2];
                                if (!Ext.isObject(record.data[curAttribute])) {
                                    keyAttributes[curAttribute] = record.data[curAttribute];
                                }
                            }
                            selidIdBase = Ext.ux.SeleniumPrep.prefixParentSelid + parentSelid + Ext.ux.SeleniumPrep.selidElementSeperator + Ext.encode(keyAttributes);
                        } else {
                            selidIdBase = Ext.ux.SeleniumPrep.prefixParentSelid + parentSelid + Ext.ux.SeleniumPrep.selidElementSeperator +  Ext.encode(record.data);
                        }
                    } else {
                        selidIdBase = Ext.ux.SeleniumPrep.prefixParentSelid + parentSelid + Ext.ux.SeleniumPrep.selidElementSeperator +  domElemn.dom.innerHTML;    
                    }
                    Ext.ux.SeleniumPrep.applySelid(selidIdBase, domElemn, this);
                }
            }
        }
    });
    Ext.ux.SeleniumPrep.js
    Code:
    /**
     * @author Will Ferrer, Ethan Brooks
     * @copyright (c) 2012, Intellectual Property Private Equity Group
     * @licensee 2012 developed under license for Switchsoft LLC http://www.switchsoft.com a "Direct response telephony company" as part of it's "VOIP Call distribution, ROI analysis platform, call recording, and IVR for inbound and outbound sales" and Run the Business Systems LLC a "Technology development investment group" as part of it's "PHP, Javascript rapid application development framework and MySQL analysis tools"
     * @license licensed under the terms of
     * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
     * that the code/component(s) do NOT become part of another Open Source or Commercially
     * licensed development library or toolkit without explicit permission.
     * <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
     * target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
    * We are pretty nice just ask. We want to meet our licensees
    */
    /*
     * author: Will Ferrer
     * date: 01/24/11
     * @class Ext.ux.SeleniumPrep
     * @singleton
     * @extends Object
     * A singleton object used to create and track selid ids created for selenium tracking through sauceIde to turn on the selniumn ids either call: Ext.ux.SeleniumPrep.setUpGenerateSelids() (before any ext components have already loaded) or set the property Ext.ux.SeleniumPrep.generateSelids to true.
     * @constructor
     * @param {Object} config The config object
     */
    Ext.ns('Ext.ux');
    Ext.ux.SeleniumPrep = function(){
        return {
            /**
             * @private internal config {Object}
             * An object containing keys for all the selids used with a value of an array that contains objects with the div and component that use that selid. This is used to keep a count for each selid so we can number the actual selids as they come in so we can keep them unique. Is only used if strictSelids is set to true
             */
            logged : {
                
            },
    
            /**
            * @cfg {Boolean} generateSelids
            * Causes selids to be generated via the setUpGenerateSelids method
            */
            generateSelids : true,
            /**
            * @cfg {Boolean} listenForRemoting
            * Sets whether or not we should listen for remoting calls. If this is set to true then we can use the selenium user extention method waitForRemote.
            */
            listenForRemoting : true,
            /**
            * @cfg {Boolean} displayRemotingErrors
            * sets whether or not we should try to detect results from remote that has a success of false and display their messages in an alert window.
            */
            displayRemotingErrors : true,
            /**
            * @cfg {Boolean} strictSelids
            * sets whether or not we should use strict selids. If set to false then when a selid is generated we will run a dom query to see if the selid currently exists and add a number to the end of the selids if it does. If set to true then we will add a number to the end of the selid if a duplicate selid ever existed.
            */
            strictSelids : false,
            /**
            * @cfg {String} nameValueSeperator
            * When generating selids this will be put between the name of a property and the value of that property when creating the base selid
            */
            nameValueSeperator : ':',
            /**
            * @cfg {String} prefixParentSelid
            * when including a parents selid in the baseSelid this will be put infront of it.
            */
            prefixParentSelid : 'parentSelid:',
            /**
            * @cfg {String} selidElementSeperator
            * when multiple pieces of information are strung together for a selid this is put between them.
            */
            selidElementSeperator : '-',
            /**
            * @cfg {Number} maxLengthBeforeHash
            * How long a selid can be before we hash it to make it shorter
            */
            maxLengthBeforeHash : 256,
            /**
            * @cfg {Regex} selidRegEx
            * a regular expression used to parse selids -- replacing characters that do not match.
            */
            selidRegEx : /[^a-z0-9_\-\=\+\|\^\&\*\%\$\#\@\!\>\<\?\\\/\?\;\:\s]/ig,
            /**
            * @cfg {Regex} selidSubstitutionArray
            * array of substetutions to make in selids -- contains sub arrays with 2 elements: pattern to match and replacement to make.
            */
            selidSubstitutionArray : [[/\,/g, '|'], [/[\{\(]/g, '|'], [/[\}\)]/g, '|']],
            
            // @private
            pendingRequestCount : 0,
            // @private
            lastPendingRequestCount : 0,
            // @private
            pendingProcessCount : 0,
            // @private
            lastPendingProcessCount : null,
            // @private
            lastLoadingMask : null,
             /**
             * Puts listeners on the Ext.ComponentMgr.all to generate the selid properties in the dom
             */
            setUpGenerateSelids : function (){
                Ext.ComponentMgr.all.on('add', Ext.ux.SeleniumPrep.onAdd);
                Ext.ComponentMgr.all.on('replace', Ext.ux.SeleniumPrep.onReplace);
            },
            /**
             * Formats the string work as a selid -- if there are characters other than a-z0-9_- or if the string is longer than Ext.ux.SeleniumPrep.maxLengthBeforeHash chars, then the first usable Ext.ux.SeleniumPrep.maxLengthBeforeHash chars will be used along with a md5 hash of the whole string. Also logs the needed info in the logged property - a count number will be added to the end of the selid if an identical 1 has already been logged. 
             * @param {String} string string to hash
             * @param {Object} dom the dom element to add the id to
             * @param {Object} component a component associated with the selid
             */
            formatSelId : function (baseSelid, dom, component){
                var cleanedString, hexedString, baseSelid, domQueriedComponents, fullSelid,
                    regEx = Ext.ux.SeleniumPrep.selidRegEx,
                    n;
                for(n=0;n<Ext.ux.SeleniumPrep.selidSubstitutionArray.length;n++){
                    baseSelid = baseSelid.replace(Ext.ux.SeleniumPrep.selidSubstitutionArray[n][0], Ext.ux.SeleniumPrep.selidSubstitutionArray[n][1]);
                }
                if (regEx.test(baseSelid) || baseSelid.length > Ext.ux.SeleniumPrep.maxLengthBeforeHash) {
                    hexedString = Ext.ux.Crypto.SHA1.hash(baseSelid);
                    cleanedString = baseSelid.replace( /(<([^>]+)>)/ig, "");
                    cleanedString = baseSelid.replace(regEx, "");
                    cleanedString = (!Ext.isEmpty(cleanedString))?cleanedString.substring(0, Ext.ux.SeleniumPrep.maxLengthBeforeHash):'';
                    baseSelid = cleanedString + '-' + hexedString;
                } else {
                    baseSelid = baseSelid;
                }
                if (Ext.ux.SeleniumPrep.strictSelids) {
                    if (Ext.isEmpty(this.logged[baseSelid])) {
                        this.logged[baseSelid] = [];
                    }
                    this.logged[baseSelid].push({
                        dom : dom,
                        component : component
                    });
                    count = this.logged[baseSelid].length - 1;
                    
                } else {
                    domQueriedComponents = Ext.query('[@selid^='+ baseSelid + ']');
                    count = domQueriedComponents.length;
                }
                fullSelid = (count>0)?baseSelid + '-' + count:baseSelid;
                return fullSelid;
            },
            /**
             * Applies a selid to the passed dom element passing it through the formatSelId
             * @param {String} baseSelid a selid to start with before formating it with the formatSelId
             * @param {Object} dom the dom element to add the id to
             * @param {Object} component a component associated with the selid
             * @param {Object} extra extra properties to be added to the dom of the element.
             */
            applySelid : function (baseSelid, dom, component, extra){
                var count, fullSelid, params,
                    extra = (Ext.isEmpty(extra))?{}:extra;
                if (Ext.isEmpty(dom.getAttribute('selid')) || !dom.getAttribute('selid')) {
                    fullSelid = Ext.ux.SeleniumPrep.formatSelId(baseSelid, dom, component);
                    params = Ext.apply(extra, {
                        selid : fullSelid
                    });
                    dom.set(params);
                    return fullSelid;
                }
                return '';
            },
            /**
             * A method to be called on add for the Ext.ComponentMgr
             * @param {Number} baseSelid a selid to start with, a "-[count]" will be added to end if this selid has been used already.
             * @param {Object} dom the dom element to add the id to
             */
            onAdd : function (index, o){
                if (!Ext.isEmpty(o.setUpSelid)) {
                    o.setUpSelid();
                }
            },
            /**
             * A method to be called on replace for the Ext.ComponentMgr
             * @param {Number} baseSelid a selid to start with, a "-[count]" will be added to end if this selid has been used already.
             * @param {Object} dom the dom element to add the id to
             */
            onReplace : function (key, oldObj, newObj){
                if (!Ext.isEmpty(newObj.setUpSelid)) {
                    newObj.setUpSelid();
                }
            },
            /**
             * listens for remoting and counts up and down the Ext.ux.pendingRequestCount
             * @param {Object} provider the provider to listen on
             */
            countRemoting : function (provider) {
                provider.on("call", Ext.ux.SeleniumPrep.countUpPendingRequestCount, this);
                provider.on("data", Ext.ux.SeleniumPrep.countDownPendingRequestCount, this);
                provider.on("exception", Ext.ux.SeleniumPrep.countDownPendingRequestCount, this);
                Ext.Ajax.on("beforerequest", Ext.ux.SeleniumPrep.countUpPendingRequestCount, this);
                Ext.Ajax.on("requestcomplete", Ext.ux.SeleniumPrep.countDownPendingRequestCount, this);
                Ext.Ajax.on("requestexception", Ext.ux.SeleniumPrep.countDownPendingRequestCount, this);
            },
            
            /**
             * listens for remoting and counts up and down the Ext.ux.pendingRequestCount
             * @param {Object} provider the provider to listen on
             */
            setUpDisplayRemotingErrors : function (provider) {
                provider.on("data", Ext.ux.SeleniumPrep.showRemotingAlerts, this);
                provider.on("exception", Ext.ux.SeleniumPrep.showRemotingAlerts, this);
                Ext.Ajax.on("requestcomplete", Ext.ux.SeleniumPrep.showRemotingAlerts, this);
                Ext.Ajax.on("requestexception", Ext.ux.SeleniumPrep.showRemotingAlerts, this);
            },
            /**
             * increases the pending process count by one. When all pending processes are depleted the checkPendingProcesses method will return true. Used by the waitForProcesses selenium user extention method.
             */
            countUpPendingProcessCount : function (){
                Ext.ux.SeleniumPrep.lastPendingProcessCount = (Ext.isEmpty(Ext.ux.SeleniumPrep.lastPendingProcessCount))?0:Ext.ux.SeleniumPrep.lastPendingProcessCount;
                Ext.ux.SeleniumPrep.lastPendingProcessCount = Ext.ux.SeleniumPrep.pendingProcessCount;
                Ext.ux.SeleniumPrep.pendingProcessCount++;
            },
             /**
             * decreases the pending process count by one. When all pending processes are depleted the checkPendingProcesses method will return true. Used by the waitForProcesses selenium user extention method.
             */
            countDownPendingProcessCount : function (pendingId){
                Ext.ux.SeleniumPrep.lastPendingProcessCount = Ext.ux.SeleniumPrep.pendingProcessCount;
                Ext.ux.SeleniumPrep.pendingProcessCount--;
                if (Ext.ux.SeleniumPrep.pendingProcessCount<0) {
                    Ext.ux.SeleniumPrep.pendingProcessCount = 0;
                }
            },
            /**
             * Checks if there is anything in the pending array.
             * @return {Boolean}
             */
            checkPendingProcesses : function (pendingId){
                var returnValue = (Ext.ux.SeleniumPrep.pendingProcessCount<=0 && (Ext.ux.SeleniumPrep.lastPendingProcessCount > 0 || Ext.isEmpty(Ext.ux.SeleniumPrep.lastPendingProcessCount)))?true:false;
                Ext.ux.SeleniumPrep.lastPendingProcessCount = (returnValue)?null:Ext.ux.SeleniumPrep.lastPendingProcessCount;
                return returnValue;
                /*var returnValue = (Ext.ux.SeleniumPrep.pendingProcessCount<=0 && (Ext.ux.SeleniumPrep.lastPendingProcessCount > 0 || Ext.isEmpty(Ext.ux.SeleniumPrep.lastPendingProcessCount)))?true:false;
                Ext.ux.SeleniumPrep.lastPendingProcessCount = (returnValue)?0:Ext.ux.SeleniumPrep.lastPendingProcessCount;
                return returnValue;*/
                //return (Ext.ux.SeleniumPrep.pendingProcessCount<=0 && (Ext.ux.SeleniumPrep.lastPendingProcessCount > 0 || Ext.isEmpty(Ext.ux.SeleniumPrep.lastPendingProcessCount)))?true:false;
            },
            /**
             * Checks if there are no more pending requests
             * @return {Boolean}
             */
            checkPendingRequests : function (){
                var returnValue = (Ext.ux.SeleniumPrep.pendingRequestCount<=0 && Ext.ux.SeleniumPrep.lastPendingRequestCount > 0)?true:false;
                /*console.log(returnValue);
                console.log(Ext.ux.SeleniumPrep.pendingRequestCount);
                console.log(Ext.ux.SeleniumPrep.lastPendingRequestCount);*/
                Ext.ux.SeleniumPrep.lastPendingRequestCount = (returnValue)?0:Ext.ux.SeleniumPrep.lastPendingRequestCount;
                return returnValue;
                //console.log(returnValue);
                //console.log((Ext.ux.SeleniumPrep.pendingRequestCount<=0 && Ext.ux.SeleniumPrep.lastPendingRequestCount > 0));
                //return false;
                //return (Ext.ux.SeleniumPrep.pendingRequestCount<=0 && Ext.ux.SeleniumPrep.lastPendingRequestCount > 0)?true:false;
            },
            /**
             * if both checkPendingProcesses and checkPendingRequests are done
             * @return {Boolean}
             */
            checkComplete : function (){
                return (Ext.ux.SeleniumPrep.checkPendingProcesses() && Ext.ux.SeleniumPrep.checkPendingRequests())?true:false;
            },
            // @private
            countUpPendingRequestCount : function () {
                Ext.ux.SeleniumPrep.lastPendingRequestCount = Ext.ux.SeleniumPrep.pendingRequestCount;
                Ext.ux.SeleniumPrep.pendingRequestCount++;
            },
            // @private
            countDownPendingRequestCount : function () {
                Ext.ux.SeleniumPrep.lastPendingRequestCount = Ext.ux.SeleniumPrep.pendingRequestCount;
                Ext.ux.SeleniumPrep.pendingRequestCount--;
                if (Ext.ux.SeleniumPrep.pendingRequestCount<0) {
                    Ext.ux.SeleniumPrep.pendingRequestCount = 0;
                }
            },
            // @private
            showRemotingAlerts : function (info, response) {
                var response = (!Ext.isEmpty(response.result))?response.result:response,
                    message;
                if (response.success == false && Ext.isEmpty(response.status) && !Ext.isEmpty(response.message)) {
                    alert(response.message);
                }
            }
        };
    }();
    
    
    Ext.onReady(function () {
        var obj, 
            seleniumPresent=(Ext.isEmpty(seleniumPresent))?false:seleniumPresent;
            
        // First way to detect if selenuium is present is by checking the window name
        if (!seleniumPresent) {
            if (/selenium|sauce/i.test(window.name)) {
                seleniumPresent = true;
            }
        }
        
        // We can also detect selenium when running in sauce rc by checking for javascript properties created by sauce rc
        if (!seleniumPresent) {
            for(obj in window.content) {
                if (/selenium|sauce/i.test(obj)) {
                    seleniumPresent = true;
                    break;
                }
            }
        }
    
        // We can detect selemium if we can't access properties of the parent window:
        if (!seleniumPresent) {
            try {
                window.opener.name;
            } catch (e) {
                if (/Error: Permission denied/.test(e)) {
                    seleniumPresent = true;
                }
            }
        }
        
    
        //Do the selids if selenium is present:
        if (seleniumPresent) {
            if (!Ext.isEmpty(Ext.ux.SeleniumPrep.generateSelids) && Ext.ux.SeleniumPrep.generateSelids) {
                Ext.ux.SeleniumPrep.setUpGenerateSelids();
            }
            if (Ext.ux.SeleniumPrep.listenForRemoting) {
                Ext.onReady(function () {
                    Ext.ux.SeleniumPrep.countRemoting(directProvider);
                });
            }
            
            if (Ext.ux.SeleniumPrep.listenForRemoting && Ext.ux.SeleniumPrep.displayRemotingErrors) {
                Ext.onReady(function () {
                    Ext.ux.SeleniumPrep.setUpDisplayRemotingErrors(directProvider);
                });
            }
        }
        
    });

    Selenium / Sauce RC components:


    selidLocator.js
    Code:
    /**
     * @author Will Ferrer, Ethan Brooks
     * @copyright (c) 2012, Intellectual Property Private Equity Group
     * @licensee 2012 developed under license for Switchsoft LLC http://www.switchsoft.com a "Direct response telephony company" as part of it's "VOIP Call distribution, ROI analysis platform, call recording, and IVR for inbound and outbound sales" and Run the Business Systems LLC a "Technology development investment group" as part of it's "PHP, Javascript rapid application development framework and MySQL analysis tools"
     * @license licensed under the terms of
     * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
     * that the code/component(s) do NOT become part of another Open Source or Commercially
     * licensed development library or toolkit without explicit permission.
     * <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
     * target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
    * We are pretty nice just ask. We want to meet our licensees
    */
    /*
     * date: 01/24/11
     * Registers a locator for sauce ide to find elements by a selid attribute on the dom node.
     */
    /**
     * Locator for when a selid is applied to a down element directly.
     */
    LocatorBuilders.add('xpath:selid', function(e) {
        if(e.hasAttribute('selid')) {
            return "//*[@selid='" + e.getAttribute('selid') + "']";
        }
        return null;
    });
    
    
    /**
     * Locator for when a selid is at a level above the current element in the dom
     */
    LocatorBuilders.add('xpath:selidRelative', function(e) {
        var path = '';
        var current = e;
        while (current != null) {
            if (current.parentNode != null) {
                path = this.relativeXPathFromParent(current) + path;
                if (1 == current.parentNode.nodeType && // ELEMENT_NODE
                    current.parentNode.getAttribute("selid")) {
                    return "//" + this.xpathHtmlElement(current.parentNode.nodeName.toLowerCase()) +
                        "[@selid=" + this.attributeValue(current.parentNode.getAttribute("selid")) + "]" +
                        path;
                }
            } else {
                return null;
            }
            current = current.parentNode;
        }
        return null;
    });
    
    /**
     * Locator for when a selid is at a level above the current element in the dom and we wish to find the current dom element by its inner html
     */
    LocatorBuilders.add('xpath:selidToInnerhtml', function(e) {
        var path = '',
            current = e,
            first = current;
        while (current != null) {
            if (current.parentNode != null) {
                path = this.relativeXPathFromParent(current) + path;
                if (1 == current.parentNode.nodeType && // ELEMENT_NODE
                    current.parentNode.getAttribute("selid")) {
                    return "//" + this.xpathHtmlElement(current.parentNode.nodeName.toLowerCase()) + 
                        "[@selid=" + this.attributeValue(current.parentNode.getAttribute("selid")) + "]//" + 
                        this.xpathHtmlElement(first.nodeName.toLowerCase()) + "[.='" + first.innerHTML + "']";
                }
            } else {
                return null;
            }
            current = current.parentNode;
        }
        return null;
    });
    
    
    
    
    
    /**
     * Locator for when a selid is at a level above the current element in the dom and we wish to ignor selids that were generated based on a dom class (the css class of an element in the dom)
     */
    LocatorBuilders.add('xpath:selidNoDCSelidsRelative', function(e) {
        var path = '',
            current = e,
            foundDomClassSelid = false;
        while (current != null) {
            if (current.parentNode != null) {
                path = this.relativeXPathFromParent(current) + path;
                if (current.parentNode.getAttribute("isdomclassselid")) {
                    foundDomClassSelid = true;
                }
                if (1 == current.parentNode.nodeType && // ELEMENT_NODE
                    current.parentNode.getAttribute("selid") && 
                    !current.parentNode.getAttribute("isdomclassselid") &&
                    foundDomClassSelid) {
                    return "//" + this.xpathHtmlElement(current.parentNode.nodeName.toLowerCase()) +
                        "[@selid=" + this.attributeValue(current.parentNode.getAttribute("selid")) + "]" +
                        path;
                }
            } else {
                return null;
            }
            current = current.parentNode;
        }
        return null;
    });
    
    /**
     * Locator for when a selid is at a level above the current element in the dom, we wish to ignor selids that were generated based on a dom class (the css class of an element in the dom) and find the current dom element by its inner html
     */
    LocatorBuilders.add('xpath:selidNoDCSelidsToInnerhtml', function(e) {
        var path = '',
            current = e,
            first = current,
            foundDomClassSelid = false;
        while (current != null) {
            if (current.parentNode != null) {
                path = this.relativeXPathFromParent(current) + path;
                if (current.parentNode.getAttribute("isdomclassselid")) {
                    foundDomClassSelid = true;
                }
                if (1 == current.parentNode.nodeType && // ELEMENT_NODE
                    current.parentNode.getAttribute("selid") && 
                    !current.parentNode.getAttribute("isdomclassselid") &&
                    foundDomClassSelid) {
                    return "//" + this.xpathHtmlElement(current.parentNode.nodeName.toLowerCase()) + 
                        "[@selid=" + this.attributeValue(current.parentNode.getAttribute("selid")) + "]//" + 
                        this.xpathHtmlElement(first.nodeName.toLowerCase()) + "[.='" + first.innerHTML + "']";
                }
            } else {
                return null;
            }
            current = current.parentNode;
        }
        return null;
    });
    user-extensions.js
    Code:
    /**
     * @author Will Ferrer, Ethan Brooks
     * @copyright (c) 2012, Intellectual Property Private Equity Group
     * @licensee 2012 developed under license for Switchsoft LLC http://www.switchsoft.com a "Direct response telephony company" as part of it's "VOIP Call distribution, ROI analysis platform, call recording, and IVR for inbound and outbound sales" and Run the Business Systems LLC a "Technology development investment group" as part of it's "PHP, Javascript rapid application development framework and MySQL analysis tools"
     * @license licensed under the terms of
     * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
     * that the code/component(s) do NOT become part of another Open Source or Commercially
     * licensed development library or toolkit without explicit permission.
     * <p>License details: <a href="http://www.gnu.org/licenses/lgpl.html"
     * target="_blank">http://www.gnu.org/licenses/lgpl.html</a></p>
    * We are pretty nice just ask. We want to meet our licensees
    */
    /**
     * If you've set up with watchAjaxRequests, this routine will wait until all Ajax request has finished and then return.
     * @param {number} timeout
     */
    Selenium.prototype.doWaitForRemote = function(timeout) {
        return Selenium.decorateFunctionWithTimeout(function() {
        if (selenium.browserbot.getCurrentWindow().Ext.ux.SeleniumPrep.checkPendingRequests()) {
          return true;
        }
        return false;
        }, timeout);
    };
    
    /**
     * Waits until no process are left in the Ext.ux.SeleniumPrep.pendingProcesses object
     * @param {number} timeout
     */
    Selenium.prototype.doWaitForProcesses = function(timeout) {
        return Selenium.decorateFunctionWithTimeout(function() {
        if (selenium.browserbot.getCurrentWindow().Ext.ux.SeleniumPrep.checkPendingProcesses()) {
          return true;
        }
        return false;
        }, timeout);
    };
    
    
    /**
     * Waits until no process are left in the Ext.ux.SeleniumPrep.pendingProcesses object and no ajax requests are pending
     * @param {number} timeout
     */
    Selenium.prototype.doWaitForComplete = function(timeout) {
        return Selenium.decorateFunctionWithTimeout(function() {
            if (selenium.browserbot.getCurrentWindow().Ext.ux.SeleniumPrep.checkComplete()) {
              return true;
            }
            return false;
        }, timeout);
    };
    
    
    
    /**
     * Make errors throw alerts
     */
    Selenium.prototype.doErrorsToAlerts = function() {
        selenium.browserbot.getCurrentWindow().window.onerror = function customHandler(desc,page,line,chr)  {
         alert(
              'JavaScript error occurred! \n'
             +'The error was handled by '
             +'a customized error handler.\n'
             +'\nError description: \t'+desc
             +'\nPage address:      \t'+page
             +'\nLine number:       \t'+line
             )
             return true
        }
    };
    
    // Set context code which allows overlays on the screen while tests are running -- found at: http://saucelabs.com/blog/index.php/2010/11/test-videos-fun/
    window.contextTimeout = null;
    
    function fade(ctx) {
        var alpha = ctx.style.opacity;
        var new_alpha = alpha - 0.1;
        ctx.style.opacity = new_alpha;
        if (new_alpha){
            window.contextTimeout = setTimeout(function(){fade(ctx);}, 50);
        } else {
            this.browserbot.getUserWindow().document.body.removeChild(ctx);
        }
    }
    
    Selenium.prototype.doSetContext = function(context) {
       var ctx = this.browserbot.getUserWindow().document.getElementById("selenium-context");
       if (ctx) {
           clearTimeout(window.contextTimeout);
       } else {
           ctx = this.browserbot.getUserWindow().document.createElement("div");
       }
       ctx.setAttribute('id', "selenium-context");
       ctx.style.zIndex = "500";
       ctx.style.position = "fixed";
       ctx.style.left = "50%";
       ctx.style.top = "10px";
       ctx.style.width = "500px";
       ctx.style.maxHeight = "100px";
       ctx.style.overflow = "hidden";
       ctx.style.margin = "0 0 0 -250px";
       ctx.style.padding = "5px";
       ctx.style.MozBorderRadius = "8px";
       ctx.style.borderRadius = "8px";
       ctx.style.textAlign = "center";
       ctx.style.font = "normal normal 20px/25px Arial,sans-serif";
       ctx.style.background = "#000";
       ctx.style.border = "1px solid #CCC";
       ctx.style.color = "#EEE";
       ctx.style.opacity = 0.8;
       ctx.innerHTML = context; 
       try {
          this.browserbot.getUserWindow().document.body.appendChild(ctx);
       } catch (e){
           
       }
       window.contextTimeout = setTimeout(function(){fade(ctx);}, 3000);
    }
    Best regards

    Will Ferrer (Run the Business)

  2. #2
    Sencha - Senior Forum Manager mitchellsimoens's Avatar
    Join Date
    Mar 2007
    Location
    Gainesville, FL
    Posts
    36,791
    Vote Rating
    833
    mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute mitchellsimoens has a reputation beyond repute

      0  

    Default


    People will like this! Thanks for the contribution
    Mitchell Simoens @SenchaMitch
    Sencha Inc, Senior Forum Manager
    ________________
    Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
    https://github.com/mitchellsimoens

    Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/

    Need more help with your app? Hire Sencha Services services@sencha.com

    Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is in print!

    When posting code, please use BBCode's CODE tags.

Thread Participants: 1

Tags for this Thread

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi