Qt Object API

Object operation API methods are divided into two categories: Operations and Properties. Operations perform actual actions on the control, while properties retrieve the runtime attributes of the control. Since control access is asynchronous, properties are also accessed via methods, which return a Promise object—Promise<T>, meaning you need to add the await keyword before the call to retrieve the result from the Promise.

API Syntax Description

The Qt API documentation is built upon the leanpro.qt type definition file (you can check the leanpro.qt.d.ts file to see how to call the API). Therefore, it uses TypeScript syntax. Below is a brief introduction to the knowledge required to read the documentation. for further understanding, you can visit the TypeScript Handbook to learn more about the syntax.

First is the class name, here it is IQtControl, which stands for Interface of Qt Control, representing the interface definition for generic Qt controls.

Next is the base class, indicating which class the current class extends from. Extending means inheriting properties and methods from the base class. Here, it extends the container class IQtContainer, which contains various object acquisition APIs, allowing for chained object retrieval.

For example, a complete call to get the "Family" cell in the "sheet1" table within the "Table Overview" window can be written as:

JavaScript
Python
model.getWindow("Table Overview").getTable("sheet1").getTableItem("Family");
model.getWindow("Table Overview").getTable("sheet1").getTableItem("Family")
CukeTest optimizes the generated control call code, so typically you won't see such long calls.

Finally, there are the operation methods and property methods of the current class, separated by an empty line. The () indicates the number of parameters passed. The parameter format is [argName]:[argType]. If there is a ? before the :, it means the parameter has a default value and does not affect execution if omitted. The end of the method (after the last :) represents the return value type. Promise<T> indicates an asynchronous method, while T alone indicates a synchronous method.

Here T represents a type name, such as void, string, number, etc.

Class Relationships

In CukeTest, the inheritance relationship between classes is roughly as follows:

  1. Base Class: The container class IQtContainer, containing methods for acquiring automation objects.
  2. Secondary Base Class: The basic control class IQtControl, containing common operation and property methods for all controls.
  3. Specific Control Classes: Such as IQWindow, IQLabel, etc. In addition to inherited methods, most controls contain their own specific operation and property methods to achieve automation for different controls.

API Overview

Action Methods

Method Name Description
click Simulates a mouse click on the control, specifying the position and mouse button.
dblClick Simulates a mouse double-click on the control, specifying the position and mouse button.
moveMouse Moves the mouse to a specified position on the control, with optional speed.
touch Simulates touch operations on the control, supporting single or multi-touch.
wheel Scrolls the mouse wheel.
drag Simulates the first step of a drag operation: mouse press.
drop Simulates the second step of a drag operation: mouse release.
pressKeys Inputs key combinations or strings.
exists Checks if the control exists, with an optional timeout.
highlight Highlights the control for debugging and verification.
takeScreenshot Takes a screenshot of the control, with an optional file path.
invoke Calls a specified method of the control and returns the result.
scrollIntoView Scrolls the control into the visible area.

Property Methods

Method Name Description
rect Gets the position and size of the control.
winId Gets the window handle ID of the control.
enabled Checks if the control is enabled.
visible Checks if the control is visible.
modelProperties Gets the properties of the control cached in the model.
modelImage Gets the screenshot snapshot of the control cached in the model.
allProperties Gets all runtime properties of the target control.
property Gets a specified property value of the control.
waitProperty Waits for a specified property of the control to reach a certain value.
checkProperty Verifies if a property of the control matches the expected value.
checkImage Verifies if the control's image matches the expected reference image.
Method Name Description
firstChild Gets the first child control.
lastChild Gets the last child control.
next Gets the next sibling control.
previous Gets the previous sibling control.
parent Gets the parent control.
findControls Finds controls based on conditions.
all Gets all matching sibling controls.

Common API

Different types of object operations have different actions and properties. They all share some common actions and properties that can be called by any control, as follows:

JavaScript
Python
export interface IQtControl extends IQtContainer {
    // Common Action Methods
    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, seconds?: number): Promise<void>;
    moveMouse(path: [], seconds?: number): Promise<void>;
    touch(path: number[][][]): Promise<void>;
    wheel(value: number): Promise<void>;
    drag(x?: number, y?: number, mouseKey: number): Promise<void>;
    drop(x?: number, y?: number, seconds?: number): Promise<void>;
    drop(x?: number, y?: number, {seconds?: number, mouseKey?: number}): Promise<void>;
    pressKeys(keys: string, options?: PressKeysOptions | number): Promise<void>;
    highlight(milliseconds?: number);
    takeScreenshot(filePath?: string): Promise<void | string>;
    invoke(methodName: string, args?: (string | number | boolean)[]): Promise<object>;
    all(): Promise<IQtControl[]>;
    scrollIntoView(): Promise<void>;
    
    // Common Property Methods
    rect(): Promise<Rect>;
    winId(): Promise<number>;
    enabled(): Promise<boolean>;
    visible(): Promise<boolean>;
    modelProperties(): {[x: string]: any};
    modelImage(options?: {encoding: 'buffer' | 'base64'}): Promise<Buffer | string>;  //base64 is the default
    allProperties(): Promise<object>
    property(propertyName: string): Promise<string | boolean | number | object>;
    waitProperty(propertyName: QtPropertyIds, value: string | number | boolean, timeOutSeconds: number): Promise<boolean>
    checkProperty(propertyName: QtPropertyIds, expectedValue: string | number | boolean | RegExp, message: string): Promise<void>;
    checkProperty(propertyName: QtPropertyIds, expectedValue: string | number | boolean | RegExp, options: {message: string, operation: any}): Promise<void>;
    checkImage(options?: CheckImageCompareOptions | string): Promise<void>;

    // Common Navigation Methods
    firstChild(): Promise<IQtControl>;
    lastChild(): Promise<IQtControl>;
    next(): Promise<IQtControl>;
    previous(): Promise<IQtControl>;
    parent(): Promise<IQtControl>;

    // Common Search Method
    findControls(...conditions: ConditionFilter[]): Promise<IQtControl[]>; 
}
class QtControl(QtContainer):
    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, seconds: Optional[int]=None) -> None
    def moveMouse(path: List[Any], seconds: Optional[int]=None) -> None
    def touch(paths: List[List[List[int]]]) -> None
    def wheel(value: int) -> None
    def drag(x: Optional[int]=None, y: Optional[int]=None, mouseKey: int) -> None
    def drop(x: Optional[int]=None, y: Optional[int]=None, options: Optional[Union[int, TypedDict]]=None) -> None
    def pressKeys(keys: str, opt: Optional[Union[int, PressKeysOptions]]=None) -> None
    def highlight(milliseconds: Optional[int]=None) -> None
    def takeScreenshot(filePath: Optional[str]=None) -> Union[str, None]
    def invoke(methodName: str, args: Optional[List[str]]=None) -> "any"
    def all() -> List["QtControl"]
    def scrollIntoView() -> None

    def rect() -> "Rect"
    def winId() -> int
    def enabled() -> bool
    def visible() -> bool
    def modelProperties(all: Optional[bool]=None) -> TypedDict
    def modelImage(options: Optional[TypedDict]=None) -> Union[str, bytearray]
    def allProperties() -> TypedDict
    def property(propertyIds: str) -> Union[str, int, bool, TypedDict]
    def waitProperty(propertyName: str, value: Union[str, int, bool], timeOutSeconds: Optional[int]=None) -> bool
    def checkProperty(propertyName: str, expectedValue: Union[str, int, bool], optionsOrMessage: Optional[Union[str, TypedDict]]=None) -> None
    def checkImage(options: Optional[any]=None) -> None

    def firstChild() -> "QtControl"
    def lastChild() -> "QtControl"
    def next() -> "QtControl"
    def previous() -> "QtControl"
    def parent() -> "QtControl"

    def findControls(*conditions: Union[str, Dict, List[Union[str, Dict]]]) -> List[QtControl]

