qt4w.webdriver package

Submodules

qt4w.webdriver.iewebdriver module

IE的WebDriver实现

class qt4w.webdriver.iewebdriver.IEWebDriver(webview)

基类:qt4w.webdriver.webdriver.WebDriverBase

IE的WebDriver实现

driver_script = '/*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */\n(function(){function N(p,r){function q(a){if(q[a]!==w)return q[a];var c;if("bug-string-char-index"==a)c="a"!="a"[0];else if("json"==a)c=q("json-stringify")&&q("json-parse");else{var e;if("json-stringify"==a){c=r.stringify;var b="function"==typeof c&&s;if(b){(e=function(){return 1}).toJSON=e;try{b="0"===c(0)&&"0"===c(new t)&&\'""\'==c(new A)&&c(u)===w&&c(w)===w&&c()===w&&"1"===c(e)&&"[1]"==c([e])&&"[null]"==c([w])&&"null"==c(null)&&"[null,null,null]"==c([w,u,null])&&\'{"a":[1,true,false,null,"\\\\u0000\\\\b\\\\n\\\\f\\\\r\\\\t"]}\'==\nc({a:[e,!0,!1,null,"\\x00\\b\\n\\f\\r\\t"]})&&"1"===c(null,e)&&"[\\n 1,\\n 2\\n]"==c([1,2],null,1)&&\'"-271821-04-20T00:00:00.000Z"\'==c(new C(-864E13))&&\'"+275760-09-13T00:00:00.000Z"\'==c(new C(864E13))&&\'"-000001-01-01T00:00:00.000Z"\'==c(new C(-621987552E5))&&\'"1969-12-31T23:59:59.999Z"\'==c(new C(-1))}catch(f){b=!1}}c=b}if("json-parse"==a){c=r.parse;if("function"==typeof c)try{if(0===c("0")&&!c(!1)){e=c(\'{"a":[1,true,false,null,"\\\\u0000\\\\b\\\\n\\\\f\\\\r\\\\t"]}\');var n=5==e.a.length&&1===e.a[0];if(n){try{n=!c(\'"\\t"\')}catch(d){}if(n)try{n=\n1!==c("01")}catch(g){}if(n)try{n=1!==c("1.")}catch(m){}}}}catch(X){n=!1}c=n}}return q[a]=!!c}p||(p=k.Object());r||(r=k.Object());var t=p.Number||k.Number,A=p.String||k.String,H=p.Object||k.Object,C=p.Date||k.Date,G=p.SyntaxError||k.SyntaxError,K=p.TypeError||k.TypeError,L=p.Math||k.Math,I=p.JSON||k.JSON;"object"==typeof I&&I&&(r.stringify=I.stringify,r.parse=I.parse);var H=H.prototype,u=H.toString,v,B,w,s=new C(-0xc782b5b800cec);try{s=-109252==s.getUTCFullYear()&&0===s.getUTCMonth()&&1===s.getUTCDate()&&\n10==s.getUTCHours()&&37==s.getUTCMinutes()&&6==s.getUTCSeconds()&&708==s.getUTCMilliseconds()}catch(Q){}if(!q("json")){var D=q("bug-string-char-index");if(!s)var x=L.floor,M=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,c){return M[c]+365*(a-1970)+x((a-1969+(c=+(1<c)))/4)-x((a-1901+c)/100)+x((a-1601+c)/400)};(v=H.hasOwnProperty)||(v=function(a){var c={},e;(c.__proto__=null,c.__proto__={toString:1},c).toString!=u?v=function(a){var c=this.__proto__;a=a in(this.__proto__=null,this);this.__proto__=\nc;return a}:(e=c.constructor,v=function(a){var c=(this.constructor||e).prototype;return a in this&&!(a in c&&this[a]===c[a])});c=null;return v.call(this,a)});B=function(a,c){var e=0,b,f,n;(b=function(){this.valueOf=0}).prototype.valueOf=0;f=new b;for(n in f)v.call(f,n)&&e++;b=f=null;e?B=2==e?function(a,c){var e={},b="[object Function]"==u.call(a),f;for(f in a)b&&"prototype"==f||v.call(e,f)||!(e[f]=1)||!v.call(a,f)||c(f)}:function(a,c){var e="[object Function]"==u.call(a),b,f;for(b in a)e&&"prototype"==\nb||!v.call(a,b)||(f="constructor"===b)||c(b);(f||v.call(a,b="constructor"))&&c(b)}:(f="valueOf toString toLocaleString propertyIsEnumerable isPrototypeOf hasOwnProperty constructor".split(" "),B=function(a,c){var e="[object Function]"==u.call(a),b,h=!e&&"function"!=typeof a.constructor&&F[typeof a.hasOwnProperty]&&a.hasOwnProperty||v;for(b in a)e&&"prototype"==b||!h.call(a,b)||c(b);for(e=f.length;b=f[--e];h.call(a,b)&&c(b));});return B(a,c)};if(!q("json-stringify")){var U={92:"\\\\\\\\",34:\'\\\\"\',8:"\\\\b",\n12:"\\\\f",10:"\\\\n",13:"\\\\r",9:"\\\\t"},y=function(a,c){return("000000"+(c||0)).slice(-a)},R=function(a){for(var c=\'"\',b=0,h=a.length,f=!D||10<h,n=f&&(D?a.split(""):a);b<h;b++){var d=a.charCodeAt(b);switch(d){case 8:case 9:case 10:case 12:case 13:case 34:case 92:c+=U[d];break;default:if(32>d){c+="\\\\u00"+y(2,d.toString(16));break}c+=f?n[b]:a.charAt(b)}}return c+\'"\'},O=function(a,c,b,h,f,n,d){var g,m,k,l,p,r,s,t,q;try{g=c[a]}catch(z){}if("object"==typeof g&&g)if(m=u.call(g),"[object Date]"!=m||v.call(g,\n"toJSON"))"function"==typeof g.toJSON&&("[object Number]"!=m&&"[object String]"!=m&&"[object Array]"!=m||v.call(g,"toJSON"))&&(g=g.toJSON(a));else if(g>-1/0&&g<1/0){if(E){l=x(g/864E5);for(m=x(l/365.2425)+1970-1;E(m+1,0)<=l;m++);for(k=x((l-E(m,0))/30.42);E(m,k+1)<=l;k++);l=1+l-E(m,k);p=(g%864E5+864E5)%864E5;r=x(p/36E5)%24;s=x(p/6E4)%60;t=x(p/1E3)%60;p%=1E3}else m=g.getUTCFullYear(),k=g.getUTCMonth(),l=g.getUTCDate(),r=g.getUTCHours(),s=g.getUTCMinutes(),t=g.getUTCSeconds(),p=g.getUTCMilliseconds();\ng=(0>=m||1E4<=m?(0>m?"-":"+")+y(6,0>m?-m:m):y(4,m))+"-"+y(2,k+1)+"-"+y(2,l)+"T"+y(2,r)+":"+y(2,s)+":"+y(2,t)+"."+y(3,p)+"Z"}else g=null;b&&(g=b.call(c,a,g));if(null===g)return"null";m=u.call(g);if("[object Boolean]"==m)return""+g;if("[object Number]"==m)return g>-1/0&&g<1/0?""+g:"null";if("[object String]"==m)return R(""+g);if("object"==typeof g){for(a=d.length;a--;)if(d[a]===g)throw K();d.push(g);q=[];c=n;n+=f;if("[object Array]"==m){k=0;for(a=g.length;k<a;k++)m=O(k,g,b,h,f,n,d),q.push(m===w?"null":\nm);a=q.length?f?"[\\n"+n+q.join(",\\n"+n)+"\\n"+c+"]":"["+q.join(",")+"]":"[]"}else B(h||g,function(a){var c=O(a,g,b,h,f,n,d);c!==w&&q.push(R(a)+":"+(f?" ":"")+c)}),a=q.length?f?"{\\n"+n+q.join(",\\n"+n)+"\\n"+c+"}":"{"+q.join(",")+"}":"{}";d.pop();return a}};r.stringify=function(a,c,b){var h,f,n,d;if(F[typeof c]&&c)if("[object Function]"==(d=u.call(c)))f=c;else if("[object Array]"==d){n={};for(var g=0,k=c.length,l;g<k;l=c[g++],(d=u.call(l),"[object String]"==d||"[object Number]"==d)&&(n[l]=1));}if(b)if("[object Number]"==\n(d=u.call(b))){if(0<(b-=b%1))for(h="",10<b&&(b=10);h.length<b;h+=" ");}else"[object String]"==d&&(h=10>=b.length?b:b.slice(0,10));return O("",(l={},l[""]=a,l),f,n,h,"",[])}}if(!q("json-parse")){var V=A.fromCharCode,W={92:"\\\\",34:\'"\',47:"/",98:"\\b",116:"\\t",110:"\\n",102:"\\f",114:"\\r"},b,J,l=function(){b=J=null;throw G();},z=function(){for(var a=J,c=a.length,e,h,f,k,d;b<c;)switch(d=a.charCodeAt(b),d){case 9:case 10:case 13:case 32:b++;break;case 123:case 125:case 91:case 93:case 58:case 44:return e=\nD?a.charAt(b):a[b],b++,e;case 34:e="@";for(b++;b<c;)if(d=a.charCodeAt(b),32>d)l();else if(92==d)switch(d=a.charCodeAt(++b),d){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:e+=W[d];b++;break;case 117:h=++b;for(f=b+4;b<f;b++)d=a.charCodeAt(b),48<=d&&57>=d||97<=d&&102>=d||65<=d&&70>=d||l();e+=V("0x"+a.slice(h,b));break;default:l()}else{if(34==d)break;d=a.charCodeAt(b);for(h=b;32<=d&&92!=d&&34!=d;)d=a.charCodeAt(++b);e+=a.slice(h,b)}if(34==a.charCodeAt(b))return b++,e;l();default:h=\nb;45==d&&(k=!0,d=a.charCodeAt(++b));if(48<=d&&57>=d){for(48==d&&(d=a.charCodeAt(b+1),48<=d&&57>=d)&&l();b<c&&(d=a.charCodeAt(b),48<=d&&57>=d);b++);if(46==a.charCodeAt(b)){for(f=++b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}d=a.charCodeAt(b);if(101==d||69==d){d=a.charCodeAt(++b);43!=d&&45!=d||b++;for(f=b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}return+a.slice(h,b)}k&&l();if("true"==a.slice(b,b+4))return b+=4,!0;if("false"==a.slice(b,b+5))return b+=5,!1;if("null"==a.slice(b,\nb+4))return b+=4,null;l()}return"$"},P=function(a){var c,b;"$"==a&&l();if("string"==typeof a){if("@"==(D?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(c=[];;b||(b=!0)){a=z();if("]"==a)break;b&&(","==a?(a=z(),"]"==a&&l()):l());","==a&&l();c.push(P(a))}return c}if("{"==a){for(c={};;b||(b=!0)){a=z();if("}"==a)break;b&&(","==a?(a=z(),"}"==a&&l()):l());","!=a&&"string"==typeof a&&"@"==(D?a.charAt(0):a[0])&&":"==z()||l();c[a.slice(1)]=P(z())}return c}l()}return a},T=function(a,b,e){e=S(a,b,e);e===\nw?delete a[b]:a[b]=e},S=function(a,b,e){var h=a[b],f;if("object"==typeof h&&h)if("[object Array]"==u.call(h))for(f=h.length;f--;)T(h,f,e);else B(h,function(a){T(h,a,e)});return e.call(a,b,h)};r.parse=function(a,c){var e,h;b=0;J=""+a;e=P(z());"$"!=z()&&l();b=J=null;return c&&"[object Function]"==u.call(c)?S((h={},h[""]=e,h),"",c):e}}}r.runInContext=N;return r}var K=typeof define==="function"&&define.amd,F={"function":!0,object:!0},G=F[typeof exports]&&exports&&!exports.nodeType&&exports,k=F[typeof window]&&\nwindow||this,t=G&&F[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;!t||t.global!==t&&t.window!==t&&t.self!==t||(k=t);if(G&&!K)N(k,G);else{var L=k.JSON,Q=k.JSON3,M=!1,A=N(k,k.JSON3={noConflict:function(){M||(M=!0,k.JSON=L,k.JSON3=Q,L=Q=null);return A}});k.JSON={parse:A.parse,stringify:A.stringify}}K&&define(function(){return A})}).call(this);\n\n if ( !window.Element || !Element.prototype || !(document.documentElement instanceof Element)) {\n var __Element = window.Element;\n var __prototype = window.Element ? Element.prototype : null;\n window.Element = function(){};\n if (!__prototype) {\n // copy origin attrs\n for(var key in __Element)\n Element.prototype[key] = __Element[key];\n }\n var _hookElement = function (element) {\n if (!element) return;\n if (!element.hooked) {\n console.log(\'hook \' + element);\n for(var key in Element.prototype) {\n try{\n element[key] = Element.prototype[key];\n }catch(e){\n console.warn(element.outerHTML + \':\' + key + \':\' + e.message);\n }\n }\n element.hooked = true;\n }\n }\n\n var hookAllElements = function () {\n var elements = [document.documentElement];\n while (elements.length > 0) {\n var element = elements.splice(0, 1)[0];\n if (!element) continue;\n _hookElement(element);\n if (element.children) {\n for (var i = 0; i < element.children.length; i++) {\n elements.push(element.children[i]);\n }\n }\n }\n }\n\n var hookCreateElement = function () {\n if (document.__createElement) return;\n document.__createElement = document.createElement;\n document.createElement = function (tagName) {\n console.log(\'create element \' + tagName);\n var element = document.__createElement(tagName);\n for(var key in Element.prototype)\n element[key] = Element.prototype[key];\n element.hooked = true;\n return element;\n }\n }\n\n setTimeout(function () {\n try {\n hookCreateElement();\n hookAllElements();\n } catch (e) {\n alert(\'Hook element error: \' + e.message);\n }\n }, 100);\n \n }\n\n Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) {\n centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded;\n var rect = this.getBoundingClientRect();\n var clientWidth = document.documentElement.clientWidth - 20;\n var clientHeight = document.documentElement.clientHeight - 20;//\xe9\x81\xbf\xe5\x85\x8d\xe5\xad\x98\xe5\x9c\xa8\xe6\xbb\x9a\xe5\x8a\xa8\xe6\x9d\xa1\xe5\xaf\xbc\xe8\x87\xb4\xe9\x81\xae\xe6\x8c\xa1\xe6\x8e\xa7\xe4\xbb\xb6\n if(rect.left >= clientWidth || rect.right <= 0 || rect.top >= clientHeight || rect.bottom <= 0){\n this.scrollIntoView();\n }\n }\n if (!Element.prototype.dispatchEvent) {\n Element.prototype.dispatchEvent = function (event) {\n if (event.type == \'input\') {\n event.type = \'propertychange\';\n event.propertyName = \'value\';\n }\n event.srcElement = event.target = this;\n this.fireEvent(\'on\' + event.type, event);\n }\n }\n\n Array.prototype.forEach = Array.prototype.forEach || function (callback) {\n if (typeof callback != \'function\') {\n throw TypeError(typeof callback);\n }\n for(var i = 0; i < this.length; i ++) {\n callback.call(arguments[1], this[i], i, this);\n }\n };\n\n if (Function.prototype.bind && window.console && typeof console.log == "object"){\n // \xe8\xa7\xa3\xe5\x86\xb3console.log\xe6\xb2\xa1\xe6\x9c\x89apply/bind\xe6\x96\xb9\xe6\xb3\x95\xe9\x97\xae\xe9\xa2\x98\n ["log","info","warn","error","assert","dir","clear","profile","profileEnd"].forEach(function (method) {\n console[method] = this.bind(console[method], console);\n }, Function.prototype.call);\n }\n // Avoid `console` errors in browsers that lack a console.\n (function() {\n var method;\n var noop = function () {};\n var methods = [\n \'assert\', \'clear\', \'count\', \'debug\', \'dir\', \'dirxml\', \'error\',\n \'exception\', \'group\', \'groupCollapsed\', \'groupEnd\', \'info\', \'log\',\n \'markTimeline\', \'profile\', \'profileEnd\', \'table\', \'time\', \'timeEnd\',\n \'timeStamp\', \'trace\', \'warn\'\n ];\n var length = methods.length;\n var console = (window.console = window.console || {});\n\n while (length--) {\n method = methods[length];\n\n // Only stub undefined methods.\n if (!console[method]) {\n console[method] = noop;\n }\n }\n }());\n\n if (!document.createEvent) {\n document.createEvent = function (event) {\n var evt = document.createEventObject(event);\n evt.initEvent = function (type) {\n evt.type = type;\n }\n return evt;\n }\n }\n \n if (typeof window.qt4w_hook_console == \'undefined\') window.qt4w_hook_console = true;\n window[\'qt4w_driver_lib\'] = {\n getScale : function(){\n return 1;\n },\n \n getScreenSize: function(){\n var result = new Array();\n result.push(screen.availWidth);\n result.push(screen.availHeight);\n return result.toString();\n },\n \n selectNodes : function(xpath){\n var oResult = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);\n var aNodes = new Array(); \n if (oResult != null) { \n var oElement = oResult.iterateNext(); \n while (oElement) { \n aNodes.push(oElement); \n oElement = oResult.iterateNext(); \n } \n }\n return aNodes;\n },\n \n selectNode : function(xpath){\n var nodes = this.selectNodes(xpath);\n if(nodes.length == 0) throw new Error(\'Find element \'+xpath+\' failed\');\n else if(nodes.length > 1) throw new Error(\'Find \'+nodes.length+\' elements match \'+xpath);\n return nodes[0];\n },\n \n getElementZoom: function(node){\n var scale = 1;\n while(node != null && node != document.documentElement){\n var zoom = parseFloat(window.getComputedStyle(node, null).zoom);\n if(zoom != 1){\n scale *= zoom;\n }\n node = node.parentNode;\n }\n return scale;\n },\n \n getElemRect: function(node){\n var result = new Array();\n var rect = node.getBoundingClientRect();\n var scale = this.getScale();\n scale *= this.getElementZoom(node);\n var left = rect.left;\n var top = rect.top;\n var width = rect.width;\n var height = rect.height;\n if (typeof width == \'undefined\') width = rect.right - rect.left;\n if (typeof height == \'undefined\') height = rect.bottom - rect.top;\n result.push(left * scale);\n result.push(top * scale);\n result.push(width * scale);\n result.push(height * scale);\n return result.toString();\n },\n \n initHighlightDiv: function(){\n this.bd0 = document.createElement("div");\n this.bd1 = document.createElement("div");\n this.bd2 = document.createElement("div");\n this.bd3 = document.createElement("div");\n },\n \n showDiv: function(cnt){\n if(cnt % 2 != 0){\n document.body.appendChild(this.bd0);\n document.body.appendChild(this.bd1);\n document.body.appendChild(this.bd2);\n document.body.appendChild(this.bd3);\n } else {\n document.body.removeChild(this.bd0);\n document.body.removeChild(this.bd1);\n document.body.removeChild(this.bd2);\n document.body.removeChild(this.bd3);\n }\n if (cnt){\n cnt--;\n if(window.console) console.log(\'show\' + cnt);\n setTimeout("qt4w_driver_lib.showDiv(" + cnt + ")", 200);\n }\n },\n \n highlight: function(node){\n if (!this.bd0) {\n this.initHighlightDiv();\n }\n var rect = node.getBoundingClientRect();\n var left= rect.left;\n var top = rect.top;\n var width = node.offsetWidth;\n var height = node.offsetHeight;\n if(window.console) console.log(left+\',\'+top+\',\'+width+\',\'+height);\n \n this.bd0.setAttribute("style", "left:" + (left - 1) + "px;top:" + (top - 1) + "px;z-index:32767;"\n + "width:" + (width + 2) + "px;height:2px;position:fixed;background-color: red");\n this.bd1.setAttribute("style", "left:" + (left - 1) + "px;top:" + (top - 1) + "px;z-index:32767;"\n + "width:2px;height:" + (height) + "px;position:fixed;;background-color: red");\n this.bd2.setAttribute("style", "left:" + (left + width - 1) + "px;top:" + (top) + "px;z-index:32767;"\n + "width:2px;height:" + (height) + "px;position:fixed;;background-color: red");\n this.bd3.setAttribute("style", "left:" + (left - 1) + "px;top:" + (top + height - 1) + "px;z-index:32767;"\n + "width:" + (width + 2) + "px;height:2px;position:fixed;;background-color: red");\n //console.log(\'style\'+this.bd0.getAttribute(\'style\')+\'\');\n this.showDiv(3);\n },\n \n scrollToVisible: function(node){\n if(node.scrollIntoViewIfNeeded){\n node.scrollIntoViewIfNeeded();\n }else if(node.scrollIntoView){\n node.scrollIntoView();\n }\n },\n \n logData: [],\n hookConsole: function(){\n var self = this;\n if(window.console && console.log && console.log.apply && window.JSON){\n var hookedConsoleFunc = function(){\n var timeStr = new Date().toLocaleString();\n for(var i=1;i<arguments.length;i++){\n var data = arguments[i];\n if(data instanceof Array){\n data = JSON.stringify(data);\n }else if(data instanceof Object){\n var jsonData = {};\n for(var key in data){\n jsonData[key] = data[key];\n if(jsonData[key]) jsonData[key] = jsonData[key].toString();\n }\n data = JSON.stringify(jsonData);\n }\n self.logData.push(\'[\' + timeStr + \'][console.\' + arguments[0].name + \'] \' + data);\n }\n var args = Array.prototype.slice.call(arguments);\n args.splice(0, 1);\n return arguments[0].apply(this, args);\n }\n\n var hookFunction = function (funcName) {\n if (!console[funcName]) return;\n var origFunc = console[funcName];\n console[funcName] = function(){\n var args = Array.prototype.slice.call(arguments);\n args.splice(0, 0, origFunc);\n return hookedConsoleFunc.apply(this, args);\n }\n }\n\n hookFunction(\'log\');\n hookFunction(\'dir\');\n hookFunction(\'info\');\n hookFunction(\'warn\');\n hookFunction(\'error\');\n }\n },\n \n readLogData: function (count) {\n if (count < 0) count = this.logData.length;\n return this.logData.splice(0, count);\n }\n \n };\n\n if (window.qt4w_hook_console) qt4w_driver_lib.hookConsole();\n \n window[\'qt4w_driver_lib\'][\'getScale\'] = function(){return screen.deviceXDPI / screen.logicalXDPI;};\n window[\'qt4w_driver_lib\'][\'getElementZoom\'] = function(node){\n return 1;\n };\n '
eval_script(frame_xpaths, script)

