diff --git a/lib/web_ui/dart_test_edge.yaml b/lib/web_ui/dart_test_edge.yaml new file mode 100644 index 0000000000000..944cb83a0cefc --- /dev/null +++ b/lib/web_ui/dart_test_edge.yaml @@ -0,0 +1,7 @@ +# For more information on test and runner configurations: +# +# * https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#platforms + +platforms: + - ie + - vm diff --git a/lib/web_ui/dev/common.dart b/lib/web_ui/dev/common.dart index 17bf4d8010a48..717528b73c0a3 100644 --- a/lib/web_ui/dev/common.dart +++ b/lib/web_ui/dev/common.dart @@ -51,6 +51,7 @@ abstract class PlatformBinding { String getFirefoxExecutablePath(io.Directory versionDir); String getFirefoxLatestVersionUrl(); String getSafariSystemExecutablePath(); + String getCommandToRunEdge(); } const String _kBaseDownloadUrl = @@ -86,6 +87,12 @@ class _WindowsBinding implements PlatformBinding { @override String getSafariSystemExecutablePath() => throw UnsupportedError('Safari is not supported on Windows'); + + // TODO(nurhan): Add code to check and install MicrosoftEdgeLauncher + // if missing. + // See: https://github.com/flutter/flutter/issues/48823 + @override + String getCommandToRunEdge() => 'MicrosoftEdgeLauncher'; } class _LinuxBinding implements PlatformBinding { @@ -118,6 +125,10 @@ class _LinuxBinding implements PlatformBinding { @override String getSafariSystemExecutablePath() => throw UnsupportedError('Safari is not supported on Linux'); + + @override + String getCommandToRunEdge() => + throw UnsupportedError('Edge is not supported on Linux'); } class _MacBinding implements PlatformBinding { @@ -155,6 +166,10 @@ class _MacBinding implements PlatformBinding { @override String getSafariSystemExecutablePath() => '/Applications/Safari.app/Contents/MacOS/Safari'; + + @override + String getCommandToRunEdge() => + throw UnimplementedError('Tests for Edge are not implemented for MacOS.'); } class BrowserInstallation { diff --git a/lib/web_ui/dev/edge.dart b/lib/web_ui/dev/edge.dart new file mode 100644 index 0000000000000..1aa0321bc7644 --- /dev/null +++ b/lib/web_ui/dev/edge.dart @@ -0,0 +1,53 @@ +// Copyright 2013 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. + +import 'dart:async'; +import 'dart:io'; + +import 'browser.dart'; +import 'common.dart'; +import 'edge_installation.dart'; + +/// A class for running an instance of Edge. +/// +/// Most of the communication with the browser is expected to happen via HTTP, +/// so this exposes a bare-bones API. The browser starts as soon as the class is +/// constructed, and is killed when [close] is called. +/// +/// Any errors starting or running the process are reported through [onExit]. +class Edge extends Browser { + @override + final name = 'Edge'; + + static String version; + + /// Starts a new instance of Safari open to the given [url], which may be a + /// [Uri] or a [String]. + factory Edge(Uri url, {bool debug = false}) { + version = EdgeArgParser.instance.version; + + assert(version != null); + return Edge._(() async { + // TODO(nurhan): Configure info log for LUCI. + final BrowserInstallation installation = await getEdgeInstallation( + version, + infoLog: DevNull(), + ); + + // Debug is not a valid option for Edge. Remove it. + String pathToOpen = url.toString(); + if(pathToOpen.contains('debug')) { + int index = pathToOpen.indexOf('debug'); + pathToOpen = pathToOpen.substring(0, index-1); + } + + var process = + await Process.start(installation.executable, ['$pathToOpen','-k']); + + return process; + }); + } + + Edge._(Future startBrowser()) : super(startBrowser); +} diff --git a/lib/web_ui/dev/edge_installation.dart b/lib/web_ui/dev/edge_installation.dart new file mode 100644 index 0000000000000..5c302a5fea2ef --- /dev/null +++ b/lib/web_ui/dev/edge_installation.dart @@ -0,0 +1,79 @@ +// Copyright 2013 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. + +import 'dart:async'; +import 'dart:io' as io; + +import 'package:args/args.dart'; + +import 'common.dart'; + +class EdgeArgParser extends BrowserArgParser { + static final EdgeArgParser _singletonInstance = EdgeArgParser._(); + + /// The [EdgeArgParser] singleton. + static EdgeArgParser get instance => _singletonInstance; + + String _version; + + EdgeArgParser._(); + + @override + void populateOptions(ArgParser argParser) { + argParser + ..addOption( + 'edge-version', + defaultsTo: 'system', + help: 'The Edge version to use while running tests. The Edge ' + 'browser installed on the system is used as the only option now.', + ); + } + + @override + void parseOptions(ArgResults argResults) { + _version = argResults['edge-version']; + assert(_version == 'system'); + } + + @override + String get version => _version; +} + +/// Returns the installation of Edge. +/// +/// Currently uses the Edge version installed on the operating system. +/// +/// As explained on the Microsoft help page: `Microsoft Edge comes +/// exclusively with Windows 10 and cannot be downloaded or installed separately.` +/// See: https://support.microsoft.com/en-us/help/17171/microsoft-edge-get-to-know +/// +// TODO(nurhan): Investigate running tests for the tech preview downloads +// from the beta channel. +Future getEdgeInstallation( + String requestedVersion, { + StringSink infoLog, +}) async { + // For now these tests are aimed to run only on Windows machines local or on LUCI/CI. + // In the future we can investigate to run them on Android or on MacOS. + if (!io.Platform.isWindows) { + throw UnimplementedError( + 'Tests for Edge on ${io.Platform.operatingSystem} is' + ' not supported.'); + } + + infoLog ??= io.stdout; + + if (requestedVersion == 'system') { + // Since Edge is included in Windows, always assume there will be one on the + // system. + infoLog.writeln('Using the system version that is already installed.'); + return BrowserInstallation( + version: 'system', + executable: PlatformBinding.instance.getCommandToRunEdge(), + ); + } else { + infoLog.writeln('Unsupported version $requestedVersion.'); + throw UnimplementedError(); + } +} diff --git a/lib/web_ui/dev/supported_browsers.dart b/lib/web_ui/dev/supported_browsers.dart index 5581e1ba82eb2..b2c146df2321d 100644 --- a/lib/web_ui/dev/supported_browsers.dart +++ b/lib/web_ui/dev/supported_browsers.dart @@ -8,7 +8,9 @@ import 'browser.dart'; import 'chrome.dart'; import 'chrome_installer.dart'; import 'common.dart'; +import 'edge.dart'; import 'environment.dart'; +import 'edge_installation.dart'; import 'firefox.dart'; import 'firefox_installer.dart'; import 'safari.dart'; @@ -23,21 +25,43 @@ import 'safari_installation.dart'; /// /// One should also implement [BrowserArgParser] and add it to the [argParsers]. class SupportedBrowsers { - final List argParsers = - List.of([ChromeArgParser.instance, FirefoxArgParser.instance, SafariArgParser.instance]); + final List argParsers = List.of([ + ChromeArgParser.instance, + EdgeArgParser.instance, + FirefoxArgParser.instance, + SafariArgParser.instance + ]); - final List supportedBrowserNames = ['chrome', 'firefox', 'safari']; + final List supportedBrowserNames = [ + 'chrome', + 'edge', + 'firefox', + 'safari' + ]; final Map supportedBrowsersToRuntimes = { 'chrome': Runtime.chrome, + 'edge': Runtime.internetExplorer, 'firefox': Runtime.firefox, 'safari': Runtime.safari, }; + final Map supportedBrowserToPlatform = { + 'chrome': 'chrome', + 'edge': 'ie', + 'firefox': 'firefox', + 'safari': 'safari', + }; + final Map browserToConfiguration = { - 'chrome': '--configuration=${environment.webUiRootDir.path}/dart_test_chrome.yaml', - 'firefox': '--configuration=${environment.webUiRootDir.path}/dart_test_firefox.yaml', - 'safari': '--configuration=${environment.webUiRootDir.path}/dart_test_safari.yaml', + 'chrome': + '--configuration=${environment.webUiRootDir.path}/dart_test_chrome.yaml', + 'edge': + '--configuration=${environment.webUiRootDir.path}/dart_test_edge.yaml', + 'firefox': + '--configuration=${environment.webUiRootDir.path}/dart_test_firefox.yaml', + 'safari': + '--configuration=${environment.webUiRootDir.path}/dart_test_safari.yaml', }; static final SupportedBrowsers _singletonInstance = SupportedBrowsers._(); @@ -48,8 +72,10 @@ class SupportedBrowsers { SupportedBrowsers._(); Browser getBrowser(Runtime runtime, Uri url, {bool debug = false}) { - if (runtime == Runtime.chrome) { + if (runtime == Runtime.chrome) { return Chrome(url, debug: debug); + } else if (runtime == Runtime.internetExplorer) { + return Edge(url, debug: debug); } else if (runtime == Runtime.firefox) { return Firefox(url, debug: debug); } else if (runtime == Runtime.safari) { diff --git a/lib/web_ui/dev/test_runner.dart b/lib/web_ui/dev/test_runner.dart index f6ccebdf2a2bd..1c8cffcbc8c50 100644 --- a/lib/web_ui/dev/test_runner.dart +++ b/lib/web_ui/dev/test_runner.dart @@ -250,9 +250,7 @@ class TestCommand extends Command { } Future _buildTests({List targets}) async { - final int exitCode = await runProcess( - environment.pubExecutable, - [ + List arguments = [ 'run', 'build_runner', 'build', @@ -264,7 +262,10 @@ class TestCommand extends Command { '--build-filter=${path.relativeToWebUi}.js', '--build-filter=${path.relativeToWebUi}.browser_test.dart.js', ], - ], + ]; + final int exitCode = await runProcess( + environment.pubExecutable, + arguments, workingDirectory: environment.webUiRootDir.path, ); @@ -287,7 +288,7 @@ class TestCommand extends Command { ...['-r', 'compact'], '--concurrency=$concurrency', if (isDebug) '--pause-after-load', - '--platform=$browser', + '--platform=${SupportedBrowsers.instance.supportedBrowserToPlatform[browser]}', '--precompiled=${environment.webUiRootDir.path}/build', SupportedBrowsers.instance.browserToConfiguration[browser], '--',