Making clicks reliable (readiness & waits)
The most common flake is a click that "works sometimes." It happens when Trq clicks a button before the page's JavaScript has wired up its handler β the element is on screen, but the framework (React/Angular/Vue) hasn't attached the onClick yet, or a still-loading chunk hasn't run. The click lands on nothing and the step silently does nothing.
Trq fixes this with a layered set of waits. Each layer is independent β use as few or as many as your app needs. They're listed from "always on, zero config" to "most explicit, most control."
Layer 1 β Actionability checks (automatic)β
Before every click, Trq already waits until the target element is:
- enabled β not
disabled,aria-disabled, orpointer-events:none, - stable β its position hasn't moved for two animation frames (not mid-animation), and
- the real hit-target β nothing is covering it (no overlay/modal/spinner on top).
This is on by default and needs no configuration. It catches overlay and disabled-button flakes. It does not, on its own, wait for late-loading JS β that's what the next layers add.
Layer 2 β Wait before each action (Settings β Readiness)β
Open Settings β Readiness β "wait before action" and pick a page state to wait for before every click / input / keypress / drag / upload in the session:
| Option | Waits until⦠| Use when |
|---|---|---|
| off (default) | (no extra wait) | the app is fast / static |
| DOM content loaded | the HTML is parsed | you only need the DOM present |
| load | the load event fired (HTML + images + CSS + scripts) | sub-resources matter |
| network idle | load and the network has been quiet (~500 ms) | the flaky-click fix β SPAs that attach handlers after their JS chunks finish loading |
For the "sometimes works" click problem, choose network idle. It holds each action until the late-loading chunk that wires up the handler has actually finished. It's best-effort: if the page never settles within the readiness timeout (Settings β Timeouts β readiness, default 5000 ms), Trq proceeds anyway rather than failing.
Heads-up on
network idle. It adds up to ~half a second per action on fast pages, and on apps with constant background polling it may always hit the timeout. Turn it on for sessions that are actually flaky, not globally.
Layer 3 β Wait before one step (per-event override)β
If only one click is flaky, you don't need to slow the whole run. Open the Edit drawer on that step β "Wait before this step" β custom condition, and set a wait that applies to just that event. You can wait for a load state, or for a specific element/text/URL/network response β e.g. "wait until #submit is enabled before clicking it."
Layer 4 β Insert a standalone wait/assert stepβ
Right-click any step in the Events tab β Insert event above / below to drop a free-standing wait step into the timeline. Pick what to wait for:
- load state β
domcontentloaded/load/network idle - element state β
visible/hidden/enabled/attached/detached - text present β text appears (optionally scoped to a selector)
- url matches β the URL matches a substring or
*glob - network response β a response for a URL pattern arrives
- fixed delay β a flat pause (escape hatch; see below)
Each wait has a mode:
- soft (default) β wait: if the condition isn't met by the timeout, proceed anyway.
- hard β assert: if the condition isn't met by the timeout, fail the run.
What to do β and what to avoidβ
β
Do β wait on a consequence. The most robust pattern is to assert on what the click was supposed to cause, not to guess a delay. After a click that opens a dashboard, add an assertion (or a hard wait) for "Dashboard heading is visible" or "url matches */dashboard". Waiting for the real outcome auto-retries until it's true β precise, self-documenting, and fast.
β
Do β prefer the narrowest layer that fixes it. A per-step "wait until this button is enabled" (Layer 3) is better than turning on network idle for the whole session (Layer 2), which is better than sprinkling fixed delays.
π« Don't β lean on delay (fixed sleeps). Too short and it still races, too long and every run pays. Use it only when there's genuinely no observable signal to wait on.
π« Don't β globally enable network idle "just in case." On chatty apps it never goes idle and burns the timeout on every action.
π« Don't β crank timeouts to paper over a missing wait. A 60-second action timeout doesn't make a too-early click correct β it just makes failures slow.
Rule of thumb: assert the consequence (Layer 4, hard) when you have a clear outcome to check; use
network idle(Layer 2/3) for "handler not wired yet" flakes; reserve fixed delays for nothing-else-works cases.