Align web terminal messages with the VM (#163268)

- Adds better instructions for hot reload (if using the right flags),
hot restart, quitting, clearing, and more. These were already being
printed when using the VM, so this aligns with that.
- Adds an extra parameter for `CommandHelp` to `ResidentRunner` so
`ResidentWebRunner` can pass a version of it that uses its separate
logger and not `globals`. In order to support this, classes up the stack
also provide a `Terminal`, `Platform`, and `OutputPreferences`.
- Fixes up use of `globals` from an earlier change to implement hot
reload to use the logger instead. Same with `globals.platform`.
- Adds tests to check that only hot restart is printed when not using
the extra front-end flags, and both hot restart and hot reload is
printed when you are.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
This commit is contained in:
Srujan Gaddam 2025-02-14 11:57:53 -08:00 committed by GitHub
parent 6a912ee9dc
commit 9393aae393
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 276 additions and 81 deletions

View File

@ -218,6 +218,8 @@ List<FlutterCommand> generateCommands({required bool verboseHelp, required bool
fileSystem: globals.fs,
logger: globals.logger,
platform: globals.platform,
terminal: globals.terminal,
outputPreferences: globals.outputPreferences,
signals: globals.signals,
),
EmulatorsCommand(),

View File

@ -15,7 +15,7 @@ const int maxLineWidth = 84;
class CommandHelp {
CommandHelp({
required Logger logger,
required AnsiTerminal terminal,
required Terminal terminal,
required Platform platform,
required OutputPreferences outputPreferences,
}) : _logger = logger,
@ -25,7 +25,7 @@ class CommandHelp {
final Logger _logger;
final AnsiTerminal _terminal;
final Terminal _terminal;
final Platform _platform;

View File

@ -710,6 +710,9 @@ class AppDomain extends Domain {
analytics: globals.analytics,
systemClock: globals.systemClock,
logger: globals.logger,
terminal: globals.terminal,
platform: globals.platform,
outputPreferences: globals.outputPreferences,
fileSystem: globals.fs,
);
} else if (enableHotReload) {

View File

@ -17,6 +17,7 @@ import '../base/io.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/signals.dart';
import '../base/terminal.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../dart/package_map.dart';
@ -60,11 +61,15 @@ class DriveCommand extends RunCommandBase {
required FileSystem fileSystem,
required Logger logger,
required Platform platform,
required Terminal terminal,
required OutputPreferences outputPreferences,
required this.signals,
}) : _flutterDriverFactory = flutterDriverFactory,
_fileSystem = fileSystem,
_logger = logger,
_platform = platform,
_terminal = terminal,
_outputPreferences = outputPreferences,
_fsUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform),
super(verboseHelp: verboseHelp) {
requiresPubspecYaml();
@ -200,6 +205,8 @@ class DriveCommand extends RunCommandBase {
final FileSystem _fileSystem;
final Logger _logger;
final Platform _platform;
final Terminal _terminal;
final OutputPreferences _outputPreferences;
final FileSystemUtils _fsUtils;
Timer? timeoutTimer;
Map<ProcessSignal, Object>? screenshotTokens;
@ -298,6 +305,8 @@ class DriveCommand extends RunCommandBase {
applicationPackageFactory: ApplicationPackageFactory.instance!,
logger: _logger,
platform: _platform,
terminal: _terminal,
outputPreferences: _outputPreferences,
processUtils: globals.processUtils,
dartSdkPath: globals.artifacts!.getArtifactPath(Artifact.engineDartBinary),
devtoolsLauncher: DevtoolsLauncher.instance!,

View File

@ -720,6 +720,9 @@ class RunCommand extends RunCommandBase {
fileSystem: globals.fs,
analytics: globals.analytics,
logger: globals.logger,
terminal: globals.terminal,
platform: globals.platform,
outputPreferences: globals.outputPreferences,
systemClock: globals.systemClock,
);
}

View File

@ -15,6 +15,7 @@ import '../base/dds.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/terminal.dart';
import '../build_info.dart';
import '../device.dart';
import '../resident_runner.dart';
@ -26,12 +27,16 @@ class FlutterDriverFactory {
required ApplicationPackageFactory applicationPackageFactory,
required Platform platform,
required Logger logger,
required Terminal terminal,
required OutputPreferences outputPreferences,
required ProcessUtils processUtils,
required String dartSdkPath,
required DevtoolsLauncher devtoolsLauncher,
}) : _applicationPackageFactory = applicationPackageFactory,
_platform = platform,
_logger = logger,
_terminal = terminal,
_outputPreferences = outputPreferences,
_processUtils = processUtils,
_dartSdkPath = dartSdkPath,
_devtoolsLauncher = devtoolsLauncher;
@ -39,6 +44,8 @@ class FlutterDriverFactory {
final ApplicationPackageFactory _applicationPackageFactory;
final Platform _platform;
final Logger _logger;
final Terminal _terminal;
final OutputPreferences _outputPreferences;
final ProcessUtils _processUtils;
final String _dartSdkPath;
final DevtoolsLauncher _devtoolsLauncher;
@ -48,7 +55,9 @@ class FlutterDriverFactory {
if (web) {
return WebDriverService(
logger: _logger,
terminal: _terminal,
platform: _platform,
outputPreferences: _outputPreferences,
processUtils: _processUtils,
dartSdkPath: _dartSdkPath,
);

View File

@ -15,6 +15,7 @@ import '../base/io.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/terminal.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../convert.dart';
@ -32,15 +33,21 @@ class WebDriverService extends DriverService {
required String dartSdkPath,
required Platform platform,
required Logger logger,
required Terminal terminal,
required OutputPreferences outputPreferences,
}) : _processUtils = processUtils,
_dartSdkPath = dartSdkPath,
_platform = platform,
_logger = logger;
_logger = logger,
_terminal = terminal,
_outputPreferences = outputPreferences;
final ProcessUtils _processUtils;
final String _dartSdkPath;
final Platform _platform;
final Logger _logger;
final Terminal _terminal;
final OutputPreferences _outputPreferences;
late ResidentRunner _residentRunner;
Uri? _webUri;
@ -99,6 +106,9 @@ class WebDriverService extends DriverService {
fileSystem: globals.fs,
analytics: globals.analytics,
logger: _logger,
terminal: _terminal,
platform: _platform,
outputPreferences: _outputPreferences,
systemClock: globals.systemClock,
);
final Completer<void> appStartedCompleter = Completer<void>.sync();

View File

@ -12,11 +12,13 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart' hide
import '../application_package.dart';
import '../base/async_guard.dart';
import '../base/command_help.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/net.dart';
import '../base/platform.dart';
import '../base/terminal.dart';
import '../base/time.dart';
import '../base/utils.dart';
@ -52,6 +54,9 @@ class DwdsWebRunnerFactory extends WebRunnerFactory {
required DebuggingOptions debuggingOptions,
UrlTunneller? urlTunneller,
required Logger logger,
required Terminal terminal,
required Platform platform,
required OutputPreferences outputPreferences,
required FileSystem fileSystem,
required SystemClock systemClock,
required Analytics analytics,
@ -69,6 +74,9 @@ class DwdsWebRunnerFactory extends WebRunnerFactory {
systemClock: systemClock,
fileSystem: fileSystem,
logger: logger,
terminal: terminal,
platform: platform,
outputPreferences: outputPreferences,
);
}
}
@ -88,6 +96,9 @@ class ResidentWebRunner extends ResidentRunner {
required DebuggingOptions debuggingOptions,
required FileSystem fileSystem,
required Logger logger,
required Terminal terminal,
required Platform platform,
required OutputPreferences outputPreferences,
required SystemClock systemClock,
required Analytics analytics,
UrlTunneller? urlTunneller,
@ -95,6 +106,7 @@ class ResidentWebRunner extends ResidentRunner {
ResidentDevtoolsHandlerFactory devtoolsHandler = createDefaultHandler,
}) : _fileSystem = fileSystem,
_logger = logger,
_platform = platform,
_systemClock = systemClock,
_analytics = analytics,
_urlTunneller = urlTunneller,
@ -105,10 +117,17 @@ class ResidentWebRunner extends ResidentRunner {
stayResident: stayResident,
machine: machine,
devtoolsHandler: devtoolsHandler,
commandHelp: CommandHelp(
logger: logger,
terminal: terminal,
platform: platform,
outputPreferences: outputPreferences,
),
);
final FileSystem _fileSystem;
final Logger _logger;
final Platform _platform;
final SystemClock _systemClock;
final Analytics _analytics;
final UrlTunneller? _urlTunneller;
@ -146,6 +165,20 @@ class ResidentWebRunner extends ResidentRunner {
bool get _enableDwds => debuggingEnabled;
@override
bool get reloadIsRestart =>
// Web behavior when not using the DDC library bundle format is to restart
// when a reload is issued. We can't use `canHotReload` to signal this
// since we still want a reload command to succeed, but to do a hot
// restart.
debuggingOptions.buildInfo.ddcModuleFormat != DdcModuleFormat.ddc ||
debuggingOptions.buildInfo.canaryFeatures != true;
// TODO(srujzs): Return true when web supports detaching.
// https://github.com/flutter/flutter/issues/163329
@override
bool get supportsDetach => false;
ConnectionResult? _connectionResult;
StreamSubscription<vmservice.Event>? _stdOutSub;
StreamSubscription<vmservice.Event>? _stdErrSub;
@ -205,24 +238,6 @@ class ResidentWebRunner extends ResidentRunner {
appFinished();
}
@override
void printHelp({bool details = true}) {
if (details) {
return printHelpDetails();
}
const String fire = '🔥';
const String rawMessage = ' To hot restart changes while running, press "r" or "R".';
final String message = _logger.terminal.color(
fire + _logger.terminal.bolden(rawMessage),
TerminalColor.red,
);
_logger.printStatus(message);
const String quitMessage = 'To quit, press "q".';
_logger.printStatus('For a more detailed help message, press "h". $quitMessage');
_logger.printStatus('');
printDebuggerList();
}
@override
Future<void> stopEchoingDeviceLog() async {
// Do nothing for ResidentWebRunner
@ -310,7 +325,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
isWasm: debuggingOptions.webUseWasm,
useLocalCanvasKit: debuggingOptions.buildInfo.useLocalCanvasKit,
rootDirectory: fileSystem.directory(projectRootPath),
isWindows: globals.platform.isWindows,
isWindows: _platform.isWindows,
);
Uri url = await device!.devFS!.create();
if (debuggingOptions.tlsCertKeyPath != null && debuggingOptions.tlsCertPath != null) {
@ -475,10 +490,10 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
// has some internal error, we should still surface it to make
// debugging easier.
String reloadFailedMessage = 'Hot reload failed:';
globals.printError(reloadFailedMessage);
_logger.printError(reloadFailedMessage);
for (final ReasonForCancelling reason in contents.notices) {
reloadFailedMessage += reason.toString();
globals.printError(reason.toString());
_logger.printError(reason.toString());
}
return OperationResult(1, reloadFailedMessage);
}

View File

@ -611,6 +611,9 @@ abstract class ResidentHandlers {
/// Whether all of the connected devices support hot reload.
bool get canHotReload;
/// Whether an application can be detached without being stopped.
bool get supportsDetach;
// TODO(bkonyi): remove when ready to serve DevTools from DDS.
ResidentDevtoolsHandler? get residentDevtoolsHandler;
@ -621,6 +624,8 @@ abstract class ResidentHandlers {
FileSystem? get fileSystem;
/// Called to print help to the terminal.
///
/// If [details] is true, prints out extra help information.
void printHelp({required bool details});
/// Perform a hot reload or hot restart of all attached applications.
@ -992,6 +997,7 @@ abstract class ResidentRunner extends ResidentHandlers {
String? dillOutputPath,
this.machine = false,
ResidentDevtoolsHandlerFactory devtoolsHandler = createDefaultHandler,
CommandHelp? commandHelp,
}) : mainPath = globals.fs.file(target).absolute.path,
packagesFilePath = debuggingOptions.buildInfo.packageConfigPath,
projectRootPath = projectRootPath ?? globals.fs.currentDirectory.path,
@ -1001,12 +1007,14 @@ abstract class ResidentRunner extends ResidentHandlers {
? globals.fs.systemTempDirectory.createTempSync('flutter_tool.')
: globals.fs.file(dillOutputPath).parent,
assetBundle = AssetBundleFactory.instance.createBundle(),
commandHelp = CommandHelp(
logger: globals.logger,
terminal: globals.terminal,
platform: globals.platform,
outputPreferences: globals.outputPreferences,
) {
commandHelp =
commandHelp ??
CommandHelp(
logger: globals.logger,
terminal: globals.terminal,
platform: globals.platform,
outputPreferences: globals.outputPreferences,
) {
if (!artifactDirectory.existsSync()) {
artifactDirectory.createSync(recursive: true);
}
@ -1132,6 +1140,9 @@ abstract class ResidentRunner extends ResidentHandlers {
@override
bool get canHotReload => hotMode;
/// Whether the hot reload support is implemented as hot restart.
bool get reloadIsRestart => false;
/// Start the app and keep the process running during its lifetime.
///
/// Returns the exit code that we should use for the flutter tool process; 0
@ -1426,7 +1437,7 @@ abstract class ResidentRunner extends ResidentHandlers {
}
if (includeVmService) {
// Caution: This log line is parsed by device lab tests.
globals.printStatus(
logger.printStatus(
'A Dart VM Service on ${device.device!.displayName} '
'is available at: ${device.vmService!.httpAddress}',
);
@ -1435,14 +1446,14 @@ abstract class ResidentRunner extends ResidentHandlers {
if (_residentDevtoolsHandler!.printDtdUri) {
final Uri? dtdUri = residentDevtoolsHandler!.dtdUri;
if (dtdUri != null) {
globals.printStatus('The Dart Tooling Daemon is available at: $dtdUri\n');
logger.printStatus('The Dart Tooling Daemon is available at: $dtdUri\n');
}
}
final Uri? uri = devToolsServerAddress!.uri?.replace(
queryParameters: <String, dynamic>{'uri': '${device.vmService!.httpAddress}'},
);
if (uri != null) {
globals.printStatus(
logger.printStatus(
'The Flutter DevTools debugger and profiler '
'on ${device.device!.displayName} '
'is available at: ${urlToDisplayString(uri)}',
@ -1453,6 +1464,32 @@ abstract class ResidentRunner extends ResidentHandlers {
_reportedDebuggers = true;
}
@override
void printHelp({required bool details}) {
logger.printStatus('Flutter run key commands.');
// Don't print the command in the case where the runner implements reload as
// restart since it's misleading.
if (canHotReload && !reloadIsRestart) {
commandHelp.r.print();
}
if (supportsRestart) {
commandHelp.R.print();
}
if (details) {
printHelpDetails();
commandHelp.hWithDetails.print();
} else {
commandHelp.hWithoutDetails.print();
}
if (supportsDetach) {
commandHelp.d.print();
}
commandHelp.c.print();
commandHelp.q.print();
logger.printStatus('');
printDebuggerList();
}
void printHelpDetails() {
commandHelp.v.print();
if (flutterDevices.any((FlutterDevice? d) => d!.device!.supportsScreenshot)) {

View File

@ -41,6 +41,9 @@ class ColdRunner extends ResidentRunner {
@override
FileSystem get fileSystem => globals.fs;
@override
bool get supportsDetach => _didAttach;
@override
Future<int> run({
Completer<DebugConnectionInfo>? connectionInfoCompleter,
@ -187,23 +190,6 @@ class ColdRunner extends ResidentRunner {
await stopEchoingDeviceLog();
}
@override
void printHelp({required bool details}) {
globals.printStatus('Flutter run key commands.');
if (details) {
printHelpDetails();
commandHelp.hWithDetails.print();
} else {
commandHelp.hWithoutDetails.print();
}
if (_didAttach) {
commandHelp.d.print();
}
commandHelp.c.print();
commandHelp.q.print();
printDebuggerList();
}
@override
Future<void> preExit() async {
for (final FlutterDevice? device in flutterDevices) {

View File

@ -133,6 +133,9 @@ class HotRunner extends ResidentRunner {
String? flavor;
@override
bool get supportsDetach => stopAppDuringCleanup;
Future<void> _calculateTargetPlatform() async {
if (_targetPlatform != null) {
return;
@ -1156,28 +1159,6 @@ class HotRunner extends ResidentRunner {
);
}
@override
void printHelp({required bool details}) {
globals.printStatus('Flutter run key commands.');
commandHelp.r.print();
if (supportsRestart) {
commandHelp.R.print();
}
if (details) {
printHelpDetails();
commandHelp.hWithDetails.print();
} else {
commandHelp.hWithoutDetails.print();
}
if (stopAppDuringCleanup) {
commandHelp.d.print();
}
commandHelp.c.print();
commandHelp.q.print();
globals.printStatus('');
printDebuggerList();
}
@visibleForTesting
Future<void> evictDirtyAssets() async {
final List<Future<void>> futures = <Future<void>>[];

View File

@ -8,6 +8,8 @@ import '../base/context.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/net.dart';
import '../base/platform.dart';
import '../base/terminal.dart';
import '../base/time.dart';
import '../device.dart';
import '../project.dart';
@ -28,6 +30,9 @@ abstract class WebRunnerFactory {
required DebuggingOptions debuggingOptions,
UrlTunneller? urlTunneller,
required Logger logger,
required Terminal terminal,
required Platform platform,
required OutputPreferences outputPreferences,
required FileSystem fileSystem,
required SystemClock systemClock,
required Analytics analytics,

View File

@ -1515,7 +1515,7 @@ class FakeHotRunner extends Fake implements HotRunner {
bool stayResident = true;
@override
void printHelp({required bool details}) {}
void printHelp({required bool details, bool reloadIsRestart = false}) {}
}
class FakeHotRunnerFactory extends Fake implements HotRunnerFactory {

View File

@ -15,6 +15,7 @@ import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/signals.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/drive.dart';
@ -34,6 +35,8 @@ void main() {
late FileSystem fileSystem;
late BufferLogger logger;
late Platform platform;
late Terminal terminal;
late OutputPreferences outputPreferences;
late FakeDeviceManager fakeDeviceManager;
late FakeSignals signals;
@ -41,6 +44,8 @@ void main() {
fileSystem = MemoryFileSystem.test();
logger = BufferLogger.test();
platform = FakePlatform();
terminal = Terminal.test();
outputPreferences = OutputPreferences.test();
fakeDeviceManager = FakeDeviceManager();
signals = FakeSignals();
});
@ -60,6 +65,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
fileSystem.file('lib/main.dart').createSync(recursive: true);
@ -89,6 +96,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
fileSystem.file('lib/app.dart').createSync(recursive: true);
@ -116,6 +125,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
fileSystem.file('lib/main.dart').createSync(recursive: true);
@ -148,6 +159,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
fileSystem.file('lib/main.dart').createSync(recursive: true);
@ -188,6 +201,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
flutterDriverFactory: FailingFakeFlutterDriverFactory(),
);
@ -229,6 +244,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
fileSystem.file('lib/main.dart').createSync(recursive: true);
@ -269,6 +286,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
flutterDriverFactory: FailingFakeFlutterDriverFactory(),
);
@ -321,6 +340,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
@ -365,6 +386,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: Signals.test(),
flutterDriverFactory: NeverEndingFlutterDriverFactory(() {}),
);
@ -430,6 +453,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: Signals.test(),
flutterDriverFactory: NeverEndingFlutterDriverFactory(() {
signal.controller.add(signal);
@ -485,6 +510,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
@ -522,6 +549,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
@ -582,6 +611,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
@ -616,6 +647,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
@ -650,6 +683,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);
@ -684,6 +719,8 @@ void main() {
fileSystem: fileSystem,
logger: logger,
platform: platform,
terminal: terminal,
outputPreferences: outputPreferences,
signals: signals,
);

View File

@ -9,6 +9,7 @@ import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/net.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/device.dart';
@ -346,6 +347,9 @@ class FakeWebRunnerFactory implements WebRunnerFactory {
required DebuggingOptions debuggingOptions,
UrlTunneller? urlTunneller,
Logger? logger,
Terminal? terminal,
Platform? platform,
OutputPreferences? outputPreferences,
FileSystem? fileSystem,
SystemClock? systemClock,
Usage? usage,
@ -410,9 +414,11 @@ WebDriverService setUpDriverService() {
final BufferLogger logger = BufferLogger.test();
return WebDriverService(
logger: logger,
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
processUtils: ProcessUtils(logger: logger, processManager: FakeProcessManager.any()),
dartSdkPath: 'dart',
platform: FakePlatform(),
);
}

View File

@ -1390,7 +1390,7 @@ flutter:
commandHelp.hWithDetails,
commandHelp.c,
commandHelp.q,
'',
'\n',
].join('\n'),
),
);
@ -1425,7 +1425,7 @@ flutter:
commandHelp.hWithoutDetails,
commandHelp.c,
commandHelp.q,
'',
'\n',
].join('\n'),
),
);

View File

@ -8,6 +8,8 @@ import 'package:file/memory.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
@ -62,6 +64,9 @@ void main() {
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
analytics: getInitializedFakeAnalyticsInstance(
fs: fileSystem,
@ -96,6 +101,9 @@ void main() {
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
analytics: getInitializedFakeAnalyticsInstance(
fs: fileSystem,
@ -126,6 +134,9 @@ void main() {
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
analytics: getInitializedFakeAnalyticsInstance(
fs: fileSystem,
@ -155,6 +166,9 @@ void main() {
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
analytics: getInitializedFakeAnalyticsInstance(
fs: fileSystem,
@ -188,6 +202,9 @@ void main() {
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
analytics: getInitializedFakeAnalyticsInstance(
fs: fileSystem,

View File

@ -14,6 +14,7 @@ import 'package:flutter_tools/src/base/dds.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/tools/scene_importer.dart';
@ -143,6 +144,9 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
);
@ -172,6 +176,9 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
);
@ -193,6 +200,9 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
);
@ -204,6 +214,9 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
);
@ -343,6 +356,9 @@ void main() {
stayResident: false,
fileSystem: fileSystem,
logger: logger,
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
devtoolsHandler: createNoOpHandler,
@ -371,6 +387,9 @@ void main() {
stayResident: false,
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
devtoolsHandler: createNoOpHandler,
@ -586,6 +605,9 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true),
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
devtoolsHandler: createNoOpHandler,
@ -990,14 +1012,46 @@ void main() {
);
testUsingContext(
'printHelp without details shows hot restart help message',
'printHelp without details shows only hot restart help message',
() async {
final BufferLogger logger = BufferLogger.test();
final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice, logger: logger);
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
residentWebRunner.printHelp(details: false);
expect(logger.statusText, contains('To hot restart changes'));
expect(logger.statusText, contains('Hot restart'));
expect(logger.statusText.contains('Hot reload'), false);
},
overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
},
);
testUsingContext(
'printHelp without details shows hot restart and hot reload help message '
'if using DDC library bundle format',
() async {
final BufferLogger logger = BufferLogger.test();
final ResidentRunner residentWebRunner = setUpResidentRunner(
flutterDevice,
logger: logger,
debuggingOptions: DebuggingOptions.enabled(
const BuildInfo(
BuildMode.debug,
null,
trackWidgetCreation: true,
treeShakeIcons: false,
packageConfigPath: '.dart_tool/package_config.json',
extraFrontEndOptions: <String>['--dartdevc-module-format=ddc', '--dartdevc-canary'],
),
),
);
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
residentWebRunner.printHelp(details: false);
expect(logger.statusText, contains('Hot restart'));
expect(logger.statusText, contains('Hot reload'));
},
overrides: <Type, Generator>{
FileSystem: () => fileSystem,
@ -1130,6 +1184,9 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
fileSystem: fileSystem,
logger: logger,
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
devtoolsHandler: createNoOpHandler,
@ -1175,6 +1232,9 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
fileSystem: fileSystem,
logger: logger,
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
devtoolsHandler: createNoOpHandler,
@ -1217,6 +1277,9 @@ void main() {
stayResident: false,
fileSystem: fileSystem,
logger: BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
analytics: globals.analytics,
systemClock: globals.systemClock,
devtoolsHandler: createNoOpHandler,
@ -1512,6 +1575,9 @@ ResidentRunner setUpResidentRunner(
systemClock: systemClock ?? SystemClock.fixed(DateTime.now()),
fileSystem: globals.fs,
logger: logger ?? BufferLogger.test(),
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
devtoolsHandler: createNoOpHandler,
);
}
@ -1533,6 +1599,9 @@ class FakeDevice extends Fake implements Device {
@override
late DartDevelopmentService dds;
@override
bool get supportsHotRestart => true;
@override
Future<LaunchResult> startApp(
ApplicationPackage? package, {

View File

@ -1229,6 +1229,9 @@ class FakeResidentRunner extends ResidentHandlers {
@override
bool supportsRestart = true;
@override
bool supportsDetach = true;
@override
bool supportsServiceProtocol = true;
@ -1246,7 +1249,7 @@ class FakeResidentRunner extends ResidentHandlers {
}
@override
void printHelp({required bool details}) {
void printHelp({required bool details, bool reloadIsRestart = false}) {
if (details) {
calledPrintWithDetails = true;
} else {
@ -1398,7 +1401,7 @@ class TestRunner extends Fake implements ResidentRunner {
Future<void> cleanupAtFinish() async {}
@override
void printHelp({bool? details}) {
void printHelp({bool? details, bool reloadIsRestart = false}) {
hasHelpBeenPrinted = true;
}

View File

@ -6,6 +6,7 @@ import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/drive/web_driver_service.dart';
import 'package:package_config/package_config_types.dart';
@ -19,9 +20,11 @@ void main() {
final BufferLogger logger = BufferLogger.test();
final WebDriverService service = WebDriverService(
logger: logger,
terminal: Terminal.test(),
platform: FakePlatform(),
outputPreferences: OutputPreferences.test(),
processUtils: ProcessUtils(logger: logger, processManager: FakeProcessManager.empty()),
dartSdkPath: 'dart',
platform: FakePlatform(),
);
const String link = 'https://flutter.dev/to/integration-test-on-web';
try {