Java Convenience API
Note: The Java Convenience API is only available for Squish for Java editions.
Java Convenience Function Parameters
Some of the Java convenience functions can take a modifierState
argument which indicates which special keys are pressed at the time of a mouse click. And some of the functions can also take a button
argument which indicates which mouse button was clicked.
The modifierState
values are different for AWT/Swing/JavaFX and for SWT. The modifier states don't have an enumeration so you must use the values from the following table that are relevant to the GUI toolkit.
Modifier | AWT/Swing/JavaFX | Value | SWT | Value |
---|---|---|---|---|
No modifier | 0 | 0 | ||
Shift | java.awt.Event.SHIFT_MASK | 1 | org.eclipse.swt.SWT.SHIFT | 131072 |
Control | java.awt.Event.CTRL_MASK | 2 | org.eclipse.swt.SWT.CTRL | 262144 |
Meta | java.awt.Event.META_MASK | 4 | ||
Alt | java.awt.Event.ALT_MASK | 8 | org.eclipse.swt.SWT.ALT | 65536 |
Command | org.eclipse.swt.SWT.COMMAND | 4194304 |
If more than one is used they must be OR
-d together, for example, for Shift and Control use 1|2
for AWT/Swing/JavaFX, and 131072|262144
for SWT.
The button
can be any one of the following:
Button Specifier | Information |
---|---|
Button.NoButton | Usually: Make target visible and move mouse, but do not click. |
Button.Button1 | Left mouse button |
Button.Button2 | Middle mouse button |
Button.Button3 | Right mouse button |
The form shown above works for Python and JavaScript. For Perl use this: Button::Button1
, etc. For Ruby use this: Button::BUTTON1
, etc. For Tcl use this: enum Button Button1
, etc.
Java Convenience API Members
Here are some quick links to the Java Convenience API's members:
|
activateAction(objectName)
This function activates the JFace action object with the objectName
symbolic or real name.
Note: This function is only available when testing Java/SWT applications.
activateItem(objectOrName, itemText)
This function activates the menu item with the specified itemText
in the objectName
menu, context menu, or menu bar.
chooseColor(objectOrName, red, green, blue)
This function invisibly invokes the platform's native "choose color" dialog. The objectOrName
must always be the application's "SWT" object (":SWT"
). The color parameters must all be integers each in the range 0 to 255. They are used to specify the color that is chosen using the dialog.
Note: This function is only available when testing Java/SWT applications.
chooseDirectory(objectOrName, path)
This function invisibly invokes the platform's native "choose directory" dialog. The objectOrName
must always be the application's "SWT" object (":SWT"
) or "SquishJavaFX" object (":SquishJavaFX"
). The path
is a string which specifies the directory chosen using the dialog.
Note: This function is only available when testing SWT or JavaFX applications.
chooseFile(objectOrName, filename)
This function invisibly invokes the platform's native "choose file" dialog. The objectOrName
must always be the application's "SWT" object (":SWT"
) or "SquishJavaFX" object (":SquishJavaFX"
). The filename
is a string (that may include a path) which specifies the filename chosen using the dialog.
Note: This function is only available when testing SWT or JavaFX applications.
chooseFile(objectOrName, array of filenames)
Multiple filenames can be set with array of filenames
.
chooseFile(":SWT", ["file1", "file2"]);
chooseFile(":SWT", ["file1", "file2"]);
chooseFile(":SWT", ["file1", "file2"])
chooseFile(":SWT", ["file1", "file2"])
chooseFile(":SWT", [list "file1" "file2"])
clickButton(objectOrName)
This function clicks the specified objectOrName
button.
clickItem(objectOrName, itemOrIndex, x, y)
clickItem(objectOrName, itemOrIndex, x, y, modifierState, button)
This function clicks the mouse on the item with the specified itemOrIndex
inside the given objectOrName
view widget. This function is typically used to access items inside views such as lists, tables, and trees. For tables the itemOrIndex
is a string with the format row/column, e.g., "4/21"
; for other views it is the relevant item's text.
The click is made at position x
and y
in the itemOrIndex
item's coordinates. The button
and modifierState
parameters are optional. If they are not specified, the click is made with the left mouse button and using a null keyboard modifier state. If the button
and modifierState
are given, the click is made with the specified button and keyboard modifier state.
Supported view widgets are List, Combo, and ToolBar for the SWT toolkit, and JList, JTable, JTree, List, and Choice for the AWT/Swing toolkit.
See Java Convenience Function Parameters for which values are valid for the modifierState
and for the button
arguments.
clickTab(objectOrName, tabText)
clickTab(objectOrName, tabText, x, y)
clickTab(objectOrName, tabText, x, y, modifierState, button)
This function clicks on the tab that has the specified tabText
on the objectOrName
tab widget. The x
, y
, modifierState
, and button
parameters are optional. If the optional parameters are not given, the click is made with the left mouse button in the middle of the tab and with a null keyboard modifier state. And if all the parameters are given, this function clicks on the tab that has the specified tabText
on the objectOrName
tab widget at the position x
and y
(in the objectOrName
tab widget's coordinates) using the specified button
and the modifierState
modifier.
Note: This function can only be used with the org.eclipse.swt.custom.CTabFolder
and javax.swing.JTabbedPane
tab widgets.
See Java Convenience Function Parameters for which values are valid for the modifierState
and for the button
arguments.
clickTreeHandle(objectOrName, itemText)
This function clicks on the expand/collapse (tree handle) for the item that has the specified itemText
on the objectOrName
tree widget. The supported tree widgets are Tree for the SWT toolkit and JTree for the AWT/Swing toolkit.
closeMessageBox(objectOrName, result)
This function invisibly invokes the platform's native "message box" close dialog operation. The objectOrName
must always be the application's "SWT" object (":SWT"
). The result
is a constant which specifies the button clicked inside the dialog. Valid values for the result
are SWT.ABORT
, SWT.CANCEL
, SWT.IGNORE
, SWT.NO
, SWT.OK
, SWT.RETRY
, and SWT.YES
.
Note: This function is only available when testing Java/SWT applications.
closeWindow(objectOrName)
This function closes the objectName
Window
(or Shell
in SWT) as if it was closed using its window system menu.
collapse(treeItem)
If the treeItem
is a Swing JTree item or an SWT Tree item (e.g., as returned by the Object waitForObjectItem(objectOrName, itemOrIndex) function), it is collapsed so that none of its child items (if it has any) are visible; otherwise an exception is thrown. (See also expand(treeItem).)
doubleClick(objectOrName, x, y, modifierState, button)
This function double-clicks the mouse on the objectOrName
widget at position x
and y
(in the objectOrName
widget's coordinates) using the specified button
and with the modifierState
modifier state.
See Java Convenience Function Parameters for which values are valid for the modifierState
and for the button
arguments.
doubleClickItem(objectOrName, itemText, x, y)
doubleClickItem(objectOrName, itemText, x, y, modifierState, button)
This function double-clicks the mouse on the item with the specified itemText
inside the given objectOrName
view widget. The double-click is made at position x
and y
(in the itemText
item's coordinates). The button
and modifierState
parameters are optional; if they are not specified, the double-click is made with the left mouse button and using a null keyboard modifier state. If the button
and modifierState
are given, the double-click is made with the specified button and keyboard modifier state.
The supported view widgets are List, Combo, and ToolBar for the SWT toolkit, and JList, JTable, JTree, List, and Choice for the AWT/Swing toolkit.
See Java Convenience Function Parameters for which values are valid for the modifierState
and for the button
arguments.
dragAndDrop(source_objectOrName, sx, sy, target_objectOrName, tx, ty, operation)
dragAndDrop(source_objectOrName, target_objectOrName, operation)
This function performs a drag and drop operation. It begins by initiating a drag on the source_objectOrName
widget starting at position sx
and sy
(in the source_objectOrName
widget's coordinates), and then it does the drop on the target_objectOrName
widget at position tx
and ty
(in the target_objectOrName
widget's coordinates). If sx
, sy
and tx
, ty
are omitted, then the respectively center of the object is taken. The operation
is one of DnD.DropNone
, DnD.DropCopy
, DnD.DropMove
, DnD.DropLink
, DnD.DropMoveTarget
, or DnD.DropDefault
.
dragItemBy(objectOrName, x, y, dx, dy, modifierState, button)
This function performs a drag operation. It initiates a drag of the specified objectOrName
widget starting at position x
and y
(in the objectOrName
widget's coordinates), using the specified button
and with the modifierState
modifier state. The objectOrName
widget is dragged by dx
pixels horizontally and by dy
pixels vertically.
See Java Convenience Function Parameters for which values are valid for the modifierState
and for the button
arguments.
dropOn(target_objectOrName, tx, ty, operation)
dropOn(target_objectOrName, operation)
This function performs a drop that was initiated by a call to the startDrag(source_objectOrName, sx, sy) function. It does the drop on the target_objectOrName
widget at position tx
and ty
(in the target_objectOrName
widget's coordinates, if omitted the widget's center is taken). The operation
is one of DnD.DropNone
, DnD.DropCopy
, DnD.DropMove
, DnD.DropLink
, DnD.DropMoveTarget
, or DnD.DropDefault
.
expand(treeItem)
If the treeItem
is a Swing JTree item or an SWT Tree item (e.g., as returned by the Object waitForObjectItem(objectOrName, itemOrIndex) function), it is expanded to show its child items (if it has any); otherwise an exception is thrown. See also collapse(treeItem).
gesture(objectOrName, touches)
This function plays a gesture. The specified objectOrName
can refer to any object that is visible and serves for synchronization only. The specified touches
refers to a GestureBuilder object, which can be retrieved using readGesture(gesture-file).
installEventHandler(eventName, handlerFunctionNameOrReference)
This function installs a global event handler. The script function named or referenced in handlerFunctionNameOrReference
, will be called when an event of the eventName
type occurs.
The eventName
can be the name of any of the following event types:
- Crash: This event occurs if the AUT crashes.
- DialogOpened: This event occurs when a Dialog is opened.
- MessageBoxOpened: This event occurs when a native SWT message box is opened.
- Timeout: This event occurs when the Squish response timeout is reached.
The function named in handlerFunctionName
is called with a single argument—either the object on which the event occurred, or in the case of MessageBoxOpened
, the text of the message box.
Note: In Python scripts, you can specify the callback function to invoke by passing an actual function or a lambda function.
Using SWT's MessageBoxOpened
as an example, an event handler might look like this:
import names import os def handleMessageBox(notUsedText): test.log("MessageBox opened: '{}' - '{}'".format(lastAlert.title, lastAlert.text)) if lastAlert.text.startswith("Save"): closeMessageBox(waitForObject(names.sWT), SWT.NO) else: closeMessageBox(waitForObject(names.sWT), SWT.YES) def main(): fn = os.path.join(os.getenv("SQUISH_PREFIX"), "examples/java/addressbook_swt/AddressBookSWT.jar") startApplication('"{}"'.format(fn)) installEventHandler("MessageBoxOpened", handleMessageBox) activateItem(waitForObjectItem(names.address_Book_Menu, "File"))
import * as names from 'names.js'; function messageBoxHandler(text) { test.log("MessageBox opened [" + lastAlert.title + ": " + lastAlert.text + "]") if (text.indexOf("Save") == 0) closeMessageBox(waitForObject(names.sWT), SWT.NO) else closeMessageBox(waitForObject(names.sWT), SWT.YES) } function main() { startApplication('"' + OS.getenv("SQUISH_PREFIX") + '/examples/java/addressbook_swt/AddressBookSWT.jar"'); installEventHandler("MessageBoxOpened", messageBoxHandler) activateItem(waitForObjectItem(names.addressBookMenu, "File"));
require 'names.pl'; sub messageBoxHandler() { my ($text) = @_; test::log ("MessageBox Opened: [" . lastAlert->title() . ": " . lastAlert->text() . "]"); if ($text =~ "^Save.*") { closeMessageBox(waitForObject($Names::swt), SWT->NO); } else { closeMessageBox(waitForObject($Names::swt), SWT->YES); } } sub main() { startApplication("\"$ENV{'SQUISH_PREFIX'}/examples/java/addressbook_swt/AddressBookSWT.jar\""); installEventHandler("MessageBoxOpened", "messageBoxHandler"); activateItem(waitForObjectItem($Names::address_book_menu, "File"));
require 'squish' require 'names' include Squish def HandleMessageBox(text) Test.log("MessageBox [" + LC::LastAlert.title + ": " + LC::LastAlert.text + "]") end def main fn = File.join(ENV['SQUISH_PREFIX'], "examples/java/addressbook_swt/AddressBookSWT.jar") startApplication('"' + fn + '"'); installEventHandler("MessageBoxOpened", "HandleMessageBox") activateItem(waitForObjectItem(Names::Address_Book_Menu, "File"))
source [findFile "scripts" "names.tcl"] proc handleMessageBox {text} { test log [concat "Text: " $text] test log [concat "LastAlert (" [property get lastAlert title] ": " [property get lastAlert text] ")"] } proc main {} { startApplication "\"$::env(SQUISH_PREFIX)/examples/java/addressbook_swt/AddressBookSWT.jar\"" installEventHandler "MessageBoxOpened" "handleMessageBox" invoke activateItem [waitForObjectItem $names::Address_Book_Menu "File"]
Note: The installEventHandler
function will only work if it is called after the AUT has been started. For example, by using the ApplicationContext startApplication(autName) function.
int lastAlert.style
This property contains the style of SWT MessageBox
or DirectoryDialog
of the last suppressed native dialog. See closeMessageBox(objectOrName, result), chooseDirectory(objectOrName, path) and chooseFile(objectOrName, filename).
String lastAlert.text
This property contains the message, in case of SWT MessageBox
or DirectoryDialog
, or title, in case of JavaFX DirectoryChooser
or FileChooser
of the last suppressed native dialog. See closeMessageBox(objectOrName, result), chooseDirectory(objectOrName, path) and chooseFile(objectOrName, filename).
String lastAlert.title
This property contains the title of a SWT MessageBox
or DirectoryDialog
of the last suppressed native dialog. See closeMessageBox(objectOrName, result), chooseDirectory(objectOrName, path) and chooseFile(objectOrName, filename).
mouseClick(objectOrName)
mouseClick(objectOrName, x, y, modifierState, button)
This function clicks the mouse on the specified objectOrName
widget. The x
and y
coordinates, modifierState
, and button
are all optional. If they are not specified the click is made in the center of the widget with the left mouse button and using a null keyboard modifier state. On the other hand, if the additional parameters are given, the click is made at position x
and y
(in the objectOrName
widget's coordinates) using the specified button
and with the modifierState
modifier state.
See Java Convenience Function Parameters for which values are valid for the modifierState
and for the button
arguments.
mouseClick(objectOrName, x, y, clicks, modifierState, button)
This function clicks the mouse on the specified objectOrName
widget. The click is made at position x
and y
(in the objectOrName
widget's coordinates) using the specified button
and with the modifierState
modifier state. The clicks
parameter is a count of the number of clicks.
Note: The clicks
parameter corresponds to Java's MouseEvent.getClickCount
function.
See Java Convenience Function Parameters for which values are valid for the modifierState
and for the button
arguments.
mouseDrag(objectOrName, x, y, dx, dy, modifierState, button)
This function performs a mouse drag operation. It initiates a mouse drag of the specified objectOrName
widget starting at position x
and y
(in the objectOrName
widget's coordinates), using the specified button
and with the modifierState
modifier state. The objectOrName
widget is dragged by dx
pixels horizontally and by dy
pixels vertically.
See Java Convenience Function Parameters for which values are valid for the modifierState
and for the button
arguments.
mouseWheel(n)
mouseWheel(n, modifierState)
This function moves the mouse wheel with n
number of ticks. When n
is positive, the wheel is rotated forward and when negative, the wheel rotates backward. The optional modifierState
indicates the mouse wheel action will be carried out while holding one or more modifier keys.
Note: mouseWheel(n) should be used like the Interaction Functions for the modifierState
argument. See Java Convenience Function Parameters.
nativeMouseClick(objectOrName)
nativeMouseClick(objectOrName, x, y, modifierState, button)
Note: This function is specific to the AWT/Swing toolkit. All SWT mouse clicks are always performed natively, so this function would be redundant for SWT.
This function clicks the mouse on the specified objectOrName
widget. The x
and y
coordinates, modifierState
, and button
are all optional. If they are not specified the click is made in the center of the widget with the left mouse button and using a null keyboard modifier state. On the other hand, if the additional parameters are given, the click is made at position x
and y
(in the objectOrName
widget's coordinates) using the specified button
and with the modifierState
modifier state.
See Java Convenience Function Parameters for which values are valid for the modifierState
and for the button
arguments.
readGesture(gesture-file)
This function opens a gesture file from a test suite directory and returns a GestureBuilder object. This can then be passed to gesture(objectOrName, touches). The specified gesture-file
refers to the filename.
startDrag(source_objectOrName, sx, sy)
startDrag(source_objectOrName)
This function initiates a drag on the source_objectOrName
widget starting at position sx
and sy
(in the source_objectOrName
widget's coordinates, if omitted the widget's center is taken). The drop can be done using the dropOn(target_objectOrName, tx, ty, operation) function.
Normally the dragAndDrop(source_objectOrName, sx, sy, target_objectOrName, tx, ty, operation) function is used to perform a drag and drop in a single action. However, in some situations it may be necessary to move the mouse over a different object before the drop can take place. In such cases the test code would look something like this:
startDrag(sourceObject, sx, sy) mouseMove(otherObject, x, y) dropOn(targetObject, tx, ty, operation)
type(objectOrName, text)
This function types the specified text
(as if the user had used the keyboard) into the objectOrName
editable widget. If the text is surrounded by angle brackets (<>), it is interpreted as a key combination, e.g "<Ctrl+Return>"
. The input is case-sensitive, so type(object, "R")
is different from type(object, "r")
. For a list of the supported special keys, see the nativeType(keys) function's documentation.
uninstallEventHandler(eventName, handlerFunctionNameOrReference)
This function uninstalls an event handler that has been previously installed using installEventHandler(eventName, handlerFunctionNameOrReference).
Native Java Arrays
In addition to the functions described above, test scripts can create native Java arrays, and insert and retrieve objects stored in the arrays. For examples of use, see Creating and Using JavaArrays.
Array JavaArray(size)
Array JavaArray(size, nameOfType)
This is a constructor function for creating native Java arrays. The size
specifies how many objects it may contain (indexed from 0, so the last valid index is size
- 1
). If the optional nameOfType
string is omitted, the function will return an array of type java.lang.Object[size]
; otherwise the array will be of type nameOfType[size]
.
The nameOfType
is a string that can specify a non-object type such as "int"
, or an object type such as "java.lang.String"
.
JavaArray
s have two functions and one property.
Object JavaArray.at(index)
This function returns the object at position index
in the array. If the index
is out of bounds a catchable exception is raised.
int javaArray.length
This read-only property holds the number of positions in the array. The first item is at position 0 and the last item is at position javaArray.length - 1
.
Object JavaArray.set(index, object)
This function sets the item at position index
in the array to the given object
. If the index
is out of bounds or if the object
is of an invalid type (e.g., a string when the JavaArray holds integers), a catchable exception is raised.
GestureBuilder
Objects of this type hold the touch strokes information needed to replay gesture(objectOrName, touches). An instance of this class is returned by readGesture(gesture-file). Strokes are defined by JavaFX scene coordinates points.
For examples of how GestureBuilder
objects can be used to manipulate the gesture information, see How to Use the GestureBuilder class.
int GestureBuilder.areaWidth
The width of the area in which this gesture is defined. This will be the scene width.
int GestureBuilder.areaHeight
The height of the area in which this gesture is defined. This will be the scene height.
All GestureBuilder methods listed in the Gesture creation and Gesture manipulation section, return the GestureBuilder object itself, unless specified differently.
Gesture creation
This section lists the methods for manually creating a GestureBuilder object.
GestureBuilder(width, height, unit)
GestureBuilder(xml)
Two constructor functions for creating a GestureBuilder object. The width
and height
are the target scene sizes. The unit
can be either 0 or 1, meaning respectively in pixels or millimeters. The constants GestureBuilder.Pixel
and GestureBuilder.MilliMeter
can be used as well.
The second constructor function constructs a GestureBuilder object by passing a string containing XML, which should be in the same format as the recorded gesture files.
Object GestureBuilder.addStroke(x, y)
Object GestureBuilder.addStroke(startTime, x, y)
Starts a new stroke. The whole movement of one finger or pen from touch down to releasing the screen is called a stroke. The touch down coordinate is (x
, y
).
For the non-first stroke, a time offset can be specified in milliseconds using the startTime
argument. Strokes cannot be disjointed in time, at least one finger or pen has to be down during the whole gesture. The maximum simultaneous touches is device dependent.
Object GestureBuilder.curveTo(duration, controlX, controlY, endX, endy)
Object GestureBuilder.curveTo(duration, control1X, control1Y, control2X, control2Y, endX, endy)
Adds a bézier curve movement to the latest added stroke in duration
milliseconds. The curve starts with the end coordinate of the last added movement or, if none added to the stroke, the stroke touch down coordinate. The end coordinate is specified with endX
and endY
. One or two so called control points can be used.
Object GestureBuilder.lineTo(duration, endX, endy)
Adds a line movement to the latest added stroke in duration
milliseconds. The line starts with the end coordinate of the last added movement or, if none added to the stroke, the stroke touch down coordinate. The end coordinate is specified with endX
and endY
.
Object GestureBuilder.build()
Creates the gesture from the added strokes and movements. After calling this method, no strokes or movements can be added.
Gesture manipulation
Object GestureBuilder.accelerate(factor)
Changes stroke speed given a factor. A factor between 0.0 and 1.0 slows down the gesture, above 1.0 will speed it up.
Object GestureBuilder.rotate(degrees)
Object GestureBuilder.rotate(degrees, originX, originY)
Rotates the strokes. The degrees
is the agle in degrees in a counter clockwise direction. The originX
and originY
define the origin of the rotate operation. If omitted, the area center is taken as origin.
Object GestureBuilder.scale(scale)
Object GestureBuilder.scale(scaleX, scaleY)
Object GestureBuilder.scale(scaleX, scaleY, originX, originY)
Changes the size of the strokes. The scaleX
is the scale factor in the horizontal direction and scaleY
in the vertical direction. The originX
and originY
define the origin of the scale operation. If omitted, the area center is taken as origin. When also scaleY
is omitted, then the scaling is homogeneous in both directions.
Object GestureBuilder.translate(x, y)
Moves the strokes. The x
and y
specifies the movement. A positive value for x
moves the strokes to the right and a positive value for y
moves the strokes downwards.
Java Hardcoded Synthetic Properties
In addition to the public Java class fields, and synthetic properties generated from get*
and is*
functions, Squish provides some additional properties to make it easier to identify objects. (See Defining Property Sets for more details.)
These properties can only be used with the object name. And are not visible in the object properties list.
Property | Type | Description |
---|---|---|
aboveWidget | Object | Holds the object above this widget in the same logical parent Container or Composite . This should be used for objects that don't have a caption but often come with an accompanying widget. For example, edit boxes have no caption but might have a label above them. |
arrowDirection | String | Holds the direction of SWT buttons that have the arrow style enabled. |
buttonType | String | Holds the type of SWT buttons. This property is useful for identifying buttons with arrows. |
caption | String | Holds the object's title, caption, or text, if this object typically has such text to display. |
container | Object | Holds the parent Container or Composite that contains this object. These are typically tab pages or the menu bar. |
firstItemText | String | Holds the first text to be found for child SWT ToolItem objects. If no text is found, then the tooltip text is used. This property's value could be the empty string if no text is found and no tooltip text is set. |
firstTabCaption | String | Holds the caption of the first CTabItem of a CTabFolder . This property's value could be the empty string if no text is found. |
leftWidget | Object | Holds the object to the left of this widget in the same logical parent Container or Composite . This should be used for objects that don't have a caption but often come with an accompanying widget. For example, edit boxes have no caption but often have a label on their left. |
menuStyle | String | Holds the style of SWT menu—this indicates whether the menu is a menu bar, a popup menu, or a pull-down menu. |
type | String | Holds the object's class name—but with any periods in the name replaced with underscores. |
window | Object | Holds the top-level window that contains this object. |
Java Extension API for Custom Widgets
Introduction
Squish can work with all the standard AWT/SWT widgets out of the box. However, some custom widgets may represent their child components in a non-standard way, that is, not as AWT/SWT components. For example, a canvas might use normal Java objects to represent the items it displays. Or a Gantt diagram component might render its own contents, taking its data from a model. Squish's Java extension API makes it possible to extend Squish so that non-standard components in AWT and SWT applications can expose their APIs so that they become accessible to Squish and can therefore be accessed in test scripts just like any other component.
In order to tell Squish what functionality to expose, we introduce the concept of an Inspectable class. An Inspectable class is one that can respond to Squish's queries about objects of a particular type. For example, an Inspectable could handle canvas item types, and provide an API that can give Squish the canvas's bounds or its parent, or that returns all of its child items. The precise APIs are listed in the Inspectable interface; see Java Extension API Reference.
Once the Inspectables are registered, whenever Squish encounters an object, Squish queries each Inspectable to see if the Inspectable can handle the object (i.e., objects of the object's type). If one of the Inspectables reports that it recognizes the type as one it can handle, Squish uses that Inspectable's interface to interact with the object. This allows Squish to treat the object just like any of the standard AWT/SWT types that it supports out of the box—for example, Squish can query the Inspectable to see if the object has received a mouse click.
All the Inspectables for the types you want to Squish to be able to handle are placed together in a "wrapper" library. A clean way to do this is to put all the Inspectables classes in their own jar, although it is also possible to add them to the application's existing jar. The canvastest example shows how to put the Inspectables into their own jar.
Using the Java Extension API and a suitable wrapper, it is possible to support non-AWT/SWT components alongside standard AWT/SWT components so that Squish can:
- Identify both AWT/SWT and non-AWT/SWT components in test scripts.
- Use verification points on both AWT/SWT and non-AWT/SWT components.
- Show both AWT/SWT and non-AWT/SWT components in the overall Spy hierarchy.
- Pick both AWT/SWT and non-AWT/SWT components using the object picker.
See also, Wrapping custom classes
Custom canvas Example
To show how a wrapper to extend an existing AWT application works, we will use the canvastest example which is shipped together with Squish for Java. You can find the source code in SQUISHDIR/examples/java/canvastest
. (We could just as easily have extended an SWT application using exactly the same approach.)
The application's source files are CanvasTest.java
, MyCanvas.java
, MyCanvasItem.java
, MyCanvasGroup.java
, MyCanvasShape.java
, MyRectCanvasItem.java
, MyCircleCanvasItem.java
, and together they comprise an AWT application that provides a simple canvas with multiple items.
We want test scripts that test the canvastest application to be able to query the application's MyCanvas
objects—to retrieve a MyCanvas
, to get a MyCanvas
's parent object, to get the canvas's bounding rectangle, and to get the MyCanvasItem
item at a particular point, or all of the canvas's MyCanvasItem
items. In addition, we want to be able to query MyCanvasItem
objects, to get their bounding rectangles, and so on. To do all this we must create suitable Inspectable Java classes that Squish can query to get interfaces through which it can query the application's canvas and canvas items as if they were standard AWT/SWT objects.
We have put the Inspectable classes in the MyCanvasFactory.java
file in the same directory as the application's other Java files. The Squish Java extension API classes are contained in the file SQUISHDIR/lib/squishjava.jar
, and so this file must be in the class path to be able to compile MyCanvasFactory.java
.
See Java Extension API Reference for information about the extension API.
Once the Inspectable classes have been created, Squish must be informed that they exist so that it can make use of them. All that is required to do this is to tell Squish which application the wrapper should be used for and where the wrapper is located. This is done by setting a configuration on the squishserver:
squishserver --config setConfig CanvasTest.jar \ $SQUISHDIR/examples/canvastest/Extension.ini
Here we have used a Unix-style path and assumed that the environment variable SQUISHDIR
has Squish's installation directory. It doesn't matter what the path used actually is (so long as it is an absolute path, and the correct one for the Extension.ini
file).
The Extension.ini
file must list the directory where the extension is located. A relative path is possible and should be relative to the working directory of the application. Here's the canvastest's Extension.ini
file's contents:
[general] JavaExtensionDir="."
If you are using Windows you should either use forward slashes or escape the backslash by writing the directory to the ini file.
To demonstrate testing the AUT with the wrapper we have provided a very basic test suite in SQUISHDIR/examples/java/suite_canvastest_js
.
Sometimes the application provided objects aren't suitable because they don't provide parent/child relationship. In that case, a helper class can be used. This class must be added to the extension.jar.
For example, take a popularity component, that draws five stars and the coloring shows the percentage. In such a case, a helper class with the component and index represents one star. The component children are five of such helper class instances. For each instance, the component is the parent.
Thus the Inspectable for the component creates helper objects in getChildren and getChildAt when at a star. An additional Inspectable for the helper objects makes them visible to Squish. Add public getter functions for any properties that you may need, e.g. a getIndex and getFill.
Make sure that helper classes override the java Object equals and hashCode methods, such that equals returns true when the fields are equal and hashCode is a value distinguishing the equality. In above example, the following code is required:
public boolean equals(Object obj) { if ( obj == null || !( obj instanceof StarHelper)) return false; StarHelper other = (StarHelper)obj; return other.index == index && other.component.equals( component); } public int hashCode() { return component.hashCode() + index + /*some random number*/ 43; }
Creating the .jar File
The manifest file must contain an Extension
entry that has as its value the class which has the public static void init(InspectableRegistry registry)
method. This function is the entry point for the extension and should register the factory class in the registry
.
For applications that load their classes with one or more class loaders that differ from the system class loader, an entry LoadAtClass
must be added. All RCP fall in this category.
The value of this entry is the class that will trigger the extension registration, as soon as that class gets loaded by a class loader. This may require some trial and error, because all the fields of the factory classes that get registered must already be known to the class loader.
For this example, LoadAtClass
is set to the Canvas
class. Here the manifest file for the extension jar.
Extension: MyCanvasFactory LoadAtClass: MyCanvas
Java Extension API Reference
Class Color | |
Interface Inspectable — This interface needs to be implemented for custom Java support in Squish. | |
Class InspectableAdapter — Adapter class for writing extensions. | |
Interface InspectableFactory — A Factory that delivers an Inspectable for custom Objects that it manages. | |
Class InspectableRegistry — This class allows registration of factories of extensions that implement Inspectable. | |
Interface ItemExtension — This interface must be implemented when the Inspectable handles objects that have textual items, written in the test scripts using waitForObjectItem. | |
Interface ObjectQuery | |
Class Point — Toolkit independent Point class. | |
Class Rect — Toolkit independent Rectangle class. | |
Interface TableExtension — This interface can be implemented by an Inspectable, where its inspectable object has rows and columns. | |
Interface TargetExtension — This interface can be implemented when the inspectable object is part of another object. | |
Interface ViewportExtension — This interface can be implemented when the inspectable object has scrolling capabilities. |
© 2024 The Qt Company Ltd.
Documentation contributions included herein are the copyrights of
their respective owners.
The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation.
Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property
of their respective owners.