在指定frame中执行JavaScript,并返回执行结果

参数:
  • frame_xpaths (list) – frame元素的XPATH路径,如果是顶层页面,怎传入“[]”
  • script (string) – 要执行的JavaScript语句
get_style(elem_xpaths, style_name)

获取元素的某一样式值

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • style_name (string) – 样式名称

qt4w.webdriver.webdriver module

IWebDriver接口

class qt4w.webdriver.webdriver.IWebDriver(webview)

基类:object

IWebDriver接口

eval_script(frame_xpaths, script)

在指定frame中执行JavaScript,并返回执行结果

参数:
  • frame_xpaths (list) – frame元素的XPATH路径,如果是顶层页面,怎传入“[]”
  • script (string) – 要执行的JavaScript语句
get_attribute(elem_xpaths, attr_name)

获取元素属性

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • attr_name (string) – 属性名
get_elem_rect(elem_xpaths, rav=True)

获取元素在页面中的坐标

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • rav (bool) – 是否是相对于当前frame
get_property(elem_xpaths, prop_name)

获取元素的特定值,例如:node.innerHTML

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • prop_name (string) – property名
get_style(elem_xpaths, style_name)

获取元素的某一样式值

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • style_name (string) – 样式名称
highlight(elem_xpaths)

使元素高亮

