Index: /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/.DS_Store =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/.DS_Store ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Index: /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/css/tests.css =================================================================== --- /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/css/tests.css (revision 0) +++ /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/css/tests.css (revision 0) @@ -0,0 +1,42 @@ +body{ + height: 100%; + margin: 0; + padding: 0; +} + +html{ + height: 100%; +} + +.activate { + height:3%; +} + +#testFrame{ + height: 100%; + width: 100%; + margin: 0; + padding: 0; + border: none; + display: block; + overflow: auto; +} + +button{ + height: auto; + width: auto; + margin: 0 auto; + display: block; +} + +/* These widths are slightly brittle in that if the width of an individual + thumbnail is changed in Lightbox.css these will need to be updated. */ +.width-6-thumbs { + width: 1050px !important; +} + +.tabs-min-width { + min-width:425px; +} + + Index: /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/_browserRunner.js =================================================================== --- /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/_browserRunner.js (revision 0) +++ /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/_browserRunner.js (revision 0) @@ -0,0 +1,546 @@ +if(window["dojo"]){ + dojo.provide("doh._browserRunner"); +} + +// FIXME: need to add prompting for monkey-do testing +// FIXME: need to implement progress bar +// FIXME: need to implement errors in progress bar + +(function(){ + if(window.parent == window){ + // we're the top-dog window. + + // borrowed from Dojo, etc. + var byId = function(id){ + return document.getElementById(id); + }; + + var _addOnEvt = function( type, // string + refOrName, // function or string + scope){ // object, defaults is window + + if(!scope){ scope = window; } + + var funcRef = refOrName; + if(typeof refOrName == "string"){ + funcRef = scope[refOrName]; + } + var enclosedFunc = function(){ return funcRef.apply(scope, arguments); }; + + if((window["dojo"])&&(type == "load")){ + dojo.addOnLoad(enclosedFunc); + }else{ + if(window["attachEvent"]){ + window.attachEvent("on"+type, enclosedFunc); + }else if(window["addEventListener"]){ + window.addEventListener(type, enclosedFunc, false); + }else if(document["addEventListener"]){ + document.addEventListener(type, enclosedFunc, false); + } + } + }; + + // + // Over-ride or implement base runner.js-provided methods + // + var escapeXml = function(str){ + //summary: + // Adds escape sequences for special characters in XML: &<>"' + // Optionally skips escapes for single quotes + return str.replace(/&/gm, "&").replace(//gm, ">").replace(/"/gm, """); // string + }; + + var _logBacklog = []; + var sendToLogPane = function(args, skip){ + var msg = ""; + for(var x=0; x "); + if(!byId("logBody")){ + _logBacklog.push(msg); + return; + }else if(_logBacklog.length && !skip){ + var tm; + while((tm=_logBacklog.shift())){ + sendToLogPane(tm, true); + } + } + var tn = document.createElement("div"); + tn.innerHTML = msg; + byId("logBody").appendChild(tn); + } + + doh._init = (function(oi){ + return function(){ + var lb = byId("logBody"); + if(lb){ + // clear the console before each run + while(lb.firstChild){ + lb.removeChild(lb.firstChild); + } + } + this._suiteCount = 0; + oi.apply(doh, arguments); + } + })(doh._init); + + if(this["opera"] && opera.postError){ + doh.debug = function(){ + var msg = ""; + for(var x=0; x
 
