模拟桌面操作API
在CukeTest的leanpro.common
库中提供了一套模拟鼠标、键盘和屏幕操作的对象:
由于操作是通过模拟实现的,因此可以全平台上使用。
用途
CukeTest中,有针对控件直接操作的对象识别高级API,有些时候,仍旧需要通过键盘和鼠标的一些组合操作完成自动化。因此CukeTest提供了一套模拟鼠标和键盘操作的对象:Mouse
和Keyboard
。它们能处理鼠标移动的目标位置没有控件,或对象操作API完成不了的功能。例如某些应用中的菜单是隐藏在屏幕边缘的,需要鼠标移至屏幕边缘才会展开,这个时候就需要使用直接的鼠标和键盘操作。
使得操作鼠标和键盘的自动化脚本可以写作:
const { Keyboard, Mouse } = require('leanpro.common');
Mouse.move(1920,1080);
Keyboard.keyDown("control");
Keyboard.keyTap("a");
Keyboard.keyUp("control");
from leanproAuto import Keyboard, Mouse
Mouse.move(1920,1080)
Keyboard.keyDown("control")
Keyboard.keyTap("a")
Keyboard.keyUp("control")
另外,由于Mouse
的移动、点击操作都建立在屏幕坐标系上,因此CukeTest另外提供了操作屏幕的对象Screen
,不仅可以获取屏幕属性(分辨率等),还可以进行截屏操作。
Screen.capture();
Screen.capture()
注意,这些方法都是同步方法,不需要使用
await
。
鼠标自动化对象: Mouse
用于实现鼠标移动,以及各个鼠标按钮的点击、按下/释放的自动化对象。比如某些应用中的界面是隐藏在屏幕边缘的,需要鼠标移至屏幕边缘才会出现,那么这种场景就不好用控件操作来实现了。而Mouse
对象正是为了解决这类问题而推出的。
类型文件定义
export class Mouse {
static move(x: number, y: number): void;
static moveSmooth(x: number, y: number, seconds?: number): void;
static drag(x: number, y: number, seconds?: number): void;
static setDelay(delay: number): void;
static position(): Point;
static click(button: MouseKey): void;
static doubleClick(button: MouseKey): void;
static keyDown(button: MouseKey): void;
static keyUp(button: MouseKey): void;
static wheel(vertical: number, horizontal: number): void;
}
enum MouseKey {
LButton = 1,
RButton = 2,
MButton = 4,
Ctrl = 8,
Shift = 16,
Alt = 32
}
interface Point {
x: number,
y: number
}
class Mouse():
def move(x: int, y: int) -> None
def moveSmooth(x: int, y: int, seconds: Optional[int]=None) -> None
def setDelay(delay: int) -> None
def drag(x: int, y: int, seconds: Optional[int]=None) -> None
def position() -> TypedDict
def click(button: Optional[int]=None) -> None
def doubleClick(button: Optional[int]=None) -> None
def keyDown(button: Optional[int]=None) -> None
def keyUp(button: Optional[int]=None) -> None
def wheel(vertical: int, horizontal: Optional[int]=None) -> None
class Point():
x: int
y: int
API介绍
move(x, y): void
鼠标移动到目标位置,移动前会释放鼠标按键。
- x:
number
类型,桌面坐标的水平像素; - y:
number
类型,桌面坐标的垂直像素; - 返回值: 不返回任何值的同步方法。
moveSmooth(x: number, y: number, seconds?: number): void
平滑移动鼠标到目标位置,移动行为更接近人工操作.
- x:
number
类型,桌面坐标的水平像素; - y:
number
类型,桌面坐标的垂直像素; - seconds: (可选)
number
类型,动作完成的耗时,值越小动作越快。 - 返回值: 不返回任何值的同步方法。
drag(x: number, y: number, seconds?: number): void
鼠标移动到目标位置,配合keyDown()
与keyUp()
完成拖拽操作。
- x:
number
类型,桌面坐标的水平像素; - y:
number
类型,桌面坐标的垂直像素; - seconds: (可选)
number
类型,动作完成的耗时,值越小动作越快。 - 返回值: 不返回任何值的同步方法。
setDelay(delay: number): void
所有的鼠标操作之间的都有10ms的等待时间,也可以使用此方法修改等待时间,单位为毫秒。
- delay:
number
类型,间隔时间,单位为毫秒。 - 返回值: 不返回任何值的同步方法。
position(): Point
获取鼠标位置。
- 返回值:
Point
类型。形如{x:100, y:100}
click(button: MouseKey): void
完成一次鼠标点击。
- button:
MouseKey
类型,可以查看类型文件定义,为枚举型,传入MouseKey.LButton
和1
效果一样。 - 返回值: 不返回任何值的同步方法。
使用
单击鼠标左键操作传入数字1
。
await Mouse.click(1);
Mouse.click(1)
2
。
await Mouse.click(2);
Mouse.click(2)
4
。
await Mouse.click(4);
Mouse.click(4)
doubleClick(button: MouseKey): void
完成一次鼠标双击。
- button:
MouseKey
类型,可以查看类型文件定义,为枚举型,传入MouseKey.LButton
和1
效果一样。 - 返回值: 不返回任何值的同步方法。
使用方法可参考上面的click()
keyDown(button: MouseKey): void
按下鼠标按键,通常用于实现拖拽操作。
- button:
MouseKey
类型,可以查看类型文件定义,为枚举型,传入MouseKey.LButton
和1
效果一样。 - 返回值: 不返回任何值的同步方法。
keyUp(button: MouseKey): void
释放鼠标按键,通常用于实现拖拽操作。
- button:
MouseKey
类型,可以查看类型文件定义,为枚举型,传入MouseKey.LButton
和1
效果一样。 - 返回值: 不返回任何值的同步方法。
将鼠标移动至指定坐标位置按住鼠标一定时间后松开。
await Mouse.move(128,400)
await Mouse.keyDown()
await Util.delay(5000)
await Mouse.keyUp()
Mouse.move(128,400)
Mouse.keyDown()
Util.delay(5000)
Mouse.keyUp()
wheel(vertical: number, horizontal: number): void
滚动鼠标滚轮,不仅可以进行常规的垂直滚动,还可以进行水平滚动。
- vertical:
number
类型,垂直滚动的值,向上滚动为正,向下滚动为负。 - horizontal:
number
类型,水平滚动的值,向左滚动为正,向右滚动为负。 - 返回值: 不返回任何值的同步方法。
wheel()
方法的精度比较高,因此在调用时可以适当的将参数取大一点,好观察到现象。
拖拽操作的脚本
实现拖拽操作的脚本如下:
mouse.move(0, 0);
mouse.keyDown(MouseKey.LButton);
mouse.drag(100, 100);
mouse.keyUp(1);
mouse.move(0, 0)
mouse.keyDown(MouseKey.LButton)
mouse.drag(100, 100)
mouse.keyUp(1)
键盘自动化对象: Keyboard
与模拟鼠标相对应的就是模拟键盘操作了,与键盘相关的操作属于Keyboard
对象。
类型文件定义
export class Keyboard {
static Keys: Keys,
static keyTap(key: string): void;
static unicodeTap(keyCode: number): void;
static keyDown(key: string): void;
static keyUp(key: string): void;
static setDelay(milliseconds: number): void;
// static typeString(str: string, cpm?: number): void; // deprecated
static pressKeys(keys: string, options?: PressKeysOptions | number): Promise<void>;
static disableIme();
}
class Keyboard():
def keyTap(key: str) -> None
def unicodeTap(keyCode: int) -> None
def keyDown(key: str) -> None
def keyUp(key: str) -> None
def setDelay(milliseconds: int) -> None
def typeString(str: str, cpm: Optional[int]=None) -> None
def pressKeys(keys: str, cpm: Optional[int]=None) -> None
def disableIme() -> None
API介绍
keyTap(key): void
按下一个键。
- key:
string
类型,目标键的键值,可以参考Keys
表。 - 返回值: 不返回任何值的同步方法。
unicodeTap(key): void
按下一个键,键值由Unicode指定。在JavaScript中,可调用字符串的charCodeAt
获得键值。例如下面的代码可以将字符串输出,等效于调用typeString
的效果:
'您好,中国(China)'.split('').map(k => Keyboard.unicodeTap(k.charCodeAt(0)));
- key:
string
类型,目标键的键值,可以参考Keys
表。 - 返回值: 不返回任何值的同步方法。
keyDown(key): void
按住一个键。
- key:
string
类型,目标键的键值,可以参考Keys
表。 - 返回值: 不返回任何值的同步方法。
keyUp(key): void
释放一个键。
- key:
string
类型,目标键的键值,可以参考Keys
表。 - 返回值: 不返回任何值的同步方法。
setDelay(delay): void
控制每个键盘操作的间隔,默认为10ms。
- delay:
number
类型,间隔时间,单位为毫秒。 - 返回值: 不返回任何值的同步方法。
typeString(str, cpm): Promise<void>
已弃用,建议使用
pressKeys(str, {textOnly: true})
代替。
输入一串字符。
- str:
string
类型,需要输入的字符串。 - cpm(可选):
number
类型,"Character Per Minute",即每分钟中输入的字符,控制输入字符从速度。 如果有些被测应用在快速输入字符时无法及时处理导致显示不正常,可通过设置较低的cpm解决,例如cpm = 60; - 返回值: 不返回任何值的异步方法。
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方法。
disableIme(): void
禁用当前聚焦应用的输入法,即切换到中文键盘。这样在调用其他输入键盘操作的方法,如typeString或pressKeys时,不会受输入法的干扰。
- 返回值: 不返回任何值的异步方法。 注意:输入法是跟应用相关的。如果启动了一个新的被测应用,可能需要再次调用disableIme()。
Keys
Keys
是一个枚举对象,枚举了所有的按键,用于keyTap
、keyDown
、keyUp
方法的参数。按键名和描述见下表。
对于字母键和数字键是直接使用同名的字符即可,因此没在下表列出。比如按下字母键b和数字键5直接传入参数"b"
和"5"
即可。
Windows徽标键: 作为Windows键盘特有的一个控制键,与Mac的cmd键一样,都可以使用
"command"
的按键名来使用。
按键名 | 描述 | 备注 |
---|---|---|
backspace | 退格键 | |
delete | 删除键 | |
enter | 回车键 | |
tab | Tab键 | |
escape | Esc键 | |
up | 上方向键 | |
down | 下方向键 | |
right | 右方向键 | |
left | 左方向键 | |
home | Home键 | |
end | End键 | |
pageup | Page Up键 | |
pagedown | Page Down键 | |
f1 | F1键 | |
f2 | F2键 | |
f3 | F3键 | |
f4 | F4键 | |
f5 | F5键 | |
f6 | F6键 | |
f7 | F7键 | |
f8 | F8键 | |
f9 | F9键 | |
f10 | F10键 | |
f11 | F11键 | |
f12 | F12键 | |
command | CMD键或Windows键(取决系统) | |
alt | Alt键 | |
control | Ctrl键 | |
shift | Shift键 | |
right_shift | 右Shift键 | |
space | 空格键 | |
printscreen | 打印屏幕键 | 不支持Mac |
insert | 插入键 | 不支持Mac |
audio_mute | 静音键 | |
audio_vol_down | 音量减小键 | |
audio_vol_up | 音量增大键 | |
audio_play | 播放键 | |
audio_stop | 停止键 | |
audio_pause | 暂停键 | |
audio_prev | 上一首键 | |
audio_next | 下一首键 | |
audio_rewind | 倒带键 | 只有Linux有效 |
audio_forward | 快进键 | 只有Linux有效 |
audio_repeat | 重复播放键 | 只有Linux有效 |
audio_random | 随机播放键 | 只有Linux有效 |
numpad_0 | 数字键盘0 | |
numpad_1 | 数字键盘1 | |
numpad_2 | 数字键盘2 | |
numpad_3 | 数字键盘3 | |
numpad_4 | 数字键盘4 | |
numpad_5 | 数字键盘5 | |
numpad_6 | 数字键盘6 | |
numpad_7 | 数字键盘7 | |
numpad_8 | 数字键盘8 | |
numpad_9 | 数字键盘9 | |
numpad_+ | 数字键盘+ | |
numpad_- | 数字键盘- | |
numpad_* | 数字键盘* | |
numpad_/ | 数字键盘/ | |
numpad_. | 数字键盘. | |
lights_mon_up | 提高显示器亮度 | Windows不支持 |
lights_mon_down | 降低显示器亮度 | Windows不支持 |
lights_kbd_toggle | 开/关键盘背灯 | Windows不支持 |
lights_kbd_up | 提高键盘背灯亮度 | Windows不支持 |
lights_kbd_down | 降低键盘背灯亮度 | Windows不支持 |
keys的用法
Keys
枚举类常用于特殊按键,有两种用法。比如在需要同时按下Ctrl
键与A
键执行全选操作时,可以这样写:
const { Keyboard } = require('leanpro.common');
Keyboard.keyDown('control')
Keyboard.keyTap('a');
Keyboard.keyUp('control')
from leanproAuto import Keyboard
Keyboard.keyDown('control')
Keyboard.keyTap('a')
Keyboard.keyUp('control')
由于keyTap
、keyDown
、keyUp
方法默认只接收单个字符(如'a'
),如果接收到字符串(如'control'
),则会自动使用Keys
枚举类,等效于引入Keys
枚举类,如下:
const { Keyboard, Keys } = require('leanpro.common');
Keyboard.keyDown(Keys.control)
Keyboard.keyTap('a');
Keyboard.keyUp(Keys.control)
如果希望直接输入字符串,应该使用
pressKeys(str, {textOnly: true})
。
组合键操作
如果需要在操作过程中按住某个键,比如按住Ctrl键并拖拽、按住Shift并点击这类的操作,借由keyDown()
和keyUp()
方法可以灵活地实现:
const { Keyboard } = require('leanpro.common');
Keyboard.keyDown('shift')
// 在此处放入控制键按下期间的操作脚本
// ...
Keyboard.keyUp('shift')
from leanproAuto import Keyboard
Keyboard.keyDown('shift')
# 在此处放入控制键按下期间的操作脚本
# ...
Keyboard.keyUp('shift')
屏幕自动化对象: Screen
屏幕自动化对象Screen
,用于获取屏幕属性,以及操作屏幕。
类型文件定义
类型文件定义如下:
export class Screen {
static screenRect(moniter?: number): Rect
static all(moniter?: number): Rect[]
static colorAt(x: number, y: number): string;
static capture(rect?: Rect): Buffer;
static captureToFile(filePath: string, rect?: Rect): void;
static takeScreenshot(filePath: string, monitor?: number): string | void;
static highlight(rect: Rect, duration?: number);
// deprecated 弃用
static screenSize(): {width: number, height: number};
}
class Screen():
def all() -> "List[Rect]"
def screenRect(monitor: Optional[int]=None) -> "Rect"
def screenSize() -> TypedDict
def colorAt(x: int, y: int) -> str
def capture(rect: Optional[Rect]=None) -> "bytearray"
def captureToFile(filePath: str, rect: Optional[Rect]=None) -> None
def takeScreenshot(filePath: str, monitor: Optional[int]=None) -> Union[str, None]
def highlight(rect: Rect, duration: Optional[int]=None) -> "any"
class ScreenSize():
width: int
height: int
API介绍
screenRect(monitor?:number): Rect
用于获取指定监视器(或者默认取所有屏幕合并后的)的边界信息。
- monitor: (可选)要获取边界信息的监视器的编号。不传参数或传
-1
,会获取所有屏幕合并后的尺寸,数值上等于Screen.capture方法获取到截图的尺寸。传0返回第一个显示屏,1返回第二个,以此类推。 - 返回值:
Rect
对象,表示指定监视器的边界信息。Rect
对象包含以下属性:- x: 屏幕左上角的水平坐标。
- y: 屏幕左上角的垂直坐标。
- width: 屏幕的宽度,单位为像素。
- height: 屏幕的高度,单位为像素。
使用示例
以下示例展示了如何使用 Screen.screenRect
方法获取指定监视器的边界信息:
const { Screen } = require('leanpro.common');
// 获取主屏幕的边界信息
const mainScreenRect = Screen.screenRect();
console.log('Main Screen Rect:', mainScreenRect);
// 获取编号为1的监视器的边界信息
const monitor1Rect = Screen.screenRect(1);
console.log('Monitor 1 Rect:', monitor1Rect);
from leanproAuto import Screen
# 获取主屏幕的边界信息
main_screen_rect = Screen.screenRect()
print('Main Screen Rect:', main_screen_rect)
# 获取编号为1的监视器的边界信息
monitor1_rect = Screen.screenRect(1)
print('Monitor 1 Rect:', monitor1_rect)
在这个例子中,我们首先获取主屏幕的边界信息,然后获取编号为1的监视器的边界信息,然后将这些信息打印出来。
all(): Rect[]
用于获取所有屏幕的边界信息。这对于多屏幕环境尤其有用,可以通过此方法获取每个屏幕的位置和尺寸。
- 返回值:
Rect
对象组成的数组,其中每个Rect
对象表示一个屏幕的边界信息。
使用示例
以下示例展示了如何使用 Screen.all
方法获取所有屏幕的边界信息:
const { Screen } = require('leanpro.common');
const screens = Screen.all();
screens.forEach((screen, i) => {
console.log(`Screen ${i}:`, screen);
});
from leanproAuto import Screen
screens = Screen.all()
for i, screen in enumerate(screens):
print(f"Screen {i}: {screen}")
在这个例子中,我们首先使用 Screen.all
方法来获取所有屏幕的信息,然后遍历结果并打印出每个屏幕的边界信息。
screenSize(): {width: number, height: number}
不建议使用,可以用screenRect代替。
用于获取当前屏幕的尺寸,即屏幕的宽度和高度。它不需要任何参数。
- 返回值:
{width: number, height: number}
,这两个属性分别表示屏幕的宽度和高度,以像素为单位。
colorAt(x: number, y: number): string
用于获取屏幕上特定点的颜色。通过输入特定的 x 和 y 坐标,您可以获取该点的颜色值。返回值为一串十六进制格式的RGB颜色代码字符串,形如"FFFFFF"
。
- x:
number
类型,定义所需获取颜色点的水平坐标。x的起点在屏幕的最左边。 - y:
number
类型,定义所需获取颜色点的垂直坐标。y的起点在屏幕的最顶部。 - 返回值:
string
类型,一串十六进制格式的RGB颜色代码字符串。
使用示例
以下示例展示了如何使用 Screen.colorAt
方法来获取屏幕上某个特定点的颜色:
const { Screen } = require('leanpro.common');
const x = 500;
const y = 300;
const color = Screen.colorAt(x, y);
console.log(`Color at (${x}, ${y}): ${color}`);
from leanproAuto import Screen
x = 500
y = 300
color = Screen.colorAt(x, y)
print(f"Color at ({x}, {y}): {color}")
在这个例子中,我们首先定义了所需点的 x 和 y 坐标,然后使用 Screen.colorAt
方法来获取这个点的颜色。最后,我们打印出这个颜色值。
capture(rect?: Rect): Buffer
用于捕获屏幕上的特定矩形区域的截图。如果没有指定矩形区域,那么此方法将捕获整个屏幕的截图。
- rect: (可选)
Rect
类型,这是一个包含x
,y
,width
,和height
属性的对象,用来定义要截图的矩形区域的位置和尺寸。x
和y
属性定义了矩形的左上角在屏幕上的坐标,而width
和height
定义了矩形的宽度和高度。如果此参数未提供,那么方法将捕获整个屏幕的截图。具体定义详见Rect类型介绍。 - 返回值:
Buffer
类型。其中包含了捕获的截图数据,这个Buffer
对象可以被用来将截图数据保存为文件,或者用于其他需要使用图像数据的场景。例如用于报告附件,或者使用Image.from()
方法构造Image
对象。
使用示例
以下示例展示了如何使用 Screen.capture
方法来捕获一个特定的屏幕区域的截图,并将其保存为文件:
const { Screen } = require('leanpro.common');
const fs = require('fs');
const rect = {"x":555,"y":358,"width":126,"height":34};
const buffer = Screen.capture(rect);
fs.writeFileSync('screenshot.png', buffer);
from leanproAuto import Screen
rect = {"x":555, "y":358, "width":126, "height":34}
buffer = Screen.capture(rect)
with open('screenshot--2.png', 'wb') as f:
f.write(buffer)
在这个例子中,我们首先定义了矩形区域的坐标和尺寸,然后使用 Screen.capture
方法来捕获截图,最后使用 fs.writeFileSync
方法将截图数据保存为一个 PNG 文件。
captureToFile(filePath: string, rect?: Rect): void
用于捕获屏幕截图并将其保存到指定文件路径的函数。用户可以选择截取整个屏幕或者截取屏幕上的特定区域。filePath
为路径以及文件名。如果指定了rect
参数,则会只截取指定方框的截图。
- filePath:
string
类型,这是一个字符串,表示截图保存的文件路径。文件路径应包含文件名和扩展名。支持的文件格式包括.jpg
,.png
,.bmp
等。 - rect: (可选)
Rect
类型,这是一个包含x
,y
,width
,和height
属性的对象,用来定义要截取的矩形区域的位置和尺寸。x
和y
属性定义了矩形的左上角在屏幕上的坐标,而width
和height
定义了矩形的宽度和高度。如果这个参数没有提供,那么会捕获整个屏幕的截图。具体定义详见Rect类型介绍。 - 返回值: 此方法没有返回值。
使用示例
以下示例展示了如何使用 Screen.captureToFile
方法来截取整个屏幕的截图并保存到指定的文件路径:
const { Screen } = require('leanpro.common');
Screen.captureToFile("C:/Users/Username/Desktop/screenshot.png");
from leanproAuto import Screen
Screen.captureToFile("C:/Users/Username/Desktop/screenshot.png")
以下示例展示了如何使用 Screen.captureToFile
方法来截取屏幕上特定区域的截图并保存到指定的文件路径:
const { Screen } = require('leanpro.common');
Screen.captureToFile("C:/Users/Username/Desktop/screenshot.png", {"x":555,"y":358,"width":126,"height":34});
from leanproAuto import Screen
Screen.captureToFile("C:/Users/Username/Desktop/screenshot.png", {"x":555,"y":358,"width":126,"height":34})
在这个例子中,矩形区域的左上角坐标是 (555,358)
,矩形的宽度是 126
像素,高度是 34
像素。
highlight(rect: Rect, duration?: number)
用于高亮显示屏幕上指定矩形区域的函数。这个功能在标识和追踪特定屏幕区域时特别有用,如在测试过程中,它可以直观地显示出正在测试或分析的区域。
rect:
Rect
类型。这是一个包含x
,y
,width
,和height
属性的对象,用来定义要高亮的矩形区域的位置和尺寸。x
和y
属性定义了矩形的左上角在屏幕上的坐标,而width
和height
定义了矩形的宽度和高度。具体定义详见Rect类型介绍。duration: (可选)
number
类型。这是一个代表高亮显示持续时间的数字,单位是毫秒。如果这个参数没有提供,那么高亮显示将持续到下一个highlight
调用,或者到测试结束。返回值: 此方法没有返回值。
使用示例
以下示例展示了如何使用 Screen.highlight 方法来高亮显示一个特定的屏幕区域:
const { Screen } = require('leanpro.common');
Screen.highlight({"x":555,"y":358,"width":126,"height":34});
from leanproAuto import Screen
Screen.highlight({"x":555,"y":358,"width":126,"height":34})
(555,358)
,矩形的宽度是 126
像素,高度是 34
像素。
takeScreenshot(filePath: string, monitor?: number): string
由原先的Util.takeScreenshot
方法合并而来,获取屏幕截屏。详见takeScreenshot()方法介绍。
不推荐使用。