Action Methods

click(x, y, mousekey)

Simulates a mouse click on the control. You can modify the relative position (offset) of the click and the mouse button used by passing parameters. The default is to click the center of the target control with the left mouse button.

Parameters:

  • x: number type. The horizontal pixel point of the click position relative to the top-left corner of the control. 0 represents the horizontal center of the control, and the default value is 0.
  • y: number type. The vertical pixel point of the click position relative to the top-left corner of the control. 0 represents the vertical center of the control, and the default value is 0.
  • mouseKey: MouseKey Type. The mouse button to operate with. The default is 1, which is the left mouse button.

Returns:

  • Asynchronous method that returns no value.

Example

The simplest way to call it is without passing any parameters, which directly clicks the center of the control:

JavaScript
Python
// Click the center of the button
await model.getButton("Button").click();
# Click the center of the button
model.getButton("Button").click()

If you need to click a specific coordinate position on the control, you can pass the horizontal pixel value (x) and vertical pixel value (y) relative to the top-left corner of the control:

JavaScript
Python
// Click the position on the button 590 pixels horizontally and 10 pixels vertically from the top-left corner
await model.getButton("Button").click(590, 10);
# Click the position on the button 590 pixels horizontally and 10 pixels vertically from the top-left corner
model.getButton("Button").click(590, 10)

Note: click(0, 0) will not click the top-left origin of the control, but the center of the control; if you expect to click the top-left corner, please use click(1, 1).

If you need to right-click the control, you need to pass a third parameter and set it to 2:

JavaScript
Python
// Right-click a specific position on the button
await model.getButton("Button").click(590, 10, 2);
# Right-click a specific position on the button
model.getButton("Button").click(590, 10, 2)

If you need to right-click the center of the control, you can use the following method:

JavaScript
Python
// Right-click the center of the button
await model.getButton("Button").click(0, 0, 2);
await model.getButton("Button").click(null, null, 2);
# Right-click the center of the button
model.getButton("Button").click(0, 0, 2)
model.getButton("Button").click(None, None, 2)

dblClick(x, y, mousekey)

Simulates a mouse double-click on the control. The calling method is consistent with click().

Parameters:

  • x: number type. The horizontal pixel point of the double-click position relative to the top-left corner of the control. The default value is 0.
  • y: number type. The vertical pixel point of the double-click position relative to the top-left corner of the control. The default value is 0.
  • mouseKey: MouseKey Type. The mouse button to operate with. The default is 1.

Returns:

  • Asynchronous method that returns no value.

Example

Double-click the center of the control:

JavaScript
Python
// Double-click the center of the button
await model.getButton("Button").dblClick();
# Double-click the center of the button
model.getButton("Button").dblClick()

moveMouse(x, y, seconds)

Moves the mouse cursor to a specified position on the control.

Parameters:

  • x: number type. The horizontal pixel point of the target position relative to the top-left corner of the control. The default value is 0.
  • y: number type. The vertical pixel point of the target position relative to the top-left corner of the control. The default value is 0.
  • seconds: number type. The duration of the mouse movement in seconds.

Returns:

  • Asynchronous method that returns no value.

Example

Move the mouse to the center position of the control:

JavaScript
Python
// Move mouse to the center of the Pane control
await model.getPane("Pane").moveMouse();
# Move mouse to the center of the Pane control
model.getPane("Pane").moveMouse()

If you need to move the mouse to a specified position on the control and control the speed:

JavaScript
Python
// Move mouse to the specified position (500, 70) within 5 seconds
await model.getPane("Pane").moveMouse(500, 70, 5);
# Move mouse to the specified position (500, 70) within 5 seconds
model.getPane("Pane").moveMouse(500, 70, 5)

touch(paths)

Simulates touch operations on the control, capable of simulating single-point or multi-point touches as well as touch trajectories.

Parameters:

  • paths: Array<Array<Array<number>>> type. An array containing touch paths. Each touch path is an array containing a series of arrays representing the touch point coordinates [x, y] relative to the top-left corner of the control. Multiple paths can be passed to simulate multi-touch.

Returns:

  • Asynchronous method that returns no value.

Example

Simulate a single-point touch sliding trajectory:

