Describe your idea
Problem
Detox already tracks app idle/busy state internally and exposes it through the
undocumented device.deviceDriver.client.currentStatus() (iOS returns a
structured { app_status: "idle" | "busy", ... } payload). This is useful for
building idle-aware polling on top of waitFor(...).withTimeout(...): if the
poll times out and the app is genuinely idle, fail fast; if the app is still
busy, keep polling.
The catch: once await device.disableSynchronization() is called,
currentStatus() reports app_status: "idle" unconditionally — even while the
app is mid-navigation, fetching, laying out, etc. So the idle signal becomes
unusable in exactly the scenarios where you'd want to disable sync (slow/flaky
sync sources, long-polling sockets, animations you'd rather poll past).
In other words, today users have to choose between:
- sync on → reliable idle signal, but tests can hang indefinitely on
background tasks Detox tracks as "busy" forever, and
- sync off → tests progress, but no trustworthy idle/busy signal at all.
Proposed enhancement
Expose a public, supported API that reports the app's current idle/busy
state and that continues to function when synchronization is disabled.
Something like:
const { idle, busyResources } = await device.appStatus();
// idle: boolean
// busyResources: string[] // e.g. ["RN bridge", "JS timers", "layout"]
Key requirements:
- Independent of
disableSynchronization(). Disabling sync should stop
Detox from blocking on busy resources, not stop it from observing them.
- Cross-platform. Today the underlying
currentStatus() returns a
structured object on iOS but a free-form string ("The app seems to be idle")
on Android, which isn't programmatically usable. A unified shape would help.
- Stable / documented. A public method on
device so consumers don't
reach into device.deviceDriver.client (which can break across versions).
Use case
Layered idle-aware polling for tests that run with sync disabled:
// pseudo-code
while (Date.now() < deadline) {
try {
await waitFor(el).toBeVisible().withTimeout(200);
return;
} catch {
const { idle } = await device.appStatus();
if (idle) throw new Error(\"element not visible and app is idle\");
// app is still busy → keep polling
}
}
This pattern only works if appStatus() reflects real busy/idle state
regardless of whether synchronization is enabled.
Alternatives considered
- Re-enabling sync selectively — not viable for us; some background work
legitimately never settles from Detox's perspective.
- Reading
deviceDriver.client.currentStatus() directly — what we do today;
fragile (private API) and broken-by-design on Android + when sync is off.
- Polling app-side test hooks — pollutes production code with test-only
paths, which we want to avoid.
Describe your idea
Problem
Detox already tracks app idle/busy state internally and exposes it through the
undocumented
device.deviceDriver.client.currentStatus()(iOS returns astructured
{ app_status: "idle" | "busy", ... }payload). This is useful forbuilding idle-aware polling on top of
waitFor(...).withTimeout(...): if thepoll times out and the app is genuinely idle, fail fast; if the app is still
busy, keep polling.
The catch: once
await device.disableSynchronization()is called,currentStatus()reportsapp_status: "idle"unconditionally — even while theapp is mid-navigation, fetching, laying out, etc. So the idle signal becomes
unusable in exactly the scenarios where you'd want to disable sync (slow/flaky
sync sources, long-polling sockets, animations you'd rather poll past).
In other words, today users have to choose between:
background tasks Detox tracks as "busy" forever, and
Proposed enhancement
Expose a public, supported API that reports the app's current idle/busy
state and that continues to function when synchronization is disabled.
Something like:
Key requirements:
disableSynchronization(). Disabling sync should stopDetox from blocking on busy resources, not stop it from observing them.
currentStatus()returns astructured object on iOS but a free-form string ("The app seems to be idle")
on Android, which isn't programmatically usable. A unified shape would help.
deviceso consumers don'treach into
device.deviceDriver.client(which can break across versions).Use case
Layered idle-aware polling for tests that run with sync disabled:
This pattern only works if
appStatus()reflects real busy/idle stateregardless of whether synchronization is enabled.
Alternatives considered
legitimately never settles from Detox's perspective.
deviceDriver.client.currentStatus()directly — what we do today;fragile (private API) and broken-by-design on Android + when sync is off.
paths, which we want to avoid.