Add Android Chrome support to Flutter Web Driver. (#51677)

* Support Android Chrome for Flutter Web Driver.
This commit is contained in:
Angjie Li 2020-03-09 13:01:07 -07:00 committed by GitHub
parent 28e15ccc5e
commit 665d380f81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 24 deletions

View file

@ -20,10 +20,8 @@ import 'timeline.dart';
/// An implementation of the Flutter Driver using the WebDriver.
///
/// Example of how to test WebFlutterDriver:
/// 1. Have Selenium server (https://bit.ly/2TlkRyu) and WebDriver binary (https://chromedriver.chromium.org/downloads) downloaded and placed under the same folder
/// 2. Launch WebDriver Server: java -jar selenium-server-standalone-3.141.59.jar
/// 3. Launch Flutter Web application: flutter run -v -d chrome --target=test_driver/scroll_perf_web.dart
/// 4. Run test script: flutter drive --target=test_driver/scroll_perf_web.dart -v --use-existing-app=/application address/
/// 1. Launch WebDriver binary: ./chromedriver --port=4444
/// 2. Run test script: flutter drive --target=test_driver/scroll_perf_web.dart -d web-server --release
class WebFlutterDriver extends FlutterDriver {
/// Creates a driver that uses a connection provided by the given
/// [_connection].
@ -47,7 +45,7 @@ class WebFlutterDriver extends FlutterDriver {
/// [hostUrl] which would fallback to environment variable VM_SERVICE_URL.
/// Driver also depends on environment variables DRIVER_SESSION_ID,
/// BROWSER_SUPPORTS_TIMELINE, DRIVER_SESSION_URI, DRIVER_SESSION_SPEC
/// and DRIVER_SESSION_CAPABILITIES for configurations.
/// and ANDROID_CHROME_ON_EMULATOR for configurations.
static Future<FlutterDriver> connectWeb(
{String hostUrl, Duration timeout}) async {
hostUrl ??= Platform.environment['VM_SERVICE_URL'];
@ -56,7 +54,7 @@ class WebFlutterDriver extends FlutterDriver {
'session-id': Platform.environment['DRIVER_SESSION_ID'],
'session-uri': Platform.environment['DRIVER_SESSION_URI'],
'session-spec': Platform.environment['DRIVER_SESSION_SPEC'],
'session-capabilities': Platform.environment['DRIVER_SESSION_CAPABILITIES'],
'android-chrome-on-emulator': Platform.environment['ANDROID_CHROME_ON_EMULATOR'] == 'true',
};
final FlutterWebConnection connection = await FlutterWebConnection.connect
(hostUrl, settings, timeout: timeout);
@ -183,7 +181,7 @@ class FlutterWebConnection {
_supportsTimelineAction = value;
}
/// Starts WebDriver with the given [capabilities] and
/// Starts WebDriver with the given [settings] and
/// establishes the connection to Flutter Web application.
static Future<FlutterWebConnection> connect(
String url,
@ -195,6 +193,13 @@ class FlutterWebConnection {
settings['session-id'].toString(),
uri: Uri.parse(settings['session-uri'].toString()),
spec: _convertToSpec(settings['session-spec'].toString().toLowerCase()));
if (settings['android-chrome-on-emulator'] == true) {
final Uri localUri = Uri.parse(url);
// Converts to Android Emulator Uri.
// Hardcode the host to 10.0.2.2 based on
// https://developer.android.com/studio/run/emulator-networking
url = Uri(scheme: localUri.scheme, host: '10.0.2.2', port:localUri.port).toString();
}
await driver.get(url);
await waitUntilExtensionInstalled(driver, timeout);

View file

@ -14,7 +14,6 @@ import '../base/file_system.dart';
import '../base/process.dart';
import '../build_info.dart';
import '../cache.dart';
import '../convert.dart';
import '../dart/package_map.dart';
import '../dart/sdk.dart';
import '../device.dart';
@ -92,6 +91,7 @@ class DriveCommand extends RunCommandBase {
'Following browsers are supported: \n'
'Chrome, Firefox, Safari (macOS and iOS) and Edge. Defaults to Chrome.',
allowed: <String>[
'android-chrome',
'chrome',
'edge',
'firefox',
@ -104,7 +104,11 @@ class DriveCommand extends RunCommandBase {
help: 'The dimension of browser when running Flutter Web test. \n'
'This will affect screenshot and all offset-related actions. \n'
'By default. it is set to 1600,1024 (1600 by 1024).',
);
)
..addFlag('android-emulator',
defaultsTo: true,
help: 'Whether to perform Flutter Driver testing on Android Emulator.'
'Works only if \'browser-name\' is set to \'android-chrome\'');
}
@override
@ -187,7 +191,15 @@ class DriveCommand extends RunCommandBase {
target: targetFile,
flutterProject: flutterProject,
ipv6: ipv6,
debuggingOptions: DebuggingOptions.enabled(buildInfo),
debuggingOptions: getBuildInfo().isRelease ?
DebuggingOptions.disabled(
getBuildInfo(),
port: stringArg('web-port')
)
: DebuggingOptions.enabled(
getBuildInfo(),
port: stringArg('web-port')
),
stayResident: false,
urlTunneller: null,
);
@ -243,25 +255,27 @@ class DriveCommand extends RunCommandBase {
);
}
final bool isAndroidChrome = browser == Browser.androidChrome;
final bool useEmulator = argResults['android-emulator'] as bool;
// set window size
final List<String> dimensions = argResults['browser-dimension'].split(',') as List<String>;
assert(dimensions.length == 2);
int x, y;
try {
x = int.parse(dimensions[0]);
y = int.parse(dimensions[1]);
} on FormatException catch (ex) {
throwToolExit('''
// for android chrome, skip such action
if (!isAndroidChrome) {
final List<String> dimensions = argResults['browser-dimension'].split(
',') as List<String>;
assert(dimensions.length == 2);
int x, y;
try {
x = int.parse(dimensions[0]);
y = int.parse(dimensions[1]);
} on FormatException catch (ex) {
throwToolExit('''
Dimension provided to --browser-dimension is invalid:
$ex
''');
}
final async_io.Window window = await driver.window;
try {
}
final async_io.Window window = await driver.window;
await window.setLocation(const math.Point<int>(0, 0));
await window.setSize(math.Rectangle<int>(0, 0, x, y));
} on Exception {
// Error might be thrown in some browsers.
}
// add driver info to environment variables
@ -269,9 +283,9 @@ $ex
'DRIVER_SESSION_ID': driver.id,
'DRIVER_SESSION_URI': driver.uri.toString(),
'DRIVER_SESSION_SPEC': driver.spec.toString(),
'DRIVER_SESSION_CAPABILITIES': jsonEncode(driver.capabilities),
'SUPPORT_TIMELINE_ACTION': (browser == Browser.chrome).toString(),
'FLUTTER_WEB_TEST': 'true',
'ANDROID_CHROME_ON_EMULATOR': (isAndroidChrome && useEmulator).toString(),
});
}
@ -489,6 +503,8 @@ Future<bool> _stopApp(DriveCommand command) async {
/// A list of supported browsers
@visibleForTesting
enum Browser {
/// Chrome on Android: https://developer.chrome.com/multidevice/android/overview
androidChrome,
/// Chrome: https://www.google.com/chrome/
chrome,
/// Edge: https://www.microsoft.com/en-us/windows/microsoft-edge
@ -504,6 +520,7 @@ enum Browser {
/// Converts [browserName] string to [Browser]
Browser _browserNameToEnum(String browserName){
switch (browserName) {
case 'android-chrome': return Browser.androidChrome;
case 'chrome': return Browser.chrome;
case 'edge': return Browser.edge;
case 'firefox': return Browser.firefox;
@ -592,6 +609,15 @@ Map<String, dynamic> getDesiredCapabilities(Browser browser, bool headless) {
'browserName': 'safari',
'safari:useSimulator': true
};
case Browser.androidChrome:
return <String, dynamic>{
'browserName': 'chrome',
'platformName': 'android',
'goog:chromeOptions': <String, dynamic>{
'androidPackage': 'com.android.chrome',
'args': <String>['--disable-fullscreen']
},
};
default:
throw UnsupportedError('Browser $browser not supported.');
}

View file

@ -713,6 +713,19 @@ void main() {
expect(getDesiredCapabilities(Browser.iosSafari, false), expected);
});
test('android chrome', () {
final Map<String, dynamic> expected = <String, dynamic>{
'browserName': 'chrome',
'platformName': 'android',
'goog:chromeOptions': <String, dynamic>{
'androidPackage': 'com.android.chrome',
'args': <String>['--disable-fullscreen']
},
};
expect(getDesiredCapabilities(Browser.androidChrome, false), expected);
});
});
}