JavaScript
Python
// Simulate single-point touch slide, starting from (60,70), then moving along the specified path
await modelQt.getGeneric("TouchWidget").touch([[[60,70],[0,1],[0,1],[0,2],[0,4],[0,5]]]);
# Simulate single-point touch slide, starting from (60,70), then moving along the specified path
modelQt.getGeneric("TouchWidget").touch([[[60,70],[0,1],[0,1],[0,2],[0,4],[0,5]]])

Simulate multi-touch, where each array represents the movement trajectory of a touch point:

JavaScript
Python
// Simulate three touch points operating simultaneously
await modelQt.getGeneric("MultiTouchWidget").touch([
  [[10,20],[-5,3],[-3,2],[-3,2],[-2,1],[-2,2]],  // Trajectory of the first touch point
  [[20,30],[0,1],[0,1],[0,1],[0,1],[0,1]],        // Trajectory of the second touch point
  [[30,40],[0,1],[0,1],[0,1],[0,1],[0,1],[0,1]]   // Trajectory of the third touch point
]);
# Simulate three touch points operating simultaneously
modelQt.getGeneric("MultiTouchWidget").touch([
  [[10,20],[-5,3],[-3,2],[-3,2],[-2,1],[-2,2]],  # Trajectory of the first touch point
  [[20,30],[0,1],[0,1],[0,1],[0,1],[0,1]],        # Trajectory of the second touch point
  [[30,40],[0,1],[0,1],[0,1],[0,1],[0,1],[0,1]]   # Trajectory of the third touch point
])

wheel(value)

Scrolls the mouse wheel, with the input parameter being the scale of the wheel rotation.

Parameters:

  • value: number type. Wheel scale. Positive values scroll forward, negative values scroll backward.

Returns:

  • Asynchronous method that returns no value.

Example

Scroll the mouse wheel up by one scale:

JavaScript
Python
// Scroll up one scale on the Pane control
await model.getPane("Pane").wheel(1);
# Scroll up one scale on the Pane control
model.getPane("Pane").wheel(1)

drag(x, y, mouseKey)

The first step of a drag operation. Press and hold the mouse at the target position without releasing. x and y are the horizontal and vertical pixels relative to the control position, defaulting to the center position.

Parameters:

  • x: number type. The horizontal pixel point of the drag start position relative to the top-left corner of the control.
  • y: number type. The vertical pixel point of the drag start position relative to the top-left corner of the control.
  • mouseKey: MouseKey Type. The mouse button used, default is 1.

Returns:

  • Asynchronous method that returns no value.

Example

Start dragging from the center of the control:

JavaScript
Python
// Press the mouse at the center of the button to start dragging
await model.getButton("sourceButton").drag(0, 0);
# Press the mouse at the center of the button to start dragging
model.getButton("sourceButton").drag(0, 0)

Refer to Drag and Drop Selection for more details.

drop(x, y, options)

The second step of a drag operation. Move the mouse cursor to the specified position and release the mouse. x and y are the horizontal and vertical pixels relative to the control position. The third parameter is used to control the speed of mouse movement and the mouse button used.

You can execute the drag() method on control A and the drop() method on control B to achieve the effect of dragging control A to control B. For detailed documentation, see Drag and Drop Selection.

Parameters:

  • x: number type. The horizontal pixel point of the mouse release position relative to the top-left corner of the control, defaulting to 0.
  • y: number type. The vertical pixel point of the mouse release position relative to the top-left corner of the control, defaulting to 0.
  • options: object type. Configuration object for custom drag behavior. Supported options include:
    • duration: number type. The duration of the mouse movement to the target position in seconds. Default is 1 (1 second).
    • mouseKeys: number type. The mouse button used in the drag operation. 1 for left button, 2 for right button. Default is left button (1).

Returns:

  • Asynchronous method that returns no value.

Example

Complete the drag operation:

JavaScript
Python
// Drag the button to another control
await model.getButton("sourceButton").drag(0, 0);
await model.getButton("targetButton").drop(10, 10);
# Drag the button to another control
model.getButton("sourceButton").drag(0, 0)
model.getButton("targetButton").drop(10, 10)

pressKeys(keys, options?)

Inputs strings or simulated key combinations via keyboard signals. Therefore, it can be used not only for simple text input but also for complex keyboard operations such as simulated login, navigation, copy, paste, etc.

Note that some special characters in the string (such as ^+~%{}()) will be parsed as control keys (such as Shift, Ctrl) instead of being input as characters. Please refer to Appendix: Key Code Table for specific key commands. If you wish to input pure text and ignore these control key symbols, please use the {textOnly: true} option, calling it like this: pressKeys(str, {textOnly: true}).

Parameters:

  • keys: string type. The keys, combination keys, or string to be input. Supports up to 1024 characters.
  • options: PressKeysOptions | number (optional). Optional parameters controlling input mode, containing the following:

    • textOnly: boolean type. When set to true, all characters are treated as plain text, ignoring control key instructions.
    • cpm: number type. Characters per minute, used to control input speed. It is recommended to set the cpm value above 200. Due to differences in how different systems and applications handle input speed, the actual input speed may deviate from the set value.

    If a number is passed directly as options, the value will be treated as the cpm parameter.

Returns:

  • Asynchronous method that returns no value.

Example

Input pure text:

JavaScript
Python
// Input text in the input box, ignoring the control key function of special characters
await model.getEdit("Edit").pressKeys("Hello, World!", { textOnly: true });
# Input text in the input box, ignoring the control key function of special characters
model.getEdit("Edit").pressKeys("Hello, World!", { "textOnly": True })

For more explanations or examples, please refer to the pressKeys method.

exists(seconds)

Checks if the control exists. The input parameter is the maximum remaining time (timeout) to wait for the check. It returns true immediately when the control appears, and returns false when the control matching result matches an error or waits until timeout. By default, this method only checks once and does not retry or wait.

Parameters:

  • seconds: (Optional) number type. The maximum number of seconds to wait for the control to appear. If omitted, it defaults to waiting 0 seconds, which means checking only once.

Returns:

  • Asynchronously returns whether the control exists. true for exists, false for does not exist.

Example

  1. Without specifying wait time