"; + tds[3].innerHTML = ""; + + tb.appendChild(tg); + return tg; + } + + var addFixtureToList = function(group, fixture){ + if(!testTemplate){ return; } + var cgn = groupNodes[group]; + if(!cgn["__items"]){ cgn.__items = []; } + var tn = testTemplate.cloneNode(true); + var tds = tn.getElementsByTagName("td"); + + tds[2].innerHTML = fixture.name; + tds[3].innerHTML = ""; + + var nn = (cgn.__lastFixture||cgn.__groupNode).nextSibling; + if(nn){ + nn.parentNode.insertBefore(tn, nn); + }else{ + cgn.__groupNode.parentNode.appendChild(tn); + } + // FIXME: need to make group display toggleable!! + tn.style.display = "none"; + cgn.__items.push(tn); + return (cgn.__lastFixture = tn); + } + + var getFixtureNode = function(group, fixture){ + if(groupNodes[group]){ + return groupNodes[group][fixture.name]; + } + return null; + } + + var getGroupNode = function(group){ + if(groupNodes[group]){ + return groupNodes[group].__groupNode; + } + return null; + } + + var updateBacklog = []; + doh._updateTestList = function(group, fixture, unwindingBacklog){ + if(!loaded){ + if(group && fixture){ + updateBacklog.push([group, fixture]); + } + return; + }else if(updateBacklog.length && !unwindingBacklog){ + var tr; + while((tr=updateBacklog.shift())){ + doh._updateTestList(tr[0], tr[1], true); + } + } + if(group && fixture){ + if(!groupNodes[group]){ + groupNodes[group] = { + "__groupNode": addGroupToList(group) + }; + } + if(!groupNodes[group][fixture.name]){ + groupNodes[group][fixture.name] = addFixtureToList(group, fixture) + } + } + } + + doh._testRegistered = doh._updateTestList; + + doh._groupStarted = function(group){ + if(this._suiteCount == 0){ + this._runedSuite = 0; + this._currentGlobalProgressBarWidth = 0; + this._suiteCount = this._testCount; + } + this._runedSuite++; + // console.debug("_groupStarted", group); + if(doh._inGroup != group){ + doh._totalTime = 0; + doh._runed = 0; + doh._inGroup = group; + } + var gn = getGroupNode(group); + if(gn){ + gn.className = "inProgress"; + } + } + + doh._groupFinished = function(group, success){ + // console.debug("_groupFinished", group); + var gn = getGroupNode(group); + if(gn && doh._inGroup == group){ + gn.className = (success) ? "success" : "failure"; + gn.getElementsByTagName("td")[3].innerHTML = doh._totalTime+"ms"; + gn.getElementsByTagName("td")[2].lastChild.className = ""; + doh._inGroup = null; + //doh._runedSuite++; + doh._updateGlobalProgressBar(this._runedSuite/this._suiteCount,success); + //doh._runedSuite--; + doh._currentGlobalProgressBarWidth = parseInt(this._runedSuite/this._suiteCount*10000)/100; + //byId("progressOuter").style.width = parseInt(this._runedSuite/this._suiteCount*100)+"%"; + } + if(doh._inGroup == group){ + this.debug("Total time for GROUP \"",group,"\" is ",doh._totalTime,"ms"); + } + } + + doh._testStarted = function(group, fixture){ + // console.debug("_testStarted", group, fixture.name); + var fn = getFixtureNode(group, fixture); + if(fn){ + fn.className = "inProgress"; + } + } + + var _nameTimes = {}; + var _playSound = function(name){ + if(byId("hiddenAudio") && byId("audio") && byId("audio").checked){ + // console.debug("playing:", name); + var nt = _nameTimes[name]; + // only play sounds once every second or so + if((!nt)||(((new Date)-nt) > 700)){ + _nameTimes[name] = new Date(); + var tc = document.createElement("span"); + byId("hiddenAudio").appendChild(tc); + tc.innerHTML = ''; + } + } + } + + doh._updateGlobalProgressBar = function(p,success){ + var outerContainer=byId("progressOuter"); + + var gdiv=outerContainer.childNodes[doh._runedSuite-1]; + if(!gdiv){ + gdiv=document.createElement('div'); + outerContainer.appendChild(gdiv); + gdiv.className='success'; + } + if(!success){ + gdiv._failure=true; + gdiv.className='failure'; + } + var tp=parseInt(p*10000)/100; + gdiv.style.width = (tp-doh._currentGlobalProgressBarWidth)+"%"; + return gdiv._failure; + } + doh._testFinished = function(group, fixture, success){ + var fn = getFixtureNode(group, fixture); + var elapsed = fixture.endTime-fixture.startTime; + if(fn){ + fn.getElementsByTagName("td")[3].innerHTML = elapsed+"ms"; + fn.className = (success) ? "success" : "failure"; + + if(!success){ + _playSound("doh"); + var gn = getGroupNode(group); + if(gn){ + gn.className = "failure"; + _getGroupToggler(group)(null, true); + } + } + } + if(doh._inGroup == group){ + var gn = getGroupNode(group); + doh._runed++; + if(gn && doh._curTestCount){ + var p = doh._runed/doh._curTestCount; + var groupfail = this._updateGlobalProgressBar((doh._runedSuite+p-1)/doh._suiteCount,success); + + var pbar = gn.getElementsByTagName("td")[2].lastChild; + pbar.className = groupfail?"failure":"success"; + pbar.style.width = parseInt(p*100)+"%"; + gn.getElementsByTagName("td")[3].innerHTML = parseInt(p*10000)/100+"%"; + } + } + this._totalTime += elapsed; + this.debug((success ? "PASSED" : "FAILED"), "test:", fixture.name, elapsed, 'ms'); + } + + // FIXME: move implementation to _browserRunner? + doh.registerUrl = function( /*String*/ group, + /*String*/ url, + /*Integer*/ timeout){ + var tg = new String(group); + this.register(group, { + name: url, + setUp: function(){ + doh.currentGroupName = tg; + doh.currentGroup = this; + doh.currentUrl = url; + this.d = new doh.Deferred(); + doh.currentTestDeferred = this.d; + showTestPage(); + byId("testBody").src = url; + }, + timeout: timeout||10000, // 10s + // timeout: timeout||1000, // 10s + runTest: function(){ + // FIXME: implement calling into the url's groups here!! + return this.d; + }, + tearDown: function(){ + doh.currentGroupName = null; + doh.currentGroup = null; + doh.currentTestDeferred = null; + doh.currentUrl = null; + // this.d.errback(false); + // byId("testBody").src = "about:blank"; + showLogPage(); + } + }); + } + + // + // Utility code for runner.html + // + // var isSafari = navigator.appVersion.indexOf("Safari") >= 0; + var tabzidx = 1; + var _showTab = function(toShow, toHide){ + // FIXME: I don't like hiding things this way. + byId(toHide).style.display = "none"; + with(byId(toShow).style){ + display = ""; + zIndex = ++tabzidx; + } + } + + showTestPage = function(){ + _showTab("testBody", "logBody"); + } + + showLogPage = function(){ + _showTab("logBody", "testBody"); + } + + var runAll = true; + toggleRunAll = function(){ + // would be easier w/ query...sigh + runAll = !runAll; + if(!byId("testList")){ return; } + var tb = byId("testList").tBodies[0]; + var inputs = tb.getElementsByTagName("input"); + var x=0; var tn; + while((tn=inputs[x++])){ + tn.checked = runAll; + doh._groups[tn.group].skip = (!runAll); + } + } + + var listHeightTimer = null; + var setListHeight = function(){ + if(listHeightTimer){ + clearTimeout(listHeightTimer); + } + var tl = byId("testList"); + if(!tl){ return; } + listHeightTimer = setTimeout(function(){ + tl.style.display = "none"; + tl.style.display = ""; + + }, 10); + } + + _addOnEvt("resize", setListHeight); + _addOnEvt("load", setListHeight); + _addOnEvt("load", function(){ + if(loaded){ return; } + loaded = true; + groupTemplate = byId("groupTemplate"); + if(!groupTemplate){ + // make sure we've got an ammenable DOM structure + return; + } + groupTemplate.parentNode.removeChild(groupTemplate); + groupTemplate.style.display = ""; + testTemplate = byId("testTemplate"); + testTemplate.parentNode.removeChild(testTemplate); + testTemplate.style.display = ""; + doh._updateTestList(); + }); + + _addOnEvt("load", + function(){ + // let robot code run if it gets to this first + var __onEnd = doh._onEnd; + doh._onEnd = function(){ + __onEnd.apply(doh, arguments); + if(doh._failureCount == 0){ + doh.debug("WOOHOO!!"); + _playSound("woohoo"); + }else{ + console.debug("doh._failureCount:", doh._failureCount); + } + if(byId("play")){ + toggleRunning(); + } + } + if(!byId("play")){ + // make sure we've got an amenable DOM structure + return; + } + var isRunning = false; + var toggleRunning = function(){ + // ugg, this would be so much better w/ dojo.query() + if(isRunning){ + byId("play").style.display = byId("pausedMsg").style.display = ""; + byId("playingMsg").style.display = byId("pause").style.display = "none"; + isRunning = false; + }else{ + byId("play").style.display = byId("pausedMsg").style.display = "none"; + byId("playingMsg").style.display = byId("pause").style.display = ""; + isRunning = true; + } + } + doh.run = (function(oldRun){ + return function(){ + if(!doh._currentGroup){ + toggleRunning(); + } + return oldRun.apply(doh, arguments); + } + })(doh.run); + var btns = byId("toggleButtons").getElementsByTagName("span"); + var node; var idx=0; + while((node=btns[idx++])){ + node.onclick = toggleRunning; + } + } + ); + }else{ + // we're in an iframe environment. Time to mix it up a bit. + + _doh = window.parent.doh; + var _thisGroup = _doh.currentGroupName; + var _thisUrl = _doh.currentUrl; + if(_thisGroup){ + doh._testRegistered = function(group, tObj){ + _doh._updateTestList(_thisGroup, tObj); + } + doh._onEnd = function(){ + _doh._errorCount += doh._errorCount; + _doh._failureCount += doh._failureCount; + _doh._testCount += doh._testCount; + // should we be really adding raw group counts? + _doh._groupCount += doh._groupCount; + _doh.currentTestDeferred.callback(true); + } + var otr = doh._getTestObj; + doh._getTestObj = function(){ + var tObj = otr.apply(doh, arguments); + tObj.name = _thisUrl+"::"+arguments[0]+"::"+tObj.name; + return tObj; + } + doh.debug = doh.hitch(_doh, "debug"); + doh.registerUrl = doh.hitch(_doh, "registerUrl"); + doh._testStarted = function(group, fixture){ + _doh._testStarted(_thisGroup, fixture); + } + doh._testFinished = function(g, f, s){ + _doh._testFinished(_thisGroup, f, s); + } + doh._groupStarted = function(g){ + if(!this._setParent){ + _doh._curTestCount = this._testCount; + _doh._curGroupCount = this._groupCount; + this._setParent = true; + } + } + doh._report = function(){}; + } + } + +})(); Index: /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/_rhinoRunner.js =================================================================== --- /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/_rhinoRunner.js (revision 0) +++ /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/_rhinoRunner.js (revision 0) @@ -0,0 +1,17 @@ +if(this["dojo"]){ + dojo.provide("doh._rhinoRunner"); +} + +doh.debug = print; + +// Override the doh._report method to make it quit with an +// appropriate exit code in case of test failures. +(function(){ + var oldReport = doh._report; + doh._report = function(){ + oldReport.apply(doh, arguments); + if(this._failureCount > 0 || this._errorCount > 0){ + quit(1); + } + } +})(); Index: /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/LICENSE =================================================================== --- /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/LICENSE (revision 0) +++ /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/LICENSE (revision 0) @@ -0,0 +1,195 @@ +Dojo is available under *either* the terms of the modified BSD license *or* the +Academic Free License version 2.1. As a recipient of Dojo, you may choose which +license to receive this code under (except as noted in per-module LICENSE +files). Some modules may not be the copyright of the Dojo Foundation. These +modules contain explicit declarations of copyright in both the LICENSE files in +the directories in which they reside and in the code itself. No external +contributions are allowed under licenses which are fundamentally incompatible +with the AFL or BSD licenses that Dojo is distributed under. + +The text of the AFL and BSD licenses is reproduced below. + +------------------------------------------------------------------------------- +The "New" BSD License: +********************** + +Copyright (c) 2005-2008, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------- +The Academic Free License, v. 2.1: +********************************** + +This Academic Free License (the "License") applies to any original work of +authorship (the "Original Work") whose owner (the "Licensor") has placed the +following notice immediately following the copyright notice for the Original +Work: + +Licensed under the Academic Free License version 2.1 + +1) Grant of Copyright License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license to do the +following: + +a) to reproduce the Original Work in copies; + +b) to prepare derivative works ("Derivative Works") based upon the Original +Work; + +c) to distribute copies of the Original Work and Derivative Works to the +public; + +d) to perform the Original Work publicly; and + +e) to display the Original Work publicly. + +2) Grant of Patent License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license, under patent +claims owned or controlled by the Licensor that are embodied in the Original +Work as furnished by the Licensor, to make, use, sell and offer for sale the +Original Work and Derivative Works. + +3) Grant of Source Code License. The term "Source Code" means the preferred +form of the Original Work for making modifications to it and all available +documentation describing how to modify the Original Work. Licensor hereby +agrees to provide a machine-readable copy of the Source Code of the Original +Work along with each copy of the Original Work that Licensor distributes. +Licensor reserves the right to satisfy this obligation by placing a +machine-readable copy of the Source Code in an information repository +reasonably calculated to permit inexpensive and convenient access by You for as +long as Licensor continues to distribute the Original Work, and by publishing +the address of that information repository in a notice immediately following +the copyright notice that applies to the Original Work. + +4) Exclusions From License Grant. Neither the names of Licensor, nor the names +of any contributors to the Original Work, nor any of their trademarks or +service marks, may be used to endorse or promote products derived from this +Original Work without express prior written permission of the Licensor. Nothing +in this License shall be deemed to grant any rights to trademarks, copyrights, +patents, trade secrets or any other intellectual property of Licensor except as +expressly stated herein. No patent license is granted to make, use, sell or +offer to sell embodiments of any patent claims other than the licensed claims +defined in Section 2. No right is granted to the trademarks of Licensor even if +such marks are included in the Original Work. Nothing in this License shall be +interpreted to prohibit Licensor from licensing under different terms from this +License any Original Work that Licensor otherwise would have a right to +license. + +5) This section intentionally omitted. + +6) Attribution Rights. You must retain, in the Source Code of any Derivative +Works that You create, all copyright, patent or trademark notices from the +Source Code of the Original Work, as well as any notices of licensing and any +descriptive text identified therein as an "Attribution Notice." You must cause +the Source Code for any Derivative Works that You create to carry a prominent +Attribution Notice reasonably calculated to inform recipients that You have +modified the Original Work. + +7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that +the copyright in and to the Original Work and the patent rights granted herein +by Licensor are owned by the Licensor or are sublicensed to You under the terms +of this License with the permission of the contributor(s) of those copyrights +and patent rights. Except as expressly stated in the immediately proceeding +sentence, the Original Work is provided under this License on an "AS IS" BASIS +and WITHOUT WARRANTY, either express or implied, including, without limitation, +the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. +This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No +license to Original Work is granted hereunder except under this disclaimer. + +8) Limitation of Liability. Under no circumstances and under no legal theory, +whether in tort (including negligence), contract, or otherwise, shall the +Licensor be liable to any person for any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License +or the use of the Original Work including, without limitation, damages for loss +of goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses. This limitation of liability shall not +apply to liability for death or personal injury resulting from Licensor's +negligence to the extent applicable law prohibits such limitation. Some +jurisdictions do not allow the exclusion or limitation of incidental or +consequential damages, so this exclusion and limitation may not apply to You. + +9) Acceptance and Termination. If You distribute copies of the Original Work or +a Derivative Work, You must make a reasonable effort under the circumstances to +obtain the express assent of recipients to the terms of this License. Nothing +else but this License (or another written agreement between Licensor and You) +grants You permission to create Derivative Works based upon the Original Work +or to exercise any of the rights granted in Section 1 herein, and any attempt +to do so except under the terms of this License (or another written agreement +between Licensor and You) is expressly prohibited by U.S. copyright law, the +equivalent laws of other countries, and by international treaty. Therefore, by +exercising any of the rights granted to You in Section 1 herein, You indicate +Your acceptance of this License and all of its terms and conditions. + +10) Termination for Patent Action. This License shall terminate automatically +and You may no longer exercise any of the rights granted to You by this License +as of the date You commence an action, including a cross-claim or counterclaim, +against Licensor or any licensee alleging that the Original Work infringes a +patent. This termination provision shall not apply for an action alleging +patent infringement by combinations of the Original Work with other software or +hardware. + +11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this +License may be brought only in the courts of a jurisdiction wherein the +Licensor resides or in which Licensor conducts its primary business, and under +the laws of that jurisdiction excluding its conflict-of-law provisions. The +application of the United Nations Convention on Contracts for the International +Sale of Goods is expressly excluded. Any use of the Original Work outside the +scope of this License or after its termination shall be subject to the +requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et +seq., the equivalent laws of other countries, and international treaty. This +section shall survive the termination of this License. + +12) Attorneys Fees. In any action to enforce the terms of this License or +seeking damages relating thereto, the prevailing party shall be entitled to +recover its costs and expenses, including, without limitation, reasonable +attorneys' fees and costs incurred in connection with such action, including +any appeal of such action. This section shall survive the termination of this +License. + +13) Miscellaneous. This License represents the complete agreement concerning +the subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent necessary to +make it enforceable. + +14) Definition of "You" in This License. "You" throughout this License, whether +in upper or lower case, means an individual or a legal entity exercising rights +under, and complying with all of the terms of, this License. For legal +entities, "You" includes any entity that controls, is controlled by, or is +under common control with you. For purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty percent +(50%) or more of the outstanding shares, or (iii) beneficial ownership of such +entity. + +15) Right to Use. You may use the Original Work in all ways not otherwise +restricted or conditioned by this License or by law, and Licensor promises not +to interfere with or be responsible for such uses by You. + +This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. +Permission is hereby granted to copy and distribute this license without +modification. This license may not be modified without the express written +permission of its copyright owner. Index: /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/README =================================================================== --- /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/README (revision 0) +++ /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/README (revision 0) @@ -0,0 +1,12 @@ +DOH may be run standalone by issuing a command like the following: + +java -jar ../shrinksafe/custom_rhino.jar runner.js testModule=tests.colors + +where the testModule argument is optional and custom_rhino.jar is just a +convenient copy of the Rhino JavaScript engine -- the custom patch is not +required. + +Optional arguments include: + * dojoUrl - specifies the location of dojo.js + * testUrl - specifies a Javascript file to load with initialization code + * testModule - specifies a test module in the dojo package namespace Index: /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/Robot.html =================================================================== --- /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/Robot.html (revision 0) +++ /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/Robot.html (revision 0) @@ -0,0 +1,141 @@ + + + + + + + + + Index: /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/robot.js =================================================================== --- /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/robot.js (revision 0) +++ /Users/justin/Documents/Aptana Studio/fluid-components/src/webapp/tests/fluid-tests/automated/doh/robot.js (revision 0) @@ -0,0 +1,486 @@ +if(window["dojo"]){ + dojo.provide("doh.robot"); + dojo.experimental("doh.robot"); + dojo.require("doh.runner"); +}else if(!doh["robot"]){ + doh.robot={}; +} + +if(!doh.robot["_robotLoaded"]){ +(function(){ + + // loading state + var _robot = null; + + var isSecure = (function(){ + var key = Math.random(); + return function(fcn){ + return key; + }; + })(); + + // no dojo available + // hijack doh.run instead + var _run = doh.run; + doh.run = function(){ + if(!doh.robot._runsemaphore.unlock()){ + // hijack doh._onEnd to clear the applet + // have to do it here because _browserRunner sets it in onload in standalone case + var __onEnd = doh._onEnd; + doh._onEnd = function(){ + doh.robot.killRobot(); + doh._onEnd = __onEnd; + doh._onEnd(); + }; + // if the iframe requested the applet and got a 404, then _robot is obviously unavailable + // at least run the non-robot tests! + if(doh.robot._appletDead){ + doh.robot._onKeyboard(); + }else{ + _robot._callLoaded(isSecure()); + } + } + }; + + var _keyPress = function(/*Number*/ charCode, /*Number*/ keyCode, /*Boolean*/ alt, /*Boolean*/ ctrl, /*Boolean*/ shift, /*Integer, optional*/ delay, /*Boolean*/ async){ + // internal function to type one non-modifier key + + // typecasting Numbers helps Sun's IE plugin lookup methods that take int arguments + + // otherwise JS will send a double and Sun will complain + _robot.typeKey(isSecure(), Number(charCode), Number(keyCode), Boolean(alt), Boolean(ctrl), Boolean(shift), Number(delay||0), Boolean(async||false)); + }; + + doh.robot = { + _robotLoaded: true, + + _killApplet: function(){}, // overridden by Robot.html + + killRobot: function(){ + doh.robot._robotLoaded = false; + document.documentElement.className = document.documentElement.className.replace(/ ?dohRobot/); + doh.robot._killApplet(); + }, + + // Robot init methods + + // controls access to doh.run + // basically, doh.run takes two calls to start the robot: + // one (or more after the robot loads) from the test page + // one from either the applet or an error condition + _runsemaphore: { + lock:["lock"], + unlock:function(){ + try{ + return this.lock.shift(); + }catch(e){ + return null; + } + } + }, + + _initRobot: function(r){ + // called from Robot + // Robot calls _initRobot in its startup sequence + // add dohRobot class to HTML element so tests can use that in CSS rules if desired + document.documentElement.className = document.documentElement.className.replace(/\S$/, "& ") + "dohRobot"; + window.scrollTo(0, 0); +// document.documentElement.scrollTop = document.documentElement.scrollLeft = 0; + _robot = r; + _robot._setKey(isSecure()); + // lazy load + doh.run(); + }, + + // some utility functions to help the iframe use private variables + _run: function(frame){ + frame.style.visibility = "hidden"; + doh.run = _run; + doh.run(); + }, + + _initKeyboard: function(){ + _robot._initKeyboard(isSecure()); + }, + + _initWheel: function(){ + _robot._initWheel(isSecure()); + }, + + _setDocumentBounds: function(docScreenX, docScreenY){ + var robotView = document.getElementById("dohrobotview"); + _robot.setDocumentBounds(isSecure(), Number(docScreenX), Number(docScreenY), Number(robotView.offsetLeft), Number(robotView.offsetTop)); + }, + + _notified: function(keystring){ + _robot._notified(isSecure(), keystring); + }, + + _time:0, + + // if the applet is 404 or cert is denied, this becomes true and kills tests + _appletDead:false, + + _assertRobot:function(){ + // make sure the applet is there and cert accepted + // otherwise, skip the test requesting the robot action + if(doh.robot._appletDead){ throw new Error('doh.robot not available; skipping test.'); } + }, + + _mouseMove: function(/*Number*/ x, /*Number*/ y, /*Boolean*/ absolute, /*Integer, optional*/ duration){ + if (typeof (x) === "function") { x = x();} // allows for multiple page scrolls, added by FLUID + if (typeof (y) === "function") { y = y();} // allows for multiple page scrolls, added by FLUID + if(absolute){ + var scroll = {y: (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0), + x: (window.pageXOffset || (window["dojo"]?dojo._fixIeBiDiScrollLeft(document.documentElement.scrollLeft):undefined) || document.body.scrollLeft || 0)}; + y -= scroll.y; + x -= scroll.x; + } + _robot.moveMouse(isSecure(), Number(x), Number(y), Number(0), Number(duration||100)); + }, + + // Main doh.robot API + sequence:function(/*Function*/ f, /*Integer, optional*/ delay, /*Integer, optional*/ duration){ + // summary: + // Defer an action by adding it to the robot's incrementally delayed queue of actions to execute. + // + // f: + // A function containing actions you want to defer. + // + // delay: + // Delay, in milliseconds, to wait before firing. + // The delay is a delta with respect to the previous automation call. + // For example, the following code ends after 600ms: + // doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms + // doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all + // + // duration: + // Delay to wait after firing. + // + + delay = delay || 1; + doh.robot._time += delay; + setTimeout(function(){ + doh.robot._time -= delay; + f(); + if(duration){ + setTimeout(function(){ + doh.robot._time -= duration; + }, duration); + } + }, doh.robot._time); + if(duration){ + doh.robot._time += duration; + } + }, + + typeKeys: function(/*String||Number*/ chars, /*Integer, optional*/ delay, /*Integer, optional*/ duration){ + // summary: + // Types a string of characters in order, or types a dojo.keys.* constant. + // + // description: + // Types a string of characters in order, or types a dojo.keys.* constant. + // Example: doh.robot.typeKeys("dijit.ed", 500); + // + // chars: + // String of characters to type, or a dojo.keys.* constant + // + // delay: + // Delay, in milliseconds, to wait before firing. + // The delay is a delta with respect to the previous automation call. + // For example, the following code ends after 600ms: + // doh.robot.mouseClick({left:true}, 100) // first call; wait 100ms + // doh.robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all + // + // duration: + // Time, in milliseconds, to spend pressing all of the keys. + // + + this._assertRobot(); + this.sequence(function(){ + duration=duration||0; + if(typeof(chars) == Number){ + _keyPress(chars, chars, false, false, false, delay); + }else if(chars.length){ + for(var i = 0; i