Skip to content

fix(actions): tick duration = max(pause) across sources, not sum#497

Merged
goosewobbler merged 2 commits into
mainfrom
fix/actions-pause-max-per-tick
Jun 30, 2026
Merged

fix(actions): tick duration = max(pause) across sources, not sum#497
goosewobbler merged 2 commits into
mainfrom
fix/actions-pause-max-per-tick

Conversation

@goosewobbler

Copy link
Copy Markdown
Contributor

Closes #496. Follow-up to the tick-by-tick work (#491/#488/#492).

Problem

W3C WebDriver Actions §17.4.3 defines a tick's duration as the maximum pause/move/scroll duration across its sources — not the sum. After the tick-by-tick refactor, both embedded-driver handlers still slept each source's duration sequentially within a tick, so e.g. pause(100ms) in one source + pause(200ms) in another at the same tick took 300 ms instead of the spec's 200 ms.

Fix (both handlers, kept converged)

  • packages/dioxus-embedded-driver/src/server/handlers/actions.rs
  • packages/tauri-plugin-webdriver/src/server/handlers/actions.rs

Each handler now computes the tick duration up front via a pure ActionSequence::duration_at(tick) helper (mirroring the existing action_count), dispatches the tick's actions without per-source sleeps, and sleeps the single max once at the end of the tick. Pause arms become no-ops; pointer-move / wheel-scroll dispatch immediately and contribute their duration to the tick max.

This also makes a single-source pointerMove/scroll fire the event at tick start and wait afterward (vs. wait-then-dispatch before) — same end state per tick, and more spec-aligned (all tick actions dispatch, then the tick lasts its max duration).

Tests

  • New tick_duration_is_max_across_sources_not_sum unit test in each crate: a 3-source request asserts tick 0 = max(100,200,80)=200 (not the sum 380) and tick 1 = max(50,30)=50 (exhausted source contributes nothing).
  • Dioxus cargo test --lib: 17 passed (was 16). Tauri cargo test --lib: 4 passed (was 3). cargo clippy --all-targets clean on both (the 2 Tauri incompatible_msrv warnings are pre-existing in platform/executor.rs, untouched). Cargo.locks unchanged.

🤖 Generated with Claude Code

W3C WebDriver Actions §17.4.3 defines a tick's duration as the *maximum*
pause/move/scroll duration across its sources, not the sum. Both embedded
drivers slept each source's duration sequentially within a tick, so a tick
with pause(100) in one source and pause(200) in another took 300ms instead
of the required 200ms.

Both handlers now compute the tick duration up front via a pure
`ActionSequence::duration_at(tick)` helper (mirroring `action_count`),
dispatch the tick's actions without per-source sleeps, and sleep the single
max once at the end. Adds a `tick_duration_is_max_across_sources_not_sum`
unit test to each crate.

Closes #496.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes W3C WebDriver Actions §17.4.3 compliance: a tick's duration should be the maximum pause/move/scroll duration across its sources, not their sum. Both the dioxus and tauri handlers were sleeping each source's duration sequentially within a tick, making multi-source ticks take far longer than the spec requires.

  • Adds ActionSequence::duration_at(tick) to each crate as a pure helper that returns the duration contributed by a given tick's action, mirroring the existing action_count pattern; the tick loop now computes max(duration_at(tick)) up front and sleeps once after dispatching all actions.
  • Per-source sleep calls are removed from all Pause, PointerMove, and WheelScroll arms; the sleep_for wrapper in dioxus is also deleted.
  • A new tick_duration_is_max_across_sources_not_sum unit test in each crate exercises a 3-source scenario to confirm the 200 ms (not 380 ms sum) and 50 ms results.

Confidence Score: 5/5

Safe to merge — the change is a targeted, well-tested correction to how tick sleep time is computed, with no structural changes to action dispatch logic beyond removing the per-source sleeps.

Both handlers are changed symmetrically, the duration_at helper correctly propagates Option<u64> through filter_map so zero-duration and absent actions contribute nothing to the max, the ordering change (dispatch then sleep vs. sleep then dispatch) is intentional and more spec-aligned, and unit tests directly exercise the multi-source max vs. sum invariant in both crates.

No files require special attention.

Important Files Changed