JavaScript
Python
// Check immediately if the control exists
let exists = await model.getApplication("dirview").exists();
# Check immediately if the control exists
exists = model.getApplication("dirview").exists()
This code checks once immediately. If the control is found, exists is true, otherwise false.

  1. With specified wait time

JavaScript
Python
// Wait up to 10 seconds for the control to appear
let bool = await model.getApplication("dirview").exists(10);
assert.strictEqual(bool, true);
# Wait up to 10 seconds for the control to appear
bool = model.getApplication("dirview").exists(10)
assert bool == True
This code waits up to 10 seconds. If the control is found within these 10 seconds, bool is true, otherwise false.

highlight(duration)

Highlights the control, used for debugging and verification. You can pass the duration of the highlight frame (in milliseconds). The default value is 1000, i.e., lasting 1 second.

Parameters:

  • duration: (Optional) number type. The duration of the highlight, in milliseconds.

Returns:

  • Asynchronous method that returns no value.

Example

JavaScript
Python
// Highlight the button for 2 seconds for debugging verification
await model.getButton("Button").highlight(2000);
# Highlight the button for 2 seconds for debugging verification
model.getButton("Button").highlight(2000)

takeScreenshot(filePath?)

Takes a screenshot of the control. You can pass a path to save the screenshot to that location.

Parameters:

  • filePath: (Optional) string type. The save path for the screenshot file, such as "./images/screenshot1.png".

Returns:

  • Asynchronously returns the base64 string of the screenshot.

Example

JavaScript
Python
// Take a screenshot of the button control and save it to a file
await model.getButton("Button").takeScreenshot("./screenshots/button.png");
# Take a screenshot of the button control and save it to a file
model.getButton("Button").takeScreenshot("./screenshots/button.png")

The base64 encoded image returned by the takeScreenshot() method can be directly inserted into the run report as an image. For details, please refer to Report Attachments.

invoke(methodName, args?)

Calls the specified method of the control and returns the execution result of the method.

Parameters:

  • methodName: string type. The name of the method to be executed.
  • args: (Optional) An array of strings, numbers, or booleans, representing the list of parameters passed to the method.

Returns:

  • Asynchronously returns the execution result after the method call.

Example

JavaScript
Python
// Get the number of rows in the table
const result = await table.invoke("model.rowCount", []);
// Get the value of the cell at row 1, column 1
const cellValue = await table.invoke("model.data", [0, 0]);
# Get the number of rows in the table
result = table.invoke("model.rowCount", [])
# Get the value of the cell at row 1, column 1
cellValue = table.invoke("model.data", [0, 0])

Depending on the control and method, the invoke method can accept different parameters. For example, in a table control, you can use the invoke method to get the number of rows and columns of the table, or even directly get all the data inside the table, as shown in the example above. Depending on the specific needs, you can pass different parameters to call different methods.

Please note that depending on the specific application scenario and control, the parameters and return values of the invoke method may vary. Please refer to the documentation, source code, or API documentation for the description of the method of that class to obtain accurate parameter and return value information.

scrollIntoView()

Scrolls until the control is visible in the view.

Returns:

  • Asynchronous method that returns no value.

Property Methods

rect()

Gets the position and size of the control.

Returns:

  • Returns a Rect object, containing the control's coordinate information x and y, and width and height information width and height.

Example

JavaScript
Python
// Get the rectangle information (position and size) of the Button control
let rect = await model.getButton("Button").rect();
console.log(`Button position: (${rect.x}, ${rect.y}) size: ${rect.width}x${rect.height}`);
# Get the rectangle information (position and size) of the Button control
rect = model.getButton("Button").rect()
print(f"Button position: ({rect['x']}, {rect['y']}) size: {rect['width']}x{rect['height']}")

winId()

Gets the window handle ID of the control.

Returns:

  • Asynchronously returns a number representing the window handle ID.

Example

JavaScript
Python
// Get window handle ID
let id = await model.getWindow("Window").winId();
console.log("Window Handle ID:", id);
# Get window handle ID
id = model.getWindow("Window").winId()
print(f"Window Handle ID: {id}")

enabled()

Checks if the control is enabled.

Returns:

  • Asynchronously returns a boolean value indicating whether the control is enabled.

Example

JavaScript
Python
// Check if the Button control is enabled, return a boolean value
let isEnabled = await model.getButton("Button").enabled();
console.log(`Is Button control enabled: ${isEnabled}`);
# Check if the Button control is enabled, return a boolean value
is_enabled = model.getButton("Button").enabled()
print(f"Is Button control enabled: {is_enabled}")

visible()

Checks if the control is visible.

Returns:

  • Asynchronously returns a boolean value indicating whether the control is visible.

Example

JavaScript
Python
// Check if the control is visible
let isVisible = await model.getButton("Button").visible();
console.log(`Is Button control visible: ${isVisible}`);
# Check if the control is visible
is_visible = model.getButton("Button").visible()
print(f"Is Button control visible: {is_visible}")

modelProperties()

Gets the model properties of the target control, i.e., the properties of the corresponding model object (including identification properties and other properties).

Returns:

  • Asynchronously returns an object composed of the properties of the target model object.

Example

Get the model properties of the window control:

JavaScript
Python
// Get the model properties of the window
let modelProperties = await model.getWindow("Standard_Dialogs").modelProperties();
console.log(modelProperties);
// Verify control type
assert.equal('Window', modelProperties.type);
# Get the model properties of the window
modelProperties = model.getWindow("Standard_Dialogs").modelProperties()
print(modelProperties)
# Verify control type
assert modelProperties['type'] == 'Window'

The output modelProperties is:

{ type: 'Window', className: 'Dialog', text: 'Standard Dialogs' }

By calling the modelProperties() method, you can retrieve the model properties of the target control, including identification properties and other details. The returned modelProperties object contains various attribute information of the target model object, such as type (type), class name (className), and text (text), etc.

modelImage(options?)

Gets the screenshot file content of the target control in the model.

Parameters:

  • options: object type, optional parameter, containing the following fields:
    • encoding: 'buffer' | 'base64' type, the format of the return value. Defaults to 'base64'.

Returns:

  • Asynchronously returns the screenshot file stream (base64 encoded or Buffer) of the target control in the model.

Example

