Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Register Espresso IdlingResources with new API #909

Merged
merged 2 commits into from
Aug 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,20 @@
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.IdlingRegistry;
import android.support.test.espresso.base.IdlingResourceRegistry;
import android.util.Log;

import com.wix.detox.espresso.AnimatedModuleIdlingResource;
import com.wix.detox.espresso.LooperIdlingResource;
import com.wix.detox.espresso.ReactNativeNetworkIdlingResource;
import com.wix.detox.espresso.ReactBridgeIdlingResource;
import com.wix.detox.espresso.RNExperimentalNetworkIR;
import com.wix.detox.espresso.ReactNativeTimersIdlingResource;
import com.wix.detox.espresso.ReactNativeUIModuleIdlingResource;

import org.joor.Reflect;
import org.joor.ReflectException;

import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

Expand Down Expand Up @@ -280,9 +278,7 @@ private static void createBridgeIdleSignaler() {
private static ReactNativeUIModuleIdlingResource rnUIModuleIdlingResource = null;
private static AnimatedModuleIdlingResource animIdlingResource = null;

private static void setupEspressoIdlingResources(
@NonNull Object reactNativeHostHolder,
@NonNull Object reactContext) {
private static void setupEspressoIdlingResources(@NonNull Object reactNativeHostHolder, @NonNull Object reactContext) {
removeEspressoIdlingResources(reactNativeHostHolder, reactContext);
Log.i(LOG_TAG, "Setting up Espresso Idling Resources for React Native.");

Expand All @@ -297,55 +293,42 @@ private static void setupEspressoIdlingResources(
rnUIModuleIdlingResource = new ReactNativeUIModuleIdlingResource(reactContext);
animIdlingResource = new AnimatedModuleIdlingResource(reactContext);

Espresso.registerIdlingResources(
rnTimerIdlingResource,
rnBridgeIdlingResource,
rnUIModuleIdlingResource,
animIdlingResource);
IdlingRegistry.getInstance().register(rnTimerIdlingResource);
IdlingRegistry.getInstance().register(rnBridgeIdlingResource);
IdlingRegistry.getInstance().register(rnUIModuleIdlingResource);
IdlingRegistry.getInstance().register(animIdlingResource);

if (networkSyncEnabled) {
setupNetworkIdlingResource();
}
}

private static ArrayList<LooperIdlingResource> looperIdlingResources = new ArrayList<>();

private static void setupReactNativeQueueInterrogators(@NonNull Object reactContext) {
HashSet<Looper> excludedLoopers = new HashSet<>();
excludedLoopers.add(InstrumentationRegistry.getTargetContext().getMainLooper());
setupRNQueueInterrogator(reactContext, FIELD_UI_MSG_QUEUE, excludedLoopers);
setupRNQueueInterrogator(reactContext, FIELD_UI_BG_MSG_QUEUE, excludedLoopers);
setupRNQueueInterrogator(reactContext, FIELD_JS_MSG_QUEUE, excludedLoopers);
setupRNQueueInterrogator(reactContext, FIELD_NATIVE_MODULES_MSG_QUEUE, excludedLoopers);
Looper UIBackgroundMessageQueue = getLooperFromQueue(reactContext, FIELD_UI_BG_MSG_QUEUE);
Looper JSMessageQueue = getLooperFromQueue(reactContext, FIELD_JS_MSG_QUEUE);
Looper JMativeModulesMessageQueue = getLooperFromQueue(reactContext, FIELD_NATIVE_MODULES_MSG_QUEUE);

// IdlingRegistry.getInstance().registerLooperAsIdlingResource(UIBackgroundMessageQueue);
IdlingRegistry.getInstance().registerLooperAsIdlingResource(JSMessageQueue);
IdlingRegistry.getInstance().registerLooperAsIdlingResource(JMativeModulesMessageQueue);

IdlingResourceRegistry irr = Reflect.on("android.support.test.espresso.Espresso").field("baseRegistry").get();
irr.sync(IdlingRegistry.getInstance().getResources(), IdlingRegistry.getInstance().getLoopers());
}

private static void setupRNQueueInterrogator(
@NonNull Object reactContext,
@NonNull String field,
@NonNull HashSet<Looper> excludedLoopers) {
private static Looper getLooperFromQueue(@NonNull Object reactContext, String queueName) {
Object queue;
Object looper;
Looper looper = null;

try {
if ((queue = Reflect.on(reactContext).field(field).get()) != null) {
if ((looper = Reflect.on(queue).call(METHOD_GET_LOOPER).get()) != null) {
if (!excludedLoopers.contains(looper)) {
LooperIdlingResource looperIdlingResource = new LooperIdlingResource((Looper)looper, false);

looperIdlingResources.add(looperIdlingResource);
Espresso.registerIdlingResources(looperIdlingResource);
excludedLoopers.add((Looper)looper);
}
}
queue = Reflect.on(reactContext).field(queueName).get();
if (queue != null) {
looper = Reflect.on(queue).call(METHOD_GET_LOOPER).get();
}
} catch (ReflectException e) {
// The mUiBackgroundMessageQueueThread field is stripped at runtime
// in the current RN release.
// We still keep trying to grab it to be future proof.
if (!field.equals("mUiBackgroundMessageQueueThread")) {
Log.d(LOG_TAG, "Can't set up monitoring for " + field, e);
}
return null;
}
return looper;
}

static void removeEspressoIdlingResources(@NonNull Object reactNativeHostHolder) {
Expand All @@ -360,28 +343,14 @@ static void removeEspressoIdlingResources(@NonNull Object reactNativeHostHolder)
removeEspressoIdlingResources(reactNativeHostHolder, reactContext);
}

private static void removeEspressoIdlingResources(
@NonNull Object reactNativeHostHolder,
Object reactContext) {
private static void removeEspressoIdlingResources(@NonNull Object reactNativeHostHolder, Object reactContext) {

Log.i(LOG_TAG, "Removing Espresso IdlingResources for React Native.");

if (rnBridgeIdlingResource != null
&& rnTimerIdlingResource != null
&& rnUIModuleIdlingResource != null
&& animIdlingResource != null) {
Espresso.unregisterIdlingResources(
rnTimerIdlingResource,
rnBridgeIdlingResource,
rnUIModuleIdlingResource,
animIdlingResource);
rnTimerIdlingResource = null;
rnBridgeIdlingResource = null;
rnUIModuleIdlingResource = null;
animIdlingResource = null;
}

removeReactNativeQueueInterrogators();
IdlingRegistry.getInstance().unregister(rnTimerIdlingResource);
IdlingRegistry.getInstance().unregister(rnBridgeIdlingResource);
IdlingRegistry.getInstance().unregister(rnUIModuleIdlingResource);
IdlingRegistry.getInstance().unregister(animIdlingResource);

final Object instanceManager = getInstanceManager(reactNativeHostHolder);
if (instanceManager == null) {
Expand All @@ -398,14 +367,6 @@ private static void removeEspressoIdlingResources(
}
}

private static void removeReactNativeQueueInterrogators() {
for (LooperIdlingResource res : looperIdlingResources) {
res.stop();
Espresso.unregisterIdlingResources(res);
}
looperIdlingResources.clear();
}

private static boolean networkSyncEnabled = true;
public static void enableNetworkSynchronization(boolean enable) {
if (!isReactNativeApp()) return;
Expand All @@ -419,7 +380,7 @@ public static void enableNetworkSynchronization(boolean enable) {
networkSyncEnabled = enable;
}

private static RNExperimentalNetworkIR networkIR = null;
private static ReactNativeNetworkIdlingResource networkIR = null;
private final static String CLASS_NETWORK_MODULE = "com.facebook.react.modules.network.NetworkingModule";
private final static String METHOD_GET_NATIVE_MODULE = "getNativeModule";
private final static String METHOD_HAS_NATIVE_MODULE = "hasNativeModule";
Expand Down Expand Up @@ -448,8 +409,9 @@ private static void setupNetworkIdlingResource() {
.call(METHOD_GET_NATIVE_MODULE, networkModuleClass)
.field(FIELD_OKHTTP_CLIENT)
.get();
networkIR = new RNExperimentalNetworkIR(client.dispatcher());
Espresso.registerIdlingResources(networkIR);
networkIR = new ReactNativeNetworkIdlingResource(client.dispatcher());
IdlingRegistry.getInstance().register(networkIR);

} catch (ReflectException e) {
Log.e(LOG_TAG, "Can't set up Networking Module listener", e.getCause());
}
Expand All @@ -458,7 +420,7 @@ private static void setupNetworkIdlingResource() {
private static void removeNetworkIdlingResource() {
if (networkIR != null) {
networkIR.stop();
Espresso.unregisterIdlingResources(networkIR);
IdlingRegistry.getInstance().unregister(networkIR);
networkIR = null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public class AnimatedModuleIdlingResource implements IdlingResource, Choreograph
private static final String LOG_TAG = "Detox";

private final static String CLASS_ANIMATED_MODULE = "com.facebook.react.animated.NativeAnimatedModule";
private final static String METHOD_HAS_CATALYST_INSTANCE = "hasActiveCatalystInstance";
private final static String METHOD_GET_NATIVE_MODULE = "getNativeModule";
private final static String METHOD_HAS_NATIVE_MODULE = "hasNativeModule";
private final static String METHOD_IS_EMPTY = "isEmpty";
Expand All @@ -44,6 +43,7 @@ public class AnimatedModuleIdlingResource implements IdlingResource, Choreograph
private final static String FIELD_ITERATIONS = "mIterations";
private final static String FIELD_ACTIVE_ANIMATIONS = "mActiveAnimations";
private final static String FIELD_UPDATED_NODES = "mUpdatedNodes";
private final static String FIELD_CATALYST_INSTANCE = "mCatalystInstance";

private final static String METHOD_SIZE = "size";
private final static String METHOD_VALUE_AT = "valueAt";
Expand Down Expand Up @@ -78,7 +78,7 @@ public boolean isIdleNow() {
try {
// reactContext.hasActiveCatalystInstance() should be always true here
// if called right after onReactContextInitialized(...)
if (!(boolean) Reflect.on(reactContext).call(METHOD_HAS_CATALYST_INSTANCE).get()) {
if (Reflect.on(reactContext).field(FIELD_CATALYST_INSTANCE).get() == null) {
Log.e(LOG_TAG, "No active CatalystInstance. Should never see this.");
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public static void setURLBlacklist(final ArrayList<String> urls) {
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
RNExperimentalNetworkIR.setURLBlacklist(urls);
ReactNativeNetworkIdlingResource.setURLBlacklist(urls);
}
});
}
Expand Down

This file was deleted.

Loading