Create a new instrumentation test that does not enforce rendering a single RN component

Reviewed By: mdvacca

Differential Revision: D7293466

fbshipit-source-id: 8ddaf9a52f4d6324e8b37f3c6fd4d3e0db6f3a12
This commit is contained in:
Andrew Chen (Eng) 2018-03-19 10:34:57 -07:00 committed by Facebook Github Bot
parent 15bc6d1e0b
commit 12c208cbd4
2 changed files with 177 additions and 35 deletions

View File

@ -176,8 +176,36 @@ public class ReactAppTestActivity extends FragmentActivity
String bundleName,
boolean useDevSupport,
UIImplementationProvider uiImplementationProvider) {
loadBundle(spec, bundleName, useDevSupport, uiImplementationProvider);
renderComponent(appKey, initialProps);
}
public void renderComponent(String appKey, @Nullable Bundle initialProps) {
final CountDownLatch currentLayoutEvent = mLayoutEvent = new CountDownLatch(1);
Assertions.assertNotNull(mReactRootView).getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
currentLayoutEvent.countDown();
}
});
Assertions.assertNotNull(mReactRootView)
.startReactApplication(mReactInstanceManager, appKey, initialProps);
}
public void loadBundle(
ReactInstanceSpecForTest spec,
String bundleName,
boolean useDevSupport) {
loadBundle(spec, bundleName, useDevSupport, null);
}
public void loadBundle(
ReactInstanceSpecForTest spec,
String bundleName,
boolean useDevSupport,
UIImplementationProvider uiImplementationProvider) {
mBridgeIdleSignaler = new ReactBridgeIdleSignaler();
ReactInstanceManagerBuilder builder =
@ -200,49 +228,39 @@ public class ReactAppTestActivity extends FragmentActivity
.setBridgeIdleDebugListener(mBridgeIdleSignaler)
.setInitialLifecycleState(mLifecycleState)
.setJSIModulesProvider(
new JSIModulesProvider() {
@Override
public List<JSIModuleHolder> getJSIModules(
final ReactApplicationContext reactApplicationContext,
final JavaScriptContextHolder jsContext) {
new JSIModulesProvider() {
@Override
public List<JSIModuleHolder> getJSIModules(
final ReactApplicationContext reactApplicationContext,
final JavaScriptContextHolder jsContext) {
List<JSIModuleHolder> modules = new ArrayList<>();
modules.add(
new JSIModuleHolder() {
List<JSIModuleHolder> modules = new ArrayList<>();
modules.add(
new JSIModuleHolder() {
@Override
public Class<? extends JSIModule> getJSIModuleClass() {
return UIManager.class;
}
@Override
public Class<? extends JSIModule> getJSIModuleClass() {
return UIManager.class;
}
@Override
public FabricUIManager getJSIModule() {
List<ViewManager> viewManagers =
getReactInstanceManager().getOrCreateViewManagers(reactApplicationContext);
FabricUIManager fabricUIManager =
new FabricUIManager(
reactApplicationContext, new ViewManagerRegistry(viewManagers));
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
return fabricUIManager;
}
});
@Override
public FabricUIManager getJSIModule() {
List<ViewManager> viewManagers =
getReactInstanceManager().getOrCreateViewManagers(reactApplicationContext);
FabricUIManager fabricUIManager =
new FabricUIManager(
reactApplicationContext, new ViewManagerRegistry(viewManagers));
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
return fabricUIManager;
}
});
return modules;
}})
return modules;
}})
.setUIImplementationProvider(uiImplementationProvider);
mReactInstanceManager = builder.build();
mReactInstanceManager.onHostResume(this, this);
Assertions.assertNotNull(mReactRootView).getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
currentLayoutEvent.countDown();
}
});
Assertions.assertNotNull(mReactRootView)
.startReactApplication(mReactInstanceManager, appKey, initialProps);
}
private ReactInstanceManager getReactInstanceManager() {

View File

@ -0,0 +1,124 @@
/**
* 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.
*/
package com.facebook.react.testing;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.view.ViewGroup;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.testing.idledetection.IdleWaiter;
/**
* Base class for instrumentation tests that runs React based application.
*
* This is similar to ReactAppInstrumentationTestCase except ReactInstrumentationTest allows
* optional rendering of components. A test case can render no components or render multiple
* components.
*/
public abstract class ReactInstrumentationTest extends
ActivityInstrumentationTestCase2<ReactAppTestActivity> implements IdleWaiter {
public ReactInstrumentationTest() {
super(ReactAppTestActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
Intent intent = new Intent();
intent.putExtra(ReactAppTestActivity.EXTRA_IS_FABRIC_TEST, isFabricTest());
setActivityIntent(intent);
final ReactAppTestActivity activity = getActivity();
try {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.loadBundle(
createReactInstanceSpecForTest(),
getBundleName(),
getEnableDevSupport());
}
});
} catch (Throwable t) {
throw new Exception("Unable to load react bundle " + getBundleName(), t);
}
}
/**
* Renders this component within this test's activity
*/
public void renderComponent(final String componentName) throws Exception {
final ReactAppTestActivity activity = getActivity();
try {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.renderComponent(componentName, null);
}
});
} catch (Throwable t) {
throw new Exception("Unable to render component " + componentName, t);
}
assertTrue("Layout never occurred!", activity.waitForLayout(5000));
waitForBridgeAndUIIdle();
}
@Override
protected void tearDown() throws Exception {
ReactAppTestActivity activity = getActivity();
super.tearDown();
activity.waitForDestroy(5000);
}
public ViewGroup getRootView() {
return (ViewGroup) getActivity().getRootView();
}
public <T extends View> T getViewByTestId(String testID) {
return (T) ReactTestHelper
.getViewWithReactTestId((ViewGroup) getRootView().getParent(), testID);
}
public SingleTouchGestureGenerator createGestureGenerator() {
return new SingleTouchGestureGenerator(getRootView(), this);
}
public void waitForBridgeAndUIIdle() {
getActivity().waitForBridgeAndUIIdle();
}
public void waitForBridgeAndUIIdle(long timeoutMs) {
getActivity().waitForBridgeAndUIIdle(timeoutMs);
}
protected boolean getEnableDevSupport() {
return false;
}
protected boolean isFabricTest() {
return false;
}
/**
* Override this method to provide extra native modules to be loaded before the app starts
*/
protected ReactInstanceSpecForTest createReactInstanceSpecForTest() {
return new ReactInstanceSpecForTest();
}
/**
* Implement this method to provide the bundle for this test
*/
protected abstract String getBundleName();
protected ReactContext getReactContext() {
return getActivity().getReactContext();
}
}