Get the model screenshot of the control (default base64 format):

JavaScript
Python
// Get the model screenshot of the button (base64 format)
let imageBase64 = await model.getButton("Button").modelImage();
console.log("Image data length:", imageBase64.length);
# Get the model screenshot of the button (base64 format)
image_base64 = model.getButton("Button").modelImage()
print(f"Image data length: {len(image_base64)}")

Get the screenshot in Buffer format:

JavaScript
Python
// Get the model screenshot of the button (Buffer format)
let imageBuffer = await model.getButton("Button").modelImage({ encoding: 'buffer' });
console.log("Buffer size:", imageBuffer.length);
# Get the model screenshot of the button (Buffer format)
image_buffer = model.getButton("Button").modelImage({ "encoding": "buffer" })
print(f"Buffer size: {len(image_buffer)}")

allProperties()

Gets all runtime properties of the target control, returned as an object.

Returns:

  • Asynchronously returns an object composed of the properties of the target model object.

Example

Get all runtime properties of the button control:

JavaScript
Python
// Get all runtime properties of the button
let properties = await model.getButton("Button").allProperties();
console.log(properties);
// Get just one of the properties, like objectName
console.log('objectName=' + properties['objectName']);
# Get all runtime properties of the button
properties = model.getButton("Button").allProperties()
print(properties)
# Get just one of the properties, like objectName
print('objectName=' + properties['objectName'])

It will get all properties of the button and print:

{
  "acceptDrops": false,
  "accessibleDescription": "",
  "accessibleName": "",
  "arrowType": 0,
  "autoExclusive": false,
  ...
  "objectName": "Button1",
  "x": 11,
  "y": 11
}

The code above will print a specific property:

objectName=Button1

property(name)

Gets a specified runtime property of the target control. Supports passing property names of various controls, and also supports directly using field names from the allProperties() method.

If a non-existent property name is passed, it will return undefined instead of throwing an error.

Parameters:

Returns:

  • Asynchronously returns various property values.

Example

Directly get the specified property value:

JavaScript
Python
// Get the objectName property of the button
let objectName = await model.getButton("Button").property('objectName');
console.log('Object Name:', objectName);
# Get the objectName property of the button
object_name = model.getButton("Button").property('objectName')
print(f'Object Name: {object_name}')

Compared to using allProperties() and then taking a field, the property() method is more concise and efficient:

JavaScript
Python
// Using allProperties() method
let properties = await model.getButton("Button").allProperties();
console.log(properties['objectName']);

// Using property() method is more concise
let objectName = await model.getButton("Button").property('objectName');
# Using allProperties() method
properties = model.getButton("Button").allProperties()
print(properties['objectName'])

# Using property() method is more concise
object_name = model.getButton("Button").property('objectName')

waitProperty(propertyName, value, timeOutSeconds)

Waits for a specified property of the control to become a specific value. You can use it to determine whether the state of the control meets expectations, such as waiting for a button to become enabled.

Parameters:

  • propertyName: string type, property name. Supported property names include enabled, text, value, etc., see Optional Property Fields.
  • value: string | number | boolean type, the property value to wait for.
  • timeOutSeconds: number type, wait time in seconds. Default is 5 seconds. -1 means wait indefinitely.

Returns:

  • boolean type, wait result. true indicates successfully waited for the value, false indicates timeout. If an error is thrown, it means the control was not matched, possibly because the control did not appear or there is a problem with the object name.

Example

Wait for the text content of the control to become a specified value:

JavaScript
Python
// Wait for the button text to become "OK", wait up to 30 seconds
let isReady = await model.getButton("Button").waitProperty("text", "OK", 30);
if (isReady) {
    console.log("Button text has become OK");
} else {
    console.log("Wait timed out");
}
# Wait for the button text to become "OK", wait up to 30 seconds
is_ready = model.getButton("Button").waitProperty("text", "OK", 30)
if is_ready:
    print("Button text has become OK")
else:
    print("Wait timed out")

Wait for the control to become enabled:

JavaScript
Python
// Wait for the button to become enabled, wait up to 10 seconds
let isEnabled = await model.getButton("SubmitButton").waitProperty("enabled", true, 10);
# Wait for the button to become enabled, wait up to 10 seconds
is_enabled = model.getButton("SubmitButton").waitProperty("enabled", True, 10)

checkProperty(propertyName, expectedValue, optionsOrMessage)

Verifies if the property value of the control meets expectations. If the specified property value does not match the expected value, an error will be thrown.

You can quickly generate property check scripts based on this method during recording. For details, please refer to Adding Property Checkpoints during Recording.

Parameters:

  • propertyName: string type, the name of the property to check. Supported property names include enabled, text, value, etc., as well as all fields returned by the allProperties() method.
  • expectedValue: string | number | boolean | RegExp type, the expected property value. When the control's property value matches the expected value, the test will pass; otherwise, an error will be thrown.
  • optionsOrMessage: string | object type, optional parameter. If it is a string, it will be used as a custom error message; if it is an object, it can contain the following fields:
    • message: string type, custom error message.
    • operation: any type, specify the operator used to compare the control property with the expected value. The default value is equal, which verifies whether the property value is equal to the expected value.

Returns:

  • Asynchronous method that returns no value.

Example

For examples of using regular expressions in checkProperty(), please refer to Check via Regex.

Verify if the text property of the text box control is "Hello World":

JavaScript
Python
// Verify the text content of the text box
await model.getEdit("textEdit").checkProperty('text', 'Hello World', 'Text does not match expected value');
# Verify the text content of the text box
model.getEdit("textEdit").checkProperty('text', 'Hello World', 'Text does not match expected value')

If the text does not meet expectations, an error will be thrown with the error message "Text does not match expected value".

Verify if the button is enabled:

JavaScript
Python
// Verify if the button is in enabled state
await model.getButton("SubmitButton").checkProperty('enabled', true, 'Button should be enabled');
# Verify if the button is in enabled state
model.getButton("SubmitButton").checkProperty('enabled', True, 'Button should be enabled')

checkImage(options?)

Used to verify if the current image of the control matches the specified reference image. This method is a key tool for visual verification in automated testing, ensuring that the visual appearance of UI controls meets expectations.