参数:elem_xpaths (list) – 元素的XPATH路径
ready_state

页面状态

set_attribute(elem_xpaths, attr_name, value)

设置元素属性

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • attr_name (string) – 属性名
  • value (string) – 新的值
set_property(elem_xpaths, prop_name, value)

设置元素的特定值,例如:node.innerHTML

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • prop_name (string) – property名
  • value (string) – 新的值
class qt4w.webdriver.webdriver.WebDriverBase(webview)

基类:qt4w.webdriver.webdriver.IWebDriver

WebDriver基类

static create_driver(webview)

根据webview类型创建对应的WebDriver实例

参数:webview (object) – WebView实例
drag_element(elem_xpaths, from_x, from_y, to_x, to_y)

拖拽元素

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • from_x (int/float) – 起点横坐标,相对于WebView左上角
  • from_y (int/float) – 起点纵坐标,相对于WebView左上角
  • to_x (int/float) – 终点横坐标,相对于WebView左上角
  • to_y (int/float) – 终点纵坐标,相对于WebView左上角
driver_script = '\n if (typeof window.qt4w_hook_console == \'undefined\') window.qt4w_hook_console = true;\n window[\'qt4w_driver_lib\'] = {\n getScale : function(){\n return 1;\n },\n \n getScreenSize: function(){\n var result = new Array();\n result.push(screen.availWidth);\n result.push(screen.availHeight);\n return result.toString();\n },\n \n selectNodes : function(xpath){\n var oResult = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);\n var aNodes = new Array(); \n if (oResult != null) { \n var oElement = oResult.iterateNext(); \n while (oElement) { \n aNodes.push(oElement); \n oElement = oResult.iterateNext(); \n } \n }\n return aNodes;\n },\n \n selectNode : function(xpath){\n var nodes = this.selectNodes(xpath);\n if(nodes.length == 0) throw new Error(\'Find element \'+xpath+\' failed\');\n else if(nodes.length > 1) throw new Error(\'Find \'+nodes.length+\' elements match \'+xpath);\n return nodes[0];\n },\n \n getElementZoom: function(node){\n var scale = 1;\n while(node != null && node != document.documentElement){\n var zoom = parseFloat(window.getComputedStyle(node, null).zoom);\n if(zoom != 1){\n scale *= zoom;\n }\n node = node.parentNode;\n }\n return scale;\n },\n \n getElemRect: function(node){\n var result = new Array();\n var rect = node.getBoundingClientRect();\n var scale = this.getScale();\n scale *= this.getElementZoom(node);\n var left = rect.left;\n var top = rect.top;\n var width = rect.width;\n var height = rect.height;\n if (typeof width == \'undefined\') width = rect.right - rect.left;\n if (typeof height == \'undefined\') height = rect.bottom - rect.top;\n result.push(left * scale);\n result.push(top * scale);\n result.push(width * scale);\n result.push(height * scale);\n return result.toString();\n },\n \n initHighlightDiv: function(){\n this.bd0 = document.createElement("div");\n this.bd1 = document.createElement("div");\n this.bd2 = document.createElement("div");\n this.bd3 = document.createElement("div");\n },\n \n showDiv: function(cnt){\n if(cnt % 2 != 0){\n document.body.appendChild(this.bd0);\n document.body.appendChild(this.bd1);\n document.body.appendChild(this.bd2);\n document.body.appendChild(this.bd3);\n } else {\n document.body.removeChild(this.bd0);\n document.body.removeChild(this.bd1);\n document.body.removeChild(this.bd2);\n document.body.removeChild(this.bd3);\n }\n if (cnt){\n cnt--;\n if(window.console) console.log(\'show\' + cnt);\n setTimeout("qt4w_driver_lib.showDiv(" + cnt + ")", 200);\n }\n },\n \n highlight: function(node){\n if (!this.bd0) {\n this.initHighlightDiv();\n }\n var rect = node.getBoundingClientRect();\n var left= rect.left;\n var top = rect.top;\n var width = node.offsetWidth;\n var height = node.offsetHeight;\n if(window.console) console.log(left+\',\'+top+\',\'+width+\',\'+height);\n \n this.bd0.setAttribute("style", "left:" + (left - 1) + "px;top:" + (top - 1) + "px;z-index:32767;"\n + "width:" + (width + 2) + "px;height:2px;position:fixed;background-color: red");\n this.bd1.setAttribute("style", "left:" + (left - 1) + "px;top:" + (top - 1) + "px;z-index:32767;"\n + "width:2px;height:" + (height) + "px;position:fixed;;background-color: red");\n this.bd2.setAttribute("style", "left:" + (left + width - 1) + "px;top:" + (top) + "px;z-index:32767;"\n + "width:2px;height:" + (height) + "px;position:fixed;;background-color: red");\n this.bd3.setAttribute("style", "left:" + (left - 1) + "px;top:" + (top + height - 1) + "px;z-index:32767;"\n + "width:" + (width + 2) + "px;height:2px;position:fixed;;background-color: red");\n //console.log(\'style\'+this.bd0.getAttribute(\'style\')+\'\');\n this.showDiv(3);\n },\n \n scrollToVisible: function(node){\n if(node.scrollIntoViewIfNeeded){\n node.scrollIntoViewIfNeeded();\n }else if(node.scrollIntoView){\n node.scrollIntoView();\n }\n },\n \n logData: [],\n hookConsole: function(){\n var self = this;\n if(window.console && console.log && console.log.apply && window.JSON){\n var hookedConsoleFunc = function(){\n var timeStr = new Date().toLocaleString();\n for(var i=1;i<arguments.length;i++){\n var data = arguments[i];\n if(data instanceof Array){\n data = JSON.stringify(data);\n }else if(data instanceof Object){\n var jsonData = {};\n for(var key in data){\n jsonData[key] = data[key];\n if(jsonData[key]) jsonData[key] = jsonData[key].toString();\n }\n data = JSON.stringify(jsonData);\n }\n self.logData.push(\'[\' + timeStr + \'][console.\' + arguments[0].name + \'] \' + data);\n }\n var args = Array.prototype.slice.call(arguments);\n args.splice(0, 1);\n return arguments[0].apply(this, args);\n }\n\n var hookFunction = function (funcName) {\n if (!console[funcName]) return;\n var origFunc = console[funcName];\n console[funcName] = function(){\n var args = Array.prototype.slice.call(arguments);\n args.splice(0, 0, origFunc);\n return hookedConsoleFunc.apply(this, args);\n }\n }\n\n hookFunction(\'log\');\n hookFunction(\'dir\');\n hookFunction(\'info\');\n hookFunction(\'warn\');\n hookFunction(\'error\');\n }\n },\n \n readLogData: function (count) {\n if (count < 0) count = this.logData.length;\n return this.logData.splice(0, count);\n }\n \n };\n\n if (window.qt4w_hook_console) qt4w_driver_lib.hookConsole();\n '
eval_script(frame_xpaths, script)