Filename Overview
packages/dioxus-embedded-driver/src/server/handlers/actions.rs Adds duration_at helper, replaces per-source sleeps with a single tick-level max sleep, removes sleep_for, and adds the new unit test. Logic is correct and spec-aligned.
packages/tauri-plugin-webdriver/src/server/handlers/actions.rs Mirror of the dioxus changes: duration_at added, per-source sleeps removed from all action arms, single tick sleep at end, new unit test. Kept converged with the dioxus handler.

Reviews (2): Last reviewed commit: "refactor(dioxus): inline tick-end sleep ..." | Re-trigger Greptile

Comment thread packages/dioxus-embedded-driver/src/server/handlers/actions.rs Outdated
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Standing release PR: #456 · 10 packages queued · open 165h 34m · ✅ ready to merge

Release Preview — 13 packages

Note: Labels on this PR are advisory in standing-pr mode. Bumps come from conventional commits in the standing PR; override by editing labels on the standing PR itself. Add release:immediate to bypass the standing PR and release this PR directly.

These changes will be added to the release PR (#456) when merged:

Changelog

@wdio/dioxus-bridge 1.0.0-next.3 → 1.0.1

Changed

  • Update version to 1.0.1
@wdio/dioxus-service 1.0.0-next.3 → 1.0.1

Changed

  • Update version to 1.0.1
wdio-dioxus-driver 1.0.0-next.3 → 1.0.1

Changed

  • Update version to 1.0.1
wdio-dioxus-embedded-driver 1.0.0-next.3 → 1.0.1

Changed

  • inline tick-end sleep to match the Tauri handler (dioxus)

Fixed

@wdio/tauri-service 1.2.0 → 1.2.1

Changed

  • Update version to 1.2.1
tauri-plugin-wdio-webdriver 1.2.0 → 1.2.1

Fixed

@wdio/flutter-service 1.0.0-next.1 → 1.0.1

Changed

  • Update version to 1.0.1
wdio_flutter N/A → 1.0.1

Changed

  • Update version to 1.0.1
@wdio/electron-service 10.1.0 → 10.1.1

Changed

  • Update version to 10.1.1
@wdio/native-core 1.0.0 → 1.0.1

Changed

  • Update version to 1.0.1
@wdio/native-mobile-core 1.0.0 → 1.0.1

Changed

  • Update version to 1.0.1
@wdio/native-spy 1.1.0 → 1.1.1

Changed

  • Update version to 1.1.1
@wdio/native-utils 2.4.0 → 2.4.1

Changed

  • Update version to 2.4.1
@wdio/react-native-service 1.0.0-next.0 → 1.0.1

Changed

  • Update version to 1.0.1

After merge — predicted release

No version escalation — this PR's changes will be included in the queued release without affecting the projected versions.

Package Standing PR This PR After merge
@wdio/electron-service 10.2.0 10.1.1 10.2.0
@wdio/flutter-service 1.1.0 1.0.1 1.1.0
@wdio/native-core 1.1.0 1.0.1 1.1.0
@wdio/native-mobile-core 1.1.0 1.0.1 1.1.0
@wdio/native-spy 1.2.0 1.1.1 1.2.0
@wdio/native-utils 2.5.0 2.4.1 2.5.0
@wdio/react-native-service 1.1.0 1.0.1 1.1.0
@wdio/tauri-service 1.3.0 1.2.1 1.3.0
tauri-plugin-wdio-webdriver 1.3.0 1.2.1 1.3.0
wdio_flutter 1.1.0 1.0.1 1.1.0

Updated automatically by ReleaseKit

Greptile P2: tick_duration_ms is already a resolved u64, so wrapping it in
Some() for sleep_for just to unwrap it again was roundabout. Inline the
`if > 0 { tokio::time::sleep(...) }` form (identical to the Tauri handler,
keeping the two converged) and drop the now-unused sleep_for helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@goosewobbler goosewobbler merged commit a48cc97 into main Jun 30, 2026
109 checks passed
@goosewobbler goosewobbler deleted the fix/actions-pause-max-per-tick branch June 30, 2026 11:26
@github-actions github-actions Bot mentioned this pull request Jun 30, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Embedded drivers: tick duration should be max(pause) across sources, not the sum (W3C §17.4.3)

1 participant