The checkImage() method supports multiple parameter configurations. For more explanations and usage examples of this method, please refer to Introduction to Virtual.checkImage() method.

Parameters:

It supports various parameter configurations, allowing you to provide a reference image in the following ways:

  • Directly pass the path string of the image file.
  • Use a configuration object where you can specify:
    • image: Base64 encoded image data.
    • imagePath: Path to the image file.
    • Various comparison options (such as pixelPercentTolerance, colorTolerance, etc.) to adjust the sensitivity of the comparison.
  • If no specific image source is provided, it defaults to comparing with the reference image stored for that control in the model.

Returns:

  • Promise<void>: Asynchronous method that returns no value. If the comparison fails, an error will be thrown.

Example

Assuming we have a control Button, we can use checkImage() to verify if its currently displayed image matches expectations. For example:

JavaScript
Python
await model.getButton("Button").checkImage();
model.getButton("Button").checkImage()

CukeTest provides a series of control navigation methods, allowing users to retrieve parent, child, and sibling controls of the target control using navigation methods. These methods enable indexing into the entire control tree via an anchor control, commonly used in scenarios like input box positioning and control traversal.

Navigation methods are asynchronous, meaning they require some time to retrieve the navigated control within the application and return. They do not navigate directly within the Model Manager's tree, so please distinguish this difference.

For usage of control navigation, you can refer to "File Explorer Traversal" in Appendix H: CukeTest Samples.

firstChild()

Gets the first child control of the control in the application. Returns null if no matching child control is found.

Note: firstChild() only finds direct children, not grandchildren. If no matching control is found among the children, it returns null immediately instead of continuing to search in grandchildren. If you wish to get all controls under a certain control, you can use the findControls method.

Returns:

  • Asynchronously returns any control type, depending on the type of control navigated to. Returns null if no control is found.

Example

Get the first child control of the container control:

JavaScript
Python
// Get the first child of the Pane control
let firstChild = await model.getPane("Container").firstChild();
if (firstChild) {
    console.log("Found first child control");
    await firstChild.highlight(1000);
}
# Get the first child of the Pane control
first_child = model.getPane("Container").firstChild()
if first_child:
    print("Found first child control")
    first_child.highlight(1000)

Note that invisible or not-yet-loaded controls are not counted. Strictly speaking, firstChild() retrieves the first of the accessible child objects, and the same applies to the lastChild() method below.

lastChild()

Gets the last child control of the control in the application. Returns null if no matching child control is found.

Returns:

  • Asynchronously returns any control type, depending on the type of control navigated to. Returns null if no control is found.

Example

Get the last child control of the container control:

JavaScript
Python
// Get the last child of the Pane control
let lastChild = await model.getPane("Container").lastChild();
if (lastChild) {
    console.log("Found last child control");
    await lastChild.highlight(1000);
}
# Get the last child of the Pane control
last_child = model.getPane("Container").lastChild()
if last_child:
    print("Found last child control")
    last_child.highlight(1000)

next()

Gets the next sibling control of the control in the application, usually the adjacent node on the right or below, depending on the container's layout direction. Returns null if no matching sibling control is found, for example when the control is the lastChild of its parent.

Returns:

  • Asynchronously returns any control type, depending on the type of control navigated to. Returns null if no control is found.

Example

Get the next sibling control of the button:

JavaScript
Python
// Get the next sibling of the current button
let nextButton = await model.getButton("Button1").next();
if (nextButton) {
    console.log("Found next sibling control");
    await nextButton.click();
}
# Get the next sibling of the current button
next_button = model.getButton("Button1").next()
if next_button:
    print("Found next sibling control")
    next_button.click()

previous()

Opposite to next(), gets the previous sibling control of the control in the application, usually the adjacent node on the left or above, depending on the container's layout direction. Returns null if no matching sibling control is found, for example when the control is the firstChild of its parent.

Returns:

  • Asynchronously returns any control type, depending on the type of control navigated to. Returns null if no control is found.

Example

Get the previous sibling control of the button:

JavaScript
Python
// Get the previous sibling of the current button
let prevButton = await model.getButton("Button2").previous();
if (prevButton) {
    console.log("Found previous sibling control");
    await prevButton.click();
}
# Get the previous sibling of the current button
prev_button = model.getButton("Button2").previous()
if prev_button:
    print("Found previous sibling control")
    prev_button.click()

parent()

Opposite to firstChild() and lastChild(), gets the parent control of the control. Returns null if the control is a top-level control.

Returns:

  • Asynchronously returns any control type, depending on the type of control navigated to. Returns null if no control is found.

Example

Get the parent control of the button:

JavaScript
Python
// Get the parent of the button
let parentControl = await model.getButton("Button").parent();
if (parentControl) {
    console.log("Found parent control");
    await parentControl.highlight(1000);
}
# Get the parent of the button
parent_control = model.getButton("Button").parent()
if parent_control:
    print("Found parent control")
    parent_control.highlight(1000)

findControls(...conditions)

The search method allows users to more granularly and autonomously match controls in the application under test using user-defined search conditions. It can be understood as similar to the children navigation method, matching all child controls within the target control and filtering them according to conditions. Therefore, you can directly pass a filtering condition object Criteria; additionally, you can choose to pass a model object name objectName, which will automatically use the identification properties of that model object as filtering conditions.

It returns an array of all control objects that match the conditions. It can retrieve all matching controls on the application in real-time based on the passed conditions, and returns a Promise of an object array. This API can be used when there are multiple similar controls on the interface, returning this group of objects at once to facilitate operations on all these corresponding controls.

Parameters:

  • conditions: ConditionFilter[] type, one or more filtering conditions, which can be Criteria objects or model object names.

Returns:

  • Asynchronously returns an array of control objects that match the conditions.

Example

Use findControls() to accomplish tasks in special scenarios:

Scenario 1: Batch Operation

Leveraging the feature that findControls() returns multiple control objects, iterate over a large number of similar controls in the application. For example, to select all checkboxes in a container control named "Dock", you can use the following script:

