Skip to content

test(e2e): drag the nested pager slowly enough to beat the outer pager - #1162

Merged
troZee merged 2 commits into
callstack:masterfrom
okwasniewski:oskar/nested-pager-e2e-race
Oct 7, 2026
Merged

troZee merged 2 commits into
callstack:masterfrom
okwasniewski:oskar/nested-pager-e2e-race

Conversation

@okwasniewski

Copy link
Copy Markdown
Contributor

Summary

Fixes the Android e2e failure on #1161 (nested-pager-view.e2e.ts:26, outer pager lands on 3-rd-pager-view).

Stacked on #1161: it needs @e2e-dev/mobile 0.10, where a path screen.swipe honors duration. Merge #1161 first and this diff shrinks to the one test file.

  • The test is racing a frame in ComposePagerView. On ACTION_DOWN the inner pager disables the outer one by setting sameOrientationChildGestureState, a Compose mutableStateOf. The outer HorizontalPager only reads it on its next recomposition.
  • The outer ComposeView gets every touch before the inner AndroidView, and nothing calls requestDisallowInterceptTouchEvent. If the first move past touch slop arrives before that recomposition, the outer pager starts dragging and the inner one gets ACTION_CANCEL.
  • momentum: 'slow' only shortens the swipe (25% of the width). Its speed is still a fling: the first move is 67 px, 25 ms after touch down. Whether a frame lands in between is luck. The e2e bump in chore: update e2e to latest versions #1161 shifted the timing so the test now loses almost every time.
  • The test now drags 70% of the width over 2 s. The first moves stay under slop, so the outer pager has recomposed by the time slop is crossed, and the page passes the halfway snap point without needing a fling.

Logcat from a temporary Log.d in ComposePagerView (316 = outer, 252 = inner), with the old swipe:

fail:
252 DOWN                              t=462
316 childGestureActive=true           t=482
252 MOVE dx=-67 -> CANCEL (action=3)  t=487   outer took the drag
316 DRAG START                        t=497
316 recompose userScrollEnabled=true  t=498

pass:
252 DOWN                              t=791
316 childGestureActive=true           t=797
316 recompose userScrollEnabled=false t=811   one frame landed first
252 MOVE dx=-67                       t=816
252 DRAG START                        t=830

The library could apply the block synchronously instead of through Compose state, which would also cover a quick real flick on a busy main thread. That belongs in a separate PR.

Test Plan

Ran it locally: yes. Pixel 7 API 36 emulator plus an iOS 26.5 simulator, release builds of the example app, on the #1161 dependency versions.

nested-pager-view.e2e.ts, --retries 0 #1161 this branch
Android 0/8 10/10
Android, yes on every core 5/5
iOS 5/5
  • Full Android suite on this branch: 11/11.
  • Before the bump (e2e 0.15.1) the same test passed about half the time locally. It was already flaky and only looked stable on CI.

Compatibility

OS Implemented
iOS ✅
Android ✅

krozniata and others added 2 commits October 7, 2026 13:31
On Android the inner pager disables the outer one through Compose state, which applies a frame after touch down. A swipe whose first move crosses touch slop before that frame goes to the outer pager. Drag 70% of the width over 2 s so the first moves stay under slop and the page lands without a fling.
@troZee
troZee merged commit 99446fc into callstack:master Oct 7, 2026
3 checks passed
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.

3 participants