Skip to content

Commit 0eb7259

Browse files
ayc1hamaron
authored andcommitted
Create a new instrumentation test that does not enforce rendering a single RN component
Reviewed By: mdvacca Differential Revision: D7293466 fbshipit-source-id: 8ddaf9a52f4d6324e8b37f3c6fd4d3e0db6f3a12
1 parent 0251436 commit 0eb7259

File tree

2 files changed

+181
-39
lines changed

2 files changed

+181
-39
lines changed

ReactAndroid/src/androidTest/java/com/facebook/react/testing/ReactAppTestActivity.java

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,36 @@ public void loadApp(
176176
String bundleName,
177177
boolean useDevSupport,
178178
UIImplementationProvider uiImplementationProvider) {
179+
loadBundle(spec, bundleName, useDevSupport, uiImplementationProvider);
180+
renderComponent(appKey, initialProps);
181+
}
179182

183+
public void renderComponent(String appKey, @Nullable Bundle initialProps) {
180184
final CountDownLatch currentLayoutEvent = mLayoutEvent = new CountDownLatch(1);
185+
Assertions.assertNotNull(mReactRootView).getViewTreeObserver().addOnGlobalLayoutListener(
186+
new ViewTreeObserver.OnGlobalLayoutListener() {
187+
@Override
188+
public void onGlobalLayout() {
189+
currentLayoutEvent.countDown();
190+
}
191+
});
192+
Assertions.assertNotNull(mReactRootView)
193+
.startReactApplication(mReactInstanceManager, appKey, initialProps);
194+
}
195+
196+
public void loadBundle(
197+
ReactInstanceSpecForTest spec,
198+
String bundleName,
199+
boolean useDevSupport) {
200+
loadBundle(spec, bundleName, useDevSupport, null);
201+
}
202+
203+
public void loadBundle(
204+
ReactInstanceSpecForTest spec,
205+
String bundleName,
206+
boolean useDevSupport,
207+
UIImplementationProvider uiImplementationProvider) {
208+
181209
mBridgeIdleSignaler = new ReactBridgeIdleSignaler();
182210

183211
ReactInstanceManagerBuilder builder =
@@ -200,49 +228,39 @@ public void loadApp(
200228
.setBridgeIdleDebugListener(mBridgeIdleSignaler)
201229
.setInitialLifecycleState(mLifecycleState)
202230
.setJSIModulesProvider(
203-
new JSIModulesProvider() {
204-
@Override
205-
public List<JSIModuleHolder> getJSIModules(
206-
final ReactApplicationContext reactApplicationContext,
207-
final JavaScriptContextHolder jsContext) {
208-
209-
List<JSIModuleHolder> modules = new ArrayList<>();
210-
modules.add(
211-
new JSIModuleHolder() {
212-
213-
@Override
214-
public Class<? extends JSIModule> getJSIModuleClass() {
215-
return UIManager.class;
216-
}
217-
218-
@Override
219-
public FabricUIManager getJSIModule() {
220-
List<ViewManager> viewManagers =
221-
getReactInstanceManager().getOrCreateViewManagers(reactApplicationContext);
222-
FabricUIManager fabricUIManager =
223-
new FabricUIManager(
224-
reactApplicationContext, new ViewManagerRegistry(viewManagers));
225-
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
226-
return fabricUIManager;
227-
}
228-
});
229-
230-
return modules;
231-
}})
231+
new JSIModulesProvider() {
232+
@Override
233+
public List<JSIModuleHolder> getJSIModules(
234+
final ReactApplicationContext reactApplicationContext,
235+
final JavaScriptContextHolder jsContext) {
236+
237+
List<JSIModuleHolder> modules = new ArrayList<>();
238+
modules.add(
239+
new JSIModuleHolder() {
240+
241+
@Override
242+
public Class<? extends JSIModule> getJSIModuleClass() {
243+
return UIManager.class;
244+
}
245+
246+
@Override
247+
public FabricUIManager getJSIModule() {
248+
List<ViewManager> viewManagers =
249+
getReactInstanceManager().getOrCreateViewManagers(reactApplicationContext);
250+
FabricUIManager fabricUIManager =
251+
new FabricUIManager(
252+
reactApplicationContext, new ViewManagerRegistry(viewManagers));
253+
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
254+
return fabricUIManager;
255+
}
256+
});
257+
258+
return modules;
259+
}})
232260
.setUIImplementationProvider(uiImplementationProvider);
233261

234262
mReactInstanceManager = builder.build();
235263
mReactInstanceManager.onHostResume(this, this);
236-
237-
Assertions.assertNotNull(mReactRootView).getViewTreeObserver().addOnGlobalLayoutListener(
238-
new ViewTreeObserver.OnGlobalLayoutListener() {
239-
@Override
240-
public void onGlobalLayout() {
241-
currentLayoutEvent.countDown();
242-
}
243-
});
244-
Assertions.assertNotNull(mReactRootView)
245-
.startReactApplication(mReactInstanceManager, appKey, initialProps);
246264
}
247265

