Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit a8c9c31

Browse files
authored
flutter view add test 2 (#55188)
- **add test back with no other changes** - **Add legacy test and setup shadow** 2 and 3 of 5 flutter/flutter/issues/154746 Improved legacy testing by validating a fullscreen and non fullscreen codepaths. Added `.git-blame-ignore-revs` because git was failing to give blame values with that file missing. I dont think I added a global config anywhere but adding an empty file should not cause a problem.
1 parent 464e460 commit a8c9c31

File tree

3 files changed

+97
-8
lines changed

3 files changed

+97
-8
lines changed

.git-blame-ignore-revs

Whitespace-only changes.

shell/platform/android/test/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,8 @@ See [Updating Embedding Dependencies](/tools/cipd/android_embedding_bundle).
3939
### My new test won't compile. It can't find one of my imports.
4040

4141
See [Updating Embedding Dependencies](/tools/cipd/android_embedding_bundle).
42+
43+
### My test does not show log output in the console
44+
45+
Import `org.robolectric.shadows.ShadowLog;` then
46+
Use `ShadowLog.stream = System.out;` in your test or setup method.

shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java

+92-8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static junit.framework.TestCase.assertTrue;
1010
import static org.mockito.ArgumentMatchers.any;
1111
import static org.mockito.ArgumentMatchers.anyInt;
12+
import static org.mockito.Mockito.clearInvocations;
1213
import static org.mockito.Mockito.doNothing;
1314
import static org.mockito.Mockito.doReturn;
1415
import static org.mockito.Mockito.mock;
@@ -36,7 +37,6 @@
3637
import android.view.DisplayCutout;
3738
import android.view.Surface;
3839
import android.view.View;
39-
import android.view.ViewGroup;
4040
import android.view.WindowInsets;
4141
import android.view.WindowManager;
4242
import android.widget.FrameLayout;
@@ -69,6 +69,7 @@
6969
import org.robolectric.annotation.Implementation;
7070
import org.robolectric.annotation.Implements;
7171
import org.robolectric.shadows.ShadowDisplay;
72+
import org.robolectric.shadows.ShadowViewGroup;
7273

7374
@Config(manifest = Config.NONE)
7475
@RunWith(AndroidJUnit4.class)
@@ -83,6 +84,8 @@ public class FlutterViewTest {
8384
public void setUp() {
8485
MockitoAnnotations.openMocks(this);
8586
when(mockFlutterJni.isAttached()).thenReturn(true);
87+
// Uncomment the following line to enable logging output in test.
88+
// ShadowLog.stream = System.out;
8689
}
8790

8891
@SuppressWarnings("deprecation")
@@ -937,6 +940,92 @@ public void ViewportMetrics_initializedPhysicalTouchSlop() {
937940
assertFalse(-1 == viewportMetricsCaptor.getValue().physicalTouchSlop);
938941
}
939942

943+
@SuppressWarnings("deprecation")
944+
// Robolectric.setupActivity
945+
// TODO(reidbaker): https://github.com/flutter/flutter/issues/133151
946+
// This test uses the API 30+ Algorithm for window insets. The legacy algorithm is
947+
// set to -1 values, so it is clear if the wrong algorithm is used.
948+
@Test
949+
@TargetApi(30)
950+
@Config(sdk = 30)
951+
public void setPaddingTopToZeroForFullscreenMode() {
952+
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
953+
FlutterEngine flutterEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
954+
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
955+
when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
956+
957+
// When we attach a new FlutterView to the engine without any system insets, the viewport
958+
// metrics
959+
// default to 0.
960+
flutterView.attachToFlutterEngine(flutterEngine);
961+
ArgumentCaptor<FlutterRenderer.ViewportMetrics> viewportMetricsCaptor =
962+
ArgumentCaptor.forClass(FlutterRenderer.ViewportMetrics.class);
963+
verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
964+
assertEquals(0, viewportMetricsCaptor.getValue().viewPaddingTop);
965+
966+
// Then we simulate the system applying a window inset.
967+
WindowInsets windowInsets =
968+
new WindowInsets.Builder()
969+
.setInsets(
970+
android.view.WindowInsets.Type.navigationBars()
971+
| android.view.WindowInsets.Type.statusBars(),
972+
Insets.of(100, 100, 100, 100))
973+
.build();
974+
flutterView.onApplyWindowInsets(windowInsets);
975+
976+
// Verify.
977+
verify(flutterRenderer, times(3)).setViewportMetrics(viewportMetricsCaptor.capture());
978+
validateViewportMetricPadding(viewportMetricsCaptor, 100, 100, 100, 100);
979+
}
980+
981+
@SuppressWarnings("deprecation")
982+
// Robolectric.setupActivity
983+
// TODO(reidbaker): https://github.com/flutter/flutter/issues/133151
984+
// This test uses the pre-API 30 Algorithm for window insets.
985+
@Test
986+
@TargetApi(28)
987+
@Config(
988+
sdk = 28,
989+
shadows = {
990+
FlutterViewTest.ShadowFullscreenView.class,
991+
})
992+
public void setPaddingTopToZeroForFullscreenModeLegacy() {
993+
FlutterView flutterView = spy(new FlutterView(ctx));
994+
FlutterEngine flutterEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
995+
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
996+
when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
997+
998+
// When we attach a new FlutterView to the engine without any system insets, the viewport
999+
// metrics
1000+
// default to 0.
1001+
flutterView.attachToFlutterEngine(flutterEngine);
1002+
ArgumentCaptor<FlutterRenderer.ViewportMetrics> viewportMetricsCaptor =
1003+
ArgumentCaptor.forClass(FlutterRenderer.ViewportMetrics.class);
1004+
verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
1005+
assertEquals(0, viewportMetricsCaptor.getValue().viewPaddingTop);
1006+
clearInvocations(flutterRenderer);
1007+
// Then we simulate the system applying a window inset.
1008+
WindowInsets windowInsets = mock(WindowInsets.class);
1009+
mockSystemWindowInsets(windowInsets, 100, 100, 100, 100);
1010+
flutterView.onApplyWindowInsets(windowInsets);
1011+
1012+
// Verify.
1013+
verify(flutterRenderer, times(1)).setViewportMetrics(viewportMetricsCaptor.capture());
1014+
validateViewportMetricPadding(viewportMetricsCaptor, 100, 100, 100, 0);
1015+
clearInvocations(flutterRenderer);
1016+
1017+
// Validation when fullscreen
1018+
when(flutterView.getWindowSystemUiVisibility()).thenReturn(View.SYSTEM_UI_FLAG_FULLSCREEN);
1019+
1020+
// Then we simulate the system applying a window inset.
1021+
mockSystemWindowInsets(windowInsets, 100, 100, 100, 100);
1022+
flutterView.onApplyWindowInsets(windowInsets);
1023+
1024+
// Verify.
1025+
verify(flutterRenderer, times(1)).setViewportMetrics(viewportMetricsCaptor.capture());
1026+
validateViewportMetricPadding(viewportMetricsCaptor, 100, 0, 100, 0);
1027+
}
1028+
9401029
@SuppressWarnings("deprecation")
9411030
private void setExpectedDisplayRotation(int rotation) {
9421031
ShadowDisplay display =
@@ -976,17 +1065,12 @@ private void mockSystemGestureInsetsIfNeed(WindowInsets windowInsets) {
9761065
/*
9771066
* A custom shadow that reports fullscreen flag for system UI visibility
9781067
*/
979-
@Implements(View.class)
1068+
@Implements(FrameLayout.class)
9801069
@SuppressWarnings("deprecation")
981-
public static class ShadowFullscreenView {
1070+
public static class ShadowFullscreenView extends ShadowViewGroup {
9821071
@Implementation
9831072
public int getWindowSystemUiVisibility() {
9841073
return View.SYSTEM_UI_FLAG_FULLSCREEN;
9851074
}
9861075
}
987-
988-
// ViewGroup is the first shadow in the type hierarchy for FlutterView. Shadows need to mimic
989-
// production classes' view hierarchy.
990-
@Implements(ViewGroup.class)
991-
public static class ShadowFullscreenViewGroup extends ShadowFullscreenView {}
9921076
}

0 commit comments

Comments
 (0)