JavaScript
Python
// Find all CheckBox controls in the Dock container
let checkboxes = await model.getGeneric("Dock").findControls({type: "CheckBox"});
console.log(`Found ${checkboxes.length} checkboxes`);
// Iterate and check all checkboxes
for (let index in checkboxes) {
    await checkboxes[index].check();
}
# Find all CheckBox controls in the Dock container
checkboxes = model.getGeneric("Dock").findControls({"type": "CheckBox"})
print(f"Found {len(checkboxes)} checkboxes")
# Iterate and check all checkboxes
for checkbox in checkboxes:
    checkbox.check()

Scenario 2: Search by Multiple Conditions

You can pass multiple filtering conditions to accurately locate controls:

JavaScript
Python
// Find all buttons whose text contains "Submit"
let buttons = await model.getPane("MainPane").findControls({
    type: "Button",
    "text~": "Submit"
});
# Find all buttons whose text contains "Submit"
buttons = model.getPane("MainPane").findControls({
    "type": "Button",
    "text~": "Submit"
})

all()

The all() method returns an array of all sibling controls that match the "identification properties" of the current control. It simplifies batch operations on multiple controls at the same level during testing, especially suitable for handling tables, lists, or a group of buttons.

Returns:

  • Asynchronously returns an array of any control type, depending on the type of control navigated to. Returns an empty array if no control is found.

Compared to findControls(), all() is more suitable for situations where you need to operate or check all controls at the same level as the current control without specific filtering conditions.

Example

Assuming there are multiple buttons arranged together in an application interface, you might need to verify the availability of these buttons or click them sequentially. Using the all() method, you can easily retrieve all button controls at this level and iterate through them.

JavaScript
Python
// Get all sibling button controls
let controls = await model.getButton("Normal").all();
console.log('Number of controls:', controls.length); // Output the number of matching controls
// Iterate through all controls and print names
for (let control of controls) {
    console.log(await control.name()); // Print the name of each control
    // Perform other operations...
}
# Get all sibling button controls
controls = model.getButton("Normal").all()
print("Number of controls:", len(controls))  # Output the number of matching controls
# Iterate through all controls and print names
for control in controls:
    print(control.name())  # Print the name of each control
    # Perform other operations...

In this example, the model.getButton("Normal").all() call will return an array of all button controls under the current model. Then, by traversing this array, you can print the text and click each button. This method simplifies the workflow for operating multiple sibling controls, improving the efficiency and readability of test scripts.

Optional Property Fields ()

Below are the property names supported by Qt automation, which can be used in property(), waitProperty(), and checkProperty() methods.

Control Type Property Field
QtControl winId
QtControl enabled
QtControl rect
QtControl visible
QTab count
QTab activeIndex
QTab activeName
QTab tabNames
QTabItem text
QTabItem itemIndex
QButton text
QLabel text
QCalendar date
QTabBar count
QTabBar activeIndex
QTabBar activeName
QTabBar tabNames
QItemView data
QItemView selectedIndex
QItemView rowCount
QItemView columnCount
QMenuBarItem itemIndex
QMenuBarItem text
QMenu itemNames
QTable columnHeaders
QTable rowHeaders
QTable data
QTable rowCount
QTable columnCount
QTableItem value
QTableItem rowIndex
QTableItem columnIndex
QTree columnHeaders
QTree childCount
QTree columnCount
QTreeItem value
QTreeItem rowData
QTreeItem expandable
QTreeItem expanded
QTreeItem childCount
QTreeItem rowIndex
QTreeItem columnIndex
QTreeItem itemPath
QList data
QList selectedIndex
QList itemCount
QListItem value
QListItem itemIndex
QRadioButton checked
QCheckBox checkState
QComboBox selectedIndex
QComboBox selectedName
QDial value
QEdit value

In addition to the properties listed above, each control also maintains some unique internal property names. You can refer to the fields in the object returned by the allProperties() method.

Rect Type

An object used to describe the shape and position information of a control. In CukeTest, all controls can be described by a Rectangle (Bounding Rectangle) for position and shape information. The Rect object contains the following properties:

  • x: number type, horizontal pixels of relative coordinates;
  • y: number type, vertical pixels of relative coordinates;
  • width: number type, horizontal width in pixels;
  • height: number type, vertical height in pixels;

This article only introduces the basic concepts of object operations and the methods of two base classes. For more documentation on API introduction, you can continue reading the next article: Basic Control API.

In addition, the definitions of each specific operation and property can be found in the Model Manager, or you can find them by opening the type file of the Qt automation API library included in CukeTest—leanpro.qt. The specific method is introduced in the section More API Introduction.

Qt Control Type Enumeration: QtControlType

Contains all Qt control types, usually used in findControls() method or Navigation Methods to get control objects of a specified type.

JavaScript
enum QtControlType {
    Button = 'Button',
    Calendar = 'Calendar',
    CheckBox = 'CheckBox',
    ComboBox = 'ComboBox',
    Dial = 'Dial',
    ItemView = 'ItemView',
    ViewItem = 'ViewItem',
    Label = 'Label',
    List = 'List',
    ListItem = 'ListItem',
    GraphicsView  = 'GraphicsView',
    GroupBox = 'GroupBox',
    Window = 'Window',
    Menu = 'Menu',
    MenuItem = 'MenuItem',
    MenuBar = 'MenuBar',
    MenuBarItem = 'MenuBarItem',
    Edit = 'Edit',
    Pane = 'Pane',
    ProgressBar = 'ProgressBar',
    RadioButton = 'RadioButton',
    ScrollArea = 'ScrollArea',
    Slider = 'Slider',
    SpinBox = 'SpinBox',
    StatusBar = 'StatusBar',
    Tab = 'Tab',
    TabBar = 'TabBar',
    TabItem = 'TabItem',
    Table = 'Table',
    TableItem = 'TableItem',
    ToolBar = 'ToolBar',
    ToolBox = 'ToolBox',
    Tree = 'Tree',
    TreeItem = 'TreeItem',
    QuickItem = 'QuickItem',
    Custom = 'Custom',
    Application = 'Application',
}

Control Criteria Class: Criteria

