Skip to content
Browse files
Add an API for Detox to check if there are any timers expiring in a c…
…ertain range (#27539)

Pull Request resolved: #27539

Detox currently relies on reflection to inspect the private timers queue in the Timing module to check if React Native is idle or not. This broke when I renamed TimingModule and moved the queue to JavaTimerManager in D17260848 and D17282187. A better solution to this problem is for us to expose a public API for checking the timers queue from TimingModule, so that Detox doesn't need to access private fields.

Using similar logic to Detox's TimersIdlingResource:

Changelog: [Android] [Added] Added an API for checking if there are busy timers to TimingModule

Reviewed By: makovkastar

Differential Revision: D19128786

fbshipit-source-id: 835ae214eba58879c8343255bba680a81801ce03
  • Loading branch information
Emily Janzer authored and facebook-github-bot committed Jan 7, 2020
1 parent 80cfa9c commit 22764e6cdcf45ca5930676f6e95f9ab2f82bc78d
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 0 deletions.
@@ -373,4 +373,23 @@ public void run() {

* Returns a bool representing whether there are any active timers that will be fired within a
* certain period of time. Disregards repeating timers (setInterval). Used for testing to
* determine if RN is idle.
* @param rangeMs The time range, in ms, to check
* @return True if there are pending timers within the given range; false otherwise
/* package */ boolean hasActiveTimersInRange(long rangeMs) {
synchronized (mTimerGuard) {
for (Timer timer : mTimers) {
if (!timer.mRepeat && timer.mInterval < rangeMs) {
return true;
return false;
@@ -11,6 +11,7 @@
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.devsupport.interfaces.DevSupportManager;
import com.facebook.react.jstasks.HeadlessJsTaskContext;
import com.facebook.react.jstasks.HeadlessJsTaskEventListener;
@@ -134,4 +135,9 @@ public void onCatalystInstanceDestroy() {

public boolean hasActiveTimersInRange(long rangeMs) {
return mJavaTimerManager.hasActiveTimersInRange(rangeMs);
@@ -28,6 +28,7 @@ rn_robolectric_test(
@@ -7,6 +7,7 @@

package com.facebook.react.modules.timing;

import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Mockito.*;

import com.facebook.react.bridge.Arguments;
@@ -254,6 +255,19 @@ public void testIdleCallback() {

public void testActiveTimersInRange() {

mTimingModule.createTimer(41, 1, 0, true);
assertThat(mTimingModule.hasActiveTimersInRange(100)).isFalse(); // Repeating

mTimingModule.createTimer(42, 150, 0, false);
assertThat(mTimingModule.hasActiveTimersInRange(100)).isFalse(); // Out of range
assertThat(mTimingModule.hasActiveTimersInRange(200)).isTrue(); // In range

private static class PostFrameIdleCallbackHandler implements Answer<Void> {

private ChoreographerCompat.FrameCallback mFrameCallback;

0 comments on commit 22764e6

Please sign in to comment.