Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkgs/test/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 1.25.3-wip

* Remove outdated StreamMatcher link from README table of contents.
* Add support for the new firefox binary location on macOS.

## 1.25.2

Expand Down
37 changes: 21 additions & 16 deletions pkgs/test/lib/src/runner/browser/default_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,30 @@ import '../executable_settings.dart';

/// Default settings for starting browser executables.
final defaultSettings = UnmodifiableMapView({
Runtime.chrome: ExecutableSettings(
linuxExecutable: 'google-chrome',
macOSExecutable:
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
windowsExecutable: r'Google\Chrome\Application\chrome.exe',
environmentOverride: 'CHROME_EXECUTABLE'),
Runtime.chrome: ExecutableSettings(linuxExecutables: [
'google-chrome'
], macOSExecutables: [
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
], windowsExecutables: [
r'Google\Chrome\Application\chrome.exe'
], environmentOverride: 'CHROME_EXECUTABLE'),
Runtime.edge: ExecutableSettings(
linuxExecutable: 'microsoft-edge-stable',
windowsExecutable: r'Microsoft\Edge\Application\msedge.exe',
macOSExecutable:
'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
linuxExecutables: ['microsoft-edge-stable'],
windowsExecutables: [r'Microsoft\Edge\Application\msedge.exe'],
macOSExecutables: [
'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'
],
environmentOverride: 'MS_EDGE_EXECUTABLE',
),
Runtime.firefox: ExecutableSettings(
linuxExecutable: 'firefox',
macOSExecutable: '/Applications/Firefox.app/Contents/MacOS/firefox-bin',
windowsExecutable: r'Mozilla Firefox\firefox.exe',
environmentOverride: 'FIREFOX_EXECUTABLE'),
Runtime.firefox: ExecutableSettings(linuxExecutables: [
'firefox'
], macOSExecutables: [
'/Applications/Firefox.app/Contents/MacOS/firefox',
'/Applications/Firefox.app/Contents/MacOS/firefox-bin'
], windowsExecutables: [
r'Mozilla Firefox\firefox.exe'
], environmentOverride: 'FIREFOX_EXECUTABLE'),
Runtime.safari: ExecutableSettings(
macOSExecutable: '/Applications/Safari.app/Contents/MacOS/Safari',
macOSExecutables: ['/Applications/Safari.app/Contents/MacOS/Safari'],
environmentOverride: 'SAFARI_EXECUTABLE'),
});
105 changes: 69 additions & 36 deletions pkgs/test/lib/src/runner/executable_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,21 @@ class ExecutableSettings {
///
/// This may be an absolute path or a basename, in which case it will be
/// looked up on the system path. It may not be relative.
final String? _linuxExecutable;
final List<String> _linuxExecutables;

/// The path to the executable on Mac OS.
///
/// This may be an absolute path or a basename, in which case it will be
/// looked up on the system path. It may not be relative.
final String? _macOSExecutable;
final List<String> _macOSExecutables;

/// The path to the executable on Windows.
///
/// This may be an absolute path; a basename, in which case it will be looked
/// up on the system path; or a relative path, in which case it will be looked
/// up relative to the paths in the `LOCALAPPDATA`, `PROGRAMFILES`, and
/// `PROGRAMFILES(X64)` environment variables.
final String? _windowsExecutable;
final List<String> _windowsExecutables;

/// The environment variable, if any, to use as an override for the default
/// path.
Expand All @@ -45,12 +45,17 @@ class ExecutableSettings {
if (envVariable != null) return envVariable;
}

if (Platform.isMacOS) return _macOSExecutable!;
if (!Platform.isWindows) return _linuxExecutable!;
final windowsExecutable = _windowsExecutable!;
if (p.isAbsolute(windowsExecutable)) return windowsExecutable;
if (p.basename(windowsExecutable) == windowsExecutable) {
return windowsExecutable;
if (Platform.isMacOS) {
return _macOSExecutables.firstWhere((path) => File(path).existsSync());
}
if (!Platform.isWindows) {
return _linuxExecutables.firstWhere((path) => File(path).existsSync());
}
for (var windowsExecutable in _windowsExecutables) {
if (p.isAbsolute(windowsExecutable)) return windowsExecutable;
if (p.basename(windowsExecutable) == windowsExecutable) {
return windowsExecutable;
}
}

var prefixes = [
Expand All @@ -62,15 +67,17 @@ class ExecutableSettings {
for (var prefix in prefixes) {
if (prefix == null) continue;

var path = p.join(prefix, windowsExecutable);
if (File(path).existsSync()) return path;
for (var windowsExecutable in _windowsExecutables) {
var path = p.join(prefix, windowsExecutable);
if (File(path).existsSync()) return path;
}
}

// If we can't find a path that works, return one that doesn't. This will
// cause an "executable not found" error to surface.
return p.join(
prefixes.firstWhere((prefix) => prefix != null, orElse: () => '.')!,
_windowsExecutable);
_windowsExecutables.first);
}

/// Whether to invoke the browser in headless mode.
Expand All @@ -97,9 +104,9 @@ class ExecutableSettings {
}
}

String? linuxExecutable;
String? macOSExecutable;
String? windowsExecutable;
final linuxExecutables = <String>[];
final macOSExecutables = <String>[];
final windowsExecutables = <String>[];
var executableNode = settings.nodes['executable'];
if (executableNode != null) {
var value = executableNode.value;
Expand All @@ -110,14 +117,22 @@ class ExecutableSettings {
_assertNotRelative(executableNode as YamlScalar);
}

linuxExecutable = value;
macOSExecutable = value;
windowsExecutable = value;
linuxExecutables.add(value);
macOSExecutables.add(value);
windowsExecutables.add(value);
} else if (executableNode is YamlMap) {
linuxExecutable = _getExecutable(executableNode.nodes['linux']);
macOSExecutable = _getExecutable(executableNode.nodes['mac_os']);
windowsExecutable = _getExecutable(executableNode.nodes['windows'],
allowRelative: true);
if (_getExecutable(executableNode.nodes['linux'])
case final linuxExecutable?) {
linuxExecutables.add(linuxExecutable);
}
if (_getExecutable(executableNode.nodes['mac_os'])
case final macOSExecutable?) {
macOSExecutables.add(macOSExecutable);
}
if (_getExecutable(executableNode.nodes['windows'], allowRelative: true)
case final windowsExecutable?) {
windowsExecutables.add(windowsExecutable);
}
} else {
throw SourceSpanFormatException(
'Must be a map or a string.', executableNode.span);
Expand All @@ -138,9 +153,9 @@ class ExecutableSettings {

return ExecutableSettings(
arguments: arguments,
linuxExecutable: linuxExecutable,
macOSExecutable: macOSExecutable,
windowsExecutable: windowsExecutable,
linuxExecutables: linuxExecutables,
macOSExecutables: macOSExecutables,
windowsExecutables: windowsExecutables,
headless: headless);
}

Expand Down Expand Up @@ -175,23 +190,41 @@ class ExecutableSettings {

ExecutableSettings(
{Iterable<String>? arguments,
String? linuxExecutable,
String? macOSExecutable,
String? windowsExecutable,
List<String> linuxExecutables = const [],
List<String> macOSExecutables = const [],
List<String> windowsExecutables = const [],
String? environmentOverride,
bool? headless})
: arguments = arguments == null ? const [] : List.unmodifiable(arguments),
_linuxExecutable = linuxExecutable,
_macOSExecutable = macOSExecutable,
_windowsExecutable = windowsExecutable,
_linuxExecutables = linuxExecutables,
_macOSExecutables = macOSExecutables,
_windowsExecutables = windowsExecutables,
_environmentOverride = environmentOverride,
_headless = headless;

/// Merges [this] with [other], with [other]'s settings taking priority.
///
/// Executable paths are not merged, but overridden by [other] unless empty.
ExecutableSettings merge(ExecutableSettings other) => ExecutableSettings(
arguments: arguments.toList()..addAll(other.arguments),
headless: other._headless ?? _headless,
linuxExecutable: other._linuxExecutable ?? _linuxExecutable,
macOSExecutable: other._macOSExecutable ?? _macOSExecutable,
windowsExecutable: other._windowsExecutable ?? _windowsExecutable);
arguments: arguments.toList()..addAll(other.arguments),
headless: other._headless ?? _headless,
linuxExecutables: [
if (other._linuxExecutables.isEmpty)
..._linuxExecutables
else
...other._linuxExecutables,
],
macOSExecutables: [
if (other._macOSExecutables.isEmpty)
..._macOSExecutables
else
...other._macOSExecutables,
],
windowsExecutables: [
if (other._windowsExecutables.isEmpty)
..._windowsExecutables
else
...other._windowsExecutables,
],
);
}
6 changes: 3 additions & 3 deletions pkgs/test/lib/src/runner/node/platform.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ class NodePlatform extends PlatformPlugin
/// it.
final _settings = {
Runtime.nodeJS: ExecutableSettings(
linuxExecutable: 'node',
macOSExecutable: 'node',
windowsExecutable: 'node.exe')
linuxExecutables: ['node'],
macOSExecutables: ['node'],
windowsExecutables: ['node.exe'])
};

