Java Automation APIs
Generating automation code for Java controls is similar to that of Windows controls.
Java Container API
The container API is the API used to fetch objects, as follows:
interface IJContainer {
parent: IJContainer;
getJWindow(...conditions: ConditionFilter[]): IJWindow;
getJButton(...conditions: ConditionFilter[]): IJButton;
getJCheckBox(...conditions: ConditionFilter[]): IJCheckBox;
getRadioButton(...conditions: ConditionFilter[]): IJRadioButton;
getJEdit(...conditions: ConditionFilter[]): IJEdit;
getJCustom(...conditions: ConditionFilter[]): IJControl;
getJList(...conditions: ConditionFilter[]): IJList;
getJMenu(...conditions: ConditionFilter[]): IJMenu;
getJLabel(...conditions: ConditionFilter[]): IJLabel;
// You can refer to the next section - "The method of dynamically obtaining controls: findControls" introduction
findControls(...conditions:ConditionFilter[]):IJControl[];
}
Java object members
Default Controls: JControl
All Java objects inherit from the IJControl
class, which in turn inherits from the IJContainer
class mentioned above, which is the Java container class:
interface IJControl extends IJContainer {
click(x?: number, y?: number, mousekey?: number): Promise<void>;
dblClick(x?: number, y?: number, mousekey?: number): Promise<void>;
moveMouse(x?: number, y?: number): Promise<void>;
pressKeys(keys: string, options?: PressKeysOptions | number): Promise<void>;
takeScreenshot(filePath?:string):Promise<string>;
name():Promise<string>;
}
And each particular object may have its own control methods and properties, For example:
RadioButton
interface IJRadioButton extends IJControl {
check(): Promise<void>;
// Get selected status
checked(): Promise<boolean>
}
JCheckBox
interface IJCheckBox extends IJControl {
checkState(): Promise<boolean>
toggleCheck(checkState: boolean): Promise<void>
}
JEdit
interface IJEdit extends IJControl {
set(value: string): Promise<void>;
value(): Promise<string>;
}
JList
interface IJList extends IJControl {
getItem(itemIndex:number):Promise<string>;
itemCount():Promise<itemCount>;
}
JMenu
interface IJMenu extends IJControl {
}
JMenu
control above, i.e. the menu control. Usually the menu that is expanded in the toolbar belongs to the JMenu
control. Since menus usually pop up only after clicking or hovering, we need to pay attention to two techniques when detecting such controls:
- hold down the
Ctrl
key to resume normal clicking: clicking on the control during detection will automatically add the control to the model manager, and holding down theCtrl
key on the keyboard during recognition will restore it to normal clicking, at which point clicking will expand the menu. - Wait a little while detecting: When detecting menu controls, it occasionally happens that the detected control is incorrect, usually in scenarios where the menu option the mouse points to jumps to a new interface, closes a window, and other scenarios that change the structure of the application model. For this, the current solution is to hold down the left button while detecting the menu control to identify the control and don't release it until the detector pops up, so that the target menu control can be correctly identified.
JTable
interface IJTable extends IJControl {
clickCell(rowIndex: number, columnToFind: string | number);
cellValue(rowIndex: number, columnNameOrIndex: number | string): Promise<string>;
data(): Promise<string[][]>;
setCellValue(rowIndex: number, columnToFind: string | number, value: string);
columnCount(): Promise<number>;
columnHeaders(): Promise<string[]>;
rowCount(): Promise<number>;
}
clickCell
method will perform double-click the target cell, if the cell can be edited will enter the editing state, you can use thepressKeys
method to enter the specified content (or directly usesetCellValue
to set the contents of the target cell, if the cell can not be edited, it is invalid).
findControls
Provides a way to directly match multiple controls that match the filter criteria without relying on the model manager.The findControls
method is used in the same way as in Windows Automation, see findControls in Windows. The findControls
method takes parameters similar to the other get[ControlType]
methods, for example:
Runtime identification properties
At code runtime, you can not only match objects in the model manager by object name, but also dynamically match controls from the application that meet the identified properties by using the identified properties. The advantage of this is that for dynamically changing, but predictable controls, adding the recognition property increases the accuracy of the match and allows you to perform the operation in the automation script without adding it to the model manager in advance. Here are a few examples of code that use the recognition property:
await model.getJButton("button1").name(); // Suppose button1 is a button control and the name property is "Press Me"
// The following two lines of code can match the same control as the previous line
await model.getJButton({name: "Press Me"}); // Only one matching JButton control will be returned, and only the first one will be returned if multiple matches are made.
await model.findControls({name: "Press Me", type:"JButton"}); // Returns an array of all eligible control objects
Introduction of identification properties
search
At code runtime, controls are matched from the application based on the properties of the action object. And since the matching direction is from the topmost control down one layer of controls, that is, when matching a control, all its parent controls are matched with increased accuracy. This poses a problem, as window controls usually act as the topmost node, which results in the lowest recognition accuracy. The search indicator property search
provides a way to specify the matching direction indication, such as indicating the matching direction upward, so that you can in turn use a control as a starting point and match the window, container, or panel where the control is located upward.
Assuming that there are multiple windows in the runtime environment at this point, the following script can be used if trying to close the login window:
let button = model.getJButton("Login"); // Login button unique to the login window
await button.getJWindow("JWindow",{search:"up"}).close(); // The window where the Login button is located is the login window
Simple Java automation sample code
The following is an example of a call to a Java object:
Sample 1:
const { JavaAuto } = require('leanpro.java');
const model = JavaAuto.loadModel(__dirname + '/java_model.tmodel');
(async function () {
try {
await model.getJEdit("text1").set('some content');
} catch(err) {
console.log('err', err)
}
})();
In order to get Java controls from the model, you should start calling from model
, which will return the root IJContainer
"` object, which in turn can get other Java objects from the model.
When you call a member on a Java object and the Java object cannot find the matching control, it will raise a "object not found" exception.
If the "text1" object can find the edit box control, it sets its content to "some content".
Sample 2:
The following is a sample snippet that gets the checkbox's checked or unchecked state and toggles its state to checked.
(async function () {
let checkbox = model.getJCheckBox('checkbox-0'); // Assume False is unchecked at this point
console.log('checked state', await checkbox.checkState());
await checkbox.toggleCheck(true);
let checkbox = model.getJCheckBox('checkbox-0'); // Then True is selected at this time
})();