Unverified Commit f7b8d62c authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tool] Refactor Logger and Terminal to (mostly) no longer depend...

[flutter_tool] Refactor Logger and Terminal to (mostly) no longer depend directly on context (#47269)
parent 0384c8c4
......@@ -15,6 +15,7 @@ import 'src/base/file_system.dart';
import 'src/base/io.dart';
import 'src/base/logger.dart';
import 'src/base/process.dart';
import 'src/base/terminal.dart';
import 'src/base/utils.dart';
import 'src/context_runner.dart';
import 'src/doctor.dart';
......@@ -223,7 +224,10 @@ Future<File> _createLocalCrashReport(List<String> args, dynamic error, StackTrac
Future<String> _doctorText() async {
try {
final BufferLogger logger = BufferLogger();
final BufferLogger logger = BufferLogger(
terminal: terminal,
outputPreferences: outputPreferences,
);
await context.run<bool>(
body: () => doctor.diagnose(verbose: true, showColor: false),
......
......@@ -247,11 +247,10 @@ class Stdio {
bool get supportsAnsiEscapes => hasTerminal && io.stdout.supportsAnsiEscapes;
}
Stdio get stdio => context.get<Stdio>() ?? const Stdio();
io.Stdout get stdout => stdio.stdout;
Stream<List<int>> get stdin => stdio.stdin;
io.IOSink get stderr => stdio.stderr;
bool get stdinHasTerminal => stdio.stdinHasTerminal;
io.Stdout get stdout => globals.stdio.stdout;
Stream<List<int>> get stdin => globals.stdio.stdin;
io.IOSink get stderr => globals.stdio.stderr;
bool get stdinHasTerminal => globals.stdio.stdinHasTerminal;
/// An overridable version of io.ProcessInfo.
abstract class ProcessInfo {
......
......@@ -4,10 +4,14 @@
import 'dart:async';
import 'package:meta/meta.dart';
import 'package:platform/platform.dart';
import '../convert.dart';
import '../globals.dart' as globals;
import 'context.dart';
import 'io.dart' as io;
import 'logger.dart';
enum TerminalColor {
red,
......@@ -41,12 +45,13 @@ class OutputPreferences {
bool wrapText,
int wrapColumn,
bool showColor,
}) : wrapText = wrapText ?? io.stdio.hasTerminal,
}) : wrapText = wrapText ?? globals.stdio.hasTerminal,
_overrideWrapColumn = wrapColumn,
showColor = showColor ?? globals.platform.stdoutSupportsAnsi ?? false;
/// A version of this class for use in tests.
OutputPreferences.test() : wrapText = false, _overrideWrapColumn = null, showColor = false;
OutputPreferences.test({this.wrapText = false, int wrapColumn = kDefaultTerminalColumns, this.showColor = false})
: _overrideWrapColumn = wrapColumn;
/// If [wrapText] is true, then any text sent to the context's [Logger]
/// instance (e.g. from the [printError] or [printStatus] functions) will be
......@@ -66,7 +71,7 @@ class OutputPreferences {
/// terminal, or to [kDefaultTerminalColumns] if not writing to a terminal.
final int _overrideWrapColumn;
int get wrapColumn {
return _overrideWrapColumn ?? io.stdio.terminalColumns ?? kDefaultTerminalColumns;
return _overrideWrapColumn ?? globals.stdio.terminalColumns ?? kDefaultTerminalColumns;
}
/// Whether or not to output ANSI color codes when writing to the output
......@@ -81,6 +86,13 @@ class OutputPreferences {
}
class AnsiTerminal {
AnsiTerminal({@required io.Stdio stdio, @required Platform platform})
: _stdio = stdio,
_platform = platform;
final io.Stdio _stdio;
final Platform _platform;
static const String bold = '\u001B[1m';
static const String resetAll = '\u001B[0m';
static const String resetColor = '\u001B[39m';
......@@ -107,7 +119,8 @@ class AnsiTerminal {
static String colorCode(TerminalColor color) => _colorMap[color];
bool get supportsColor => globals.platform.stdoutSupportsAnsi ?? false;
bool get supportsColor => _platform.stdoutSupportsAnsi ?? false;
final RegExp _boldControls = RegExp('(${RegExp.escape(resetBold)}|${RegExp.escape(bold)})');
/// Whether we are interacting with the flutter tool via the terminal.
......@@ -159,10 +172,10 @@ class AnsiTerminal {
String clearScreen() => supportsColor ? clear : '\n\n';
set singleCharMode(bool value) {
if (!io.stdinHasTerminal) {
if (!_stdio.stdinHasTerminal) {
return;
}
final io.Stdin stdin = io.stdin as io.Stdin;
final io.Stdin stdin = _stdio.stdin as io.Stdin;
// The order of setting lineMode and echoMode is important on Windows.
if (value) {
stdin.echoMode = false;
......@@ -179,7 +192,7 @@ class AnsiTerminal {
///
/// Useful when the console is in [singleCharMode].
Stream<String> get keystrokes {
_broadcastStdInString ??= io.stdin.transform<String>(const AsciiDecoder(allowInvalid: true)).asBroadcastStream();
_broadcastStdInString ??= _stdio.stdin.transform<String>(const AsciiDecoder(allowInvalid: true)).asBroadcastStream();
return _broadcastStdInString;
}
......@@ -198,6 +211,7 @@ class AnsiTerminal {
/// If [usesTerminalUi] is false, throws a [StateError].
Future<String> promptForCharInput(
List<String> acceptedCharacters, {
@required Logger logger,
String prompt,
int defaultChoiceIndex,
bool displayAcceptedCharacters = true,
......@@ -220,14 +234,14 @@ class AnsiTerminal {
singleCharMode = true;
while (choice == null || choice.length > 1 || !acceptedCharacters.contains(choice)) {
if (prompt != null) {
globals.printStatus(prompt, emphasis: true, newline: false);
logger.printStatus(prompt, emphasis: true, newline: false);
if (displayAcceptedCharacters) {
globals.printStatus(' [${charactersToDisplay.join("|")}]', newline: false);
logger.printStatus(' [${charactersToDisplay.join("|")}]', newline: false);
}
globals.printStatus(': ', emphasis: true, newline: false);
logger.printStatus(': ', emphasis: true, newline: false);
}
choice = await keystrokes.first;
globals.printStatus(choice);
logger.printStatus(choice);
}
singleCharMode = false;
if (defaultChoiceIndex != null && choice == '\n') {
......
......@@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:math' show Random, max;
import 'package:intl/intl.dart';
import 'package:meta/meta.dart';
import '../convert.dart';
import '../globals.dart' as globals;
......@@ -395,7 +396,7 @@ class _AnsiRun {
/// If [outputPreferences.wrapText] is false, then the text will be returned
/// simply split at the newlines, but not wrapped. If [shouldWrap] is specified,
/// then it overrides the [outputPreferences.wrapText] setting.
List<String> _wrapTextAsLines(String text, { int start = 0, int columnWidth, bool shouldWrap }) {
List<String> _wrapTextAsLines(String text, { int start = 0, int columnWidth, @required bool shouldWrap }) {
if (text == null || text.isEmpty) {
return <String>[''];
}
......
......@@ -974,7 +974,7 @@ class NotifyingLogger extends Logger {
}) {
assert(timeout != null);
printStatus(message);
return SilentStatus(timeout: timeout);
return SilentStatus(timeout: timeout, timeoutConfiguration: timeoutConfiguration);
}
void dispose() {
......@@ -983,6 +983,12 @@ class NotifyingLogger extends Logger {
@override
void sendEvent(String name, [Map<String, dynamic> args]) { }
@override
bool get supportsColor => throw UnimplementedError();
@override
bool get hasTerminal => false;
}
/// A running application, started by this daemon.
......@@ -1167,6 +1173,7 @@ class _AppRunLogger extends Logger {
_status = SilentStatus(
timeout: timeout,
timeoutConfiguration: timeoutConfiguration,
onFinish: () {
_status = null;
_sendProgressEvent(<String, dynamic>{
......@@ -1206,6 +1213,12 @@ class _AppRunLogger extends Logger {
domain.sendEvent(name, args);
}
}
@override
bool get supportsColor => throw UnimplementedError();
@override
bool get hasTerminal => false;
}
class LogMessage {
......
......@@ -19,6 +19,7 @@ import 'base/logger.dart';
import 'base/os.dart';
import 'base/process.dart';
import 'base/signals.dart';
import 'base/terminal.dart';
import 'base/time.dart';
import 'base/user_messages.dart';
import 'base/utils.dart';
......@@ -101,7 +102,19 @@ Future<T> runInContext<T>(
IOSWorkflow: () => const IOSWorkflow(),
KernelCompilerFactory: () => const KernelCompilerFactory(),
LinuxWorkflow: () => const LinuxWorkflow(),
Logger: () => globals.platform.isWindows ? WindowsStdoutLogger() : StdoutLogger(),
Logger: () => globals.platform.isWindows
? WindowsStdoutLogger(
terminal: globals.terminal,
stdio: globals.stdio,
outputPreferences: outputPreferences,
timeoutConfiguration: timeoutConfiguration,
)
: StdoutLogger(
terminal: globals.terminal,
stdio: globals.stdio,
outputPreferences: outputPreferences,
timeoutConfiguration: timeoutConfiguration,
),
MacOSWorkflow: () => const MacOSWorkflow(),
MDnsObservatoryDiscovery: () => MDnsObservatoryDiscovery(),
OperatingSystemUtils: () => OperatingSystemUtils(),
......
......@@ -211,7 +211,12 @@ class Doctor {
lineBuffer.write(' (${result.statusInfo})');
}
buffer.write(wrapText(lineBuffer.toString(), hangingIndent: result.leadingBox.length + 1));
buffer.write(wrapText(
lineBuffer.toString(),
hangingIndent: result.leadingBox.length + 1,
columnWidth: outputPreferences.wrapColumn,
shouldWrap: outputPreferences.wrapText,
));
buffer.writeln();
if (result.type != ValidationType.installed) {
......@@ -253,6 +258,7 @@ class Doctor {
final Status status = Status.withSpinner(
timeout: timeoutConfiguration.fastOperation,
slowWarningCallback: () => validator.slowWarning,
timeoutConfiguration: timeoutConfiguration,
);
ValidationResult result;
try {
......
......@@ -10,6 +10,7 @@ import 'base/config.dart';
import 'base/context.dart';
import 'base/error_handling_file_system.dart';
import 'base/file_system.dart';
import 'base/io.dart';
import 'base/logger.dart';
import 'base/terminal.dart';
import 'cache.dart';
......@@ -103,4 +104,10 @@ AnsiTerminal get terminal {
return context?.get<AnsiTerminal>() ?? _defaultAnsiTerminal;
}
final AnsiTerminal _defaultAnsiTerminal = AnsiTerminal();
final AnsiTerminal _defaultAnsiTerminal = AnsiTerminal(
stdio: stdio,
platform: platform,
);
/// The global Stdio wrapper.
Stdio get stdio => context.get<Stdio>() ?? const Stdio();
......@@ -243,6 +243,7 @@ Future<String> _chooseSigningIdentity(List<String> validCodeSigningIdentities) a
prompt: 'Please select a certificate for code signing',
displayAcceptedCharacters: true,
defaultChoiceIndex: 0, // Just pressing enter chooses the first one.
logger: globals.logger,
);
if (choice == 'a') {
......
......@@ -284,6 +284,7 @@ class XcodeProjectInterpreter {
}) async {
final Status status = Status.withSpinner(
timeout: timeoutConfiguration.fastOperation,
timeoutConfiguration: timeoutConfiguration,
);
final List<String> showBuildSettingsCommand = <String>[
_executable,
......
......@@ -13,7 +13,6 @@ import '../artifacts.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart' as io;
import '../base/logger.dart';
import '../base/terminal.dart';
import '../base/user_messages.dart';
......@@ -146,13 +145,20 @@ class FlutterCommandRunner extends CommandRunner<void> {
@override
String get usageFooter {
return wrapText('Run "flutter help -v" for verbose help output, including less commonly used options.');
return wrapText('Run "flutter help -v" for verbose help output, including less commonly used options.',
columnWidth: outputPreferences.wrapColumn,
shouldWrap: outputPreferences.wrapText,
);
}
@override
String get usage {
final String usageWithoutDescription = super.usage.substring(description.length + 2);
return '${wrapText(description)}\n\n$usageWithoutDescription';
final String prefix = wrapText(description,
shouldWrap: outputPreferences.wrapText,
columnWidth: outputPreferences.wrapColumn,
);
return '$prefix\n\n$usageWithoutDescription';
}
static String get defaultFlutterRoot {
......@@ -233,7 +239,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
// Check for verbose.
if (topLevelResults['verbose'] as bool) {
// Override the logger.
contextOverrides[Logger] = VerboseLogger(globals.logger);
contextOverrides[Logger] = VerboseLogger(globals.logger, stopwatch: Stopwatch());
}
// Don't set wrapColumns unless the user said to: if it's set, then all
......@@ -255,7 +261,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
// anything, unless the user explicitly said to.
final bool useWrapping = topLevelResults.wasParsed('wrap')
? topLevelResults['wrap'] as bool
: io.stdio.terminalColumns != null && topLevelResults['wrap'] as bool;
: globals.stdio.terminalColumns != null && topLevelResults['wrap'] as bool;
contextOverrides[OutputPreferences] = OutputPreferences(
wrapText: useWrapping,
showColor: topLevelResults['color'] as bool,
......
......@@ -699,7 +699,7 @@ class StreamLogger extends Logger {
int progressIndicatorPadding = kDefaultStatusPadding,
}) {
_log('[progress] $message');
return SilentStatus(timeout: timeout)..start();
return SilentStatus(timeout: timeout, timeoutConfiguration: timeoutConfiguration)..start();
}
bool _interrupt = false;
......@@ -722,6 +722,12 @@ class StreamLogger extends Logger {
@override
void sendEvent(String name, [Map<String, dynamic> args]) { }
@override
bool get supportsColor => throw UnimplementedError();
@override
bool get hasTerminal => false;
}
class LoggerInterrupted implements Exception {
......
......@@ -7,7 +7,6 @@ import 'package:platform/platform.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/commands/clean.dart';
import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/macos/xcode.dart';
......@@ -77,7 +76,6 @@ void main() {
verify(mockFile.deleteSync(recursive: true)).called(1);
}, overrides: <Type, Generator>{
Platform: () => windowsPlatform,
Logger: () => BufferLogger(),
Xcode: () => mockXcode,
});
......@@ -94,7 +92,6 @@ void main() {
verifyNever(mockFile.deleteSync(recursive: true));
}, overrides: <Type, Generator>{
Platform: () => windowsPlatform,
Logger: () => BufferLogger(),
Xcode: () => mockXcode,
});
}
......
......@@ -15,7 +15,6 @@ import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
......@@ -451,11 +450,9 @@ void main() {
});
group('Config files', () {
BufferLogger mockLogger;
Directory tempDir;
setUp(() {
mockLogger = BufferLogger();
tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_settings_aar_test.');
});
......@@ -498,13 +495,12 @@ include ':app'
createSettingsAarGradle(tempDir);
expect(mockLogger.statusText, contains('created successfully'));
expect(testLogger.statusText, contains('created successfully'));
expect(tempDir.childFile('settings_aar.gradle').existsSync(), isTrue);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
Logger: () => mockLogger,
});
testUsingContext('create settings_aar.gradle when current settings.gradle doesn\'t load plugins', () {
......@@ -532,13 +528,12 @@ include ':app'
createSettingsAarGradle(tempDir);
expect(mockLogger.statusText, contains('created successfully'));
expect(testLogger.statusText, contains('created successfully'));
expect(tempDir.childFile('settings_aar.gradle').existsSync(), isTrue);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
Logger: () => mockLogger,
});
});
......
......@@ -9,7 +9,6 @@ import 'package:file/memory.dart';
import 'package:flutter_tools/src/asset.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/devfs.dart';
......@@ -183,16 +182,15 @@ flutter:
});
});
test('Failed directory delete shows message', () async {
testUsingContext('Failed directory delete shows message', () async {
final MockDirectory mockDirectory = MockDirectory();
final BufferLogger bufferLogger = BufferLogger();
when(mockDirectory.existsSync()).thenReturn(true);
when(mockDirectory.deleteSync(recursive: true)).thenThrow(const FileSystemException('ABCD'));
await writeBundle(mockDirectory, <String, DevFSContent>{}, loggerOverride: bufferLogger);
await writeBundle(mockDirectory, <String, DevFSContent>{}, loggerOverride: testLogger);
verify(mockDirectory.createSync(recursive: true)).called(1);
expect(bufferLogger.errorText, contains('ABCD'));
expect(testLogger.errorText, contains('ABCD'));
});
}
......
......@@ -13,7 +13,6 @@ import 'package:flutter_tools/src/base/build.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/macos/xcode.dart';
import 'package:flutter_tools/src/version.dart';
......@@ -225,7 +224,6 @@ void main() {
MockAndroidSdk mockAndroidSdk;
MockArtifacts mockArtifacts;
MockXcode mockXcode;
BufferLogger bufferLogger;
setUp(() async {
fs = MemoryFileSystem();
......@@ -247,7 +245,6 @@ void main() {
mockXcode = MockXcode();
when(mockXcode.sdkLocation(any)).thenAnswer((_) => Future<String>.value(kSDKPath));
bufferLogger = BufferLogger();
for (final BuildMode mode in BuildMode.values) {
when(mockArtifacts.getArtifactPath(Artifact.snapshotDart,
platform: anyNamed('platform'), mode: mode)).thenReturn(kSnapshotDart);
......@@ -261,7 +258,6 @@ void main() {
ProcessManager: () => FakeProcessManager.any(),
GenSnapshot: () => genSnapshot,
Xcode: () => mockXcode,
Logger: () => bufferLogger,
};
testUsingContext('iOS debug AOT snapshot is invalid', () async {
......@@ -658,7 +654,7 @@ void main() {
expect(genSnapshotExitCode, 0);
expect(genSnapshot.callCount, 1);
expect(bufferLogger.statusText, matches(RegExp(r'snapshot\(CompileTime\): \d+ ms.')));
expect(testLogger.statusText, matches(RegExp(r'snapshot\(CompileTime\): \d+ ms.')));
}, overrides: contextOverrides);
});
}
......@@ -6,7 +6,6 @@ import 'dart:async';
import 'package:platform/platform.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:mockito/mockito.dart';
......@@ -69,11 +68,9 @@ void main() {
group('output formatting', () {
MockProcessManager mockProcessManager;
BufferLogger mockLogger;
setUp(() {
mockProcessManager = MockProcessManager();
mockLogger = BufferLogger();
});
MockProcess Function(List<String>) processMetaFactory(List<String> stdout, { List<String> stderr = const <String>[] }) {
......@@ -88,10 +85,10 @@ void main() {
final List<String> testString = <String>['0123456789' * 10];
mockProcessManager.processFactory = processMetaFactory(testString, stderr: testString);
await processUtils.stream(<String>['command']);
expect(mockLogger.statusText, equals('${testString[0]}\n'));
expect(mockLogger.errorText, equals('${testString[0]}\n'));
expect(testLogger.statusText, equals('${testString[0]}\n'));
expect(testLogger.errorText, equals('${testString[0]}\n'));
}, overrides: <Type, Generator>{
Logger: () => mockLogger,
ProcessManager: () => mockProcessManager,
OutputPreferences: () => OutputPreferences(wrapText: true, wrapColumn: 40),
Platform: () => FakePlatform.fromPlatform(const LocalPlatform())..stdoutSupportsAnsi = false,
......
......@@ -4,6 +4,7 @@
import 'dart:async';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:platform/platform.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/terminal.dart';
......@@ -11,24 +12,28 @@ import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:mockito/mockito.dart';
import '../../src/common.dart';
import '../../src/context.dart';
void main() {
group('output preferences', () {
testUsingContext('can wrap output', () async {
globals.printStatus('0123456789' * 8);
expect(testLogger.statusText, equals(('0123456789' * 4 + '\n') * 2));
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences(wrapText: true, wrapColumn: 40),
testWithoutContext('can wrap output', () async {
final BufferLogger bufferLogger = BufferLogger(
outputPreferences: OutputPreferences.test(wrapText: true, wrapColumn: 40),
terminal: TestTerminal(platform: FakePlatform()..stdoutSupportsAnsi = true),
);
bufferLogger.printStatus('0123456789' * 8);
expect(bufferLogger.statusText, equals(('0123456789' * 4 + '\n') * 2));
});
testUsingContext('can turn off wrapping', () async {
testWithoutContext('can turn off wrapping', () async {
final BufferLogger bufferLogger = BufferLogger(
outputPreferences: OutputPreferences.test(wrapText: false),
terminal: TestTerminal(platform: FakePlatform()..stdoutSupportsAnsi = true),
);
final String testString = '0123456789' * 20;
globals.printStatus(testString);
expect(testLogger.statusText, equals('$testString\n'));
}, overrides: <Type, Generator>{
Platform: () => FakePlatform()..stdoutSupportsAnsi = true,
OutputPreferences: () => OutputPreferences(wrapText: false),
bufferLogger.printStatus(testString);
expect(bufferLogger.statusText, equals('$testString\n'));
});
});
......@@ -36,32 +41,29 @@ void main() {
AnsiTerminal terminal;
setUp(() {
terminal = AnsiTerminal();
terminal = AnsiTerminal(
stdio: globals.stdio, // Danger, using real stdio.
platform: FakePlatform()..stdoutSupportsAnsi = true,
);
});
testUsingContext('adding colors works', () {
testWithoutContext('adding colors works', () {
for (final TerminalColor color in TerminalColor.values) {
expect(
terminal.color('output', color),
equals('${AnsiTerminal.colorCode(color)}output${AnsiTerminal.resetColor}'),
);
}
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences(showColor: true),
Platform: () => FakePlatform()..stdoutSupportsAnsi = true,
});
testUsingContext('adding bold works', () {
testWithoutContext('adding bold works', () {
expect(
terminal.bolden('output'),
equals('${AnsiTerminal.bold}output${AnsiTerminal.resetBold}'),
);
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences(showColor: true),
Platform: () => FakePlatform()..stdoutSupportsAnsi = true,
});
testUsingContext('nesting bold within color works', () {
testWithoutContext('nesting bold within color works', () {
expect(
terminal.color(terminal.bolden('output'), TerminalColor.blue),
equals('${AnsiTerminal.blue}${AnsiTerminal.bold}output${AnsiTerminal.resetBold}${AnsiTerminal.resetColor}'),
......@@ -70,12 +72,9 @@ void main() {
terminal.color('non-bold ${terminal.bolden('output')} also non-bold', TerminalColor.blue),
equals('${AnsiTerminal.blue}non-bold ${AnsiTerminal.bold}output${AnsiTerminal.resetBold} also non-bold${AnsiTerminal.resetColor}'),
);
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences(showColor: true),
Platform: () => FakePlatform()..stdoutSupportsAnsi = true,
});
testUsingContext('nesting color within bold works', () {
testWithoutContext('nesting color within bold works', () {
expect(
terminal.bolden(terminal.color('output', TerminalColor.blue)),
equals('${AnsiTerminal.bold}${AnsiTerminal.blue}output${AnsiTerminal.resetColor}${AnsiTerminal.resetBold}'),
......@@ -84,12 +83,9 @@ void main() {
terminal.bolden('non-color ${terminal.color('output', TerminalColor.blue)} also non-color'),
equals('${AnsiTerminal.bold}non-color ${AnsiTerminal.blue}output${AnsiTerminal.resetColor} also non-color${AnsiTerminal.resetBold}'),
);
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences(showColor: true),
Platform: () => FakePlatform()..stdoutSupportsAnsi = true,
});
testUsingContext('nesting color within color works', () {
testWithoutContext('nesting color within color works', () {
expect(
terminal.color(terminal.color('output', TerminalColor.blue), TerminalColor.magenta),
equals('${AnsiTerminal.magenta}${AnsiTerminal.blue}output${AnsiTerminal.resetColor}${AnsiTerminal.magenta}${AnsiTerminal.resetColor}'),
......@@ -98,12 +94,9 @@ void main() {
terminal.color('magenta ${terminal.color('output', TerminalColor.blue)} also magenta', TerminalColor.magenta),
equals('${AnsiTerminal.magenta}magenta ${AnsiTerminal.blue}output${AnsiTerminal.resetColor}${AnsiTerminal.magenta} also magenta${AnsiTerminal.resetColor}'),
);
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences(showColor: true),
Platform: () => FakePlatform()..stdoutSupportsAnsi = true,
});
testUsingContext('nesting bold within bold works', () {
testWithoutContext('nesting bold within bold works', () {
expect(
terminal.bolden(terminal.bolden('output')),
equals('${AnsiTerminal.bold}output${AnsiTerminal.resetBold}'),
......@@ -112,9 +105,6 @@ void main() {
terminal.bolden('bold ${terminal.bolden('output')} still bold'),
equals('${AnsiTerminal.bold}bold output still bold${AnsiTerminal.resetBold}'),
);
}, overrides: <Type, Generator>{
OutputPreferences: () => OutputPreferences(showColor: true),
Platform: () => FakePlatform()..stdoutSupportsAnsi = true,
});
});
......@@ -122,17 +112,22 @@ void main() {
AnsiTerminal terminalUnderTest;
setUp(() {
terminalUnderTest = TestTerminal();
terminalUnderTest = TestTerminal(stdio: MockStdio());
});
testUsingContext('character prompt throws if usesTerminalUi is false', () async {
testWithoutContext('character prompt throws if usesTerminalUi is false', () async {
expect(terminalUnderTest.promptForCharInput(
<String>['a', 'b', 'c'],
prompt: 'Please choose something',
logger: null,
), throwsA(isInstanceOf<StateError>()));
});
testUsingContext('character prompt', () async {
testWithoutContext('character prompt', () async {
final BufferLogger bufferLogger = BufferLogger(
terminal: terminalUnderTest,
outputPreferences: OutputPreferences.test(),
);
terminalUnderTest.usesTerminalUi = true;
mockStdInStream = Stream<String>.fromFutures(<Future<String>>[
Future<String>.value('d'), // Not in accepted list.
......@@ -142,17 +137,22 @@ void main() {
final String choice = await terminalUnderTest.promptForCharInput(
<String>['a', 'b', 'c'],
prompt: 'Please choose something',
logger: bufferLogger,
);
expect(choice, 'b');
expect(
testLogger.statusText,
bufferLogger.statusText,
'Please choose something [a|b|c]: d\n'
'Please choose something [a|b|c]: \n'
'\n'
'Please choose something [a|b|c]: b\n');
});
testUsingContext('default character choice without displayAcceptedCharacters', () async {
testWithoutContext('default character choice without displayAcceptedCharacters', () async {
final BufferLogger bufferLogger = BufferLogger(
terminal: terminalUnderTest,
outputPreferences: OutputPreferences.test(),
);
terminalUnderTest.usesTerminalUi = true;
mockStdInStream = Stream<String>.fromFutures(<Future<String>>[
Future<String>.value('\n'), // Not in accepted list
......@@ -162,21 +162,26 @@ void main() {
prompt: 'Please choose something',
displayAcceptedCharacters: false,
defaultChoiceIndex: 1, // which is b.
logger: bufferLogger,
);
expect(choice, 'b');
expect(
testLogger.statusText,
bufferLogger.statusText,
'Please choose something: \n'
'\n');
});
testUsingContext('Does not set single char mode when a terminal is not attached', () {
testWithoutContext('Does not set single char mode when a terminal is not attached', () {
final Stdio stdio = MockStdio();
when(stdio.stdin).thenThrow(StateError('This should not be called'));
when(stdio.stdinHasTerminal).thenReturn(false);
final AnsiTerminal ansiTerminal = AnsiTerminal(
stdio: stdio,
platform: const LocalPlatform()
);
globals.terminal.singleCharMode = true;
}, overrides: <Type, Generator>{
Stdio: () => MockStdio(),
expect(() => ansiTerminal.singleCharMode = true, returnsNormally);
});
});
}
......@@ -184,10 +189,17 @@ void main() {
Stream<String> mockStdInStream;
class TestTerminal extends AnsiTerminal {
TestTerminal({
Stdio stdio,
Platform platform = const LocalPlatform(),
}) : super(stdio: stdio, platform: platform);
@override
Stream<String> get keystrokes {
return mockStdInStream;
}
bool singleCharMode = false;
}
class MockStdio extends Mock implements Stdio {}
......@@ -7,6 +7,7 @@ import 'dart:async';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/device.dart';
......@@ -15,6 +16,7 @@ import 'package:flutter_tools/src/run_cold.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import '../src/common.dart';
import '../src/context.dart';
......@@ -26,7 +28,13 @@ void main() {
BufferLogger mockLogger;
setUp(() {
mockLogger = BufferLogger();
mockLogger = BufferLogger(
terminal: AnsiTerminal(
stdio: null,
platform: const LocalPlatform(),
),
outputPreferences: OutputPreferences.test(),
);
residentCompiler = MockResidentCompiler();
});
......@@ -114,23 +122,16 @@ void main() {
});
group('cold run', () {
BufferLogger mockLogger;
setUp(() {
mockLogger = BufferLogger();
});
testUsingContext('returns 1 if not prebuilt mode & mainPath does not exist', () async {
final MockDevice mockDevice = MockDevice();
final MockFlutterDevice mockFlutterDevice = MockFlutterDevice();
when(mockFlutterDevice.device).thenReturn(mockDevice);
final List<FlutterDevice> devices = <FlutterDevice>[mockFlutterDevice];
final int result = await ColdRunner(devices).run();
expect(result, 1);
expect(mockLogger.errorText, matches(r'Tried to run .*, but that file does not exist\.'));
expect(mockLogger.errorText, matches(r'Consider using the -t option to specify the Dart file to start\.'));
}, overrides: <Type, Generator>{
Logger: () => mockLogger,
expect(testLogger.errorText, matches(r'Tried to run .*, but that file does not exist\.'));
expect(testLogger.errorText, matches(r'Consider using the -t option to specify the Dart file to start\.'));
});
testUsingContext('calls runCold on attached device', () async {
......@@ -148,13 +149,12 @@ void main() {
applicationBinary: applicationBinary,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
).run();
expect(result, 1);
verify(mockFlutterDevice.runCold(
coldRunner: anyNamed('coldRunner'),
route: anyNamed('route'),
));
}, overrides: <Type, Generator>{
Logger: () => mockLogger,
});
});
}
......
......@@ -4,7 +4,6 @@
import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/base/file_system.dart';
......@@ -22,14 +21,12 @@ void main() {
MockXcode mockXcode;
MemoryFileSystem memoryFileSystem;
MockProcessManager mockProcessManager;
BufferLogger bufferLogger;
MockPlistUtils mockPlistUtils;
setUp(() {
mockXcode = MockXcode();
memoryFileSystem = MemoryFileSystem(style: FileSystemStyle.posix);
mockProcessManager = MockProcessManager();
bufferLogger = BufferLogger();
mockPlistUtils = MockPlistUtils();
});
......@@ -67,7 +64,6 @@ void main() {
FileSystem: () => memoryFileSystem,
ProcessManager: () => mockProcessManager,
Xcode: () => mockXcode,
Logger: () => bufferLogger,
PlistParser: () => mockPlistUtils,
});
......@@ -91,7 +87,6 @@ void main() {
FileSystem: () => memoryFileSystem,
ProcessManager: () => mockProcessManager,
Xcode: () => mockXcode,
Logger: () => bufferLogger,
PlistParser: () => mockPlistUtils,
});
......@@ -114,7 +109,6 @@ void main() {
FileSystem: () => memoryFileSystem,
ProcessManager: () => mockProcessManager,
Xcode: () => mockXcode,
Logger: () => bufferLogger,
PlistParser: () => mockPlistUtils,
});
......@@ -143,7 +137,6 @@ void main() {
FileSystem: () => memoryFileSystem,
ProcessManager: () => mockProcessManager,
Xcode: () => mockXcode,
Logger: () => bufferLogger,
PlistParser: () => mockPlistUtils,
});
......@@ -162,13 +155,12 @@ void main() {
await validateBitcode(BuildMode.release, TargetPlatform.ios);
expect(bufferLogger.statusText, '');
expect(testLogger.statusText, '');
}, overrides: <Type, Generator>{
Artifacts: () => LocalEngineArtifacts('/engine', 'ios_profile', 'host_profile'),
FileSystem: () => memoryFileSystem,
ProcessManager: () => mockProcessManager,
Xcode: () => mockXcode,
Logger: () => bufferLogger,
PlistParser: () => mockPlistUtils,
});
......@@ -187,13 +179,12 @@ void main() {
await validateBitcode(BuildMode.release, TargetPlatform.ios);
expect(bufferLogger.statusText, '');
expect(testLogger.statusText, '');
}, overrides: <Type, Generator>{
Artifacts: () => LocalEngineArtifacts('/engine', 'ios_profile', 'host_profile'),
FileSystem: () => memoryFileSystem,
ProcessManager: () => mockProcessManager,
Xcode: () => mockXcode,
Logger: () => bufferLogger,
PlistParser: () => mockPlistUtils,
});
}
......
......@@ -6,7 +6,6 @@ import 'dart:async';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/compile.dart';
......@@ -103,7 +102,6 @@ void main() {
}, overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
OutputPreferences: () => OutputPreferences(showColor: false),
Logger: () => BufferLogger(),
Platform: kNoColorTerminalPlatform,
});
......
......@@ -6,6 +6,8 @@ import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/config.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:platform/platform.dart';
import '../src/common.dart';
......@@ -49,7 +51,13 @@ void main() {
});
test('Config parse error', () {
final BufferLogger bufferLogger =BufferLogger();
final BufferLogger bufferLogger = BufferLogger(
terminal: AnsiTerminal(
stdio: null,
platform: const LocalPlatform(),
),
outputPreferences: OutputPreferences.test(),
);
final File file = memoryFileSystem.file('example')
..writeAsStringSync('{"hello":"bar');
config = Config(file, bufferLogger);
......
......@@ -6,7 +6,6 @@ import 'dart:async';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/devfs.dart';
......@@ -269,12 +268,10 @@ void main() {
group('hot attach', () {
MockResidentCompiler residentCompiler = MockResidentCompiler();
BufferLogger mockLogger;
MockLocalEngineArtifacts mockArtifacts;
setUp(() {
residentCompiler = MockResidentCompiler();
mockLogger = BufferLogger();
mockArtifacts = MockLocalEngineArtifacts();
});
......@@ -298,13 +295,12 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
).attach();
expect(exitCode, 2);
expect(mockLogger.statusText, contains('If you are using an emulator running Android Q Beta, '
expect(testLogger.statusText, contains('If you are using an emulator running Android Q Beta, '
'consider using an emulator running API level 29 or lower.'));
expect(mockLogger.statusText, contains('Learn more about the status of this issue on '
expect(testLogger.statusText, contains('Learn more about the status of this issue on '
'https://issuetracker.google.com/issues/132325318'));
}, overrides: <Type, Generator>{
Artifacts: () => mockArtifacts,
Logger: () => mockLogger,
HotRunnerConfig: () => TestHotRunnerConfig(successfulSetup: true),
});
......@@ -327,13 +323,12 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
).attach();
expect(exitCode, 2);
expect(mockLogger.statusText, contains('If you are using an emulator running Android Q Beta, '
expect(testLogger.statusText, contains('If you are using an emulator running Android Q Beta, '
'consider using an emulator running API level 29 or lower.'));
expect(mockLogger.statusText, contains('Learn more about the status of this issue on '
expect(testLogger.statusText, contains('Learn more about the status of this issue on '
'https://issuetracker.google.com/issues/132325318'));
}, overrides: <Type, Generator>{
Artifacts: () => mockArtifacts,
Logger: () => mockLogger,
HotRunnerConfig: () => TestHotRunnerConfig(successfulSetup: true),
});
});
......
......@@ -654,6 +654,8 @@ class MockConfig extends Mock implements Config {}
Stream<String> mockTerminalStdInStream;
class TestTerminal extends AnsiTerminal {
TestTerminal() : super(stdio: globals.stdio, platform: globals.platform);
@override
String bolden(String message) => '<bold>$message</bold>';
......
......@@ -4,22 +4,36 @@
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/run_hot.dart';
import 'package:platform/platform.dart';
import '../src/common.dart';
import '../src/mocks.dart';
// assumption: tests have a timeout less than 100 days
final DateTime inFuture = DateTime.now().add(const Duration(days: 100));
void main() {
BufferLogger bufferLogger;
setUp(() {
bufferLogger = BufferLogger(
terminal: AnsiTerminal(
stdio: MockStdio(),
platform: FakePlatform(),
),
outputPreferences: OutputPreferences.test(),
);
});
for (final bool asyncScanning in <bool>[true, false]) {
testWithoutContext('No last compile, asyncScanning: $asyncScanning', () async {
final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
fileSystem: MemoryFileSystem(),
platform: FakePlatform(),
logger: BufferLogger(),
logger: bufferLogger,
);
expect(
......@@ -37,7 +51,7 @@ void main() {
final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
fileSystem: MemoryFileSystem(),
platform: FakePlatform(),
logger: BufferLogger(),
logger: bufferLogger,
);
expect(
......@@ -55,7 +69,7 @@ void main() {
final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
fileSystem: MemoryFileSystem(),
platform: FakePlatform(),
logger: BufferLogger(),
logger: bufferLogger,
);
expect(
......
......@@ -7,6 +7,7 @@ import 'dart:async';
import 'package:dwds/dwds.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/base/net.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/device.dart';
......@@ -17,6 +18,7 @@ import 'package:flutter_tools/src/build_runner/resident_web_runner.dart';
import 'package:flutter_tools/src/build_runner/web_fs.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import 'package:vm_service/vm_service.dart';
import '../src/common.dart';
......@@ -84,7 +86,13 @@ void main() {
expect(debugConnectionInfo.wsUri, null);
verify(mockStatus.stop()).called(1);
}, overrides: <Type, Generator>{
Logger: () => DelegateLogger(BufferLogger()),
Logger: () => DelegateLogger(BufferLogger(
terminal: AnsiTerminal(
stdio: null,
platform: const LocalPlatform(),
),
outputPreferences: OutputPreferences.test(),
)),
}));
test('Can full restart after attaching', () => testbed.run(() async {
......
......@@ -11,6 +11,7 @@ import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/net.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_runner/resident_web_runner.dart';
import 'package:flutter_tools/src/build_runner/web_fs.dart';
......@@ -26,6 +27,7 @@ import 'package:flutter_tools/src/web/chrome.dart';
import 'package:flutter_tools/src/web/web_device.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import 'package:vm_service/vm_service.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
......@@ -257,7 +259,13 @@ void main() {
expect(bufferLogger.statusText, contains('Debug service listening on ws://127.0.0.1/abcd/'));
expect(debugConnectionInfo.wsUri.toString(), 'ws://127.0.0.1/abcd/');
}, overrides: <Type, Generator>{
Logger: () => DelegateLogger(BufferLogger()),
Logger: () => DelegateLogger(BufferLogger(
terminal: AnsiTerminal(
stdio: null,
platform: const LocalPlatform(),
),
outputPreferences: OutputPreferences.test(),
)),
}));
test('Can successfully run and disconnect with --no-resident', () => testbed.run(() async {
......@@ -1080,7 +1088,13 @@ void main() {
await expectation;
verify(mockStatus.stop()).called(2);
}, overrides: <Type, Generator>{
Logger: () => DelegateLogger(BufferLogger())
Logger: () => DelegateLogger(BufferLogger(
terminal: AnsiTerminal(
stdio: null,
platform: const LocalPlatform(),
),
outputPreferences: OutputPreferences.test(),
))
}));
}
......
......@@ -7,10 +7,12 @@ import 'dart:io';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import 'package:quiver/testing/async.dart';
import '../src/common.dart';
......@@ -167,6 +169,7 @@ class MockPeer implements rpc.Peer {
void main() {
MockStdio mockStdio;
group('VMService', () {
setUp(() {
mockStdio = MockStdio();
});
......@@ -188,8 +191,12 @@ void main() {
expect(mockStdio.writtenToStderr.join(''), '');
});
}, overrides: <Type, Generator>{
Logger: () => StdoutLogger(),
Stdio: () => mockStdio,
Logger: () => StdoutLogger(
outputPreferences: OutputPreferences.test(),
stdio: mockStdio,
terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()),
timeoutConfiguration: const TimeoutConfiguration(),
),
WebSocketConnector: () => (String url, {CompressionOptions compression}) async => throw const SocketException('test'),
});
......@@ -263,8 +270,12 @@ void main() {
expect(mockStdio.writtenToStderr.join(''), '');
});
}, overrides: <Type, Generator>{
Logger: () => StdoutLogger(),
Stdio: () => mockStdio,
Logger: () => StdoutLogger(
outputPreferences: outputPreferences,
terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()),
stdio: mockStdio,
timeoutConfiguration: const TimeoutConfiguration(),
),
});
testUsingContext('registers hot UI method', () {
......@@ -276,8 +287,12 @@ void main() {
expect(mockPeer.registeredMethods, contains('reloadMethod'));
});
}, overrides: <Type, Generator>{
Logger: () => StdoutLogger(),
Stdio: () => mockStdio,
Logger: () => StdoutLogger(
outputPreferences: outputPreferences,
terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()),
stdio: mockStdio,
timeoutConfiguration: const TimeoutConfiguration(),
),
});
testUsingContext('registers flutterMemoryInfo service', () {
......@@ -290,8 +305,12 @@ void main() {
expect(mockPeer.registeredMethods, contains('flutterMemoryInfo'));
});
}, overrides: <Type, Generator>{
Logger: () => StdoutLogger(),
Stdio: () => mockStdio,
Logger: () => StdoutLogger(
outputPreferences: outputPreferences,
terminal: AnsiTerminal(stdio: mockStdio, platform: const LocalPlatform()),
stdio: mockStdio,
timeoutConfiguration: const TimeoutConfiguration(),
),
});
});
}
......
......@@ -92,6 +92,7 @@ void testUsingContext(
return context.run<dynamic>(
name: 'mocks',
overrides: <Type, Generator>{
AnsiTerminal: () => AnsiTerminal(platform: globals.platform, stdio: globals.stdio),
Config: () => buildConfig(globals.fs),
DeviceManager: () => FakeDeviceManager(),
Doctor: () => FakeDoctor(),
......@@ -103,7 +104,10 @@ void testUsingContext(
return mock;
},
OutputPreferences: () => OutputPreferences.test(),
Logger: () => BufferLogger(),
Logger: () => BufferLogger(
terminal: globals.terminal,
outputPreferences: outputPreferences,
),
OperatingSystemUtils: () => FakeOperatingSystemUtils(),
PersistentToolState: () => buildPersistentToolState(globals.fs),
SimControl: () => MockSimControl(),
......
......@@ -38,7 +38,10 @@ final Map<Type, Generator> _testbedDefaults = <Type, Generator>{
// Keeps tests fast by avoiding the actual file system.
FileSystem: () => MemoryFileSystem(style: globals.platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix),
ProcessManager: () => FakeProcessManager.any(),
Logger: () => BufferLogger(), // Allows reading logs and prevents stdout.
Logger: () => BufferLogger(
terminal: AnsiTerminal(stdio: globals.stdio, platform: globals.platform), // Danger, using real stdio.
outputPreferences: OutputPreferences.test(),
), // Allows reading logs and prevents stdout.
OperatingSystemUtils: () => FakeOperatingSystemUtils(),
OutputPreferences: () => OutputPreferences.test(), // configures BufferLogger to avoid color codes.
Usage: () => NoOpUsage(), // prevent addition of analytics from burdening test mocks
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment