[flutter_tools] update visual studio and validator to remove globals, update test cases (#51680)

Updates VisualStudio and VisualStudioValidator to use constructors instead of global injection. Updates VisualStudio test cases to prefer FakeProcessManager
Updates build_windows test to work without injected VisualStudio
This commit is contained in:
Jonah Williams 2020-03-10 16:49:23 -07:00 committed by GitHub
parent 53dce17b35
commit ea3563ea4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 750 additions and 460 deletions

View file

@ -4,6 +4,8 @@
import 'dart:async';
import 'package:meta/meta.dart';
import '../base/common.dart';
import '../build_info.dart';
import '../cache.dart';
@ -12,6 +14,7 @@ import '../globals.dart' as globals;
import '../project.dart';
import '../runner/flutter_command.dart' show FlutterCommandResult;
import '../windows/build_windows.dart';
import '../windows/visual_studio.dart';
import 'build.dart';
/// A command to build a windows desktop target through a build shell script.
@ -36,6 +39,9 @@ class BuildWindowsCommand extends BuildSubCommand {
@override
String get description => 'build the desktop Windows target.';
@visibleForTesting
VisualStudio visualStudioOverride;
@override
Future<FlutterCommandResult> runCommand() async {
Cache.releaseLockEarly();
@ -47,7 +53,12 @@ class BuildWindowsCommand extends BuildSubCommand {
if (!globals.platform.isWindows) {
throwToolExit('"build windows" only supported on Windows hosts.');
}
await buildWindows(flutterProject.windows, buildInfo, target: targetFile);
await buildWindows(
flutterProject.windows,
buildInfo,
target: targetFile,
visualStudioOverride: visualStudioOverride,
);
return FlutterCommandResult.success();
}
}

View file

@ -188,8 +188,15 @@ Future<T> runInContext<T>(
runningOnBot: runningOnBot,
),
UserMessages: () => UserMessages(),
VisualStudio: () => VisualStudio(),
VisualStudioValidator: () => const VisualStudioValidator(),
VisualStudioValidator: () => VisualStudioValidator(
userMessages: globals.userMessages,
visualStudio: VisualStudio(
fileSystem: globals.fs,
platform: globals.platform,
logger: globals.logger,
processManager: globals.processManager,
)
),
WebWorkflow: () => const WebWorkflow(),
WindowsWorkflow: () => const WindowsWorkflow(),
Xcode: () => Xcode(

View file

@ -16,7 +16,10 @@ import 'property_sheet.dart';
import 'visual_studio.dart';
/// Builds the Windows project using msbuild.
Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, {String target}) async {
Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, {
String target,
VisualStudio visualStudioOverride,
}) async {
if (!windowsProject.solutionFile.existsSync()) {
throwToolExit(
'No Windows desktop project configured. '
@ -28,6 +31,12 @@ Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, {S
_writeGeneratedFlutterProperties(windowsProject, buildInfo, target);
createPluginSymlinks(windowsProject.project);
final VisualStudio visualStudio = visualStudioOverride ?? VisualStudio(
fileSystem: globals.fs,
platform: globals.platform,
logger: globals.logger,
processManager: globals.processManager,
);
final String vcvarsScript = visualStudio.vcvarsPath;
if (vcvarsScript == null) {
throwToolExit('Unable to find suitable Visual Studio toolchain. '

View file

@ -2,16 +2,31 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../base/context.dart';
import 'package:meta/meta.dart';
import 'package:platform/platform.dart';
import 'package:process/process.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/process.dart';
import '../convert.dart';
import '../globals.dart' as globals;
VisualStudio get visualStudio => context.get<VisualStudio>();
/// Encapsulates information about the installed copy of Visual Studio, if any.
class VisualStudio {
VisualStudio({
@required FileSystem fileSystem,
@required ProcessManager processManager,
@required Platform platform,
@required Logger logger,
}) : _platform = platform,
_fileSystem = fileSystem,
_processUtils = ProcessUtils(processManager: processManager, logger: logger);
final FileSystem _fileSystem;
final Platform _platform;
final ProcessUtils _processUtils;
/// True if Visual Studio installation was found.
///
/// Versions older than 2017 Update 2 won't be detected, so error messages to
@ -107,7 +122,7 @@ class VisualStudio {
if (details.isEmpty) {
return null;
}
return globals.fs.path.join(
return _fileSystem.path.join(
_usableVisualStudioDetails[_installationPathKey] as String,
'VC',
'Auxiliary',
@ -125,8 +140,8 @@ class VisualStudio {
/// present then there isn't a new enough installation of VS. This path is
/// not user-controllable, unlike the install location of Visual Studio
/// itself.
final String _vswherePath = globals.fs.path.join(
globals.platform.environment['PROGRAMFILES(X86)'],
String get _vswherePath => _fileSystem.path.join(
_platform.environment['PROGRAMFILES(X86)'],
'Microsoft Visual Studio',
'Installer',
'vswhere.exe',
@ -215,7 +230,7 @@ class VisualStudio {
'-utf8',
'-latest',
];
final RunResult whereResult = processUtils.runSync(<String>[
final RunResult whereResult = _processUtils.runSync(<String>[
_vswherePath,
...defaultArguments,
...?additionalArguments,

View file

@ -2,15 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import '../base/context.dart';
import '../base/user_messages.dart';
import '../base/user_messages.dart' hide userMessages;
import '../doctor.dart';
import 'visual_studio.dart';
VisualStudioValidator get visualStudioValidator => context.get<VisualStudioValidator>();
class VisualStudioValidator extends DoctorValidator {
const VisualStudioValidator() : super('Visual Studio - develop for Windows');
const VisualStudioValidator({
@required VisualStudio visualStudio,
@required UserMessages userMessages,
}) : _visualStudio = visualStudio,
_userMessages = userMessages,
super('Visual Studio - develop for Windows');
final VisualStudio _visualStudio;
final UserMessages _userMessages;
@override
Future<ValidationResult> validate() async {
@ -18,57 +28,57 @@ class VisualStudioValidator extends DoctorValidator {
ValidationType status = ValidationType.missing;
String versionInfo;
if (visualStudio.isInstalled) {
if (_visualStudio.isInstalled) {
status = ValidationType.installed;
messages.add(ValidationMessage(
userMessages.visualStudioLocation(visualStudio.installLocation)
_userMessages.visualStudioLocation(_visualStudio.installLocation)
));
messages.add(ValidationMessage(userMessages.visualStudioVersion(
visualStudio.displayName,
visualStudio.fullVersion,
messages.add(ValidationMessage(_userMessages.visualStudioVersion(
_visualStudio.displayName,
_visualStudio.fullVersion,
)));
if (visualStudio.isPrerelease) {
messages.add(ValidationMessage(userMessages.visualStudioIsPrerelease));
if (_visualStudio.isPrerelease) {
messages.add(ValidationMessage(_userMessages.visualStudioIsPrerelease));
}
// Messages for faulty installations.
if (!visualStudio.isAtLeastMinimumVersion) {
if (!_visualStudio.isAtLeastMinimumVersion) {
status = ValidationType.partial;
messages.add(ValidationMessage.error(
userMessages.visualStudioTooOld(
visualStudio.minimumVersionDescription,
visualStudio.workloadDescription,
visualStudio.necessaryComponentDescriptions(),
_userMessages.visualStudioTooOld(
_visualStudio.minimumVersionDescription,
_visualStudio.workloadDescription,
_visualStudio.necessaryComponentDescriptions(),
),
));
} else if (visualStudio.isRebootRequired) {
} else if (_visualStudio.isRebootRequired) {
status = ValidationType.partial;
messages.add(ValidationMessage.error(userMessages.visualStudioRebootRequired));
} else if (!visualStudio.isComplete) {
messages.add(ValidationMessage.error(_userMessages.visualStudioRebootRequired));
} else if (!_visualStudio.isComplete) {
status = ValidationType.partial;
messages.add(ValidationMessage.error(userMessages.visualStudioIsIncomplete));
} else if (!visualStudio.isLaunchable) {
messages.add(ValidationMessage.error(_userMessages.visualStudioIsIncomplete));
} else if (!_visualStudio.isLaunchable) {
status = ValidationType.partial;
messages.add(ValidationMessage.error(userMessages.visualStudioNotLaunchable));
} else if (!visualStudio.hasNecessaryComponents) {
messages.add(ValidationMessage.error(_userMessages.visualStudioNotLaunchable));
} else if (!_visualStudio.hasNecessaryComponents) {
status = ValidationType.partial;
messages.add(ValidationMessage.error(
userMessages.visualStudioMissingComponents(
visualStudio.workloadDescription,
visualStudio.necessaryComponentDescriptions(),
_userMessages.visualStudioMissingComponents(
_visualStudio.workloadDescription,
_visualStudio.necessaryComponentDescriptions(),
),
));
}
versionInfo = '${visualStudio.displayName} ${visualStudio.displayVersion}';
versionInfo = '${_visualStudio.displayName} ${_visualStudio.displayVersion}';
} else {
status = ValidationType.missing;
messages.add(ValidationMessage.error(
userMessages.visualStudioMissing(
visualStudio.workloadDescription,
visualStudio.necessaryComponentDescriptions(),
_userMessages.visualStudioMissing(
_visualStudio.workloadDescription,
_visualStudio.necessaryComponentDescriptions(),
),
));
}

View file

@ -8,7 +8,6 @@ import 'package:platform/platform.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build.dart';
import 'package:flutter_tools/src/commands/build_windows.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/features.dart';
@ -23,15 +22,28 @@ import '../../src/context.dart';
import '../../src/mocks.dart';
import '../../src/testbed.dart';
const String solutionPath = r'C:\windows\Runner.sln';
const String visualStudioPath = r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community';
const String vcvarsPath = visualStudioPath + r'\VC\Auxiliary\Build\vcvars64.bat';
final Platform windowsPlatform = FakePlatform(
operatingSystem: 'windows',
environment: <String, String>{
'PROGRAMFILES(X86)': r'C:\Program Files (x86)\',
'FLUTTER_ROOT': r'C:\',
}
);
final Platform notWindowsPlatform = FakePlatform(
operatingSystem: 'linux',
environment: <String, String>{
'FLUTTER_ROOT': r'C:\',
}
);
void main() {
MockProcessManager mockProcessManager;
MockProcess mockProcess;
MockPlatform windowsPlatform;
MockPlatform notWindowsPlatform;
MockVisualStudio mockVisualStudio;
const String solutionPath = r'C:\windows\Runner.sln';
const String visualStudioPath = r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community';
const String vcvarsPath = visualStudioPath + r'\VC\Auxiliary\Build\vcvars64.bat';
setUpAll(() {
Cache.disableLocking();
@ -40,9 +52,6 @@ void main() {
setUp(() {
mockProcessManager = MockProcessManager();
mockProcess = MockProcess();
windowsPlatform = MockPlatform()
..environment['PROGRAMFILES(X86)'] = r'C:\Program Files (x86)\';
notWindowsPlatform = MockPlatform();
mockVisualStudio = MockVisualStudio();
when(mockProcess.exitCode).thenAnswer((Invocation invocation) async {
return 0;
@ -53,8 +62,6 @@ void main() {
when(mockProcess.stdout).thenAnswer((Invocation invocation) {
return Stream<List<int>>.fromIterable(<List<int>>[utf8.encode('STDOUT STUFF')]);
});
when(windowsPlatform.isWindows).thenReturn(true);
when(notWindowsPlatform.isWindows).thenReturn(false);
});
// Creates the mock files necessary to look like a Flutter project.
@ -71,55 +78,58 @@ void main() {
}
testUsingContext('Windows build fails when there is no vcvars64.bat', () async {
final BuildCommand command = BuildCommand();
final BuildWindowsCommand command = BuildWindowsCommand()
..visualStudioOverride = mockVisualStudio;
applyMocksToCommand(command);
setUpMockProjectFilesForBuild();
expect(createTestCommandRunner(command).run(
const <String>['build', 'windows']
const <String>['windows']
), throwsToolExit());
}, overrides: <Type, Generator>{
Platform: () => windowsPlatform,
FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
ProcessManager: () => FakeProcessManager.any(),
VisualStudio: () => mockVisualStudio,
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
});
testUsingContext('Windows build fails when there is no windows project', () async {
final BuildCommand command = BuildCommand();
final BuildWindowsCommand command = BuildWindowsCommand()
..visualStudioOverride = mockVisualStudio;
applyMocksToCommand(command);
setUpMockCoreProjectFiles();
when(mockVisualStudio.vcvarsPath).thenReturn(vcvarsPath);
expect(createTestCommandRunner(command).run(
const <String>['build', 'windows']
const <String>['windows']
), throwsToolExit(message: 'No Windows desktop project configured'));
}, overrides: <Type, Generator>{
Platform: () => windowsPlatform,
FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
ProcessManager: () => FakeProcessManager.any(),
VisualStudio: () => mockVisualStudio,
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
});
testUsingContext('Windows build fails on non windows platform', () async {
final BuildCommand command = BuildCommand();
final BuildWindowsCommand command = BuildWindowsCommand()
..visualStudioOverride = mockVisualStudio;
applyMocksToCommand(command);
setUpMockProjectFilesForBuild();
when(mockVisualStudio.vcvarsPath).thenReturn(vcvarsPath);
expect(createTestCommandRunner(command).run(
const <String>['build', 'windows']
const <String>['windows']
), throwsToolExit());
}, overrides: <Type, Generator>{
Platform: () => notWindowsPlatform,
FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
ProcessManager: () => FakeProcessManager.any(),
VisualStudio: () => mockVisualStudio,
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
});
testUsingContext('Windows build does not spew stdout to status logger', () async {
final BuildCommand command = BuildCommand();
final BuildWindowsCommand command = BuildWindowsCommand()
..visualStudioOverride = mockVisualStudio;
applyMocksToCommand(command);
setUpMockProjectFilesForBuild();
when(mockVisualStudio.vcvarsPath).thenReturn(vcvarsPath);
@ -134,7 +144,7 @@ void main() {
});
await createTestCommandRunner(command).run(
const <String>['build', 'windows']
const <String>['windows']
);
expect(testLogger.statusText, isNot(contains('STDOUT STUFF')));
expect(testLogger.traceText, contains('STDOUT STUFF'));
@ -142,12 +152,12 @@ void main() {
FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
ProcessManager: () => mockProcessManager,
Platform: () => windowsPlatform,
VisualStudio: () => mockVisualStudio,
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
});
testUsingContext('Windows build invokes msbuild and writes generated files', () async {
final BuildCommand command = BuildCommand();
final BuildWindowsCommand command = BuildWindowsCommand()
..visualStudioOverride = mockVisualStudio;
applyMocksToCommand(command);
setUpMockProjectFilesForBuild();
when(mockVisualStudio.vcvarsPath).thenReturn(vcvarsPath);
@ -162,7 +172,7 @@ void main() {
});
await createTestCommandRunner(command).run(
const <String>['build', 'windows']
const <String>['windows']
);
// Spot-check important elements from the properties file.
@ -176,12 +186,12 @@ void main() {
FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
ProcessManager: () => mockProcessManager,
Platform: () => windowsPlatform,
VisualStudio: () => mockVisualStudio,
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
});
testUsingContext('Release build prints an under-construction warning', () async {
final BuildCommand command = BuildCommand();
final BuildWindowsCommand command = BuildWindowsCommand()
..visualStudioOverride = mockVisualStudio;
applyMocksToCommand(command);
setUpMockProjectFilesForBuild();
when(mockVisualStudio.vcvarsPath).thenReturn(vcvarsPath);
@ -196,7 +206,7 @@ void main() {
});
await createTestCommandRunner(command).run(
const <String>['build', 'windows']
const <String>['windows']
);
expect(testLogger.statusText, contains('🚧'));
@ -204,35 +214,24 @@ void main() {
FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
ProcessManager: () => mockProcessManager,
Platform: () => windowsPlatform,
VisualStudio: () => mockVisualStudio,
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
});
testUsingContext('hidden when not enabled on Windows host', () {
when(globals.platform.isWindows).thenReturn(true);
expect(BuildWindowsCommand().hidden, true);
}, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: false),
Platform: () => MockPlatform(),
Platform: () => windowsPlatform,
});
testUsingContext('Not hidden when enabled and on Windows host', () {
when(globals.platform.isWindows).thenReturn(true);
expect(BuildWindowsCommand().hidden, false);
}, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
Platform: () => MockPlatform(),
Platform: () => windowsPlatform,
});
}
class MockProcessManager extends Mock implements ProcessManager {}
class MockProcess extends Mock implements Process {}
class MockPlatform extends Mock implements Platform {
@override
Map<String, String> environment = <String, String>{
'FLUTTER_ROOT': r'C:\',
};
}
class MockVisualStudio extends Mock implements VisualStudio {}

View file

@ -2,16 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/base/user_messages.dart' hide userMessages;
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/windows/visual_studio.dart';
import 'package:flutter_tools/src/windows/visual_studio_validator.dart';
import 'package:mockito/mockito.dart';
import '../../src/common.dart';
import '../../src/context.dart';
class MockVisualStudio extends Mock implements VisualStudio {}
final UserMessages userMessages = UserMessages();
void main() {
group('Visual Studio validation', () {
@ -62,111 +61,131 @@ void main() {
when(mockVisualStudio.hasNecessaryComponents).thenReturn(false);
}
testUsingContext('Emits a message when Visual Studio is a pre-release version', () async {
testWithoutContext('Emits a message when Visual Studio is a pre-release version', () async {
final VisualStudioValidator validator = VisualStudioValidator(
userMessages: userMessages,
visualStudio: mockVisualStudio,
);
_configureMockVisualStudioAsInstalled();
when(visualStudio.isPrerelease).thenReturn(true);
when(mockVisualStudio.isPrerelease).thenReturn(true);
const VisualStudioValidator validator = VisualStudioValidator();
final ValidationResult result = await validator.validate();
final ValidationMessage expectedMessage = ValidationMessage(userMessages.visualStudioIsPrerelease);
expect(result.messages.contains(expectedMessage), true);
}, overrides: <Type, Generator>{
VisualStudio: () => mockVisualStudio,
});
testUsingContext('Emits a partial status when Visual Studio installation is incomplete', () async {
testWithoutContext('Emits a partial status when Visual Studio installation is incomplete', () async {
final VisualStudioValidator validator = VisualStudioValidator(
userMessages: userMessages,
visualStudio: mockVisualStudio,
);
_configureMockVisualStudioAsInstalled();
when(visualStudio.isComplete).thenReturn(false);
when(mockVisualStudio.isComplete).thenReturn(false);
const VisualStudioValidator validator = VisualStudioValidator();
final ValidationResult result = await validator.validate();
final ValidationMessage expectedMessage = ValidationMessage.error(userMessages.visualStudioIsIncomplete);
expect(result.messages.contains(expectedMessage), true);
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
VisualStudio: () => mockVisualStudio,
});
testUsingContext('Emits a partial status when Visual Studio installation needs rebooting', () async {
testWithoutContext('Emits a partial status when Visual Studio installation needs rebooting', () async {
final VisualStudioValidator validator = VisualStudioValidator(
userMessages: userMessages,
visualStudio: mockVisualStudio,
);
_configureMockVisualStudioAsInstalled();
when(visualStudio.isRebootRequired).thenReturn(true);
when(mockVisualStudio.isRebootRequired).thenReturn(true);
const VisualStudioValidator validator = VisualStudioValidator();
final ValidationResult result = await validator.validate();
final ValidationMessage expectedMessage = ValidationMessage.error(userMessages.visualStudioRebootRequired);
expect(result.messages.contains(expectedMessage), true);
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
VisualStudio: () => mockVisualStudio,
});
testUsingContext('Emits a partial status when Visual Studio installation is not launchable', () async {
testWithoutContext('Emits a partial status when Visual Studio installation is not launchable', () async {
final VisualStudioValidator validator = VisualStudioValidator(
userMessages: userMessages,
visualStudio: mockVisualStudio,
);
_configureMockVisualStudioAsInstalled();
when(visualStudio.isLaunchable).thenReturn(false);
when(mockVisualStudio.isLaunchable).thenReturn(false);
const VisualStudioValidator validator = VisualStudioValidator();
final ValidationResult result = await validator.validate();
final ValidationMessage expectedMessage = ValidationMessage.error(userMessages.visualStudioNotLaunchable);
expect(result.messages.contains(expectedMessage), true);
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
VisualStudio: () => mockVisualStudio,
});
testUsingContext('Emits partial status when Visual Studio is installed but too old', () async {
testWithoutContext('Emits partial status when Visual Studio is installed but too old', () async {
final VisualStudioValidator validator = VisualStudioValidator(
userMessages: userMessages,
visualStudio: mockVisualStudio,
);
_configureMockVisualStudioAsTooOld();
const VisualStudioValidator validator = VisualStudioValidator();
final ValidationResult result = await validator.validate();
final ValidationMessage expectedMessage = ValidationMessage.error(
userMessages.visualStudioTooOld(
visualStudio.minimumVersionDescription,
visualStudio.workloadDescription,
visualStudio.necessaryComponentDescriptions(),
mockVisualStudio.minimumVersionDescription,
mockVisualStudio.workloadDescription,
mockVisualStudio.necessaryComponentDescriptions(),
),
);
expect(result.messages.contains(expectedMessage), true);
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
VisualStudio: () => mockVisualStudio,
});
testUsingContext('Emits partial status when Visual Studio is installed without necessary components', () async {
testWithoutContext('Emits partial status when Visual Studio is installed without necessary components', () async {
final VisualStudioValidator validator = VisualStudioValidator(
userMessages: userMessages,
visualStudio: mockVisualStudio,
);
_configureMockVisualStudioAsInstalled();
when(visualStudio.hasNecessaryComponents).thenReturn(false);
const VisualStudioValidator validator = VisualStudioValidator();
when(mockVisualStudio.hasNecessaryComponents).thenReturn(false);
final ValidationResult result = await validator.validate();
expect(result.type, ValidationType.partial);
}, overrides: <Type, Generator>{
VisualStudio: () => mockVisualStudio,
});
testUsingContext('Emits installed status when Visual Studio is installed with necessary components', () async {
testWithoutContext('Emits installed status when Visual Studio is installed with necessary components', () async {
final VisualStudioValidator validator = VisualStudioValidator(
userMessages: userMessages,
visualStudio: mockVisualStudio,
);
_configureMockVisualStudioAsInstalled();
const VisualStudioValidator validator = VisualStudioValidator();
final ValidationResult result = await validator.validate();
final ValidationMessage expectedDisplayNameMessage = ValidationMessage(
userMessages.visualStudioVersion(visualStudio.displayName, visualStudio.fullVersion));
userMessages.visualStudioVersion(mockVisualStudio.displayName, mockVisualStudio.fullVersion));
expect(result.messages.contains(expectedDisplayNameMessage), true);
expect(result.type, ValidationType.installed);
}, overrides: <Type, Generator>{
VisualStudio: () => mockVisualStudio,
});
testUsingContext('Emits missing status when Visual Studio is not installed', () async {
testWithoutContext('Emits missing status when Visual Studio is not installed', () async {
final VisualStudioValidator validator = VisualStudioValidator(
userMessages: userMessages,
visualStudio: mockVisualStudio,
);
_configureMockVisualStudioAsNotInstalled();
const VisualStudioValidator validator = VisualStudioValidator();
final ValidationResult result = await validator.validate();
final ValidationMessage expectedMessage = ValidationMessage.error(
userMessages.visualStudioMissing(
visualStudio.workloadDescription,
visualStudio.necessaryComponentDescriptions(),
mockVisualStudio.workloadDescription,
mockVisualStudio.necessaryComponentDescriptions(),
),
);
expect(result.messages.contains(expectedMessage), true);
expect(result.type, ValidationType.missing);
}, overrides: <Type, Generator>{
VisualStudio: () => mockVisualStudio,
});
});
}
class MockVisualStudio extends Mock implements VisualStudio {}