UI Element基础知识篇
简而言之,这次介绍如何编写基本的Map文件(Extension.js文件)
一个基本的Map文件大致是这样的:
var map = new UIMap();map.addPageset( {name: 'aPageset',...} );map.addElement
(
'aPageset'
, { ... }
, {}
);map.addElement('aPageset', { ... });...map.addPageset( { name: 'anotherPageset', ... } ); 唉,我很晕这样的点啊、大括号、一推单引号的文档描述。没办法,谁让它用的是
Javascript对象标记方式写的结构呢...先整理一下代码的编写规则:
- 映射图的结构被描述成了Map.Pageset.Element的对象链的线性结构。
- 一切从一个Map对象开始,即var map = new UIMap()要写在最前面!一个
Js文件中,最好只写一个Map对象。 - 在Map对象后可通过Map对象.addXXX来增加节点(其实就是调用Map对象的Add系列
方法)。节点的内容用()包围,分号结尾(Javascript的规范写法) - 节点中的内容编写规则如下
- 字符串要用单引号括起
- 数组内容用{}括起
- 数组元素的写法是 数组元素名 : 值。这里的数组元素也可以当做是节点
对象的属性来看待.需要注意的是这里的元素设置顺序不可改变!
- 多个数据用逗号分隔,为避免遗漏,建议将逗号写在最前面
我的编写风格一般是这样的,个人觉得这样看上下关系会比较清楚。
map.addElement
(
{
'aPageset'
, name:'testman'
, description:'man'
}
,
'test'
);
搞清楚代码编写规则后,来看看map对象到底提供了什么方法和参数吧
map.addPageSet(pagesetShorthand)概述:增加Pageset节点
pagesetShorthand:这是一个数组,其中的元素(Pageset的属性)如下(见文末表1)
map.addElement(pagesetName, uiElementShorthand)
概述:在指定的Pageset节点中增加Element子节点
参数解析
1.pagesetName 字符串类型,通过设置此参数为Pageset的名字与指定的Pageset进行关联
2.uiElementShorthand 数组参数,包含了Element的诸多要素(也可看做属性)详细列
表如下(见文末表2)
核心方法就这么两个,会不会太单调了呢?当然不只这么点,不过那些以后再说。现在先看
看与核心方法相关的一些内容吧
UI Argument Shorthand
刚才的参数解析中,有提到一个args对吧,这次来仔细看看这个东东里有什么玄机。
先来看一段实例代码
map.addElement('searchPages', {
name: 'result'
, description: 'link to a result page'
, args: [
{
name: 'index'
, description: 'the index of the search result'
, defaultValues: range(1, 21)
}
, {
name: 'type'
, description: 'the type of result page'
, defaultValues: [ 'summary', 'detail' ]
}
]
, getLocator: function(args) {
var index = args['index'];
var type = args['type'];
return "//div[@class='result'][" + index + "]"
+ "/descendant::a[@class='" + type + "']";
}
});
解析:这个Element在定义的时候还指定了args参数,内有两个参数index和type,
并赋予了默认值(defaultValues语句)。随后在getLocator函数中,将接收这两个参数,
并在其函数体中起到了动态路径赋值的作用。这里的
defaultValues语句其实就是用Selenium IDE录制工具录制脚本时自动生成的默认值设置。
(也就是说,自动生成脚本代码中用到的默认参数设置就是由这个属性决定的)。在IDE的
录制模式中,IDE使用哪种定位对象方式是自动匹配的,但这往往不准确(这种事情录制时经
常发生)。UI Element则提供了一种新的UI界面元素定位方式。使用这种方式(即实例代
码所展示的)时,Selenium通过变换UI Element中定义的所有的参数中默认值来生成一个
Xpath路径列表,再进行有效匹配。在这段代码中index参数的默认值是1、2、3...20,而
type参数的默认值是summary和detail。当然,若你不想用IDE,你可以不使用UI
Argument。
下表是UI Argument对象的属性介绍(见文末表3)
关于This关键字
什么是this:一开始,在使用addPageset()
oraddElement()函数创建对象时,
this指的是Selenium IDE的窗口对象(这时的this根本没用)。接着,在geLocator函
数被调用后,this指的是
调用此函数的Element对象了。因此,使用this,为UI
Element定义的任何本地变量就可以使用了。getDefaulVlues函数也是如此。这儿有个有
点神奇的的地方。若你在UI Element Shorthand部分之前定义你的本地变量,从
Shorthand语句开始,这些本地变量就可以在arguments中使用通过this引用。注意,这
不是标准的Javascirpt行为!在理清函数定义语句和避免在函数中使用用于列表和Map的
全局变量的处理上,这种方式是有效的。这有时会很有用。比如,定义一个映射了人性化
的参数值到DOM Element ID的参数值的对象。这种情况下,当getLocator函数使用这个
map对象获得在Locator中的相关ID时,
getDefaultValues()却可以简单地返回一个
map对象的属性名。
特别注意:this关键字仅在getLocator()
和getDefaultValues()
函数中可以
使用。
表1
属性名 | 是否必选 | (数据类型)含义说明
| 代码举例
|
name | Yes | (String)对象的名字,请确保这个名字在一个Map对象中是唯一的。 | name: 'shopPages' |
description | Yes | (String)概述这个Pagest方便他人阅读 | description: 'all pages displaying product' |
pathPrefix | No | | |
paths/pathRegexp | Conditional | | |
paramRegexps | No | | |
pageContent | Conditional | | |
表2
属性名 | 是否必选
| (数据类型)含义说明
| 代码举例
|
name | Yes | (String)UI Element的名字
| name: 'article' |
description | Yes | (String)对Element的作用说明,方便阅读此文档 | description: 'front or issue page link to article' |
args | No | (Array)可修改getLocator函数的参数列表。可以不指定任何参数。 | [ { name: 'index' , description: 'the index of the author, by article' , defaultValues: range(1, 5) } ]
注意,最外层是中括号哦~ |
locator/getLocator() | Yes | (String\Function)仅可选择两种数据类型之一。若是Function则还可以带参数,此函数的返回值就是这个Element的代码级路径。
| locator: 'submit' getLocator: function(args) { return 'css=div.item:nth-child(' + args.index + ')' + ' > h5 > a'; } getLocator: function(args) { var label = args.label; var id = this._idMap[label]; return '//input[@id=' + id.quoteForXPath() + ']'; } |
genericLocator/getGenericLocator | No | | |
getOffsetLocator | No | | |
testcase* | No | | |
_* | No | (Any Data Type)为UI Element声明本地变量。这种变量在UI Element的getLocator函数和任何通过它进行参数传递的任何getDefaultValues函数中有效。这些变量以"_"开头。写法见代码举例。
| _labelMap: { 'Name': 'user' , 'Email': 'em' , 'Phone': 'tel' } |
表3
属性名 | 是否必选
| (数据类型)含义说明
| 代码举例
|
name | Yes | (String)参数的名字 | name: 'index' |
description | Yes | (String)参数的易读性描述 | description: 'the index of the article' |
defaultValues/getDefaultValues() | Yes
| (Array\Funcition)仅可选择两种数据类型之一。getDefaultValues(inDocument) ,这是此函数的结构。inDocument参数是录制时的当前页面的Document对象。
| defaultValues: [ 'alpha', 'beta', 'unlimited' ] getDefaultValues: function() { return keys(this._idMap); } getDefaultValues: function(inDocument) { var defaultValues = []; var links = inDocument .getElementsByTagName('a'); for (var i = 0; i < links.length; ++i) { var link = links[i]; if (link.className == 'category') { defaultValues.push(link.innerHTML); } } return defaultValues; } |