对象共有的方法和属性
下面介绍是每个控件(虚拟控件除外)都有的基础的操作和属性方法。这些方法不管被操作控件是何种控件(或者说都会被当作自定义控件Custom
来对待),部分方法是基于模拟用户操作,部分是基于系统提供的底层Accessibility API完成的操作。
类型定义文件
这些方法都写在控件的基类上,可以点击leanpro.win
库查看,定义如下:
export interface IWinControl extends IWinContainer {
//methods
click(x?: number, y?: number, mousekey?: MouseKey): Promise<void>;
dblClick(x?: number, y?: number, mousekey?: MouseKey): Promise<void>;
moveMouse(x?: number, y?: number, seconds?: number): Promise<void>
wheel(value: number): Promise<void>;
exists(time?: number): Promise<boolean>;
hScroll(value: number | ScrollAmount): Promise<void>;
vScroll(value: number | ScrollAmount): Promise<void>;
property(propertyIds: PropertyIds | string): Promise<string | boolean | number | Rect>;
checkImage(options?: CompareOptions): Promise<void>;
checkProperty(propertyName: string, expectedValue: string | number | boolean | RegExp, message: string): Promise<void>;
checkProperty(propertyName: string, expectedValue: string | number | boolean | RegExp, options: {message: string, operation: any}): Promise<void>;
waitProperty(propertyIds: PropertyIds, value: string, timeoutSeconds?: number/* default value 5 seconds */): Promise<boolean>;
drop(x?: number, y?: number, seconds?: number): Promise<void>;
drag(x?: number, y?: number): Promise<void>;
pressKeys(keys: string, opt?: PressKeysOptions | number): Promise<void>;
takeScreenshot(filePath?: string): Promise<void | string>;
highlight(duration?: number);
//properties
type(): Promise<string>;
text(): Promise<string>;
name(): Promise<string>;
hwnd(): Promise<number>;
x(): Promise<number>;
y(): Promise<number>;
height(): Promise<number>;
width(): Promise<number>;
enabled(): Promise<boolean>;
focused(): Promise<boolean>;
helpText(): Promise<string>;
labeledText(): Promise<string>;
value(): Promise<string | number>;
processId(): Promise<number>;
rect(): Promise<Rect>;
visible(): Promise<boolean>;
//navigation methods
firstChild(controlType?: ControlType): Promise<IWinControl>;
lastChild(controlType?: ControlType): Promise<IWinControl>;
next(controlType?: ControlType): Promise<IWinControl>;
previous(controlType?: ControlType): Promise<IWinControl>;
parent(): Promise<IWinControl>;
all(): Promise<IWinControl[]>;
findControls(...conditions: ConditionFilter[]): Promise<IWinControl[]>; //used to be getControls
modelImage(options?: {encoding: 'buffer' | 'base64'}): Promise<string | Buffer>; //base64 is the default
modelProperties(all?: boolean): {[x: string]: any};
allProperties(): Promise<object>;
doDefaultAction(): Promise<void>;
rawText(): Promise<string>;
scrollIntoView(): Promise<void>;
}
class WinControl(WinContainer):
def click(x: Optional[int]=None, y: Optional[int]=None, mousekey: Optional[int]=None) -> None
def dblClick(x: Optional[int]=None, y: Optional[int]=None, mousekey: Optional[int]=None) -> None
def moveMouse(x: Optional[int]=None, y: Optional[int]=None, seconds: Optional[int]=None) -> None
def wheel(value: int) -> None
def exists(time: Optional[int]=None) -> bool
def hScroll(value: int) -> None
def vScroll(value: int) -> None
def property(propertyds: str) -> Union[str, int, bool, Rect]
def waitProperty(propertyds: str, value: str, timeoutSeconds: Optional[int]=None) -> bool
def checkProperty(propertyName: str, expectedValue: Union[str, int, bool], optionsOrMessage: Optional[Union[str, TypedDict]]=None) -> "bool"
def checkImage(options: Optional[any]=None) -> None
def drop(x: Optional[int]=None, y: Optional[int]=None) -> None
def drag(x: Optional[int]=None, y: Optional[int]=None) -> None
def pressKeys(keys: str, opt: Optional[Union[int, PressKeysOptions]]=None) -> None
def takeScreenshot(filePath: Optional[str]=None) -> Union[str, None]
def highlight(duration: Optional[int]=None) -> None
def type() -> str
def text() -> str
def name() -> str
def hwnd() -> int
def x() -> int
def y() -> int
def height() -> int
def width() -> int
def enabled() -> bool
def focused() -> bool
def visible() -> bool
def helpText() -> str
def labeledText() -> str
def value() -> Union[str, int]
def processId() -> int
def rect() -> "Rect"
def firstChild(controlType: Optional[str]=None) -> "WinControl"
def lastChild(controlType: Optional[str]=None) -> "WinControl"
def next(controlType: Optional[str]=None) -> "WinControl"
def previous(controlType: Optional[str]=None) -> "WinControl"
def parent() -> "WinControl"
def findControls(*conditions: List[Union[str, Dict]]) -> List[WinControl]
def modelmage(encoding: Optional[str]=None) -> Union[str, bytearray]
def modelProperties(all: Optional[bool]=None) -> TypedDict
def all() -> List[WinControl]
def allProperties() -> TypedDict
def doDefaultAction() -> None
def rawText() -> str
def scrollIntoView() -> None
可能用到的类定义
以下是调用共有API时可能会使用到的一些类型定义。
控件属性名枚举类: PropertyIds
export enum PropertyIds {
automationId,
name,
text,
url,
title,
handle,
x,
y,
height,
width,
enabled,
focused,
helpText,
value,
labeledText,
processId,
rect,
...
}
除了以上列出来的属性外,各个控件还各自维护了一些特有的属性名,可以参考allProperties()方法的返回结果对象中的字段。
控件类型枚举类: ControlType
CukeTest中可以识别到的所有控件类型,可以用于findControls()
方法中指定控件类型,或者调用控件的type()
方法返回结果的类型也都在这个枚举类中。
enum ControlType {
Button,
Calendar,
CheckBox,
ComboBox,
Custom,
DataGrid,
DataItem,
Document,
Edit,
Group,
Generic,
Header,
HeaderItem,
Hyperlink,
Image,
List,
ListItem,
MenuItem,
MenuBar,
Menu,
Pane,
RadioButton,
ScrollBar,
Slider,
Spinner,
Tab,
TabItem,
Table,
Text,
Thumb,
ToolBar,
Tree,
TreeItem,
Window,
//virtual types
TableRow,
TreeCell,
}
控件筛选条件Criteria
类
CukeTest使用Criteria
对象作为条件对当前环境中的控件进行筛选,来获取目标控件并操作。详见Criteria类。
进程启动选项类SpawnOptions
用于配置进程启动选项的类,支持的属性有,具体可以参考child_processs.spawn
:
- cwd:
string
类型或URL
类型,子进程的工作目录,默认值为运行的项目目录,即process.cwd()
的值。 - env:
Object
类型,环境变量的键值对。默认值:process.env
。 - argv0:
string
类型,显式设置发送给子进程的argv[0]
的值。如果未指定,这将设置为命令。 - detached:
boolean
类型,准备子进程独立于其父进程运行。具体行为取决于平台,请参阅 options.detached)。 - uid:
number
类型,设置进程的用户身份(参考 setuid(2))。 - gid:
number
类型,设置进程的组标识(参考 setgid(2))。 - serialization:
string
类型,指定用于在进程之间发送消息的序列化类型。可能的值是“json”和“高级”。有关详细信息,请参阅高级序列化。默认值:json
。 - shell:
boolean
类型或string
类型如果为true,则会启动终端来运行命令。在Unix上使用 '/bin/sh',在Windows
上使用process.env.ComSpec
。可以传入string
类型来指定终端的路径。默认值:false
(无终端)。 - windowsVerbatimArguments:
boolean
类型在Windows上不会引用或转义参数。在Unix上被忽略。当指定shell
并且是CMD
时,它会自动设置为 true。默认值:false
。 - windowsHide:
boolean
类型隐藏通常在Windows 系统上创建的子进程控制台窗口。默认值:false
。 - timeout:
number
类型,允许进程运行的最长时间,以毫秒为单位。默认值:未定义。 - killSignal:
string
类型或int
类型,生成的进程将被超时或中止信号杀死时使用的信号值。默认值:“SIGTERM”。
操作方法定义
click(x, y, mousekey): Promise<void>
鼠标点击控件,可以通过传入参数修改点击的相对位置(偏移量)和使用的鼠标键。
- x:
number
类型,点击位置相对控件左上角的水平像素点,0
代表控件的水平中点位置,缺省值为0
; - y:
number
类型,点击位置相对控件左上角的垂直像素点,0
代表控件的垂直中点位置,缺省值为0
; - mouseKey:
MouseKey
类型,操作的鼠标键,缺省为1
,即鼠标左键。
最简单的调用方式就是不使用任何参数调用,效果是鼠标左键点击目标控件的正中心。
这里假设目标控件为按钮控件
Button
。
await model.getButton("Button").click()
model.getButton("Button").click()
如果需要点击控件的指定坐标位置,可以传入相对控件左上角的水平像素值(x
)和垂直像素值(y
)
await model.getButton("Button").click(590, 10)
model.getButton("Button").click(590, 10)
需要注意的是,
click(0, 0)
并不会点击控件左上角原点,而是点击控件正中心;如果期望点击左上角,可以用click(1, 1)
代替。
如果需要右击控件,则需要传入第三个参数并设置为2:
await model.getButton("Button").click(590, 10, 2)
model.getButton("Button").click(590, 10, 2)
await model.getButton("Button").click(0, 0, 2)
await model.getButton("Button").click(null, null, 2)
model.getButton("Button").click(0, 0, 2)
model.getButton("Button").click(None, None, 2)
dblClick(x, y, mousekey): Promise<void>
鼠标双击控件,与click()
方法的调用方式一致,通过传入参数修改点击的相对位置(偏移量)和使用的鼠标键。
- x:
number
类型,点击位置相对控件左上角的水平像素点,0
代表控件的水平中点位置,缺省值为0
; - y:
number
类型,点击位置相对控件左上角的垂直像素点,0
代表控件的垂直中点位置,缺省值为0
; - mouseKey:
MouseKey
类型,操作的鼠标键,缺省为1
,即鼠标左键。
使用方法可参考上面的click()
moveMouse(x, y): Promise<void>
移动鼠标光标到控件的相对位置,缺省移动到控件中心。
- x:
number
类型,点击位置相对控件左上角的水平像素点,0
代表控件的水平中点位置,缺省值为0
; - y:
number
类型,点击位置相对控件左上角的垂直像素点,0
代表控件的垂直中点位置,缺省值为0
;
使用 不传入任何参数调用会默认将鼠标移动到控件中心位置。
这里假设目标控件为按钮控件
Pane
。
await model.getPane("Pane").moveMouse()
model.getPane("Pane").moveMouse()
x
)和垂直像素值(y
)
await model.getPane("Pane").moveMouse(500, 70)
model.getPane("Pane").moveMouse(500, 70)
同样,
moveMouse(0, 0)
鼠标并不会移动到控件左上角原点,而是移动到控件正中心;如果期望是左上角,可以用moveMouse(1, 1)
代替。
如果需要移动鼠标的同时控制鼠标移动的速度,第三个参数可以传入持续时间多少秒。
await model.getPane("Pane").moveMouse(500, 70, 5)
model.getPane("Pane").moveMouse(500, 70, 5)
wheel(value): Promise<void>
滚动鼠标滚轮,输入参数的单位为滚轮滚动的刻度。最多翻一页,如果需要滚动多页,请循环调用。
- value:
number
类型,单位为一个滚轮刻度。
exists(time): Promise<boolean>
检查控件是否存在,输入参数为检查等待的最长时间(超时时间)。缺省调用只会检查一次而不会重试与等待。
- time:
number
类型,超时时间,单位为秒,当为0时不会重试和等待,缺省参数为0
。 - 返回值: 异步的返回控件是否存在,
true
为存在,false
为不存在。
使用 不传入参数缺省重试为0秒,即只检查1次。
await model.getApplication("dirview").exists();
model.getApplication("dirview").exists()
传入最长等待时间,如果在设置的最长等待时间内检测到控件存在则直接返回true
控件匹配结果出错或者是超过传入的最长等待时间则返回false
let bool = await model.getApplication("dirview").exists(10);
assert.strictEqual(bool, true);
bool = model.getApplication("dirview").exists(10)
assert bool == True
hScroll(value): Promise<void>
在控件上进行水平滚动,即Horizontal Scroll,参数为滚动的百分比。
- value:
number
类型,为滚动的百分比,0
为滚动到顶部,100
为滚动到底部。
vScroll(value): Promise<void>
在控件上进行垂直滚动,即Vertical Scroll,参数为滚动的百分比。
- value:
number
类型,为滚动的百分比,0
为滚动到顶部,100
为滚动到底部。
property(propertyIds): Promise<string | boolean | number | Rect>
这个方法比较特殊,虽然属于操作方法,但是却是获取指定属性的方法,传入属性名,返回对应的属性值。比如对于某个控件,调用方法.property("rect")
其实就等同于直接调用属性方法.rect()
,两个操作返回的值始终是相同的。
同时也支持直接使用allProperties()
方法中的字段,详见下面的代码示例。
如果传入了一个不存在的属性名,则会返回
undefined
,而不会出错。
- propertyIds:
propertyIds
类型,控件属性的名称。 - 返回值: 异步的返回属性名对应的各种类型的属性值,包括
string
、number
、boolean
、Rect
类型等等,取决于propertyIds
。
let properties = await model.getButton("Button").allProperties();
console.log(properties['objectName']); //只获取其中的一个属性,如objectName
properties = model.getButton("Button").allProperties()
print(properties['objectName']); #只获取其中的一个属性,如objectName
可以直接调用property()
获得:
let objectName = await model.getButton("Button").property('objectName');
objectName = model.getButton("Button").property('objectName')
waitProperty(propertyIds, value, timeoutSeconds): Promise<boolean>
与上面的property()
方法类似,但是会等待直到属性出现某值,返回值表示是否成功等到该值出现。
- propertyIds:
PropertyIds
类型,控件属性的名称。 - value:
string
类型,期望的值。 - timeoutSeconds:
number
类型,超时时间,单位为秒。等待超时秒设置,缺省为10秒,-1将无限等待。 - 返回值:
boolean
类型,等待结果,true
是成功等到该值,反之则是超出等待时间。如果报错则代表没有匹配到该控件,有可能是该控件未出现,或者是对象名称有问题。
下面的样例代码等待按钮由禁用状态变为可点击,然后点击它:
await model.getButton("下一步").waitProperty("enabled", true);
await model.getButton("下一步").click();
model.getButton("下一步").waitProperty("enabled", true)
model.getButton("下一步").click()
checkImage(options?: CompareOptions): Promise<void>
用于验证控件的当前图像与预先定义或录制的参考图像是否匹配。如果存在差异,测试会抛出错误并显示图像间的差异。这个方法可用于自动化测试中的视觉校验,确保 UI 控件的视觉展现符合预期。
- options (可选): 用于配置图像比较的选项。这些选项与
Image.imageEqual
方法的参数相同,包含以下属性:- colorTolerance:
number
类型,定义了在颜色匹配时允许的最大差异容忍度。默认值为 0.1。 - pixelPercentTolerance:
number
类型,定义了允许的最大像素百分比差异容忍度。默认值为 1,表示最多允许 1% 的像素差异。 - pixelNumberTolerance:
number
类型,定义了允许的像素数量差异容忍度。如果设置为0,则无差异容忍。 - ignoreExtraPart:
boolean
类型,用于指定是否忽略图像中的额外部分。默认为 false。 - auto:
boolean
类型,如果设置为true,则根据图像特征自动识别两幅图片,并将它们缩放到一致的比例进行比较,默认适应到较小尺寸那张图片的比例。
- colorTolerance:
- 返回值:不返回任何值的异步方法。
使用示例
假设我们有一个控件 Button,我们可以使用 checkImage()
来验证其当前显示的图像是否与预期相符。例如:
await Button.checkImage({
colorTolerance: 0.05,
pixelPercentTolerance: 0.5
});
Button.checkImage({
"colorTolerance": 0.05,
"pixelPercentTolerance": 0.5
})
在这个例子中,checkImage
方法将会验证 Button 控件的图像与预期的参考图像在颜色容忍度为 0.05 和像素百分比差异容忍度为 0.5% 的条件下是否相匹配。如果图像存在超出这些指定容忍度的差异,测试将会抛出错误。
checkProperty(propertyName, expectedValue, optionsOrMessage): Promise<void>
校验控件的属性值是否符合预期。如果指定的属性值不匹配期望值,则会抛出错误。
你可以在录制过程中快捷生成基于此方法的属性检查脚本,详情请参考录制中添加属性检查点。
参数:
- propertyName:
string
类型,需要检查的属性名称。支持的属性名包括enabled
、text
、value
等,以及所有由allProperties()
方法返回的字段。 - expectedValue:
string | number | boolean | RegExp
类型,期望的属性值。当控件的属性值与期望值匹配时,测试将通过;否则会抛出错误。 - optionsOrMessage:
string | object
类型,可选参数。如果是字符串,它将被用作自定义错误信息;如果是对象,则可包含以下字段:- message:
string
类型,自定义的错误信息。 - operation:
any
类型,指定用于比较控件属性与期望值的运算符。默认值为equal
,即验证属性值是否等于期望值。
- message:
返回值:
- 不返回任何值的异步方法。
使用示例
有关在
checkProperty()
中使用正则表达式的示例,请参考通过正则表达式检查。
验证文本框控件的 text
属性是否为 "Hello World":
await model.getEdit("textEdit").checkProperty('text', 'Hello World', 'Text does not match expected value');
model.getEdit("textEdit").checkProperty('text', 'Hello World', 'Text does not match expected value')
如果文本不符合预期,将抛出一个错误,错误信息为 "Text does not match expected value"。
drag(x, y): Promise<void>
在控件位置按下鼠标左键,也就是拖拽操作的第一步,并等待松开鼠标的指令。传入的(x, y)
为点击相对控件的坐标,当x
和y
同时为0或缺省时点击控件中心。
- x: (可选)
number
类型,相对于控件水平中心的偏移像素,默认值为控件水平中心。 - y: (可选)
number
类型,相对于控件垂直中心的偏移像素,默认值为控件垂直中心。 - mouseKey:(可选)
number
类型,拖拽时使用的鼠标键,1
表示左键,2
表示右键。默认值为左键(1
)。 - 返回值: 不返回任何值的异步方法。
可以参考拖拽控件的方式选择
drop(x, y, seconds): Promise<void>
在控件位置松开鼠标左键,也就是拖拽操作的第二步。传入的(x, y)
为点击相对控件的坐标,当x
和y
同时为0或缺省时点击控件中心。可以在A
控件上执行drag()
方法,在B
控件上执行drop()
方法,实现将A
控件拖拽到B
控件上的效果,具体文档可以查看拖拽控件的方法选择。
- x: (可选)
number
类型,相对于控件水平中心的偏移像素,左为负值,右为正值。默认值为0
。 - y: (可选)
number
类型, 相对于控件垂直中心的偏移像素,上为负值,下为正值。默认值为0
。 - options:(可选)
object
类型,自定义拖拽行为的配置对象。支持的选项包括:- duration:
number
类型,鼠标移动到目标位置的持续时间,单位为秒。默认值为1
,即1秒; - mouseKeys:
number
类型,在拖拽操作中使用的鼠标按键。1
表示左键,2
表示右键。默认值为左键(1
)。
- duration:
- 返回值: 不返回任何值的异步方法。
可以参考拖拽控件的方式选择
pressKeys(keys, options?): Promise<void>
输入按键或字符串,输入前会聚焦目标控件。传入字符串时,字符串中的一些特殊字符(^+~%{}()
)会被当作控制键(Shift
键、CTRL
键等)来执行,而不会输入相应的符号,具体可以参考附录: 输入键对应表。如果希望输入纯文本,无视这些控制键符号,则可以使用{textOnly: true}
选项,这样调用:pressKeys(str, {textOnly: true})
。
- keys:
string
类型,要输入的按键、组合键或是字符串,最大支持1024个字符。 - options: (可选)控制输入模式的一些可选参数。
- textOnly: 仅输入字符串,并将控制字符也当作文本进行输入。效果等同于调用
Keyboard.typeString()
。 - cpm: 即每分钟输入字符数,用于控制文本输入速度。自动化操作时建议
cpm
值设置在200以上。由于方法的内部实现,以及各个系统、应用对文本输入的处理不相同,实际输入速度不一定能达到设置的cpm
。 当options为数字时相当于cpm参数。
- textOnly: 仅输入字符串,并将控制字符也当作文本进行输入。效果等同于调用
- 返回值: 不返回任何值的异步方法。 更多相关说明或样例,请参照模拟按键输入pressKeys方法。
takeScreenshot(filePath): Promise<string>
控件截图,可以传入路径来将截图保存到路径位置。
- filePath: (可选)
string
类型,截图的保存路径和文件名,如"./images/screenshot1.png"
。 - 返回值: 异步的返回截图的
base64
字符串。
使用示例
takeScreenshot()
方法返回的base64
编码图片,可以直接作为图片插入到运行报告中,详细请参考报告附件。
highlight(miliseconds?: number): Promise<void>
控件高亮,可以传入高亮框的持续时间(单位为毫秒)。
- miliseconds:
number
类型,高亮框的持续时间,单位为毫秒(ms)。 - 返回值:不返回任何值的异步方法。
doDefaultAction(): Promise<void>
执行控件内部定义的默认操作,比如复选框的默认操作为切换、输入框的默认操作是编辑等。这些默认操作的定义,可以通过调用控件的allProperties()方法,查看结果中的LegacyIAccessible.defaultAction
属性。
- 返回值:不返回任何值的异步方法。
scrollIntoView(): Promise<void>
滚动到控件的可视位置。
- 返回值: 不返回任何值的异步方法。
属性方法定义
需要注意的控件的属性方法都是异步的,在调用后CukeTest会与目标控件通信,获取控件当前的属性,即实时属性,而不是模型对象中的识别属性。下面列出的属性所有控件都支持,但不一定都有值,可以根据建议尝试类似的属性方法来获取目标属性。
type(): Promise<string>
控件的类型,可能的值如控件类型枚举类所示。
text(): Promise<string>
控件的文本内容,通常是可编辑的内容,比如文本输入框Edit
、多行输入框Document
等控件拥有这个属性。如果返回值不符合预期,可以尝试name()
或者value()
属性方法。
校验是否符合预期输入文本
let actual = await model.getDocument("文本编辑器").text();
let expected = 'Hello World!'
assert.equal(actual, expected);
rawText(): Promise<string>
返回控件的内部文本信息。需要插件支持,从系统底层获取目标控件中渲染的文本信息。当name()
、value()
和text()
方法都返回空结果时,可以尝试用rawText()
方法获取文本。
此方法仅在通过“启动Windows应用”菜单启动的被测应用上能取到值,因为通过这种方式启动的被测应用会加载相应的插件。
name(): Promise<string>
控件的名称,这个名称通常情况下与模型管理器中对象的识别属性Name
相一致,因此几乎所有的控件都有这一属性的值。如果返回值不符合预期,可以尝试text()
或者value()
属性方法。
校验获取子元素是否符合预期
let item = await model.getList("List").scrollTo(0);
assert.strictEqual(await item.name(), 'First Normal Item');
item = await model.getList("List").scrollTo(0)
assert await item.name() == 'First Normal Item'
hwnd(): Promise<number>
控件所属的窗口句柄(Handle of WiNDow)。
height(): Promise<number>
控件的高度,返回值为number
类型,单位为像素点。
width(): Promise<number>
控件的宽度,返回值为number
类型,单位为像素点。
enabled(): Promise<boolean>
控件是否可用。
focused(): Promise<boolean>
控件是否被聚焦/被选中,当控件被选中时会返回true
,通常会用于验证控件是否被操作到。
visible(): Promise<boolean>
控件是否可见且未被遮挡,当控件被选中时会返回true
,通常会用于验证控件是否可以被操作。比如在以下场景中,此方法会返回false
:
- 控件被其它控件或窗口/对话框遮住;
- 控件在可视区域外;
- 控件在桌面外;
如果控件不存在,此方法会抛找不到对象
的错误。如果希望不抛错,可以结合exists()
方法来使用,如:
if await control.exists() && await control.visible(){
// 执行操作
}
if control.exists() and control.visible():
# 执行操作
helpText(): Promise<string>
控件的帮助文本,即鼠标悬停在控件上时出现的浮动提示消息的内容,通常在WPF、WinForm框架的应用中会遇到。
value(): Promise<string | number>
控件的值,比如滑动条控件Slider
、滚动条控件ScrollBar
会返回对应的数值。如果希望取得控件显示的名称或者提示文字,可以尝试text()
或者name()
属性方法。
校验控件值
let actual = await modelQt.getEdit("Edit").value();
let expected = 'Hello World!';
assert.equal(actual, expected);
processId(): Promise<number>
控件所属应用的进程号(Process Id)。
rect(): Promise<Rect>
控件的描述矩形,返回Rect
类型,包含控件的x
、y``height
和width
信息,定义Rect
类型所示。
allProperties(): Promise<object>
获取目标控件的所有运行时属性,以对象的形式返回。如果希望直接返回指定属性的值,参考property(propertyIds)
方法。
- 返回值: 异步的返回目标模型对象的属性组成的对象
object
。 例如:
let properties = await model.getButton("Button").allProperties();
console.log(properties);
console.log('objectName=' + properties['objectName']); //只获取其中的一个属性,如objectName
properties = model.getButton("Button").allProperties()
print(properties)
print('objectName=' + properties['objectName']); #只获取其中的一个属性,如objectName
会获取按钮的所有属性,并打印:
{
"name": "Normal",
"className": "CheckBox",
"automationId": "",
"accessKey": "",
"enabled": true,
"hasKeyboardFocus": false,
...
"interfaces": [
"Toggle",
"LegacyIAccessible"
],
"Toggle.toggleState": 0,
"LegacyIAccessible.defaultAction": "选定",
"LegacyIAccessible.description": "",
"LegacyIAccessible.help": "",
"LegacyIAccessible.keyboardShortcut": "",
"LegacyIAccessible.name": "Normal",
"LegacyIAccessible.role": 44,
"LegacyIAccessible.state": 1048576,
"LegacyIAccessible.value": ""
}
其中,interfaces
字段用于返回控件的模式信息(UIA Pattern Names),帮助用户确认控件支持的操作行为。LegacyIAccessible.defaultAction
是这个控件的缺省操作,如果不为空,那么用户可以通过调用doDefaultAction来执行这个缺省操作。
modelImage(options?: {encoding: 'buffer' | 'base64'}): Promise<string|Buffer>
控件的在模型中缓存的截图快照。默认返回快照的base64
字符串。
- options:(可选)选项:
- encoding:
"buffer"
或"base64"
字符串参数,控制图片返回的编码,默认为"base64"
。
- encoding:
- 返回值:
string
类型或Buffer
类型,根据指定的options.encoding
选项异步的返回图片数据,默认为string
类型。
modelProperties(all?: boolean): object
控件在模型中缓存的属性。默认仅返回识别属性,传入true
参数同时获取不用于识别的其它属性。
- all: (可选)
boolean
类型,是否获取所有属性。默认为false
,只获取识别属性。 - 返回值:属性对象。
使用示例
let modelProperties = await model.getWindow("Standard_Dialogs").modelProperties()
console.log(modelProperties)
assert.equal('Window',modelProperties.type)
modelProperties = model.getWindow("Standard_Dialogs").modelProperties()
print(modelProperties)
assert modelProperties['type'] == 'Window'
{ type: 'Window', className: 'Dialog', text: 'Standard Dialogs' }
高级方法:控件导航(Navigation)
CukeTest提供了一系列的控件导航方法,使得用户可以使用导航方法检索到目标控件的父控件、子控件以及兄弟控件。通过导航方法可以借助一个锚点控件索引到整棵控件树中所有的控件,常用于输入框定位、控件遍历等场景。
导航方法都是异步方法,也就是需要一定时间在应用里面检索到被导航的控件并返回,并不是直接在模型管理器的树中进行导航,这点需要区分不要混淆。
有关控件导航的使用,可以参考附录H:CukeTest自带样例中的"文件浏览器遍历"。
firstChild(controlType?: string): Promise<IWinControl>
获取控件在应用中的第一个子控件,可以通过传入参数controlType
指定子控件类型,可以实现筛选的效果,即获取应用中的第一个controlType
类型的子控件,controlType
为字符串,可选值可以参考ControlType。如果没有任何满足条件的子控件则返回null
。
同时,child
仅代表直系的子控件,不会检索到孙控件,如果没有在子控件中检索到满足条件的控件,会直接返回null
而不是继续在孙控件中搜索。如果仍希望获得某个控件下的所有控件,可以使用findControls方法。
注意,如果某些控件是不可见或还未加载的,那么是不会被计入的,准确来说,
firstChild()
方法只是拿到可以拿到的子对象中的第一个,下面的lastChild()
方法同样。
- controlType: (可选)字符串类型,可选值可以参考ControlType。
- 返回值: 异步的任意控件类型,具体类型取决于导航到的控件类型。没有导航到任何控件时返回
null
。
lastChild(controlType?: string): Promise<IWinControl>
获取控件在应用中的最后一个子控件,可以通过传入参数controlType
指定子控件类型,可以实现筛选的效果,即获取应用中的最后一个controlType
类型的子控件,controlType
为字符串,可选值可以参考ControlType。如果没有任何满足条件的子控件则返回null
。
注意,如果某些控件是不可见或还未加载的,那么是不会被计入的,准确来说,
firstChild()
方法只是拿到可以拿到的子对象中的第一个,下面的lastChild()
方法同样。
- controlType: (可选)字符串类型,可选值可以参考ControlType。
- 返回值: 异步的任意控件类型,具体类型取决于导航到的控件类型。没有导航到任何控件时返回
null
。
next(controlType?: string): Promise<IWinControl>
获取控件的在应用的下一个兄弟控件,通常为相邻的右侧/下方节点,取决于容器的布局方向。可以通过传入参数controlType
指定兄弟控件类型,可以实现筛选的效果,即获取应用中的下一个controlType
类型的兄弟控件,controlType
为字符串,可选值可以参考ControlType。如果没有任何满足条件的兄弟控件则返回null
,比如当控件作为父控件的lastChild
时会返回null
。
- controlType: (可选)字符串类型,可选值可以参考ControlType。
- 返回值: 异步的任意控件类型,具体类型取决于导航到的控件类型。没有导航到任何控件时返回
null
。
previous(controlType?: string): Promise<IWinControl>
与next()
方法相反,获取控件的在应用的上一个兄弟控件,通常为相邻的左侧/上方节点,取决于容器的布局方向。可以通过传入参数controlType
指定兄弟控件类型,可以实现筛选的效果,即获取应用中的下一个controlType
类型的兄弟控件,controlType
为字符串,可选值可以参考ControlType。如果没有任何满足条件的兄弟控件则返回null
,比如当控件作为父控件的firstChild
时会返回null
。
- controlType: (可选)字符串类型,可选值可以参考ControlType。
- 返回值: 异步的任意控件类型,具体类型取决于导航到的控件类型。没有导航到任何控件时返回
null
。
parent(): Promise<IWinControl>
与firstChild()
和lastChild()
方法相反,获取控件的父控件,如果控件为最顶层控件则返回null
。
- 返回值: 异步的任意控件类型,具体类型取决于导航到的控件类型。没有导航到任何控件时返回
null
。
all(): Promise<IWinControl[]>
all()
方法返回与当前控件的“标识属性”相匹配的所有同级控件数组,无需指定任何筛选条件。这个方法适用于在测试中实现对同一层级多个控件的批量操作,如表格、列表或一组按钮。详细用法参见获取对象API。
- 返回值: 异步的控件数组,包含所有子控件对象。如果当前控件下没有任何子控件,则返回空数组。
findControls(...conditions: ConditionFilter[]): Promise<IWinControl[]>
findControls()
方法是一个强大的查询工具,用于根据一系列条件筛选出满足这些条件的控件集合。它接受一个或多个ConditionFilter
对象作为参数,这些对象定义了控件筛选的条件。
此方法适用于需要根据特定条件从应用中检索控件的场景。例如,在具有动态内容的界面上,您可能需要找到所有具有特定属性或状态的控件。findControls()
方法可以根据您提供的条件动态地识别并返回这些控件。详细用法参见获取对象API。
- 返回值: 异步返回一个
IWinControl
数组,该数组包含满足提供的筛选条件的所有控件。如果没有找到符合条件的控件,则返回空数组。
控件导航应用场景
例1: 输入框定位
在部分应用中存在需要填写的表单,即:
表单:
[标签1]: [输入框1]
[标签2]: [输入框2]
[标签3]: [输入框3]
[标签4]: [输入框4]
对于一些应用的输入框可能没有足够的属性用于识别,而所有的标签和输入框又属于同一个容器(表单)中没有隔离,那么CukeTest可能会将输入框1-4当作相同的输入框,这个时候就可以通过添加标签对象,接着使用导航方法获得其右侧的输入框控件,就可以得到目标输入框:
let labels = ["标签1", "标签2", "标签3", "标签4"]
for(let label of labels){
let input = await model.getText(label).next();
await input.set("需要输入的值");
}
labels = ["标签1", "标签2", "标签3", "标签4"]
for label in labels:
input = model.getText(label).next()
input.set("需要输入的值")
例2: 控件遍历
可以通过递归调用导航方法的方式,遍历到整个应用中的所有控件。