248266
private ReactInstanceManager getReactInstanceManager() {
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.testing;
9+
10+
import android.content.Intent;
11+
import android.test.ActivityInstrumentationTestCase2;
12+
import android.view.View;
13+
import android.view.ViewGroup;
14+
import com.facebook.react.bridge.ReactContext;
15+
import com.facebook.react.testing.idledetection.IdleWaiter;
16+
17+
/**
18+
* Base class for instrumentation tests that runs React based application.
19+
*
20+
* This is similar to ReactAppInstrumentationTestCase except ReactInstrumentationTest allows
21+
* optional rendering of components. A test case can render no components or render multiple
22+
* components.
23+
*/
24+
public abstract class ReactInstrumentationTest extends
25+
ActivityInstrumentationTestCase2<ReactAppTestActivity> implements IdleWaiter {
26+
27+
public ReactInstrumentationTest() {
28+
super(ReactAppTestActivity.class);
29+
}
30+
31+
@Override
32+
protected void setUp() throws Exception {
33+
super.setUp();
34+
35+
Intent intent = new Intent();
36+
intent.putExtra(ReactAppTestActivity.EXTRA_IS_FABRIC_TEST, isFabricTest());
37+
setActivityIntent(intent);
38+
final ReactAppTestActivity activity = getActivity();
39+
try {
40+
runTestOnUiThread(new Runnable() {
41+
@Override
42+
public void run() {
43+
activity.loadBundle(
44+
createReactInstanceSpecForTest(),
45+
getBundleName(),
46+
getEnableDevSupport());
47+
}
48+
});
49+
} catch (Throwable t) {
50+
throw new Exception("Unable to load react bundle " + getBundleName(), t);
51+
}
52+
}
53+
54+
/**
55+
* Renders this component within this test's activity
56+
*/
57+
public void renderComponent(final String componentName) throws Exception {
58+
final ReactAppTestActivity activity = getActivity();
59+
try {
60+
runTestOnUiThread(new Runnable() {
61+
@Override
62+
public void run() {
63+
activity.renderComponent(componentName, null);
64+
}
65+
});
66+
} catch (Throwable t) {
67+
throw new Exception("Unable to render component " + componentName, t);
68+
}
69+
assertTrue("Layout never occurred!", activity.waitForLayout(5000));
70+
waitForBridgeAndUIIdle();
71+
}
72+
73+
@Override
74+
protected void tearDown() throws Exception {
75+
ReactAppTestActivity activity = getActivity();
76+
super.tearDown();
77+
activity.waitForDestroy(5000);
78+
}
79+
80+
public ViewGroup getRootView() {
81+
return (ViewGroup) getActivity().getRootView();
82+
}
83+
84+
public <T extends View> T getViewByTestId(String testID) {
85+
return (T) ReactTestHelper
86+
.getViewWithReactTestId((ViewGroup) getRootView().getParent(), testID);
87+
}
88+
89+
public SingleTouchGestureGenerator createGestureGenerator() {
90+
return new SingleTouchGestureGenerator(getRootView(), this);
91+
}
92+
93+
public void waitForBridgeAndUIIdle() {
94+
getActivity().waitForBridgeAndUIIdle();
95+
}
96+
97+
public void waitForBridgeAndUIIdle(long timeoutMs) {
98+
getActivity().waitForBridgeAndUIIdle(timeoutMs);
99+
}
100+
101+
protected boolean getEnableDevSupport() {
102+
return false;
103+
}
104+
105+
protected boolean isFabricTest() {
106+
return false;
107+
}
108+
109+
/**
110+
* Override this method to provide extra native modules to be loaded before the app starts
111+
*/
112+
protected ReactInstanceSpecForTest createReactInstanceSpecForTest() {
113+
return new ReactInstanceSpecForTest();
114+
}
115+
116+
/**
117+
* Implement this method to provide the bundle for this test
118+
*/
119+
protected abstract String getBundleName();
120+
121+
protected ReactContext getReactContext() {
122+
return getActivity().getReactContext();
123+
}
124+
}

0 commit comments

Comments
 (0)