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(); }; doh.robot.startRobot(); } }; var cleanup=function(){ doh.robot.killRobot(); } if(typeof dojo !== 'undefined'){ dojo.addOnUnload(cleanup) }else{ window.onunload=cleanup; } var _keyPress = function(/*Number*/ charCode, /*Number*/ keyCode, /*Boolean*/ alt, /*Boolean*/ ctrl, /*Boolean*/ shift, /*Boolean*/ meta, /*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), Boolean(meta), Number(delay||0), Boolean(async||false)); }; doh.robot = { _robotLoaded: true, _robotInitialized: false, // prime the event pump for fast browsers like Google Chrome - it's so fast, it doesn't stop to listen for keypresses! _spaceReceived: false, _primePump: false, _killApplet: function(){}, // overridden by Robot.html killRobot: function(){ if(doh.robot._robotLoaded){ 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; } } }, startRobot: function(){ //startRobot should be called to initialize the robot (after the java applet is loaded). //one good place to do this is in a dojo.addOnLoad handler. This function will be called //automatically if it is not already called when doh.run() is invoked. if(!this._robotInitialized){ this._robotInitialized = true; // 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()); } } }, _initRobot: function(r){ // called from Robot // Robot calls _initRobot in its startup sequence // Prevent rerunning the whole test (see #8958 for details) if(doh._initRobotCalled){ return; } doh._initRobotCalled = true; // 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(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, false, delay); }else if(chars.length){ for(var i = 0; i