在指定frame中执行JavaScript,并返回执行结果(该实现需要处理js基础库未注入情况的处理)

参数:
  • frame_xpaths (list) – frame元素的XPATH路径,如果是顶层页面,怎传入“[]”
  • script (string) – 要执行的JavaScript语句
fire_event(elem_xpaths, type)

触发事件

参数:
  • elem_xpaths (list) – 要触发事件的元素XPATH路径
  • type (string) – 事件类型
get_attribute(elem_xpaths, attr_name)

获取元素属性

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • attr_name (string) – 属性名
get_elem_rect(elem_xpaths, rav=True)

获取元素在页面中的坐标

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • rav (bool) – 是否是相对于当前frame
get_element(elem_xpaths)

获取控件,如果控件不存在抛出ControlNotFoundError

参数:elem_xpaths (list) – 元素xpath路径
get_element_count(elem_xpaths)

获取满足elem_xpaths的元素个数

参数:elem_xpaths (list) – 元素的XPATH路径
get_property(elem_xpaths, prop_name)

获取元素的特定值,例如:node.innerHTML

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • prop_name (string) – property名
get_ready_state(frame_xpaths)

获取页面状态

get_screen_size()

获取屏幕大小

get_style(elem_xpaths, style_name)

获取元素的某一样式值

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • style_name (string) – 样式名称
highlight(elem_xpaths)

