66import static org .junit .Assert .assertNotNull ;
77import static org .junit .Assert .assertNull ;
88import static org .junit .Assert .assertTrue ;
9+ import static org .mockito .ArgumentMatchers .any ;
910import static org .mockito .Mockito .doAnswer ;
1011import static org .mockito .Mockito .mock ;
1112import static org .mockito .Mockito .never ;
13+ import static org .mockito .Mockito .spy ;
1214import static org .mockito .Mockito .times ;
1315import static org .mockito .Mockito .verify ;
1416import static org .mockito .Mockito .when ;
@@ -36,10 +38,25 @@ public class FlutterFragmentTest {
3638 private final Context ctx = ApplicationProvider .getApplicationContext ();
3739 boolean isDelegateAttached ;
3840
41+ class TestDelegateFactory implements FlutterActivityAndFragmentDelegate .DelegateFactory {
42+ FlutterActivityAndFragmentDelegate delegate ;
43+
44+ TestDelegateFactory (FlutterActivityAndFragmentDelegate delegate ) {
45+ this .delegate = delegate ;
46+ }
47+
48+ public FlutterActivityAndFragmentDelegate createDelegate (
49+ FlutterActivityAndFragmentDelegate .Host host ) {
50+ return delegate ;
51+ }
52+ }
53+
3954 @ Test
4055 public void itCreatesDefaultFragmentWithExpectedDefaults () {
4156 FlutterFragment fragment = FlutterFragment .createDefault ();
42- fragment .setDelegate (new FlutterActivityAndFragmentDelegate (fragment ));
57+ TestDelegateFactory delegateFactory =
58+ new TestDelegateFactory (new FlutterActivityAndFragmentDelegate (fragment ));
59+ fragment .setDelegateFactory (delegateFactory );
4360
4461 assertEquals ("main" , fragment .getDartEntrypointFunctionName ());
4562 assertNull (fragment .getDartEntrypointLibraryUri ());
@@ -68,7 +85,9 @@ public void itCreatesNewEngineFragmentWithRequestedSettings() {
6885 .renderMode (RenderMode .texture )
6986 .transparencyMode (TransparencyMode .opaque )
7087 .build ();
71- fragment .setDelegate (new FlutterActivityAndFragmentDelegate (fragment ));
88+ TestDelegateFactory delegateFactory =
89+ new TestDelegateFactory (new FlutterActivityAndFragmentDelegate (fragment ));
90+ fragment .setDelegateFactory (delegateFactory );
7291
7392 assertEquals ("custom_entrypoint" , fragment .getDartEntrypointFunctionName ());
7493 assertEquals ("package:foo/bar.dart" , fragment .getDartEntrypointLibraryUri ());
@@ -127,6 +146,7 @@ public void itCreatesCachedEngineFragmentThatDelaysFirstDrawWhenRequested() {
127146 public void itCanBeDetachedFromTheEngineAndStopSendingFurtherEvents () {
128147 FlutterActivityAndFragmentDelegate mockDelegate =
129148 mock (FlutterActivityAndFragmentDelegate .class );
149+ TestDelegateFactory delegateFactory = new TestDelegateFactory (mockDelegate );
130150 FlutterFragment fragment =
131151 FlutterFragment .withCachedEngine ("my_cached_engine" )
132152 .destroyEngineWithFragment (true )
@@ -136,7 +156,7 @@ public void itCanBeDetachedFromTheEngineAndStopSendingFurtherEvents() {
136156 when (mockDelegate .isAttached ()).thenAnswer (invocation -> isDelegateAttached );
137157 doAnswer (invocation -> isDelegateAttached = false ).when (mockDelegate ).onDetach ();
138158
139- fragment .setDelegate ( mockDelegate );
159+ fragment .setDelegateFactory ( delegateFactory );
140160 fragment .onStart ();
141161 fragment .onResume ();
142162 fragment .onPostResume ();
@@ -175,13 +195,14 @@ public void itDoesNotReleaseEnginewhenDetachFromFlutterEngine() {
175195 isDelegateAttached = true ;
176196 when (mockDelegate .isAttached ()).thenAnswer (invocation -> isDelegateAttached );
177197 doAnswer (invocation -> isDelegateAttached = false ).when (mockDelegate ).onDetach ();
198+ TestDelegateFactory delegateFactory = new TestDelegateFactory (mockDelegate );
178199
179200 FlutterFragment fragment =
180201 FlutterFragment .withCachedEngine ("my_cached_engine" )
181202 .destroyEngineWithFragment (true )
182203 .build ();
183204
184- fragment .setDelegate ( mockDelegate );
205+ fragment .setDelegateFactory ( delegateFactory );
185206 fragment .onStart ();
186207 fragment .onResume ();
187208 fragment .onPostResume ();
@@ -201,13 +222,16 @@ public void itReleaseEngineWhenOnDetach() {
201222 isDelegateAttached = true ;
202223 when (mockDelegate .isAttached ()).thenAnswer (invocation -> isDelegateAttached );
203224 doAnswer (invocation -> isDelegateAttached = false ).when (mockDelegate ).onDetach ();
225+ TestDelegateFactory delegateFactory = new TestDelegateFactory (mockDelegate );
204226
205227 FlutterFragment fragment =
206- FlutterFragment .withCachedEngine ("my_cached_engine" )
207- .destroyEngineWithFragment (true )
208- .build ();
228+ spy (
229+ FlutterFragment .withCachedEngine ("my_cached_engine" )
230+ .destroyEngineWithFragment (true )
231+ .build ());
232+ when (fragment .getContext ()).thenReturn (mock (Context .class ));
209233
210- fragment .setDelegate ( mockDelegate );
234+ fragment .setDelegateFactory ( delegateFactory );
211235 fragment .onStart ();
212236 fragment .onResume ();
213237 fragment .onPostResume ();
@@ -224,7 +248,8 @@ public void itReleaseEngineWhenOnDetach() {
224248 public void itReturnsExclusiveAppComponent () {
225249 FlutterFragment fragment = FlutterFragment .createDefault ();
226250 FlutterActivityAndFragmentDelegate delegate = new FlutterActivityAndFragmentDelegate (fragment );
227- fragment .setDelegate (delegate );
251+ TestDelegateFactory delegateFactory = new TestDelegateFactory (delegate );
252+ fragment .setDelegateFactory (delegateFactory );
228253
229254 assertEquals (fragment .getExclusiveAppComponent (), delegate );
230255 }
@@ -255,7 +280,8 @@ public void itDelegatesOnBackPressedAutomaticallyWhenEnabled() {
255280 isDelegateAttached = true ;
256281 when (mockDelegate .isAttached ()).thenAnswer (invocation -> isDelegateAttached );
257282 doAnswer (invocation -> isDelegateAttached = false ).when (mockDelegate ).onDetach ();
258- fragment .setDelegate (mockDelegate );
283+ TestDelegateFactory delegateFactory = new TestDelegateFactory (mockDelegate );
284+ fragment .setDelegateFactory (delegateFactory );
259285
260286 activity .onBackPressed ();
261287
@@ -294,11 +320,43 @@ public void handleOnBackPressed() {
294320
295321 FlutterActivityAndFragmentDelegate mockDelegate =
296322 mock (FlutterActivityAndFragmentDelegate .class );
297- fragment .setDelegate (mockDelegate );
323+ TestDelegateFactory delegateFactory = new TestDelegateFactory (mockDelegate );
324+ fragment .setDelegateFactory (delegateFactory );
298325
299326 assertTrue (fragment .popSystemNavigator ());
300327
301328 verify (mockDelegate , never ()).onBackPressed ();
302329 assertTrue (onBackPressedCalled .get ());
303330 }
331+
332+ @ Test
333+ public void itRegistersComponentCallbacks () {
334+ FlutterActivityAndFragmentDelegate mockDelegate =
335+ mock (FlutterActivityAndFragmentDelegate .class );
336+ isDelegateAttached = true ;
337+ when (mockDelegate .isAttached ()).thenAnswer (invocation -> isDelegateAttached );
338+ doAnswer (invocation -> isDelegateAttached = false ).when (mockDelegate ).onDetach ();
339+ TestDelegateFactory delegateFactory = new TestDelegateFactory (mockDelegate );
340+
341+ Context spyCtx = spy (ctx );
342+ // We need to mock FlutterJNI to avoid triggering native code.
343+ FlutterJNI flutterJNI = mock (FlutterJNI .class );
344+ when (flutterJNI .isAttached ()).thenReturn (true );
345+
346+ FlutterEngine flutterEngine =
347+ new FlutterEngine (spyCtx , new FlutterLoader (), flutterJNI , null , false );
348+ FlutterEngineCache .getInstance ().put ("my_cached_engine" , flutterEngine );
349+
350+ FlutterFragment fragment = spy (FlutterFragment .withCachedEngine ("my_cached_engine" ).build ());
351+ when (fragment .getContext ()).thenReturn (spyCtx );
352+ fragment .setDelegateFactory (delegateFactory );
353+
354+ fragment .onAttach (spyCtx );
355+ verify (spyCtx , times (1 )).registerComponentCallbacks (any ());
356+ verify (spyCtx , never ()).unregisterComponentCallbacks (any ());
357+
358+ fragment .onDetach ();
359+ verify (spyCtx , times (1 )).registerComponentCallbacks (any ());
360+ verify (spyCtx , times (1 )).unregisterComponentCallbacks (any ());
361+ }
304362}
0 commit comments