JavaScript
Python
export interface Criteria {
    appName?: string,
    type?: QtControlType | string,
    className?: string,
    name?: string,
    index?: number,
    itemPath?: ItemPath,
    itemIndex?: number,
    text?: string,
    toolTip?: string,
    'text~'?: string,
    'name~'?: string,
    'toolTip~'?: string
}
class Criteria():
  appName: str
  type: str
  className: str
  name: str
  index: int
  itemPath: TypedDict
  itemIndex: int
  text: str
  toolTip: str

ItemPath

An object used to describe the position of ListItem, TreeItem, and TableItem controls.

JavaScript
export type ItemPath = (number | [number, number])[];

API Usage Tips

Distinguishing Between Synchronous and Asynchronous Methods

IQContainer, as a container class, provides APIs for acquiring objects, as follows:

JavaScript
Python
export interface IQtContainer {
    parent: IQtContainer;
    getGeneric(...conditions: ConditionFilter[]): IQtControl;
    getWindow(...conditions: ConditionFilter[]): IQWindow;
    getButton(...conditions: ConditionFilter[]): IQButton;
    ......
    getGraphicsItem(...conditions: ConditionFilter[]): IQGraphicsItem
    getQuick(...conditions: ConditionFilter[]): IQuickItem
    ......
    getTable(...conditions: ConditionFilter[]): IQTable;
    getTableItem(...conditions: ConditionFilter[]): IQTableItem;
    getTree(...conditions: ConditionFilter[]): IQTree;
    getTreeItem(...conditions: ConditionFilter[]): IQTreeItem;
    getVirtual(...conditions: ConditionFilter[]): IVirtual;
}
class QtContainer():
  def getApplication(*conditions: List[Union[str, Dict]]) -> "QApplication"
  def getGeneric(*conditions: List[Union[str, Dict]]) -> "QtControl"
  def getWindow(*conditions: List[Union[str, Dict]]) -> "QWindow"
  def getButton(*conditions: List[Union[str, Dict]]) -> "QButton"
  def getCalendar(*conditions: List[Union[str, Dict]]) -> "QtControl"
  def getCheckBox(*conditions: List[Union[str, Dict]]) -> "QCheckBox"
  def getComboBox(*conditions: List[Union[str, Dict]]) -> "QComboBox"
  def getEdit(*conditions: List[Union[str, Dict]]) -> "QEdit"
  def getGraphicsItem(*conditions: List[Union[str, Dict]]) -> "QGraphicsItem"
  def getQuick(*conditions: List[Union[str, Dict]])-> "QuickItem"
  def getItemView(*conditions: List[Union[str, Dict]]) -> "QItemView"
  def getViewItem(*conditions: List[Union[str, Dict]]) -> "QItemViewItem"
  def getList(*conditions: List[Union[str, Dict]]) -> "QList"
  def getListItem(*conditions: List[Union[str, Dict]]) -> "QListItem"
  def getMenu(*conditions: List[Union[str, Dict]]) -> "QMenu"
  def getMenuBar(*conditions: List[Union[str, Dict]]) -> "QMenuBar"
  def getMenuBarItem(*conditions: List[Union[str, Dict]]) -> "QMenuBarItem"
  def getMenuItem(*conditions: List[Union[str, Dict]]) -> "QMenuItem"
  def getRadioButton(*conditions: List[Union[str, Dict]]) -> "QRadioButton"
  def getSpinBox(*conditions: List[Union[str, Dict]]) -> "QSpinBox"
  def getTab(*conditions: List[Union[str, Dict]]) -> "QTab"
  def getTabBar(*conditions: List[Union[str, Dict]]) -> "QTabBar"
  def getTabItem(*conditions: List[Union[str, Dict]]) -> "QTabItem"
  def getTable(*conditions: List[Union[str, Dict]]) -> "QTable"
  def getTableItem(*conditions: List[Union[str, Dict]]) -> "QTableItem"
  def getTree(*conditions: List[Union[str, Dict]]) -> "QTree"
  def getTreeItem(*conditions: List[Union[str, Dict]]) -> "QTreeItem"
  def getVirtual(*conditions: List[Union[str, Dict]]) -> "Virtual"
  def getPattern(*conditions: List[Union[str, Dict]]) -> "Pattern"

For all commonly used controls ("Widgets"), there will be a container method get[Widget] that returns the object corresponding to the Widget. For example, for a Button control, getButton is provided to return the button object.

If you compare the return values with the object operation APIs in the previous section, you will immediately notice that the return values of the object acquisition APIs are direct data types, rather than Promise<T>. This means that these are synchronous methods, i.e., you do not need to add the await keyword to get the return result. There is also a special synchronous method in the object operation APIs, which is the getItem method belonging to Table, List, and Tree controls. It is also the only synchronous method in the object operation APIs.

In CukeTest, you can distinguish between synchronous and asynchronous methods by their naming. Methods with the get prefix are synchronous and do not require the await keyword; while those without this prefix are asynchronous methods. If you do not add await, they will only return a Promise object, and adding await will yield the correct return value.

Acquiring Controls using Fuzzy Matching (Regex Matching)

Observing the Criteria object used for acquiring objects, you can find several special properties suffixed with ~.
These properties with ~ suffix represent that they allow fuzzy matching, also known as regular expression matching. You can modify the matching pattern in the Model Manager. You can also match in scripts as follows:

JavaScript
Python
// Exact match
await model.getButton({"name": "Number5"}).click();
// Match control whose name property contains "Number"
await model.getButton({"name~": "Number"}).click();
// Match control whose name property ends with "5"
await model.getButton({"name~": "5$"}).click();
# Exact match
model.getButton({"name": "Number5"}).click()
# Match control whose name property contains "Number"
model.getButton({"name~": "Number"}).click()
# Match control whose name property ends with "5"
model.getButton({"name~": "5$"}).click()

These properties can be directly generated in the Model Manager through the "[Copy Node Properties]" function, and do not necessarily need to be manually constructed.

More API Introduction

More help on control operations and properties can be found in the Model Manager, or in the script generated by dragging the model file, by holding down the Ctrl key and clicking the leanpro.qt reference at the head of the script to jump to the type definition file.