Skip to content

Commit

Permalink
Fix Android RN server snapshot tests
Browse files Browse the repository at this point in the history
Summary: Trying to see what it takes to get server snapshot tests working on android. This will be landed after fixing few things.

Reviewed By: achen1

Differential Revision: D8237948

fbshipit-source-id: 926555ba752171dac4e5814f5c8e5c2c173a82c7
  • Loading branch information
himabindugadupudi authored and facebook-github-bot committed Jul 19, 2018
1 parent 165dd40 commit 7ff7572
Showing 1 changed file with 86 additions and 82 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/

package com.facebook.react.testing;

import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread;

import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
Expand Down Expand Up @@ -47,6 +47,7 @@
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;


public class ReactAppTestActivity extends FragmentActivity
implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {

Expand All @@ -56,11 +57,10 @@ public class ReactAppTestActivity extends FragmentActivity
private static final int ROOT_VIEW_ID = 8675309;
// we need a bigger timeout for CI builds because they run on a slow emulator
private static final long IDLE_TIMEOUT_MS = 120000;

private final CountDownLatch mDestroyCountDownLatch = new CountDownLatch(1);
private CountDownLatch mLayoutEvent = new CountDownLatch(1);
private @Nullable ReactBridgeIdleSignaler mBridgeIdleSignaler;
private ScreenshotingFrameLayout mScreenshotingFrameLayout;
private final CountDownLatch mDestroyCountDownLatch = new CountDownLatch(1);
private @Nullable ReactInstanceManager mReactInstanceManager;
private @Nullable ReactRootView mReactRootView;
private LifecycleState mLifecycleState = LifecycleState.BEFORE_RESUME;
Expand Down Expand Up @@ -138,10 +138,7 @@ public void loadApp(String appKey, ReactInstanceSpecForTest spec, boolean enable
loadApp(appKey, spec, null, DEFAULT_BUNDLE_NAME, enableDevSupport);
}

public void loadApp(
String appKey,
ReactInstanceSpecForTest spec,
String bundleName) {
public void loadApp(String appKey, ReactInstanceSpecForTest spec, String bundleName) {
loadApp(appKey, spec, null, bundleName, false /* = useDevSupport */);
}

Expand All @@ -160,11 +157,11 @@ public void resetRootViewForScreenshotTests() {
}

public void loadApp(
String appKey,
ReactInstanceSpecForTest spec,
@Nullable Bundle initialProps,
String bundleName,
boolean useDevSupport) {
String appKey,
ReactInstanceSpecForTest spec,
@Nullable Bundle initialProps,
String bundleName,
boolean useDevSupport) {
loadBundle(spec, bundleName, useDevSupport);
renderComponent(appKey, initialProps);
}
Expand All @@ -175,32 +172,34 @@ public void renderComponent(String appKey) {

public void renderComponent(final String appKey, final @Nullable Bundle initialProps) {
final CountDownLatch currentLayoutEvent = mLayoutEvent = new CountDownLatch(1);
runOnUiThread(new Runnable() {
@Override
public void run() {
Assertions.assertNotNull(mReactRootView).getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
currentLayoutEvent.countDown();
}
});
Assertions.assertNotNull(mReactRootView)
.startReactApplication(mReactInstanceManager, appKey, initialProps);
}
});
try {
waitForBridgeAndUIIdle();
waitForLayout(5000);
} catch (InterruptedException e) {
throw new RuntimeException("Layout never occurred for component " + appKey, e);
}
runOnUiThread(
new Runnable() {
@Override
public void run() {
Assertions.assertNotNull(mReactRootView)
.getViewTreeObserver()
.addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
currentLayoutEvent.countDown();
Assertions.assertNotNull(mReactRootView)
.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
});
Assertions.assertNotNull(mReactRootView)
.startReactApplication(mReactInstanceManager, appKey, initialProps);
}
});
try {
waitForBridgeAndUIIdle();
waitForLayout(5000);
} catch (InterruptedException e) {
throw new RuntimeException("Layout never occurred for component " + appKey, e);}
}

