Skip to content

Commit 333a805

Browse files
authored
Changing test runner and platform to be browser independent (flutter#13869)
* changes to add firefox as one of the browser options to test_platform and test_runner * Creating a supported_browsers file to put all the different browser related maps and utilities * Remove accidentaly forgotten commented out lines. Clear imports * fix error in screenshot handler * Addressing PR comments. * addressing PR comments part 2:
1 parent 226ea7b commit 333a805

File tree

9 files changed

+264
-72
lines changed

9 files changed

+264
-72
lines changed

lib/web_ui/dev/browser.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import 'package:pedantic/pedantic.dart';
1010
import 'package:stack_trace/stack_trace.dart';
1111
import 'package:typed_data/typed_buffers.dart';
1212

13-
import 'package:test_api/src/utils.dart'; // ignore: implementation_imports
13+
import 'package:test_api/src/utils.dart';
14+
15+
import 'common.dart'; // ignore: implementation_imports
1416

1517
/// An interface for running browser instances.
1618
///

lib/web_ui/dev/chrome.dart

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class Chrome extends Browser {
3232
/// Starts a new instance of Chrome open to the given [url], which may be a
3333
/// [Uri] or a [String].
3434
factory Chrome(Uri url, {bool debug = false}) {
35+
version = ChromeArgParser.instance.version;
36+
3537
assert(version != null);
3638
var remoteDebuggerCompleter = Completer<Uri>.sync();
3739
return Chrome._(() async {
@@ -50,13 +52,16 @@ class Chrome extends Browser {
5052
// --disable-gpu
5153
// --disallow-non-exact-resource-reuse
5254
// --disable-font-subpixel-positioning
53-
final bool isChromeNoSandbox = Platform.environment['CHROME_NO_SANDBOX'] == 'true';
55+
final bool isChromeNoSandbox =
56+
Platform.environment['CHROME_NO_SANDBOX'] == 'true';
5457
var dir = createTempDir();
5558
var args = [
5659
'--user-data-dir=$dir',
5760
url.toString(),
58-
if (!debug) '--headless',
59-
if (isChromeNoSandbox) '--no-sandbox',
61+
if (!debug)
62+
'--headless',
63+
if (isChromeNoSandbox)
64+
'--no-sandbox',
6065
'--window-size=$kMaxScreenshotWidth,$kMaxScreenshotHeight', // When headless, this is the actual size of the viewport
6166
'--disable-extensions',
6267
'--disable-popup-blocking',
@@ -69,10 +74,11 @@ class Chrome extends Browser {
6974
'--remote-debugging-port=$kDevtoolsPort',
7075
];
7176

72-
final Process process = await Process.start(installation.executable, args);
77+
final Process process =
78+
await Process.start(installation.executable, args);
7379

74-
remoteDebuggerCompleter.complete(getRemoteDebuggerUrl(
75-
Uri.parse('http://localhost:${kDevtoolsPort}')));
80+
remoteDebuggerCompleter.complete(
81+
getRemoteDebuggerUrl(Uri.parse('http://localhost:${kDevtoolsPort}')));
7682

7783
unawaited(process.exitCode
7884
.then((_) => Directory(dir).deleteSync(recursive: true)));

lib/web_ui/dev/chrome_installer.dart

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,42 @@ import 'package:yaml/yaml.dart';
1313
import 'common.dart';
1414
import 'environment.dart';
1515

16-
void addChromeVersionOption(ArgParser argParser) {
17-
final io.File lockFile = io.File(
18-
path.join(environment.webUiRootDir.path, 'dev', 'browser_lock.yaml'));
19-
final YamlMap lock = loadYaml(lockFile.readAsStringSync());
20-
final int pinnedChromeVersion = PlatformBinding.instance.getChromeBuild(lock);
21-
22-
argParser
23-
..addOption(
24-
'chrome-version',
25-
defaultsTo: '$pinnedChromeVersion',
26-
help: 'The Chrome version to use while running tests. If the requested '
27-
'version has not been installed, it will be downloaded and installed '
28-
'automatically. A specific Chrome build version number, such as 695653 '
29-
'this use that version of Chrome. Value "latest" will use the latest '
30-
'available build of Chrome, installing it if necessary. Value "system" '
31-
'will use the manually installed version of Chrome on this computer.',
32-
);
16+
class ChromeArgParser extends BrowserArgParser {
17+
static final ChromeArgParser _singletonInstance = ChromeArgParser._();
18+
19+
/// The [ChromeArgParser] singleton.
20+
static ChromeArgParser get instance => _singletonInstance;
21+
22+
String _version;
23+
24+
ChromeArgParser._();
25+
26+
@override
27+
void populateOptions(ArgParser argParser) {
28+
final YamlMap browserLock = BrowserLock.instance.configuration;
29+
final int pinnedChromeVersion =
30+
PlatformBinding.instance.getChromeBuild(browserLock);
31+
32+
argParser
33+
..addOption(
34+
'chrome-version',
35+
defaultsTo: '$pinnedChromeVersion',
36+
help: 'The Chrome version to use while running tests. If the requested '
37+
'version has not been installed, it will be downloaded and installed '
38+
'automatically. A specific Chrome build version number, such as 695653, '
39+
'will use that version of Chrome. Value "latest" will use the latest '
40+
'available build of Chrome, installing it if necessary. Value "system" '
41+
'will use the manually installed version of Chrome on this computer.',
42+
);
43+
}
44+
45+
@override
46+
void parseOptions(ArgResults argResults) {
47+
_version = argResults['chrome-version'];
48+
}
49+
50+
@override
51+
String get version => _version;
3352
}
3453

3554
/// Returns the installation of Chrome, installing it if necessary.
@@ -180,6 +199,7 @@ class ChromeInstaller {
180199
if (unzipResult.exitCode != 0) {
181200
throw BrowserInstallerException(
182201
'Failed to unzip the downloaded Chrome archive ${downloadedFile.path}.\n'
202+
'With the version path ${versionDir.path}\n'
183203
'The unzip process exited with code ${unzipResult.exitCode}.');
184204
}
185205

lib/web_ui/dev/common.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
import 'dart:io' as io;
66

7+
import 'package:args/args.dart';
78
import 'package:meta/meta.dart';
89
import 'package:path/path.dart' as path;
910
import 'package:yaml/yaml.dart';
1011

12+
import 'environment.dart';
13+
1114
/// The port number for debugging.
1215
const int kDevtoolsPort = 12345;
1316
const int kMaxScreenshotWidth = 1024;
@@ -124,6 +127,36 @@ class BrowserInstallation {
124127
final String executable;
125128
}
126129

130+
abstract class BrowserArgParser {
131+
const BrowserArgParser();
132+
133+
/// Populate options specific to a browser to the [ArgParser].
134+
void populateOptions(ArgParser argParser);
135+
136+
/// Populate browser with results of the arguments passed.
137+
void parseOptions(ArgResults argResults);
138+
139+
String get version;
140+
}
141+
142+
/// Provides access to the contents of the `browser_lock.yaml` file.
143+
class BrowserLock {
144+
/// Initializes the [BrowserLock] singleton.
145+
static final BrowserLock _singletonInstance = BrowserLock._();
146+
147+
/// The [Keyboard] singleton.
148+
static BrowserLock get instance => _singletonInstance;
149+
150+
YamlMap _configuration = YamlMap();
151+
YamlMap get configuration => _configuration;
152+
153+
BrowserLock._() {
154+
final io.File lockFile = io.File(
155+
path.join(environment.webUiRootDir.path, 'dev', 'browser_lock.yaml'));
156+
this._configuration = loadYaml(lockFile.readAsStringSync());
157+
}
158+
}
159+
127160
/// A string sink that swallows all input.
128161
class DevNull implements StringSink {
129162
@override

lib/web_ui/dev/firefox.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class Firefox extends Browser {
3232
/// Starts a new instance of Firefox open to the given [url], which may be a
3333
/// [Uri] or a [String].
3434
factory Firefox(Uri url, {bool debug = false}) {
35+
version = FirefoxArgParser.instance.version;
36+
3537
assert(version != null);
3638
var remoteDebuggerCompleter = Completer<Uri>.sync();
3739
return Firefox._(() async {

lib/web_ui/dev/firefox_installer.dart

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,51 @@
33
// found in the LICENSE file.
44
import 'dart:io' as io;
55

6+
import 'package:args/args.dart';
67
import 'package:http/http.dart';
78
import 'package:meta/meta.dart';
89
import 'package:path/path.dart' as path;
10+
import 'package:yaml/yaml.dart';
911

1012
import 'common.dart';
1113
import 'environment.dart';
1214

15+
class FirefoxArgParser extends BrowserArgParser {
16+
static final FirefoxArgParser _singletonInstance = FirefoxArgParser._();
17+
18+
/// The [ChromeArgParser] singleton.
19+
static FirefoxArgParser get instance => _singletonInstance;
20+
21+
String _version;
22+
23+
FirefoxArgParser._();
24+
25+
@override
26+
void populateOptions(ArgParser argParser) {
27+
final YamlMap browserLock = BrowserLock.instance.configuration;
28+
String firefoxVersion = browserLock['firefox']['version'];
29+
30+
argParser
31+
..addOption(
32+
'firefox-version',
33+
defaultsTo: '$firefoxVersion',
34+
help: 'The Firefox version to use while running tests. If the requested '
35+
'version has not been installed, it will be downloaded and installed '
36+
'automatically. Value "latest" will use the latest '
37+
'stable build of Firefox, installing it if necessary. Value "system" '
38+
'will use the manually installed version of Firefox on this computer.',
39+
);
40+
}
41+
42+
@override
43+
void parseOptions(ArgResults argResults) {
44+
_version = argResults['firefox-version'];
45+
}
46+
47+
@override
48+
String get version => _version;
49+
}
50+
1351
/// Returns the installation of Firefox, installing it if necessary.
1452
///
1553
/// If [requestedVersion] is null, uses the version specified on the
@@ -106,7 +144,7 @@ class FirefoxInstaller {
106144
/// HTTP client used to download Firefox.
107145
final Client client = Client();
108146

109-
/// Root directory that contains Chrome versions.
147+
/// Root directory that contains Firefox versions.
110148
final io.Directory firefoxInstallationDir;
111149

112150
/// Installation directory for Firefox of the requested [version].
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:test_api/src/backend/runtime.dart';
6+
7+
import 'browser.dart';
8+
import 'chrome.dart';
9+
import 'chrome_installer.dart';
10+
import 'common.dart';
11+
import 'firefox.dart';
12+
import 'firefox_installer.dart'; // ignore: implementation_imports
13+
14+
/// Utilities for browsers, that tests are supported.
15+
///
16+
/// Extending [Browser] is not enough for supporting test.
17+
///
18+
/// Each new browser should be added to the [Runtime] map, to the [getBrowser]
19+
/// method.
20+
///
21+
/// One should also implement [BrowserArgParser] and add it to the [argParsers].
22+
class SupportedBrowsers {
23+
final List<BrowserArgParser> argParsers =
24+
List.of([ChromeArgParser.instance, FirefoxArgParser.instance]);
25+
26+
final List<String> supportedBrowserNames = ['chrome', 'firefox'];
27+
28+
final Map<String, Runtime> supportedBrowsersToRuntimes = {
29+
'chrome': Runtime.chrome,
30+
'firefox': Runtime.firefox
31+
};
32+
33+
static final SupportedBrowsers _singletonInstance = SupportedBrowsers._();
34+
35+
/// The [SupportedBrowsers] singleton.
36+
static SupportedBrowsers get instance => _singletonInstance;
37+
38+
SupportedBrowsers._();
39+
40+
Browser getBrowser(Runtime runtime, Uri url, {bool debug = false}) {
41+
if (runtime == Runtime.chrome) {
42+
return Chrome(url, debug: debug);
43+
} else if (runtime == Runtime.firefox) {
44+
return Firefox(url, debug: debug);
45+
} else {
46+
throw new UnsupportedError('The browser type not supported in tests');
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)