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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example/tool_base_test_example.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:test/test.dart';
import 'package:tool_base_test/tool_base_test.dart';

main() {
void main() {
testUsingContext('test in context', () {
expect(true, isTrue);
});
Expand Down
67 changes: 11 additions & 56 deletions lib/src/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,69 +4,22 @@

import 'dart:async';

//import 'package:args/command_runner.dart';
import 'package:tool_base/src/base/common.dart';
import 'package:tool_base/src/base/file_system.dart';
import 'package:tool_base/src/base/platform.dart';
import 'package:tool_base/src/base/process.dart';
//import 'package:tool_base/src/commands/create.dart';
//import 'package:tool_base/src/runner/flutter_command.dart';
//import 'package:tool_base/src/runner/flutter_command_runner.dart';
import 'package:test_api/test_api.dart' as test_package show TypeMatcher;
import 'package:test_api/test_api.dart' hide TypeMatcher, isInstanceOf;
//import 'package:args/command_runner.dart';
import 'package:tool_base/src/base/common.dart';
import 'package:tool_base/src/base/file_system.dart';
import 'package:tool_base/src/base/process.dart';

export 'package:test_core/test_core.dart' hide TypeMatcher, isInstanceOf; // Defines a 'package:test' shim.

/// A matcher that compares the type of the actual value to the type argument T.
// TODO(ianh): Remove this once https://github.com/dart-lang/matcher/issues/98 is fixed
Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();

void tryToDelete(Directory directory) {
// This should not be necessary, but it turns out that
// on Windows it's common for deletions to fail due to
// bogus (we think) "access denied" errors.
try {
directory.deleteSync(recursive: true);
} on FileSystemException catch (error) {
print('Failed to delete ${directory.path}: $error');
}
}

/// Gets the path to the root of the Flutter repository.
///
/// This will first look for a `FLUTTER_ROOT` environment variable. If the
/// environment variable is set, it will be returned. Otherwise, this will
/// deduce the path from `platform.script`.
String getFlutterRoot() {
if (platform.environment.containsKey('FLUTTER_ROOT'))
return platform.environment['FLUTTER_ROOT'];

Error invalidScript() => StateError('Invalid script: ${platform.script}');

Uri scriptUri;
switch (platform.script.scheme) {
case 'file':
scriptUri = platform.script;
break;
case 'data':
final RegExp flutterTools = RegExp(r'(file://[^"]*[/\\]flutter_tools[/\\][^"]+\.dart)', multiLine: true);
final Match match = flutterTools.firstMatch(Uri.decodeFull(platform.script.path));
if (match == null)
throw invalidScript();
scriptUri = Uri.parse(match.group(1));
break;
default:
throw invalidScript();
}

final List<String> parts = fs.path.split(fs.path.fromUri(scriptUri));
final int toolsIndex = parts.indexOf('flutter_tools');
if (toolsIndex == -1)
throw invalidScript();
final String toolsPath = fs.path.joinAll(parts.sublist(0, toolsIndex + 1));
return fs.path.normalize(fs.path.join(toolsPath, '..', '..'));
}

//CommandRunner<void> createTestCommandRunner([ FlutterCommand command ]) {
// final FlutterCommandRunner runner = FlutterCommandRunner();
// if (command != null)
Expand All @@ -80,17 +33,19 @@ void updateFileModificationTime(
DateTime baseTime,
int seconds,
) {
final DateTime modificationTime = baseTime.add(Duration(seconds: seconds));
final modificationTime = baseTime.add(Duration(seconds: seconds));
fs.file(path).setLastModifiedSync(modificationTime);
}

/// Matcher for functions that throw [ToolExit].
Matcher throwsToolExit({ int exitCode, Pattern message }) {
Matcher matcher = isToolExit;
if (exitCode != null)
Matcher throwsToolExit({ int? exitCode, Pattern? message }) {
var matcher = isToolExit;
if (exitCode != null) {
matcher = allOf(matcher, (ToolExit e) => e.exitCode == exitCode);
if (message != null)
}
if (message != null) {
matcher = allOf(matcher, (ToolExit e) => e.message.contains(message));
}
return throwsA(matcher);
}

Expand Down
103 changes: 27 additions & 76 deletions lib/src/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import 'dart:async';
import 'dart:io' as io;

//import 'package:tool_base/src/android/android_workflow.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:tool_base/src/base/config.dart';
import 'package:tool_base/src/base/context.dart';
import 'package:tool_base/src/base/file_system.dart';
Expand All @@ -15,25 +16,16 @@ import 'package:tool_base/src/base/os.dart';
import 'package:tool_base/src/base/terminal.dart';
import 'package:tool_base/src/base/time.dart';
import 'package:tool_base/src/cache.dart';
//import 'package:tool_base/src/context_runner.dart';
//import 'package:tool_base/src/device.dart';
//import 'package:tool_base/src/doctor.dart';
//import 'package:tool_base/src/ios/plist_parser.dart';
//import 'package:tool_base/src/ios/simulators.dart';
//import 'package:tool_base/src/ios/xcodeproj.dart';
//import 'package:tool_base/src/project.dart';
import 'package:reporting/reporting.dart';
//import 'package:tool_base/src/version.dart';
import 'package:meta/meta.dart';
import 'package:mockito/mockito.dart';
import 'package:tool_base/src/flutter.dart';
import 'package:tool_base_test/src/mocks.dart';

import 'common.dart';
import 'context_runner.dart';

export 'package:tool_base/src/base/context.dart' show Generator;

/// Return the test logger. This assumes that the current Logger is a BufferLogger.
BufferLogger get testLogger => context.get<Logger>();
BufferLogger get testLogger => context.get<Logger>()! as BufferLogger;

//FakeDeviceManager get testDeviceManager => context.get<DeviceManager>();
//FakeDoctor get testDoctor => context.get<Doctor>();
Expand All @@ -43,16 +35,16 @@ typedef ContextInitializer = void Function(AppContext testContext);
@isTest
void testUsingContext(
String description,
dynamic testMethod(), {
Timeout timeout,
Map<Type, Generator> overrides = const <Type, Generator>{},
dynamic Function() testMethod, {
Timeout? timeout,
Map<Type, Generator>? overrides = const <Type, Generator>{},
bool initializeFlutterRoot = true,
String testOn,
bool skip, // should default to `false`, but https://github.com/dart-lang/test/issues/545 doesn't allow this
String? testOn,
bool? skip, // should default to `false`, but https://github.com/dart-lang/test/issues/545 doesn't allow this
}) {
// Ensure we don't rely on the default [Config] constructor which will
// leak a sticky $HOME/.flutter_settings behind!
Directory configDir;
Directory? configDir;
tearDown(() {
if (configDir != null) {
tryToDelete(configDir);
Expand All @@ -61,8 +53,8 @@ void testUsingContext(
});
Config buildConfig(FileSystem fs) {
configDir = fs.systemTempDirectory.createTempSync('flutter_config_dir_test.');
final File settingsFile = fs.file(
fs.path.join(configDir.path, '.flutter_settings')
final settingsFile = fs.file(
fs.path.join(configDir!.path, '.flutter_settings')
);
return Config(settingsFile);
}
Expand All @@ -86,14 +78,13 @@ void testUsingContext(
Logger: () => BufferLogger(),
OperatingSystemUtils: () => FakeOperatingSystemUtils(),
// SimControl: () => MockSimControl(),
Usage: () => FakeUsage(),
// XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(),
FileSystem: () => const LocalFileSystemBlockingSetCurrentDirectory(),
TimeoutConfiguration: () => const TimeoutConfiguration(),
// PlistParser: () => FakePlistParser(),
},
body: () {
final String flutterRoot = getFlutterRoot();
final flutterRoot = getFlutterRoot();
return runZoned<Future<dynamic>>(() {
try {
return context.run<dynamic>(
Expand Down Expand Up @@ -128,11 +119,12 @@ void testUsingContext(
}

void _printBufferedErrors(AppContext testContext) {
if (testContext.get<Logger>() is BufferLogger) {
final BufferLogger bufferLogger = testContext.get<Logger>();
if (bufferLogger.errorText.isNotEmpty)
print(bufferLogger.errorText);
bufferLogger.clear();
var logger = testContext.get<Logger>();
if (logger is BufferLogger) {
if (logger.errorText.isNotEmpty) {
print(logger.errorText);
}
logger.clear();
}
}

Expand Down Expand Up @@ -236,31 +228,31 @@ void _printBufferedErrors(AppContext testContext) {

class FakeOperatingSystemUtils implements OperatingSystemUtils {
@override
ProcessResult makeExecutable(File file) => null;
ProcessResult makeExecutable(File file) => FakeProcessResult();

@override
void chmod(FileSystemEntity entity, String mode) { }
void chmod(FileSystemEntity entity, String mode) {}

@override
File which(String execName) => null;
File which(String execName) => throw 'Not implemented';

@override
List<File> whichAll(String execName) => <File>[];

@override
File makePipe(String path) => null;
File makePipe(String path) => throw 'Not implemented';

@override
void zip(Directory data, File zipFile) { }
void zip(Directory data, File zipFile) {}

@override
void unzip(File file, Directory targetDirectory) { }
void unzip(File file, Directory targetDirectory) {}

@override
bool verifyZip(File file) => true;

@override
void unpack(File gzippedTarFile, Directory targetDirectory) { }
void unpack(File gzippedTarFile, Directory targetDirectory) {}

@override
bool verifyGzip(File gzippedFile) => true;
Expand All @@ -277,47 +269,6 @@ class FakeOperatingSystemUtils implements OperatingSystemUtils {

//class MockIOSSimulatorUtils extends Mock implements IOSSimulatorUtils {}

class FakeUsage implements Usage {
@override
bool get isFirstRun => false;

@override
bool get suppressAnalytics => false;

@override
set suppressAnalytics(bool value) { }

@override
bool get enabled => true;

@override
set enabled(bool value) { }

@override
String get clientId => '00000000-0000-4000-0000-000000000000';

@override
void sendCommand(String command, { Map<String, String> parameters }) { }

@override
void sendEvent(String category, String parameter, { Map<String, String> parameters }) { }

@override
void sendTiming(String category, String variableName, Duration duration, { String label }) { }

@override
void sendException(dynamic exception) { }

@override
Stream<Map<String, dynamic>> get onSend => null;

@override
Future<void> ensureAnalyticsSent() => Future<void>.value();

@override
void printWelcome() { }
}

//class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter {
// @override
// bool get isInstalled => true;
Expand Down
6 changes: 2 additions & 4 deletions lib/src/context_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,11 @@ import 'dart:async';
//import 'windows/visual_studio_validator.dart';
//import 'windows/windows_workflow.dart';

import 'package:process/process.dart';
import 'package:reporting/reporting.dart';
import 'package:tool_base/tool_base.dart';

Future<T> runInContext<T>(
FutureOr<T> runner(), {
Map<Type, Generator> overrides,
FutureOr<T> Function() runner, {
Map<Type, Generator>? overrides,
}) async {
return await context.run<T>(
name: 'global fallbacks',
Expand Down
Loading