[integration_test] Allow capture of screenshots for FlutterFragmentActivitys (#132406)

Fixes https://github.com/flutter/flutter/issues/89683.

The changes to `getFlutterView` in `FlutterDeviceScreenshot` are the fix that was required, everything else was done to get tests running (such as re-generating some lockfiles and modifying the android manifest).

The code was all currently not unit tested, and there were no other easy examples to base these java unit tests off in flutter/flutter, so let me know if this approach to testing is wrong.
This commit is contained in:
Gray Mackall 2023-09-07 18:32:48 -04:00 committed by GitHub
parent c79868b068
commit 827b5dff02
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 95 additions and 9 deletions

View file

@ -598,7 +598,7 @@ targets:
{"dependency": "clang", "version": "git_revision:5d5aba78dbbee75508f01bcaa69aedb2ab79065a"},
{"dependency": "cmake", "version": "build_id:8787856497187628321"},
{"dependency": "ninja", "version": "version:1.9.0"},
{"dependency": "open_jdk", "version": "version:11"},
{"dependency": "open_jdk", "version": "version:17"},
{"dependency": "android_sdk", "version": "version:33v6"}
]
shard: framework_tests
@ -3092,7 +3092,7 @@ targets:
[
{"dependency": "goldctl", "version": "git_revision:f808dcff91b221ae313e540c09d79696cd08b8de"},
{"dependency": "gems", "version": "v3.3.14"},
{"dependency": "open_jdk", "version": "version:11"},
{"dependency": "open_jdk", "version": "version:17"},
{"dependency": "android_sdk", "version": "version:33v6"}
]
shard: framework_tests
@ -4502,7 +4502,7 @@ targets:
[
{"dependency": "goldctl", "version": "git_revision:f808dcff91b221ae313e540c09d79696cd08b8de"},
{"dependency": "vs_build", "version": "version:vs2019"},
{"dependency": "open_jdk", "version": "version:11"},
{"dependency": "open_jdk", "version": "version:17"},
{"dependency": "android_sdk", "version": "version:33v6"}
]
shard: framework_tests

View file