使元素高亮

参数:elem_xpaths (list) – 元素的XPATH路径
is_elem_focused(elem_xpaths)

是否是当前有焦点元素

参数:elem_xpaths
read_console_log(frame_xpaths, count=1)

读取指定条数的日志

参数:
  • frame_xpaths (list) – 当前页面的XPATH路径
  • count (int) – 要读取的日志条数,默认为1
返回:

读取到的日志

scroll_to_visible(elem_xpaths)

将元素滚动到可见区域

参数:elem_xpaths (list) – 元素的XPATH路径
set_attribute(elem_xpaths, attr_name, value)

设置元素属性

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • attr_name (string) – 属性名
  • value (string) – 新的值
set_property(elem_xpaths, prop_name, value)

设置元素的特定值,例如:node.innerHTML

参数:
  • elem_xpaths (list) – 元素的XPATH路径
  • prop_name (string) – property名
  • value (string) – 新的值

qt4w.webdriver.webkitwebdriver module

Webkit WebDrvier实现

class qt4w.webdriver.webkitwebdriver.WebkitWebDriver(webview)

基类:qt4w.webdriver.webdriver.WebDriverBase

Webkit WebDrvier

driver_script = '\n if (typeof window.qt4w_hook_console == \'undefined\') window.qt4w_hook_console = true;\n window[\'qt4w_driver_lib\'] = {\n getScale : function(){\n return 1;\n },\n \n getScreenSize: function(){\n var result = new Array();\n result.push(screen.availWidth);\n result.push(screen.availHeight);\n return result.toString();\n },\n \n selectNodes : function(xpath){\n var oResult = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);\n var aNodes = new Array(); \n if (oResult != null) { \n var oElement = oResult.iterateNext(); \n while (oElement) { \n aNodes.push(oElement); \n oElement = oResult.iterateNext(); \n } \n }\n return aNodes;\n },\n \n selectNode : function(xpath){\n var nodes = this.selectNodes(xpath);\n if(nodes.length == 0) throw new Error(\'Find element \'+xpath+\' failed\');\n else if(nodes.length > 1) throw new Error(\'Find \'+nodes.length+\' elements match \'+xpath);\n return nodes[0];\n },\n \n getElementZoom: function(node){\n var scale = 1;\n while(node != null && node != document.documentElement){\n var zoom = parseFloat(window.getComputedStyle(node, null).zoom);\n if(zoom != 1){\n scale *= zoom;\n }\n node = node.parentNode;\n }\n return scale;\n },\n \n getElemRect: function(node){\n var result = new Array();\n var rect = node.getBoundingClientRect();\n var scale = this.getScale();\n scale *= this.getElementZoom(node);\n var left = rect.left;\n var top = rect.top;\n var width = rect.width;\n var height = rect.height;\n if (typeof width == \'undefined\') width = rect.right - rect.left;\n if (typeof height == \'undefined\') height = rect.bottom - rect.top;\n result.push(left * scale);\n result.push(top * scale);\n result.push(width * scale);\n result.push(height * scale);\n return result.toString();\n },\n \n initHighlightDiv: function(){\n this.bd0 = document.createElement("div");\n this.bd1 = document.createElement("div");\n this.bd2 = document.createElement("div");\n this.bd3 = document.createElement("div");\n },\n \n showDiv: function(cnt){\n if(cnt % 2 != 0){\n document.body.appendChild(this.bd0);\n document.body.appendChild(this.bd1);\n document.body.appendChild(this.bd2);\n document.body.appendChild(this.bd3);\n } else {\n document.body.removeChild(this.bd0);\n document.body.removeChild(this.bd1);\n document.body.removeChild(this.bd2);\n document.body.removeChild(this.bd3);\n }\n if (cnt){\n cnt--;\n if(window.console) console.log(\'show\' + cnt);\n setTimeout("qt4w_driver_lib.showDiv(" + cnt + ")", 200);\n }\n },\n \n highlight: function(node){\n if (!this.bd0) {\n this.initHighlightDiv();\n }\n var rect = node.getBoundingClientRect();\n var left= rect.left;\n var top = rect.top;\n var width = node.offsetWidth;\n var height = node.offsetHeight;\n if(window.console) console.log(left+\',\'+top+\',\'+width+\',\'+height);\n \n this.bd0.setAttribute("style", "left:" + (left - 1) + "px;top:" + (top - 1) + "px;z-index:32767;"\n + "width:" + (width + 2) + "px;height:2px;position:fixed;background-color: red");\n this.bd1.setAttribute("style", "left:" + (left - 1) + "px;top:" + (top - 1) + "px;z-index:32767;"\n + "width:2px;height:" + (height) + "px;position:fixed;;background-color: red");\n this.bd2.setAttribute("style", "left:" + (left + width - 1) + "px;top:" + (top) + "px;z-index:32767;"\n + "width:2px;height:" + (height) + "px;position:fixed;;background-color: red");\n this.bd3.setAttribute("style", "left:" + (left - 1) + "px;top:" + (top + height - 1) + "px;z-index:32767;"\n + "width:" + (width + 2) + "px;height:2px;position:fixed;;background-color: red");\n //console.log(\'style\'+this.bd0.getAttribute(\'style\')+\'\');\n this.showDiv(3);\n },\n \n scrollToVisible: function(node){\n if(node.scrollIntoViewIfNeeded){\n node.scrollIntoViewIfNeeded();\n }else if(node.scrollIntoView){\n node.scrollIntoView();\n }\n },\n \n logData: [],\n hookConsole: function(){\n var self = this;\n if(window.console && console.log && console.log.apply && window.JSON){\n var hookedConsoleFunc = function(){\n var timeStr = new Date().toLocaleString();\n for(var i=1;i<arguments.length;i++){\n var data = arguments[i];\n if(data instanceof Array){\n data = JSON.stringify(data);\n }else if(data instanceof Object){\n var jsonData = {};\n for(var key in data){\n jsonData[key] = data[key];\n if(jsonData[key]) jsonData[key] = jsonData[key].toString();\n }\n data = JSON.stringify(jsonData);\n }\n self.logData.push(\'[\' + timeStr + \'][console.\' + arguments[0].name + \'] \' + data);\n }\n var args = Array.prototype.slice.call(arguments);\n args.splice(0, 1);\n return arguments[0].apply(this, args);\n }\n\n var hookFunction = function (funcName) {\n if (!console[funcName]) return;\n var origFunc = console[funcName];\n console[funcName] = function(){\n var args = Array.prototype.slice.call(arguments);\n args.splice(0, 0, origFunc);\n return hookedConsoleFunc.apply(this, args);\n }\n }\n\n hookFunction(\'log\');\n hookFunction(\'dir\');\n hookFunction(\'info\');\n hookFunction(\'warn\');\n hookFunction(\'error\');\n }\n },\n \n readLogData: function (count) {\n if (count < 0) count = this.logData.length;\n return this.logData.splice(0, count);\n }\n \n };\n\n if (window.qt4w_hook_console) qt4w_driver_lib.hookConsole();\n \n window.Notification = undefined; // disable Notification\n window[\'qt4w_driver_lib\'][\'getScale\'] = function(){return window.devicePixelRatio;};\n window[\'qt4w_driver_lib\'][\'getElemRect\'] = function(node) {\n var result = new Array();\n var rect = node.getBoundingClientRect();\n var scale = this.getScale();\n scale *= this.getElementZoom(node);\n var left = rect.left;\n var top = rect.top;\n if (document.documentElement.scrollWidth > document.documentElement.clientWidth) {\n // \xe9\xa1\xb5\xe9\x9d\xa2\xe6\x9c\xaa\xe9\x80\x82\xe9\x85\x8d\xe7\xbb\x88\xe7\xab\xaf\n if (window.visualViewport) {\n // above Chrome 61\n left -= window.visualViewport.offsetLeft;\n top -= window.visualViewport.offsetTop;\n } else {\n if (window.scrollX && document.documentElement.getBoundingClientRect().left == 0) {\n // getBoundingClientRect return fix position\n left -= window.scrollX;\n }\n if (window.scrollY && document.documentElement.getBoundingClientRect().top == 0) {\n top -= window.scrollY;\n }\n }\n }\n \n result.push(left * scale);\n result.push(top * scale);\n result.push(rect.width * scale);\n result.push(rect.height * scale);\n return result.toString();\n }\n document.addEventListener(\'click\', function(event){console.log(\'[ClickListener](\' + event.clientX + \', \' + event.clientY + \')\');}, true);\n '

Module contents

IWebDriver接口定义及Windows上的实现

class qt4w.webdriver.EnumWebDriverType

基类:object

WebDriver类型(浏览器内核)

IE = 1
WEBKIT = 2