blob: aa1299ac8cf8ea3a03a06fa53ca7cd21d7eb6017 [file] [log] [blame]
// Copyright 2014 The Flutter 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:convert';
import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/android/android_studio.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/config.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:mockito/mockito.dart';
import '../../src/common.dart';
import '../../src/context.dart';
void main() {
MockAndroidStudio mockAndroidStudio;
MockAndroidSdk mockAndroidSdk;
MockFlutterVersion mockFlutterVersion;
MockUsage mockUsage;
setUpAll(() {
Cache.disableLocking();
});
setUp(() {
mockAndroidStudio = MockAndroidStudio();
mockAndroidSdk = MockAndroidSdk();
mockFlutterVersion = MockFlutterVersion();
mockUsage = MockUsage();
});
void verifyNoAnalytics() {
verifyNever(mockUsage.sendCommand(
any,
parameters: anyNamed('parameters'),
));
verifyNever(mockUsage.sendEvent(
any,
any,
label: anyNamed('label'),
value: anyNamed('value'),
parameters: anyNamed('parameters'),
));
verifyNever(mockUsage.sendTiming(
any,
any,
any,
label: anyNamed('label'),
));
}
group('config', () {
testUsingContext('machine flag', () async {
final ConfigCommand command = ConfigCommand();
await command.handleMachine();
expect(testLogger.statusText, isNotEmpty);
final dynamic jsonObject = json.decode(testLogger.statusText);
expect(jsonObject, isMap);
expect(jsonObject.containsKey('android-studio-dir'), true);
expect(jsonObject['android-studio-dir'], isNotNull);
expect(jsonObject.containsKey('android-sdk'), true);
expect(jsonObject['android-sdk'], isNotNull);
verifyNoAnalytics();
}, overrides: <Type, Generator>{
AndroidStudio: () => mockAndroidStudio,
AndroidSdk: () => mockAndroidSdk,
Usage: () => mockUsage,
});
testUsingContext('Can set build-dir', () async {
final ConfigCommand configCommand = ConfigCommand();
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
await commandRunner.run(<String>[
'config',
'--build-dir=foo',
]);
expect(getBuildDirectory(), 'foo');
verifyNoAnalytics();
}, overrides: <Type, Generator>{
Usage: () => mockUsage,
});
testUsingContext('throws error on absolute path to build-dir', () async {
final ConfigCommand configCommand = ConfigCommand();
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
expect(() => commandRunner.run(<String>[
'config',
'--build-dir=/foo',
]), throwsToolExit());
verifyNoAnalytics();
}, overrides: <Type, Generator>{
Usage: () => mockUsage,
});
testUsingContext('allows setting and removing feature flags', () async {
final ConfigCommand configCommand = ConfigCommand();
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
await commandRunner.run(<String>[
'config',
'--enable-web',
'--enable-linux-desktop',
'--enable-windows-desktop',
'--enable-macos-desktop',
]);
expect(globals.config.getValue('enable-web'), true);
expect(globals.config.getValue('enable-linux-desktop'), true);
expect(globals.config.getValue('enable-windows-desktop'), true);
expect(globals.config.getValue('enable-macos-desktop'), true);
await commandRunner.run(<String>[
'config', '--clear-features',
]);
expect(globals.config.getValue('enable-web'), null);
expect(globals.config.getValue('enable-linux-desktop'), null);
expect(globals.config.getValue('enable-windows-desktop'), null);
expect(globals.config.getValue('enable-macos-desktop'), null);
await commandRunner.run(<String>[
'config',
'--no-enable-web',
'--no-enable-linux-desktop',
'--no-enable-windows-desktop',
'--no-enable-macos-desktop',
]);
expect(globals.config.getValue('enable-web'), false);
expect(globals.config.getValue('enable-linux-desktop'), false);
expect(globals.config.getValue('enable-windows-desktop'), false);
expect(globals.config.getValue('enable-macos-desktop'), false);
verifyNoAnalytics();
}, overrides: <Type, Generator>{
AndroidStudio: () => mockAndroidStudio,
AndroidSdk: () => mockAndroidSdk,
Usage: () => mockUsage,
});
testUsingContext('warns the user to reload IDE', () async {
final ConfigCommand configCommand = ConfigCommand();
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
await commandRunner.run(<String>[
'config',
'--enable-web'
]);
expect(
testLogger.statusText,
containsIgnoringWhitespace('You may need to restart any open editors'),
);
}, overrides: <Type, Generator>{
Usage: () => mockUsage,
});
testUsingContext('displays which config settings are available on stable', () async {
when(mockFlutterVersion.channel).thenReturn('stable');
final ConfigCommand configCommand = ConfigCommand();
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
await commandRunner.run(<String>[
'config',
'--enable-web',
'--enable-linux-desktop',
'--enable-windows-desktop',
'--enable-macos-desktop',
]);
await commandRunner.run(<String>[
'config',
]);
expect(
testLogger.statusText,
containsIgnoringWhitespace('enable-web: true (Unavailable)'),
);
expect(
testLogger.statusText,
containsIgnoringWhitespace('enable-linux-desktop: true (Unavailable)'),
);
expect(
testLogger.statusText,
containsIgnoringWhitespace('enable-windows-desktop: true (Unavailable)'),
);
expect(
testLogger.statusText,
containsIgnoringWhitespace('enable-macos-desktop: true (Unavailable)'),
);
verifyNoAnalytics();
}, overrides: <Type, Generator>{
AndroidStudio: () => mockAndroidStudio,
AndroidSdk: () => mockAndroidSdk,
FlutterVersion: () => mockFlutterVersion,
Usage: () => mockUsage,
});
testUsingContext('no-analytics flag flips usage flag and sends event', () async {
final ConfigCommand configCommand = ConfigCommand();
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
when(mockUsage.sendEvent(
captureAny,
captureAny,
label: captureAnyNamed('label'),
value: anyNamed('value'),
parameters: anyNamed('parameters'),
)).thenAnswer((Invocation invocation) async {
expect(mockUsage.enabled, true);
expect(invocation.positionalArguments, <String>['analytics', 'enabled']);
expect(invocation.namedArguments[#label], 'false');
});
await commandRunner.run(<String>[
'config',
'--no-analytics',
]);
expect(mockUsage.enabled, false);
// Verify that we flushed the analytics queue.
verify(mockUsage.ensureAnalyticsSent());
// Verify that we only send the analytics disable event, and no other
// info.
verifyNever(mockUsage.sendCommand(
any,
parameters: anyNamed('parameters'),
));
verifyNever(mockUsage.sendTiming(
any,
any,
any,
label: anyNamed('label'),
));
}, overrides: <Type, Generator>{
Usage: () => mockUsage,
});
testUsingContext('analytics flag flips usage flag and sends event', () async {
final ConfigCommand configCommand = ConfigCommand();
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
await commandRunner.run(<String>[
'config',
'--analytics',
]);
expect(mockUsage.enabled, true);
// Verify that we only send the analytics disable event, and no other
// info.
verifyNever(mockUsage.sendCommand(
any,
parameters: anyNamed('parameters'),
));
verifyNever(mockUsage.sendTiming(
any,
any,
any,
label: anyNamed('label'),
));
expect(verify(mockUsage.sendEvent(
captureAny,
captureAny,
label: captureAnyNamed('label'),
value: anyNamed('value'),
parameters: anyNamed('parameters'),
)).captured,
<dynamic>['analytics', 'enabled', 'true'],
);
}, overrides: <Type, Generator>{
Usage: () => mockUsage,
});
testUsingContext('analytics reported disabled when suppressed', () async {
final ConfigCommand configCommand = ConfigCommand();
final CommandRunner<void> commandRunner = createTestCommandRunner(configCommand);
mockUsage.suppressAnalytics = true;
await commandRunner.run(<String>[
'config',
]);
expect(
testLogger.statusText,
containsIgnoringWhitespace('Analytics reporting is currently disabled'),
);
}, overrides: <Type, Generator>{
Usage: () => mockUsage,
});
});
}
class MockAndroidStudio extends Mock implements AndroidStudio, Comparable<AndroidStudio> {
@override
String get directory => 'path/to/android/stdio';
}
class MockAndroidSdk extends Mock implements AndroidSdk {
@override
String get directory => 'path/to/android/sdk';
}
class MockFlutterVersion extends Mock implements FlutterVersion {}
class MockUsage extends Mock implements Usage {
@override
bool enabled = true;
@override
bool suppressAnalytics = false;
}