public void loadBundle(
ReactInstanceSpecForTest spec,
String bundleName,
boolean useDevSupport) {
public void loadBundle(ReactInstanceSpecForTest spec, String bundleName, boolean useDevSupport) {

mBridgeIdleSignaler = new ReactBridgeIdleSignaler();

Expand All @@ -219,7 +218,7 @@ public void loadBundle(
// By not setting a JS module name, we force the bundle to be always loaded from
// assets, not the devserver, even if dev mode is enabled (such as when testing redboxes).
// This makes sense because we never run the devserver in tests.
//.setJSMainModuleName()
// .setJSMainModuleName()
.setUseDeveloperSupport(useDevSupport)
.setBridgeIdleDebugListener(mBridgeIdleSignaler)
.setInitialLifecycleState(mLifecycleState)
Expand All @@ -230,43 +229,54 @@ public List<JSIModuleSpec> getJSIModules(
final ReactApplicationContext reactApplicationContext,
final JavaScriptContextHolder jsContext) {
return Arrays.<JSIModuleSpec>asList(
new JSIModuleSpec() {
@Override
public Class<? extends JSIModule> getJSIModuleClass() {
return UIManager.class;
}

@Override
public JSIModuleProvider getJSIModuleProvider() {
return new JSIModuleProvider() {
@Override
public FabricUIManager get() {
List<ViewManager> viewManagers =
mReactInstanceManager.getOrCreateViewManagers(reactApplicationContext);
EventDispatcher eventDispatcher =
reactApplicationContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
FabricUIManager fabricUIManager =
new FabricUIManager(reactApplicationContext, new ViewManagerRegistry(viewManagers), jsContext, eventDispatcher);
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
return fabricUIManager;
}
};
}
});
}});
new JSIModuleSpec() {
@Override
public Class<? extends JSIModule> getJSIModuleClass() {
return UIManager.class;
}

@Override
public JSIModuleProvider getJSIModuleProvider() {
return new JSIModuleProvider() {
@Override
public FabricUIManager get() {
List<ViewManager> viewManagers =
mReactInstanceManager.getOrCreateViewManagers(
reactApplicationContext);
EventDispatcher eventDispatcher =
reactApplicationContext
.getNativeModule(UIManagerModule.class)
.getEventDispatcher();
FabricUIManager fabricUIManager =
new FabricUIManager(
reactApplicationContext,
new ViewManagerRegistry(viewManagers),
jsContext,
eventDispatcher);
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
return fabricUIManager;
}
};
}
});
}
});

final CountDownLatch latch = new CountDownLatch(1);
runOnUiThread(new Runnable() {
@Override
public void run() {
mReactInstanceManager = builder.build();
mReactInstanceManager.onHostResume(ReactAppTestActivity.this, ReactAppTestActivity.this);
latch.countDown();
}
});
runOnUiThread(
new Runnable() {
@Override
public void run() {
mReactInstanceManager = builder.build();
mReactInstanceManager.onHostResume(
ReactAppTestActivity.this, ReactAppTestActivity.this);
latch.countDown();
}
});
try {
latch.await(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {

throw new RuntimeException(
"ReactInstanceManager never finished initializing " + bundleName, e);
}
Expand All @@ -286,9 +296,7 @@ public void waitForBridgeAndUIIdle() {

public void waitForBridgeAndUIIdle(long timeoutMs) {
ReactIdleDetectionUtil.waitForBridgeAndUIIdle(
Assertions.assertNotNull(mBridgeIdleSignaler),
getReactContext(),
timeoutMs);
Assertions.assertNotNull(mBridgeIdleSignaler), getReactContext(), timeoutMs);
}

public View getRootView() {
Expand All @@ -309,7 +317,7 @@ private ReactContext waitForReactContext() {
while (true) {
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
if (reactContext != null) {
return reactContext;
return reactContext;
}
Thread.sleep(100);
}
Expand All @@ -323,9 +331,8 @@ public void postDelayed(Runnable r, int delayMS) {
}

/**
* Does not ensure that this is run on the UI thread or that the UI Looper is idle like
* {@link ReactAppInstrumentationTestCase#getScreenshot()}. You probably want to use that
* instead.
* Does not ensure that this is run on the UI thread or that the UI Looper is idle like {@link
* ReactAppInstrumentationTestCase#getScreenshot()}. You probably want to use that instead.
*/
public Bitmap getCurrentScreenshot() {
return mScreenshotingFrameLayout.getLastDrawnBitmap();
Expand All @@ -346,10 +353,7 @@ public void invokeDefaultOnBackPressed() {

@Override
public void onRequestPermissionsResult(
int requestCode,
String[] permissions,
int[] grantResults) {
}
int requestCode, String[] permissions, int[] grantResults) {}

@Override
public void requestPermissions(
Expand Down

0 comments on commit 7ff7572

Please sign in to comment.