source: Dev/trunk/src/client/util/doh/plugins/android-webdriver-robot.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 10.6 KB
Line 
1define(["dojo/has", "dojo/_base/xhr", "doh/runner", "dojo/sniff", "dojo/dom-geometry", "doh/plugins/remoteRobot"], function(has, xhr, doh, sniff, geom, remoteRobotURL){
2        // summary:
3        //              Wraps WebDriver APIs around doh.robot API.
4        //              Should be loaded as a doh plugin.
5        //              In theory, with a change to the base URL, this same file could also be used for iOS WebDriver.
6        //              WebDriver must be modified to accept cross-domain requests (currently it sends incomplete headers).
7        //
8       
9        var top=window.parent?window.parent:window;
10       
11        // short-term FIFO command queue, similar to the one in the applet
12        var commands=[];
13        var _inFlight=false;
14        // send requests to the WebDriver and get its JSON text back
15        function robotXHR(args){
16                var commandString=args.commandString;
17                var deferred=args.deferred;
18                var immediate=args.immediate;
19                //console.debug("remote url: "+remoteRobotURL+"/"+commandString);
20                if(immediate||!_inFlight){
21                        _inFlight=true;
22                        xhr(args.method,{
23                                url:remoteRobotURL+"/"+commandString,
24                                headers: { "Content-Type": "application/json"},
25                                postData:args.postData,
26                                load:function(response){
27                                        //console.debug("success sending webdriver command: ", response);
28                                        _inFlight=false;
29                                        if(deferred){
30                                                deferred.callback(response);
31                                        }
32                                        if(commands.length){
33                                                robotXHR(commands.shift());
34                                        }
35                                },
36                                error:function(response){
37                                        console.error("failure sending webdriver command: ", response);
38                                }
39                        });
40                }else{
41                        commands.push(args);
42                }
43        }
44       
45        // record stats about last mouse position
46        var lastX=0;
47        var lastY=0;
48        var mouse=null; // debug mouse cursor so you can see what is being touched; created on demand
49        // map dojo keys to WebDriver key codes
50        // enable/disable as we discover which ones are legit
51       
52        var keyMap={};
53        if(window["dojo"]){
54                // keyMap[dojo.keys.BACKSPACE]=0xE003;
55                //keyMap[dojo.keys.TAB]=0xE004;
56                // keyMap[dojo.keys.CLEAR]=0xE005;
57                // keyMap[dojo.keys.ENTER]=0xE007;
58                // keyMap[dojo.keys.SHIFT]=0xE008;
59                // keyMap[dojo.keys.CTRL]=0xE009;
60                // keyMap[dojo.keys.ALT]=0xE00A;
61                // keyMap[dojo.keys.META]=0xE03D;               // the apple key on macs
62                // keyMap[dojo.keys.PAUSE]=0xE00B;
63                // // dojo.keys.CAPS_LOCK: 20,
64                // keyMap[dojo.keys.ESCAPE]=0xE00C;
65                // keyMap[dojo.keys.SPACE]=0xE00D;
66                // keyMap[dojo.keys.PAGE_UP]=0xE00E;
67                // keyMap[dojo.keys.PAGE_DOWN]=0xE00F;
68                keyMap[dojo.keys.END]=0xE010;
69                keyMap[dojo.keys.HOME]=0xE011;
70                keyMap[dojo.keys.LEFT_ARROW]=0xE012;
71                keyMap[dojo.keys.UP_ARROW]=0xE013;
72                keyMap[dojo.keys.RIGHT_ARROW]=0xE014;
73                keyMap[dojo.keys.DOWN_ARROW]=0xE015;
74                // keyMap[dojo.keys.INSERT]=0xE016;
75                // keyMap[dojo.keys.DELETE]=0xE017;
76                // // dojo.keys.HELP: 47,
77                // // dojo.keys.LEFT_WINDOW: 91,
78                // // dojo.keys.RIGHT_WINDOW: 92,
79                // // dojo.keys.SELECT: 93,
80                // keyMap[dojo.keys.NUMPAD_0]=0xE01A;
81                // keyMap[dojo.keys.NUMPAD_1]=0xE01B;
82                // keyMap[dojo.keys.NUMPAD_2]=0xE01C;
83                // keyMap[dojo.keys.NUMPAD_3]=0xE01D;
84                // keyMap[dojo.keys.NUMPAD_4]=0xE01E;
85                // keyMap[dojo.keys.NUMPAD_5]=0xE01F;
86                // keyMap[dojo.keys.NUMPAD_6]=0xE020;
87                // keyMap[dojo.keys.NUMPAD_7]=0xE021;
88                // keyMap[dojo.keys.NUMPAD_8]=0xE022;
89                // keyMap[dojo.keys.NUMPAD_9]=0xE023;
90                // keyMap[dojo.keys.NUMPAD_MULTIPLY]=0xE024;
91                // keyMap[dojo.keys.NUMPAD_PLUS]=0xE025;
92                // keyMap[dojo.keys.NUMPAD_ENTER]=0xE026;
93                // keyMap[dojo.keys.NUMPAD_MINUS]=0xE027;
94                // keyMap[dojo.keys.NUMPAD_PERIOD]=0xE028;
95                // keyMap[dojo.keys.NUMPAD_DIVIDE]=0xE029;
96                keyMap[dojo.keys.F1]=0xE031;
97                keyMap[dojo.keys.F2]=0xE032;
98                keyMap[dojo.keys.F3]=0xE033;
99                keyMap[dojo.keys.F4]=0xE034;
100                keyMap[dojo.keys.F5]=0xE035;
101                keyMap[dojo.keys.F6]=0xE036;
102                keyMap[dojo.keys.F7]=0xE037;
103                keyMap[dojo.keys.F8]=0xE038;
104                keyMap[dojo.keys.F9]=0xE039;
105                keyMap[dojo.keys.F10]=0xE03A;
106                keyMap[dojo.keys.F11]=0xE03B;
107                keyMap[dojo.keys.F12]=0xE03C;
108        }
109        var lastElement={node:null,reference:""};
110        // replace applet with methods to call WebDriver
111        _robot={
112                _setKey:function(sec){
113                        // initialization
114                        // switch WebDriver to test frame so it can resolve elements!
115                        /*robotXHR({
116                                method:"POST",
117                                commandString:"frame",
118                                postData:'{"id":"testBody"}',
119                                deferred:null,
120                                immediate:false
121                        });*/
122                        // skip keyboard initialization
123                        doh.robot._onKeyboard();
124                },
125               
126                _callLoaded:function(sec){
127                        // shouldn't be called
128                },
129               
130                _initKeyboard:function(sec){
131                        // shouldn't be called
132                },
133               
134                _initWheel:function(sec){
135                        // shouldn't be called
136                },
137               
138                setDocumentBounds:function(sec, docScreenX, docScreenY, width, height){
139                        // shouldn't be called
140                },
141               
142                _spaceReceived:function(){
143                        // shouldn't be called
144                },
145               
146                _notified:function(sec, keystring){
147                        // shouldn't be called
148                },
149               
150                _nextKeyGroupACK: function(sec){
151                        // shouldn't be called
152                },
153               
154                typeKey:function(sec, charCode, keyCode, alt, ctrl, shift, meta, delay, async){
155                        // send keys to active element
156                        var deferred=new dojo.Deferred();
157                        // after active element received...
158                        deferred.then(function(response){
159                                // remove garbage characters
160                                response=response.replace(/\{/g,"({").replace(/\}/g,"})");
161                                response=response.replace(/[^ -~]/g, "");
162                                //response=response.substring(0,response.lastIndexOf(")")+1);
163                                var json=dojo.fromJson(response);
164                                var activeElement=json.value.ELEMENT;
165                                // send keys to active element
166                                var keys=(ctrl?'"'+String.fromCharCode(dojo.keys.CTRL)+'",':'')
167                                        +(shift?'"'+String.fromCharCode(dojo.keys.SHIFT)+'",':'');
168                                if(keyCode in keyMap){
169                                        keys+='"'+String.fromCharCode(keyMap[keyCode])+'"';
170                                }else if(keyCode){
171                                        keys+='"'+String.fromCharCode(keyCode)+'"';
172                                }else{
173                                        keys+='"'+String.fromCharCode(charCode)+'"';
174                                }
175                                robotXHR({
176                                        method:"POST",
177                                        commandString:"element/"+activeElement+"/value",
178                                        postData:'{"value":['+keys+']}',
179                                        deferred:null,
180                                        immediate:false
181                                });
182                        });
183                        // get active element to send keys to
184                        // strangely, this request is a POST in the WebDriver API??
185                        robotXHR({
186                                method:"POST",
187                                commandString:"execute",
188                                postData:'{"script":"return document.activeElement;","args":[]}',
189                                deferred:deferred,
190                                immediate:false
191                        });
192                },
193               
194                /* ---- do we need to add the keyUp and keyDown here? */
195                upKey:function(sec,charCode,keyCode,delay){
196                        //robotXHR("upKey?sec="+sec+"&charCode="+charCode+"&keyCode="+keyCode+"&delay="+delay);
197                },
198               
199                downKey:function(sec,charCode,keyCode,delay){
200                        //robotXHR("downKey?sec="+sec+"&charCode="+charCode+"&keyCode="+keyCode+"&delay="+delay);
201                },
202               
203                moveMouse:function(sec, x, y, delay, duration){
204                        // x,y are not being computed relative to the mobile screen for some reason (probably iframe)
205                        x=Math.round(x);
206                        y=Math.round(y);
207                        if(!mouse){
208                                // create fake mouse
209                                mouse=dojo.doc.createElement("div");
210                                dojo.style(mouse, {
211                                        // x, y relative to screen (same coordinates as WebDriver)
212                                        position:"fixed",
213                                        left:"0px",
214                                        top:"0px",
215                                        width:"5px",
216                                        height:"5px",
217                                        "background-color":"red"
218                                });
219                                dojo.body().appendChild(mouse);
220                        }
221                        // fix x and y
222                        lastX=x-top.scrollX;
223                        lastY=y-top.scrollY;
224                        // cursor needs to be away from center of event or else the cursor itself will interfere with the event!
225                        mouse.style.left=(x+5)+"px";
226                        mouse.style.top=(y+5)+"px";
227                        //mouse.style.left=((lastX+top.scrollX+dojo.global.scrollX)+5)+"px";
228                        //mouse.style.top=((lastY+top.scrollY+dojo.global.scrollY)+5)+"px";
229                        robotXHR({
230                                method:"POST",
231                                commandString:"touch/move",
232                                postData:'{"x":'+lastX+',"y":'+lastX+'}',
233                                //content:{x:x,y:y},
234                                deferred:null,
235                                immediate:false
236                        });
237                },
238               
239                pressMouse:function(sec, left, middle, right, delay){
240                        //robotXHR("pressMouse?sec="+sec+"&left="+left+"&middle="+middle+"&right="+right+"&delay="+delay,null,true);
241                        var deferred=new dojo.Deferred();
242                        deferred.then(function(){
243                                mouse.style.backgroundColor="yellow";
244                        });
245                        robotXHR({
246                                method:"POST",
247                                commandString:"touch/down",
248                                postData:'{"x":'+(lastX)+',"y":'+(lastY)+'}',
249                                //content:{x:lastX,y:lastY},
250                                deferred:deferred,
251                                immediate:false
252                        });
253                },
254               
255                releaseMouse:function(sec, left, middle, right, delay){
256                        //robotXHR("releaseMouse?sec="+sec+"&left="+left+"&middle="+middle+"&right="+right+"&delay="+delay,null,true);
257                        var deferred=new dojo.Deferred();
258                        deferred.then(function(){
259                                mouse.style.backgroundColor="red";
260                        });
261                        robotXHR({
262                                method:"POST",
263                                commandString:"touch/up",
264                                postData:'{"x":'+(lastX+1)+',"y":'+(lastY+1)+'}',
265                                //content:{x:lastX,y:lastY},
266                                deferred:deferred,
267                                immediate:false
268                        });
269                },
270               
271                // doh.robot will call these functions in place of its own
272                typeKeys:function(/*String||Number*/ chars, /*Integer, optional*/ delay, /*Integer, optional*/ duration){
273                        // send keys to active element
274                        var deferred=new dojo.Deferred();
275                        // after active element received...
276                        deferred.then(function(response){
277                                response=response.replace(/\{/g,"({").replace(/\}/g,"})");
278                                response=response.replace(/[^ -~]/g, "");
279                                //response=response.substring(0,response.lastIndexOf(")")+1);
280                                var json=dojo.fromJson(response);
281                                var activeElement=json.value.ELEMENT;
282                                // send keys to active element
283                                var deferred2= new dojo.Deferred();
284                                deferred2.then(function(){
285                                        lastElement={node:dojo.doc.activeElement,reference:activeElement};
286                                });
287                                robotXHR({
288                                        method:"POST",
289                                        commandString:"element/"+activeElement+"/value",
290                                        // TODO: add codes to sent array for press and release modifiers
291                                        postData:'{"value":["'+chars+'"]}',
292                                        deferred:deferred2,
293                                        immediate:false
294                                });
295                        });
296                        // get active element to send keys to
297                        // strangely, this request is a POST in the WebDriver API??
298                        if(dojo.doc.activeElement!=lastElement.node){
299                                lastElement={node:dojo.doc.activeElement,reference:null};
300                                robotXHR({
301                                        method:"POST",
302                                        commandString:"execute",
303                                        postData:"{script:'return document.activeElement;',args:[]}",
304                                        deferred:deferred,
305                                        immediate:false
306                                });
307                        }else{
308                                deferred.callback("{value:{ELEMENT:'"+lastElement.reference+"'}}");
309                        }
310                },
311               
312                _scrollIntoView:function(node){
313                        // for whatever reason, scrollIntoView does not work...
314                        //node.scrollIntoView(true);
315                        p = geom.position(node);
316                        // scrolling the iframe doesn't seem to do anything
317                        //dojo.global.scrollTo(p.x,p.y);
318                        // this seems to work
319                        top.scrollTo(p.x,p.y);
320                        // this is also reasonable
321                        /*var scrollBy={dx:p.x-top.scrollX,dy:p.y-top.scrollY};
322                        robotXHR({
323                                method:"POST",
324                                commandString:"touch/scroll",
325                                // TODO: add codes to sent array for press and release modifiers
326                                postData:'{"xoffset":'+scrollBy.dx+', "yoffset":'+scrollBy.dy+'}',
327                                deferred:null,
328                                immediate:false
329                        });*/
330                }
331        };
332       
333        // robot.js will use this robot instead of the applet
334        has.add("doh-custom-robot", function(){
335                return has("android") && _robot;
336        });
337        return _robot;
338});
Note: See TracBrowser for help on using the repository browser.