Changelog
All notable changes to Stowaway are documented here. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.2.2
Fixed
-
Trace no longer falsely marks the last successful step as failed when a test times out. When an
app.step(...)call's body hangs, the test runner used to mark the last entry in the trace as failed - which was the last successful sub-operation (find, tap, etc.), not the hung step. The reservedstep()header entry is now marked failed by default and only flipped to "succeeded" when the body actually completes, so a hung step shows up correctly. The auto-attribution heuristic that mis-blamed successful operations has been removed. -
scrollAndFindno longer silently scrolls the wrong scrollable. On screens with a horizontal scroller (e.g. a pill nav) above the target vertical list, the global scroll heuristic walked the fiber tree depth-first and stopped at the first match - which on these screens was the horizontalScrollView. CallingscrollTo({y})on a horizontal scroller is a no-op, so the target list never moved and the call timed out with a generic error. The bridge now scans for scrollables in this order:- Vertical
FlatList/VirtualizedList - Vertical
ScrollView - Horizontal
FlatList/VirtualizedList(fallback) - Horizontal
ScrollView(fallback - scrolled along thexaxis)
This means the common multi-scrollable case (horizontal nav + vertical list) now finds the vertical list correctly, while horizontal-only screens still work since the horizontal fallback preserves the pre-0.2.2 behaviour for those.
- Vertical
-
scrollAndFindtimeout errors now distinguish the failure mode. Instead of a generictimed out after Nms, the error message identifies which kind of scrollable was scrolled (a vertical FlatList,a horizontal ScrollView, etc.) or reportsno scrollable component found in the tree.
Added
-
New
scrollAndFind(testID, { within })option. Accepts a testID orSelectorto pin the scroll container when the heuristics can't decide (e.g. two vertical FlatLists on one screen). -
SLOW=1env var enables slow mode for the whole run - a configurable delay (default 800 ms, override withSLOW_DELAY) between every Element interaction. Intended for demo recordings where you want a steady cadence between taps, typing, etc. Doesn't affectwaitForElement(still resolves as soon as the element appears).
0.2.1
Fixed
- Visibility filter no longer rejects screens in state
1or withAnimated.ValueactivityState. The 0.2.0 check rejected fibers whose ancestor chain hadactivityState < 2, which produced false negatives for elements on screens below the top of a stack (state1= transitioning/below-top) and during navigation transitions. The check now only rejects whenactivityStateis the plain number0(fully deactivated). Animated values are skipped - they can't be read reliably from JS - and state1is allowed through. This fixes cases where elements like tab bar buttons or items in a horizontal scroll on a stack screen were unfindable.
0.2.0
Breaking changes
find() and findAll() now filter by visibility. Queries skip fibers whose ancestor chain contains either activityState < 2 (an inactive react-native-screens screen, e.g. a prerendered tab or background stack screen) or style.display === 'none'. This prevents two common false-positive patterns: matching elements on a prerendered background screen, and returning multiple matches when only one is actually on screen.
If you have tests that intentionally query prerendered or hidden subtrees, you'll need to either navigate to that screen first or restructure the test.
New
-
app.waitForInteractions(opts?)- Sleeps for a configurable delay (default 500 ms) on the test runner side. Use afterwaitForElementto give React Navigation's native-driven slide transitions time to finish before interacting. Override the delay with{ delay: 800 }for slower animations. Unnecessary if you've calleddisableAnimations(). -
app.printVisibleTree(maxDepth?)- A less noisy version ofprintTreethat prunes inactive screen subtrees anddisplay: nonenodes from the output. Useful whenprintTreeis overwhelming because of prerendered tabs or stack screens kept mounted in the background.
Improved
-
waitForElementis now commit-driven. It hooks__REACT_DEVTOOLS_GLOBAL_HOOK__.onCommitFiberRootviaRuntime.addBindingand resolves on the first React commit containing the element - typically within a few milliseconds rather than at the next 250 ms poll boundary. A polling fallback runs in parallel as a safety net, and gracefully degrades to polling-only ifRuntime.addBindingisn't available. -
Deep fiber trees no longer crash the bridge. The internal walk is now iterative, so apps with 200+ levels of nesting (common in modern Expo apps with many providers) no longer hit a call stack overflow.
-
typeTextworks with more component libraries. WhenonChangeTextisn't found on the ancestor chain, it now falls back toonChange({ nativeEvent: { text } })(the standard React NativeTextInputcontract) and thenonChange(text)(used by some component libraries that pass the raw string). Strictly additive - apps that use plainonChangeTextsee no change in behavior. -
Correct CDP target selection on expo-dev-client. When Metro exposes two pages for the same bundle ID (the dev client shell and the actual app bundle), Stowaway now connects to the actual app instead of the shell.
0.1.0
Initial release.