Compose Methods

To combine several element actions, such as a method for login that sets a username, sets a password, and clicks a button, declare a compose method.

A compose method has these properties:

  • name (Required) String. The unique name of the method within this JSON file.
  • description (Optional) String or Object. See Method Description.
  • compose (Required) Array. Each object is an element and a method.
    • element (Optional) String. The name of a basic element from the same JSON file. Defaults to self, which is a reference to the current page object. When a statement refers to the current page object, it can apply the page object's methods. Specify an element only if you need to operate on or interact with it. For an explicit wait using the waitFor keyword, omit the element.
    • apply (Optional) String. If this property isn't defined, the getter method for the element property is called.
      • Basic element: the name of a supported action to apply to the element.
      • Custom element: any public method.
    • args (Optional) Array. If the apply action needs parameters, provide them in an array. Each element of the array has these properties:
      • name (Required) String. A parameter name that is unique in the scope of the args array.
      • type (Required) String. One of these primitive types: string, number, or boolean.
    • matcher (Optional) Object. Defines the filter criteria for the data returned by the apply method or the element's getter method.
      • type (Required) String. The matcher type for filtering data. For supported types, see Matchers.
      • args (Optional) Array. If the matcher type requires arguments, pass them in this array.
    • returnAll (Optional) Boolean. If true, the method returns an array (in JavaScript) or a list (in Java) of objects. The default is false.
    • returnType (Optional) String. Explicitly set the return type for the method. You can set a primitive type, such as "string", "number", "boolean", or a custom type, such as "my/page/object". This property is optional because the return type for a compose method can sometimes be inferred by the UTAM compiler. For more information, see Method Return Types.
  • args (Optional) Array. To access an argument passed to a compose method in multiple statements, declare a reusable argument at the method level. For more information, see Argument Reference.

A compose method or element can have a description that explains its usage, return value, and parameters. The description is used to generate JavaDoc or JSDoc.

The simplified description format is one string property:

The generated method includes the following Javadoc or JSDoc. By default, the @return tag contains the inferred return type and the @param tag has the name and type of the parameter:

The extended object description format enables you to describe more information, such as the return value:

  • text string array describing what the method or element does
  • return (Optional) string that describes the return value
  • throws (Optional) string that describes a thrown exception and when it's thrown
  • deprecated (Optional) if the method is no longer supported, this string explains when and why the method was deprecated.

To provide a description for the parameter, we added a description property for the attrName argument. The description is only possible for non-literal (not hardcoded by value) arguments.

The generated method has the following Javadoc or JSDoc:

In Java, the generated method is marked with an @Deprecated annotation.

The same description format can be added to any element:

See Method Return Types.

This compose method sets text on the root element and clicks a submit button.

Here's the generated Java code:

Here's the generated JavaScript code:

The invokeSubmitForm method simply invokes the submitForm method declared in the same page object.

This pattern is useful if you want to reuse the same method in multiple compose statements. For example, you could call submitForm from login and loginWithDeepLink methods.

Here's the generated JavaScript code:

This compose method invokes the getter for the myCustomComponent element.

Here's the generated JavaScript code.

This compose method applies the someUnknownPublicMethod method to the myCustomComponent custom element.

Note that the compiler can't know if the someUnknownPublicMethod method actually exists, and what are its return value or parameters. The responsibility to validate those things belongs to the developer or a preruntime compilation step (depending on the setup).

Here's the generated JavaScript code:

Use a matcher to transform the return value of a compose statement.

This compose statement uses a matcher to return a non-null value.

For more information on matchers, see Element Filters: Matchers.

It's possible to "chain" compose statements. A chain applies a method or a getter to the result of the previous statement.

Chains are supported only if the previous statement returns a custom type (another page object).

To apply a method or a getter from the current statement to the result of the previous statement, use the "chain": true property inside a statement.

The chain methods approach has some disadvantages and limitations:

  • Because the referenced elements and methods (except the first) are defined in other JSON files, the UTAM compiler can’t validate the correctness of the chain until the page object is generated. If the element doesn’t exist, if it isn’t public, or if the type is incorrect, the problem is discovered when the generated code is compiled.
  • The current page object now depends on the content of other page objects, so changes in those might prevent the page object from compiling. We notice the issue during build, but it's more difficult to manage.
  • The page object author might not be aware of the internals. If another team adds a chained method, ownership of the page object is unclear.

Here are some examples of chaining compose statements.

Consider the following test code samples:

It's possible to compose the long version into a short version using a chain.

If both previous and current statements return lists ("returnAll": true), the method is applied to each returned element using flatMap.

Consider the use case of a table with multiple rows and cells. Assume that each row and cell is a separate component. Let's write a method that returns all cells inside a table.

  • table row JSON
  • table JSON

Generated Java code:

A pageObject type parameter can be used to invoke a container method inside a compose statement.

Generated JavaScript code:

Frame and Root Page Object type parameters can be used to compose entering a frame:

Generated JavaScript code: