flutter/packages/flutter_tools/test/commands/doctor_test.dart
Danny Tuppeny 8ccc9a45c9 Add flutter doctor support for VS Code (#14463)
Looks in default install locations on Mac, Linux and Windows for VS Code. If found, looks in default extension location to see if Dart Code is installed.

If VS Code is not installed, nothing is reported. If VS Code is installed without Dart Code, a warning is shown.
2018-02-07 10:49:54 -08:00

286 lines
12 KiB
Dart

// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/vscode/vscode.dart';
import 'package:flutter_tools/src/vscode/vscode_validator.dart';
import 'package:test/test.dart';
import '../src/context.dart';
void main() {
group('doctor', () {
testUsingContext('intellij validator', () async {
final ValidationResult result = await new IntelliJValidatorTestTarget('Test').validate();
expect(result.type, ValidationType.partial);
expect(result.statusInfo, 'version test.test.test');
expect(result.messages, hasLength(3));
ValidationMessage message = result.messages
.firstWhere((ValidationMessage m) => m.message.startsWith('Dart '));
expect(message.message, 'Dart plugin version 162.2485');
message = result.messages
.firstWhere((ValidationMessage m) => m.message.startsWith('Flutter '));
expect(message.message, contains('Flutter plugin version 0.1.3'));
expect(message.message, contains('recommended minimum version'));
});
testUsingContext('vs code validator when both installed', () async {
final ValidationResult result = await VsCodeValidatorTestTargets.installedWithExtension.validate();
expect(result.type, ValidationType.installed);
expect(result.statusInfo, 'version 1.2.3');
expect(result.messages, hasLength(2));
ValidationMessage message = result.messages
.firstWhere((ValidationMessage m) => m.message.startsWith('VS Code '));
expect(message.message, 'VS Code at ${VsCodeValidatorTestTargets.validInstall}');
message = result.messages
.firstWhere((ValidationMessage m) => m.message.startsWith('Dart Code '));
expect(message.message, 'Dart Code extension version 4.5.6');
});
testUsingContext('vs code validator when extension missing', () async {
final ValidationResult result = await VsCodeValidatorTestTargets.installedWithoutExtension.validate();
expect(result.type, ValidationType.partial);
expect(result.statusInfo, 'version 1.2.3');
expect(result.messages, hasLength(2));
ValidationMessage message = result.messages
.firstWhere((ValidationMessage m) => m.message.startsWith('VS Code '));
expect(message.message, 'VS Code at ${VsCodeValidatorTestTargets.validInstall}');
message = result.messages
.firstWhere((ValidationMessage m) => m.message.startsWith('Dart Code '));
expect(message.message, startsWith('Dart Code extension not installed'));
});
});
group('doctor with fake validators', () {
testUsingContext('validate non-verbose output format for run without issues', () async {
expect(await new FakeQuietDoctor().diagnose(verbose: false), isTrue);
expect(testLogger.statusText, equals(
'Doctor summary (to see all details, run flutter doctor -v):\n'
'[✓] Passing Validator (with statusInfo)\n'
'[✓] Another Passing Validator (with statusInfo)\n'
'[✓] Validators are fun (with statusInfo)\n'
'[✓] Four score and seven validators ago (with statusInfo)\n'
'\n'
'• No issues found!\n'
));
});
testUsingContext('validate non-verbose output format when only one category fails', () async {
expect(await new FakeSinglePassingDoctor().diagnose(verbose: false), isTrue);
expect(testLogger.statusText, equals(
'Doctor summary (to see all details, run flutter doctor -v):\n'
'[!] Partial Validator with only a Hint\n'
' ! There is a hint here\n'
'\n'
'! Doctor found issues in 1 category.\n'
));
});
testUsingContext('validate non-verbose output format for a passing run', () async {
expect(await new FakePassingDoctor().diagnose(verbose: false), isTrue);
expect(testLogger.statusText, equals(
'Doctor summary (to see all details, run flutter doctor -v):\n'
'[✓] Passing Validator (with statusInfo)\n'
'[!] Partial Validator with only a Hint\n'
' ! There is a hint here\n'
'[!] Partial Validator with Errors\n'
' ✗ A error message indicating partial installation\n'
' ! Maybe a hint will help the user\n'
'[✓] Another Passing Validator (with statusInfo)\n'
'\n'
'! Doctor found issues in 2 categories.\n'
));
});
testUsingContext('validate non-verbose output format', () async {
expect(await new FakeDoctor().diagnose(verbose: false), isFalse);
expect(testLogger.statusText, equals(
'Doctor summary (to see all details, run flutter doctor -v):\n'
'[✓] Passing Validator (with statusInfo)\n'
'[✗] Missing Validator\n'
' ✗ A useful error message\n'
' ! A hint message\n'
'[!] Partial Validator with only a Hint\n'
' ! There is a hint here\n'
'[!] Partial Validator with Errors\n'
' ✗ A error message indicating partial installation\n'
' ! Maybe a hint will help the user\n'
'\n'
'! Doctor found issues in 3 categories.\n'
));
});
testUsingContext('validate verbose output format', () async {
expect(await new FakeDoctor().diagnose(verbose: true), isFalse);
expect(testLogger.statusText, equals(
'[✓] Passing Validator (with statusInfo)\n'
' • A helpful message\n'
' • A second, somewhat longer helpful message\n'
'\n'
'[✗] Missing Validator\n'
' ✗ A useful error message\n'
' • A message that is not an error\n'
' ! A hint message\n'
'\n'
'[!] Partial Validator with only a Hint\n'
' ! There is a hint here\n'
' • But there is no error\n'
'\n'
'[!] Partial Validator with Errors\n'
' ✗ A error message indicating partial installation\n'
' ! Maybe a hint will help the user\n'
' • An extra message with some verbose details\n'
'\n'
'! Doctor found issues in 3 categories.\n'
));
});
});
}
class IntelliJValidatorTestTarget extends IntelliJValidator {
IntelliJValidatorTestTarget(String title) : super(title);
@override
String get pluginsPath => fs.path.join('test', 'data', 'intellij', 'plugins');
@override
String get version => 'test.test.test';
}
class PassingValidator extends DoctorValidator {
PassingValidator(String name) : super(name);
@override
Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[];
messages.add(new ValidationMessage('A helpful message'));
messages.add(new ValidationMessage('A second, somewhat longer helpful message'));
return new ValidationResult(ValidationType.installed, messages, statusInfo: 'with statusInfo');
}
}
class MissingValidator extends DoctorValidator {
MissingValidator(): super('Missing Validator');
@override
Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[];
messages.add(new ValidationMessage.error('A useful error message'));
messages.add(new ValidationMessage('A message that is not an error'));
messages.add(new ValidationMessage.hint('A hint message'));
return new ValidationResult(ValidationType.missing, messages);
}
}
class PartialValidatorWithErrors extends DoctorValidator {
PartialValidatorWithErrors() : super('Partial Validator with Errors');
@override
Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[];
messages.add(new ValidationMessage.error('A error message indicating partial installation'));
messages.add(new ValidationMessage.hint('Maybe a hint will help the user'));
messages.add(new ValidationMessage('An extra message with some verbose details'));
return new ValidationResult(ValidationType.partial, messages);
}
}
class PartialValidatorWithHintsOnly extends DoctorValidator {
PartialValidatorWithHintsOnly() : super('Partial Validator with only a Hint');
@override
Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[];
messages.add(new ValidationMessage.hint('There is a hint here'));
messages.add(new ValidationMessage('But there is no error'));
return new ValidationResult(ValidationType.partial, messages);
}
}
/// A doctor that fails with a missing [ValidationResult].
class FakeDoctor extends Doctor {
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
if (_validators == null) {
_validators = <DoctorValidator>[];
_validators.add(new PassingValidator('Passing Validator'));
_validators.add(new MissingValidator());
_validators.add(new PartialValidatorWithHintsOnly());
_validators.add(new PartialValidatorWithErrors());
}
return _validators;
}
}
/// A doctor that should pass, but still has issues in some categories.
class FakePassingDoctor extends Doctor {
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
if (_validators == null) {
_validators = <DoctorValidator>[];
_validators.add(new PassingValidator('Passing Validator'));
_validators.add(new PartialValidatorWithHintsOnly());
_validators.add(new PartialValidatorWithErrors());
_validators.add(new PassingValidator('Another Passing Validator'));
}
return _validators;
}
}
/// A doctor that should pass, but still has 1 issue to test the singular of
/// categories.
class FakeSinglePassingDoctor extends Doctor {
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
if (_validators == null) {
_validators = <DoctorValidator>[];
_validators.add(new PartialValidatorWithHintsOnly());
}
return _validators;
}
}
/// A doctor that passes and has no issues anywhere.
class FakeQuietDoctor extends Doctor {
List<DoctorValidator> _validators;
@override
List<DoctorValidator> get validators {
if (_validators == null) {
_validators = <DoctorValidator>[];
_validators.add(new PassingValidator('Passing Validator'));
_validators.add(new PassingValidator('Another Passing Validator'));
_validators.add(new PassingValidator('Validators are fun'));
_validators.add(new PassingValidator('Four score and seven validators ago'));
}
return _validators;
}
}
class VsCodeValidatorTestTargets extends VsCodeValidator {
static final String validInstall = fs.path.join('test', 'data', 'vscode', 'application');
static final String validExtensions = fs.path.join('test', 'data', 'vscode', 'extensions');
static final String missingExtensions = fs.path.join('test', 'data', 'vscode', 'notExtensions');
VsCodeValidatorTestTargets._(String installDirectory, String extensionDirectory)
: super(new VsCode.fromDirectory(installDirectory, extensionDirectory));
static VsCodeValidatorTestTargets get installedWithExtension =>
new VsCodeValidatorTestTargets._(validInstall, validExtensions);
static VsCodeValidatorTestTargets get installedWithoutExtension =>
new VsCodeValidatorTestTargets._(validInstall, missingExtensions);
}