NodePlatform() : _config = Configuration.current;
Expand Down
6 changes: 3 additions & 3 deletions pkgs/test/test/runner/browser/chrome_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ webSocket.addEventListener("open", function() {
test('reports an error in onExit', () {
var chrome = Chrome(Uri.https('dart.dev'), configuration(),
settings: ExecutableSettings(
linuxExecutable: '_does_not_exist',
macOSExecutable: '_does_not_exist',
windowsExecutable: '_does_not_exist'));
linuxExecutables: ['_does_not_exist'],
macOSExecutables: ['_does_not_exist'],
windowsExecutables: ['_does_not_exist']));
expect(
chrome.onExit,
throwsA(isApplicationException(
Expand Down
6 changes: 3 additions & 3 deletions pkgs/test/test/runner/browser/firefox_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ webSocket.addEventListener("open", function() {
test('reports an error in onExit', () {
var firefox = Firefox(Uri.https('dart.dev'),
settings: ExecutableSettings(
linuxExecutable: '_does_not_exist',
macOSExecutable: '_does_not_exist',
windowsExecutable: '_does_not_exist'));
linuxExecutables: ['_does_not_exist'],
macOSExecutables: ['_does_not_exist'],
windowsExecutables: ['_does_not_exist']));
expect(
firefox.onExit,
throwsA(isApplicationException(
Expand Down
6 changes: 3 additions & 3 deletions pkgs/test/test/runner/browser/microsoft_edge_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ webSocket.addEventListener("open", function() {
test('reports an error in onExit', () {
var edge = MicrosoftEdge(Uri.parse('https://dart.dev'), configuration(),
settings: ExecutableSettings(
linuxExecutable: '_does_not_exist',
macOSExecutable: '_does_not_exist',
windowsExecutable: '_does_not_exist'));
linuxExecutables: ['_does_not_exist'],
macOSExecutables: ['_does_not_exist'],
windowsExecutables: ['_does_not_exist']));
expect(
edge.onExit,
throwsA(isApplicationException(
Expand Down
6 changes: 3 additions & 3 deletions pkgs/test/test/runner/browser/safari_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ webSocket.addEventListener("open", function() {
test('reports an error in onExit', () {
var safari = Safari(Uri.https('dart.dev'),
settings: ExecutableSettings(
linuxExecutable: '_does_not_exist',
macOSExecutable: '_does_not_exist',
windowsExecutable: '_does_not_exist'));
linuxExecutables: ['_does_not_exist'],
macOSExecutables: ['_does_not_exist'],
windowsExecutables: ['_does_not_exist']));
expect(
safari.onExit,
throwsA(isApplicationException(
Expand Down