通用控件方法
下面介绍了每个控件(虚拟控件除外)共有的基础操作和属性方法。无论控件的具体类型如何,这些方法都适用。部分方法模拟用户操作,部分则是基于底层的Accessibility API完成操作。
| 方法名 | 描述 |
|---|---|
| click | 模拟鼠标点击控件,可指定点击的位置和使用的鼠标键。 |
| dblClick | 模拟鼠标双击控件,可指定双击的位置和使用的鼠标键。 |
| moveMouse | 移动鼠标到控件的指定位置,可指定速度。 |
| wheel | 滚动鼠标滚轮。 |
| exists | 检查控件是否存在,可指定最长等待时间。 |
| pressKeys | 输入组合按键或字符串。 |
| modelImage | 获取控件在模型中缓存的截图快照。 |
| modelProperties | 获取控件在模型中缓存的属性。 |
| property | 获取控件的指定属性值。 |
| waitProperty | 等待控件的指定属性达到某个值。 |
| checkProperty | 校验控件的属性是否符合预期值。 |
| highlight | 突出显示控件,用于调试和验证。 |
| takeScreenshot | 对控件截图,可指定文件路径。 |
| focus | 使控件获得焦点。 |
| firstChild | 获取控件的第一个子控件。 |
| lastChild | 获取控件的最后一个子控件。 |
| next | 获取控件的下一个兄弟控件。 |
| previous | 获取控件的上一个兄弟控件。 |
| parent | 获取控件的父控件。 |
| findControls | 根据条件查找控件。 |
| rect | 获取控件的位置和大小。 |
| name | 获取控件的名称。 |
| enabled | 控件是否可用。 |
| focused | 控件是否被聚焦/被选中。 |
| allProperties | 获取目标控件的所有运行时属性。 |
类型定义
这些方法都写在控件的基类上,可以点击leanpro.atk库查看,定义如下:
export interface IAtControl extends IAtContainer {
click(x?: number, y?: number, mousekey?: number): Promise<void>;
dblClick(x?: number, y?: number, mousekey?: number): Promise<void>;
exists(seconds?: number): Promise<boolean>;
moveMouse(x?: number, y?: number): Promise<void>;
wheel(value: number): Promise<void>;
pressKeys(keys: string, opt?: PressKeysOptions): Promise<void>;
rect(): Promise<Rect>;
highlight(milliseconds?: number);
takeScreenshot(filePath?: string): Promise<void | string>;
modelProperties(all?: boolean): {[x: string]: any};
modelImage(options?: {encoding: 'buffer' | 'base64'}): Promise<string | Buffer>; //base64 is the default
allProperties(): Promise<object>;
property(propertyName: string): Promise<string | number | boolean | Rect>;
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(propertyName: string, value: string | number | boolean, timeOutSeconds?: number): Promise<boolean>
firstChild(controlType?: AtControlType): Promise<IAtControl>;
lastChild(controlType?: AtControlType): Promise<IAtControl>;
next(controlType?: AtControlType): Promise<IAtControl>;
previous(controlType?: AtControlType): Promise<IAtControl>;
parent(): Promise<IAtControl>;
name(): Promise<string>;
enabled(): Promise<boolean>;
visible(): Promise<boolean>;
processId(): Promise<number>;
}class AtControl(AtContainer):
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 exists(seconds: Optional[int]=None) -> bool
def moveMouse(x: Optional[int]=None, y: Optional[int]=None) -> None
def wheel(value: int) -> None
def pressKeys(keys: str, cpm: Optional[int]=None) -> None
def rect() -> Rect
def highlight(milliseconds: Optional[int]=None) -> None
def takeScreenshot(filePath: Optional[str]=None) -> Union[str, None]
def focus() -> None
def modelProperties(all: Optional[bool]=None) -> { [x: string]: any; }
def modelImage(encoding: Optional[str]=None) -> Union[str, bytearray]
def allProperties() -> TypedDict
def property(propertyName: str) -> Union[str, int, bool, Rect]
def checkProperty(propertyName: str, expectedValue: Union[str, int, bool], optionsOrMessage: Optional[Union[str, TypedDict]]=None) -> None
def waitProperty(propertyName: str, value: Union[str, int, bool], timeOutSeconds: Optional[int]=None) -> bool
def firstChild(controlType: Optional[str]=None) -> AtControl
def lastChild(controlType: Optional[str]=None) -> AtControl
def next(controlType: Optional[str]=None) -> AtControl
def previous(controlType: Optional[str]=None) -> AtControl
def parent() -> AtControl
def name() -> str
def enabled() -> bool
def visible() -> bool
def processId() -> int操作方法
click(x, y, mouseKey)
模拟鼠标点击控件,可以通过传入参数修改点击的位置和使用的鼠标键。
参数:
- x:
number类型,点击位置相对控件左上角的水平像素点,0代表控件的水平中点位置,缺省值为0。 - y:
number类型,点击位置相对控件左上角的垂直像素点,0代表控件的垂直中点位置,缺省值为0。 - mouseKey:
MouseKey类型,操作的鼠标键,缺省为1,即鼠标左键。
返回值:
- 不返回任何值的异步方法。
使用示例
最简单的调用方式是不传入任何参数,直接点击控件的正中心:
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)dblClick(x, y, mouseKey)
模拟鼠标双击控件。与click()方法的调用方式一致。
参数:
- x:
number类型,双击位置相对控件左上角的水平像素点,缺省值为0。 - y:
number类型,双击位置相对控件左上角的垂直像素点,缺省值为0。 - mouseKey:
MouseKey类型,操作的鼠标键,缺省为1。
返回值:
- 不返回任何值的异步方法。
使用示例
双击控件的正中心:
await model.getButton("Button").dblClick();model.getButton("Button").dblClick()moveMouse(x, y, seconds)
移动鼠标光标到控件的指定位置。
参数:
- x:
number类型,移动位置相对控件左上角的水平像素点,缺省值为0。 - y:
number类型,移动位置相对控件左上角的垂直像素点,缺省值为0。 - seconds:
number类型,鼠标移动的持续时间,单位为秒。
返回值:
- 不返回任何值的异步方法。
使用示例
移动鼠标到控件的中心位置:
await model.getPane("Pane").moveMouse();model.getPane("Pane").moveMouse()如果需要移动鼠标到控件的指定位置并控制速度:
await model.getPane("Pane").moveMouse(500, 70, 5);model.getPane("Pane").moveMouse(500, 70, 5)wheel(value)
滚动鼠标滚轮,输入参数为滚轮滚动的刻度。
参数:
- value:
number类型,滚轮刻度。
返回值:
- 不返回任何值的异步方法。
使用示例
向上滚动鼠标滚轮一个刻度:
await model.getPane("Pane").wheel(1);model.getPane("Pane").wheel(1)exists(time)
这个方法用来判断一个控件是否存在。你可以指定一个最大等待时间,如果在指定的时间内找到了控件,就返回 true,否则返回 false。
参数:
- time:
number类型,等待控件出现的最大秒数。如果省略,默认等待0秒,也就是只检查一次。
返回值:
- 异步的返回控件是否存在,
true为存在,false为不存在。
使用示例
1.不指定等待时间
let exists = model.getButton("Button").exists();exists = model.getButton("Button").exists()这段代码会立即检查一次,如果找到了控件,exists 的值为 true,否则为 false。
2.指定等待时间
let bool = await model.getButton("Button").exists(10);
assert.strictEqual(bool, true);bool = model.getButton("Button").exists(10)
assert bool == True这段代码会等待最多 10 秒钟,如果在这 10 秒内找到了控件,bool 的值为 true,否则为 false。
pressKeys(keys, options?)
通过模拟键盘信号来实现字符串输入或组合键操作,因此不仅可以用于简单的文本输入,还可以进行复杂的键盘操作,如模拟登录、导航、剪切、粘贴等操作。
需要注意,字符串中的某些特殊字符(如
^+~%{}())会被解析为控制键(如 Shift、Ctrl),而非作为字符输入。具体的键指令请参考附录: 输入键对应表。如果希望输入纯文本,无视这些控制键符号,请使用{textOnly: true}选项,这样调用:pressKeys(str, {textOnly: true})。
参数:
- key:
string类型,要输入的按键、组合键或是字符串,最大支持 1024 个字符。 options:
PressKeysOptions | number(可选)
控制输入模式的可选参数,包含以下内容:- textOnly:
boolean类型,设为true时,将所有字符作为普通文本输入,忽略控制键指令。 - cpm:
number类型,即每分钟输入的字符数,用于控制输入速度。建议cpm值设置在 200 以上。由于不同系统及应用对输入速度的处理方式不同,实际的输入速度可能与设置值有所偏差。
如果直接传入数字作为
options,该值将被视为cpm参数。- textOnly:
返回值:
- 不返回任何值的异步方法。
使用示例
await model.getEdit("Edit").pressKeys("Hello, World!", { textOnly: true });model.getEdit("Edit").pressKeys("Hello, World!", { "textOnly": True })modelImage(options?: {encoding: 'buffer' | 'base64'})
获取控件在模型中缓存的截图快照。返回的图片可以是Buffer格式或base64字符串。
参数:
- options:
object类型,指定返回的图片格式:- encoding:
string类型,图片格式,值为'buffer'或'base64'。
- encoding:
返回值:
string类型或Buffer类型,根据指定的options.encoding选项异步的返回图片数据,默认为string类型。
使用示例
获取控件的缓存图像,并存储为base64字符串:
let img = await model.getPane("Pane").modelImage({ encoding: 'base64' });img = model.getPane("Pane").modelImage({ 'encoding': 'base64' })modelProperties(all?: boolean): object
获取控件在模型中缓存的所有属性。返回的属性键值对将包括属性名称和对应的值。
参数:
- all: (可选)
boolean类型,是否获取所有属性。默认为false,只获取识别属性。
返回值:
- 属性对象。
使用示例
let properties = await model.getButton("Button").modelProperties();properties = model.getButton("Button").modelProperties()property(propertyIds)
获取控件的指定属性值。你可以根据需要获取控件的文本、是否可见、位置等各种属性。
参数:
- propertyIds:
PropertyIds类型,要获取的属性名。
返回值:
- 异步的返回属性名对应的各种类型的属性值,包括
string、number、boolean、Rect类型等等,取决于propertyIds。
使用示例
获取控件的文本内容:
let text = await model.getButton("Button").property("text");text = model.getButton("Button").property("text")waitProperty(propertyIds, value, timeoutSeconds)
等待控件的指定属性变为某个特定的值。你可以使用它来判断控件的状态是否符合预期,比如等待一个按钮变为可用状态。
参数:
- propertyIds:
PropertyIds类型,要等待的属性名。 - value:
string类型,要等待的属性值。 - timeoutSeconds:
number类型,等待时间,单位为秒,缺省为10秒,-1将无限等待。
返回值:
boolean类型,等待结果,true是成功等到该值,反之则是超出等待时间。如果报错则代表没有匹配到该控件,有可能是该控件未出现,或者是对象名称有问题。
使用示例
等待控件的文本内容变为 "OK",最多等待 30 秒:
let isReady = await model.getButton("Button").waitProperty("text", "OK", 30);isReady = model.getButton("Button").waitProperty("text", "OK", 30)checkProperty(propertyName, expectedValue, optionsOrMessage)
校验控件的属性值是否符合预期。如果指定的属性值不匹配期望值,则会抛出错误。
你可以在录制过程中快捷生成基于此方法的属性检查脚本,详情请参考录制中添加属性检查点。
参数:
- 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"。
highlight(duration)
控件高亮,用于调试和验证,可以传入高亮框的持续时间(单位为毫秒)。
参数:
- duration:
number类型,突出显示的持续时间,单位为秒。
返回值:
- 不返回任何值的异步方法。
使用示例
高亮控件2秒:
await model.getButton("Button").highlight(2);model.getButton("Button").highlight(2)takeScreenshot(filePath)
对控件截图,可以传入路径来将截图保存到路径位置。
参数:
- filePath:
string类型,截图文件的保存路径,如"./images/screenshot1.png"。
返回值:
- 异步的返回截图的
base64字符串。
使用示例
takeScreenshot()方法返回的base64编码图片,可以直接作为图片插入到运行报告中,详细请参考报告附件。
focus()
使控件获得焦点。
使用示例
await model.getButton("Button").focus();model.getButton("Button").focus()属性方法
控件的属性方法都是异步的,这些方法会与目标控件通信,获取控件的实时属性,而不是模型对象中的识别属性。下面列出的属性方法适用于所有控件,但并非每个控件都支持所有属性。建议根据具体需求尝试类似的属性方法来获取所需的信息。
text()
控件的文本内容,通常是可编辑的内容,比如文本输入框Edit、多行输入框Document等控件拥有这个属性。如果返回值不符合预期,可以尝试name()或者value()属性方法。
返回值:
Promise<string>类型,异步返回控件的文本内容。
使用示例
获取文本编辑器中的文本,并进行断言校验
let actual = await model.getDocument("文本编辑器").text();
let expected = 'Hello World!'
assert.equal(actual, expected);actual_text = model.getDocument("文本编辑器").text()
expected_text = 'Hello World!'
assert actual_text == expected_textrect()
控件的描述矩形,返回Rect类型,包含控件的x、y``height和width信息,定义Rect 类型所示。
返回值:
Promise<Rect>类型,异步返回控件的矩形边界信息。
使用示例
获取Button控件的矩形信息(位置和尺寸)
let rect = await model.getButton("Button").rect();
console.log(`Button位置: (${rect.x}, ${rect.y}) 尺寸: ${rect.width}x${rect.height}`);rect = model.getButton("Button").rect()
print(f"Button位置: ({rect['x']}, {rect['y']}) 尺寸: {rect['width']}x{rect['height']}")name()
控件的名称,这个名称通常情况下与模型管理器中对象的识别属性Name相一致,因此几乎所有的控件都有这一属性的值。如果返回值不符合预期,可以尝试text()或者value()属性方法。
返回值:
Promise<string>类型,异步返回控件的名称。
使用示例
校验列表中第一项的名称是否正确:
let item = await model.getList("List").scrollTo(0);
assert.strictEqual(await item.name(), 'First Normal Item');item = model.getList("List").scrollTo(0)
assert await item.name() == 'First Normal Item'enabled()
控件是否可用。
返回值:
Promise<boolean>类型,异步返回控件是否启用的布尔值。
使用示例
检查Button控件是否启用,返回布尔值
let isEnabled = await model.getButton("Button").enabled();
console.log(`Button控件是否启用: ${isEnabled}`);is_enabled = model.getButton("Button").enabled()
print(f"Button控件是否启用: {is_enabled}")focused()
控件是否被聚焦/被选中,当控件被选中时会返回true,通常会用于验证控件是否被操作到。
返回值:
Promise<boolean>类型,异步返回控件是否为当前焦点的布尔值。
使用示例
判断文本框是否获得了焦点
let isFocused = await model.getEdit("TextBox").focused();
console.log(`文本框是否获得焦点: ${isFocused}`);is_focused = model.getEdit("TextBox").focused()
print(f"文本框是否获得焦点: {is_focused}")allProperties()
获取目标控件的所有运行时属性,以对象的形式返回。如果希望直接返回指定属性的值,参考property(propertyIds)方法。
返回值:
- 异步的返回目标模型对象的属性组成的对象
object。
使用示例
获取Button控件的所有属性,并输出到控制台
let properties = await model.getButton("Button").allProperties();
console.log(properties);properties = model.getButton("Button").allProperties()
print(properties)会获取按钮的所有属性,并打印:
{
"name": "新建项目",
"className": "push button",
Rect: {"x":1695,"y":373,"width":127,"height":51},
"states": "enabled,focusable,visible,showing",
"interfaces": [
"value",
"action"
],
"text": "",
"Value": {"value":"0","maximum":"1","minimum":"0"},
"Action": {
"actions": [
"单击"
]
}
}
其中,interfaces字段用于返回控件的模式信息,帮助用户确认控件支持的操作行为。
控件导航方法
CukeTest提供了一系列控件导航方法,帮助用户在应用中检索和操作界面元素。通过这些方法,您可以定位控件的父控件、子控件以及兄弟控件。它们适用于需要遍历控件树或精确定位特定控件的场景,如输入框定位、批量操作等。
这些导航方法是异步的,即它们会在应用中检索目标控件后再返回结果。与在模型管理器的树中直接导航不同,这些方法是在运行时进行的实际检索。
firstChild()
获取控件的第一个直系子控件。如果控件没有子控件或满足条件的子控件不可见,该方法将返回 null。如果希望获得某个控件下的所有控件,可以使用findControls方法。
返回值:
- 异步返回控件对象,具体类型取决于导航到的控件类型。如果没有找到子控件,则返回
null。
使用示例
获取指定控件的第一个子控件:
let firstChild = await model.getPane("Pane").firstChild();firstChild = model.getPane("Pane").firstChild()lastChild()
获取控件的最后一个直系子控件。
返回值:
- 异步返回控件对象,具体类型取决于导航到的控件类型。如果没有找到子控件,则返回
null。
使用示例
获取指定控件的最后一个子控件:
let lastChild = await model.getPane("Pane").lastChild();lastChild = model.getPane("Pane").lastChild()next()
获取控件的下一个兄弟控件,通常为相邻的右侧或下方节点,具体取决于容器的布局方向。如果没有下一个兄弟控件,则返回 null。
返回值:
- 异步返回控件对象,具体类型取决于导航到的控件类型。如果没有找到兄弟控件,则返回
null。
使用示例
获取指定控件的下一个兄弟控件:
let nextSibling = await model.getPane("Pane").next();nextSibling = model.getPane("Pane").next()previous()
获取控件的上一个兄弟控件,通常为相邻的左侧或上方节点,具体取决于容器的布局方向。如果没有上一个兄弟控件,则返回 null。
返回值:
- 异步返回控件对象,具体类型取决于导航到的控件类型。如果没有找到兄弟控件,则返回
null。
使用示例
获取指定控件的上一个兄弟控件:
let previousSibling = await model.getPane("Pane").previous();previousSibling = model.getPane("Pane").previous()parent()
用于获取控件的父控件。如果该控件为最顶层控件(没有父控件),则返回 null。
返回值:
- 异步返回控件对象,具体类型取决于导航到的控件类型。如果没有找到父控件,则返回
null。
使用示例
获取控件的父控件:
let parentControl = await model.getPane("Pane").parent();parentControl = model.getPane("Pane").parent()findControls(...conditions: ConditionFilter[])
根据条件查找控件。用于根据一系列条件筛选出满足这些条件的控件集合。它接受一个或多个ConditionFilter对象作为参数,这些对象定义了控件筛选的条件。
此方法适用于需要根据特定条件从应用中检索控件的场景。例如,在具有动态内容的界面上,您可能需要找到所有具有特定属性或状态的控件。findControls()方法可以根据您提供的条件动态地识别并返回这些控件。
详细用法参见获取对象API。
返回值:
- 异步返回一个控件对象数组,包含满足条件的所有控件。如果没有找到符合条件的控件,则返回空数组。
使用示例
根据条件查找控件,例如查找所有类型为 Button 且 className 为 Button 的控件:
let controls = await model.getPane("Pane").findControls({
"type": "Button",
"className": "Button"
});controls = model.getPane("Pane").findControls({
"type": "Button",
"className": "Button"
})