Here we introduce some tips when you use a browser testing tool to test ZK-based applications, e.g. JMeter, TestCafe, selenium.

Note: ZK distinguishes between a component’s ID (set by the developer, used server-side) and its UUID (generated by ZK, used in client-side HTML/JS and automation). For a detailed explanation, see Component ID, ID Space, and UUID.

Deal with Randomized UUID

By default, a desktop’s ID and a component’s UUID are randomized for preventing Cross-Site Request Forgery (CSRF) and allowing multiple desktops to coexist on the same web page (such as Portlet). A component’s UUID is auto-generated by ZK and different from its ID. The UUID is used as a component DOM elements’ id in a browser. However, it also means the DOM element’s IDs will change from one test run to another.

If your test code runs at the server (such ZATS and JUnit), it is not an issue at all (since DOM elements are available at the client only). However, if your test tool runs in a browser, you have to locate an element with one of the following approaches:

  1. Not to depend on a DOM element’s ID. Rather, use a component’s ID and/or component’s parent-child-sibling relationship.
  2. Implement org.zkoss.zk.ui.sys.IdGenerator

    to generate UUID in a predictable and repeatable way

Let me explain them in detail.

Approach 1: Locate by a component’s ID

With Server+client architecture, ZK maintains an identical world at the client. If your test tool is able to access JavaScript at the client, your test code can depend on a component’s ID and its widget’s parent-child relationship as your application code depends on the component’s ID and component’s parent-child relationship. They are identical, except one is JavaScript and called zk.Widget, while the other is Java and called

org.zkoss.zk.ui.Component

.

This is a suggested approach since it is much easier to test an application at the same abstract level – the component level, aka., the widget level (rather than the DOM level).

To retrieve widgets at the client, you can use one of the following JavaScript API:

  • \_global\_.jq
  • zk.Widget
\_global\_.jq

allows your test code to access the components directly, so the test code could depend on a component’s ID (zk.Widget) and the widget tree (zk.Widget,

zk.Widget

and so on).

jq('@window[border="normal"]') //returns a list of window whose border is normal
jq('$x'); //returns the widget whose component ID is x, <div id="x"/>
jq('$x $y'); //returns the widget whose ID is y and it is in an ID space owned by x

With this approach, you still can verify the DOM structure if you want, since it can be retrieved from a widget’s

zk.Widget

.

ZTL is a typical example that takes this approach. For more information, please refer to the ZTL section.

Approach 2: Use ID Generator for Fixed or Predictable UUIDs in Automated Testing

If your testing tool running in a browser cannot access JavaScript, you can implement an ID generator to generate a desktop’s ID and component’s UUID in a predictable and repeatable manner.

Since ZK 7.0.0, ZK provides a static ID generator implementation for testing, to use

org.zkoss.zk.ui.impl.StaticIdGenerator

, simply add it to zk.xml.

<system-config>
    <id-generator-class>org.zkoss.zk.ui.impl.StaticIdGenerator</id-generator-class>
</system-config>

To implement a custom ID generator, you have to do the following:

  • Implement a Java class that implements org.zkoss.zk.ui.sys.IdGenerator

    .

  • Specify the Java class FQCN at id-generator-class element in zk.xml. For example,
<system-config>
    <id-generator-class>my.IdGenerator</id-generator-class>
</system-config>

Examples

Different Configuration for Different Environment

If you prefer to have a different configuration for the testing environment (such as specifying ID generator for testing), you could put the configuration in a separate file, say, WEB-INF/config/zk-testing.xml with the following content.

<zk>
  <system-config>
    <id-generator-class>my.IdGenerator</id-generator-class>
  </system-config>
</zk>

Then, you could you could specify -Dorg.zkoss.zk.config.path=/WEB-INF/config/zk-testing.xml as one of the arguments when starting the Web server.

Disabled UUID Recycle (UUID Management for Testing and Automation)

If you want to generate UUID with some conditions, you might also want to disable UUID recycling. ( It will reuse all the UUIDs from removed components.) You could set the properties org.zkoss.zk.ui.uuidRecycle.disabled in zk.xml.

Frequently Asked Questions (FAQ)

  • How can I make ZK component UUIDs or desktop IDs static or predictable for testing?
    • See the section on using IdGenerator for fixed or repeatable UUIDs.
  • How do I implement a custom ID generator in ZK?
    • Refer to the “Approach 2: Use ID Generator for Fixed or Predictable UUIDs” section.
  • Why do UUIDs change between sessions or actions in ZK?
    • By default, ZK randomizes UUIDs for security and multi-session support. See the introduction.
  • How can I fix issues with random UUIDs when scripting tests (e.g., with JMeter, Selenium)?
    • Use a custom IdGenerator or StaticIdGenerator to generate predictable UUIDs.
  • What should I do if my test tool cannot reliably locate elements due to changing UUIDs?
    • Use component IDs and parent-child relationships, or configure a custom IdGenerator.
  • Is there a way to configure ZK to generate fixed or repeatable UUIDs for automated testing?
    • Yes, see the section on IdGenerator and StaticIdGenerator.
  • How do I handle issues with UUIDs in security testing or DAST tools?
    • Use predictable UUIDs for testing, and review upload endpoint handling for invalid UUIDs.