@ -1004,6 +1004,23 @@ Future<void> _runFrameworkTests() async {
// Web-specific tests depend on Chromium, so they run as part of the web_long_running_tests shard.
'--exclude-tags=web',
]);
// Run java unit tests for integration_test
//
// Generate Gradle wrapper if it doesn't exist.
Process.runSync(
flutter,
<String>['build', 'apk', '--config-only'],
workingDirectory: path.join(flutterRoot, 'packages', 'integration_test', 'example', 'android'),
);
await runCommand(
path.join(flutterRoot, 'packages', 'integration_test', 'example', 'android', 'gradlew$bat'),
<String>[
':integration_test:testDebugUnitTest',
'--tests',
'dev.flutter.plugins.integration_test.FlutterDeviceScreenshotTest',
],
workingDirectory: path.join(flutterRoot, 'packages', 'integration_test', 'example', 'android'),
);
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_goldens'));
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_localizations'));
await _runFlutterTest(path.join(flutterRoot, 'packages', 'flutter_test'));

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
group 'com.example.integration_test'
group 'dev.flutter.plugins.integration_test'
version '1.0-SNAPSHOT'
buildscript {
@ -47,7 +47,8 @@ android {
dependencies {
// TODO(egarciad): These dependencies should not be added to release builds.
// https://github.com/flutter/flutter/issues/56591
api 'junit:junit:4.12'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-inline:5.0.0'
// https://developer.android.com/jetpack/androidx/releases/test/#1.2.0
api 'androidx.test:runner:1.2.0'

View file

@ -3,5 +3,5 @@ Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.flutter.integration_test">
package="dev.flutter.integration_test">
</manifest>

View file

@ -19,7 +19,11 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterFragment;
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.embedding.android.FlutterSurfaceView;
import io.flutter.embedding.android.FlutterView;
import io.flutter.plugin.common.MethodChannel;
@ -51,8 +55,15 @@ class FlutterDeviceScreenshot {
* @return the Flutter view.
*/
@Nullable
private static FlutterView getFlutterView(@NonNull Activity activity) {
return (FlutterView)activity.findViewById(FlutterActivity.FLUTTER_VIEW_ID);
@VisibleForTesting
public static FlutterView getFlutterView(@NonNull Activity activity) {
if (activity instanceof FlutterActivity) {
return (FlutterView)activity.findViewById(FlutterActivity.FLUTTER_VIEW_ID);
} else if (activity instanceof FlutterFragmentActivity) {
return (FlutterView)activity.findViewById(FlutterFragment.FLUTTER_VIEW_ID);
} else {
return null;
}
}
/**
@ -110,7 +121,7 @@ class FlutterDeviceScreenshot {
}
}
// Handlers use to capture a view.
// Handlers used to capture a view.
private static Handler backgroundHandler;
private static Handler mainHandler;

View file

@ -0,0 +1,52 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package dev.flutter.plugins.integration_test;
import androidx.test.runner.AndroidJUnitRunner;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.Activity;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterFragment;
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.embedding.android.FlutterView;
public class FlutterDeviceScreenshotTest extends AndroidJUnitRunner {
@Test
public void getFlutterView_returnsNullForNonFlutterActivity() {
Activity mockActivity = mock(Activity.class);
assertNull(FlutterDeviceScreenshot.getFlutterView(mockActivity));
}
@Test
public void getFlutterView_returnsFlutterViewForFlutterActivity() {
FlutterView mockFlutterView = mock(FlutterView.class);
FlutterActivity mockFlutterActivity = mock(FlutterActivity.class);
when(mockFlutterActivity.findViewById(FlutterActivity.FLUTTER_VIEW_ID))
.thenReturn(mockFlutterView);
assertEquals(
FlutterDeviceScreenshot.getFlutterView(mockFlutterActivity),
mockFlutterView
);
}
@Test
public void getFlutterView_returnsFlutterViewForFlutterFragmentActivity() {
FlutterView mockFlutterView = mock(FlutterView.class);
FlutterFragmentActivity mockFlutterFragmentActivity = mock(FlutterFragmentActivity.class);
when(mockFlutterFragmentActivity.findViewById(FlutterFragment.FLUTTER_VIEW_ID))
.thenReturn(mockFlutterView);
assertEquals(
FlutterDeviceScreenshot.getFlutterView(mockFlutterFragmentActivity),
mockFlutterView
);
}
}

View file

@ -82,6 +82,8 @@ javax.activation:javax.activation-api:1.2.0=lintClassPath
javax.inject:javax.inject:1=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,lintClassPath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
javax.xml.bind:jaxb-api:2.3.1=lintClassPath
junit:junit:4.12=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.12.22=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
net.bytebuddy:byte-buddy:1.12.22=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
net.sf.jopt-simple:jopt-simple:4.9=lintClassPath
net.sf.kxml:kxml2:2.3.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,lintClassPath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
org.apache.commons:commons-compress:1.12=lintClassPath
@ -118,6 +120,9 @@ org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2=debugAndroidTestCompileClass
org.jetbrains.trove4j:trove4j:20160824=lintClassPath
org.jetbrains:annotations:13.0=debugAndroidTestCompileClasspath,debugAndroidTestRuntimeClasspath,debugCompileClasspath,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,lintClassPath,profileCompileClasspath,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseCompileClasspath,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
org.jvnet.staxex:stax-ex:1.8=lintClassPath
org.mockito:mockito-core:5.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
org.mockito:mockito-inline:5.0.0=debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath
org.objenesis:objenesis:3.3=debugUnitTestRuntimeClasspath,profileUnitTestRuntimeClasspath,releaseUnitTestRuntimeClasspath
org.ow2.asm:asm-analysis:7.0=lintClassPath
org.ow2.asm:asm-analysis:9.2=androidJacocoAnt
org.ow2.asm:asm-commons:7.0=lintClassPath