blob: 005a8c0a7d29a1c63bf9b49dacb942a9e103bf1f [file] [log] [blame]
// Copyright 2016 The Vanadium 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 'dart:io';
import '../runner/mdtest_command.dart';
import '../globals.dart';
import '../util.dart';
const String specTemplate =
'''
{
"devices": {
"{nickname}": {
"device-id": "{optional}",
"model-name": "{optional}",
"os-version": "{optional}",
"api-level": "{optional}",
"screen-size": "{optional}",
"app-root": "{required}",
"app-path": "{required}"
},
"{nickname}": {
"app-root": "{required}",
"app-path": "{required}"
}
}
}
''';
const String specGuide =
'Everything in the curly braces can be replaced with your own value.\n'
'"device-id", "model-name", "os-version", "api-level" and "screem-size" '
'are optional.\n'
'"app-root" and "app-path" are required.\n'
'An example spec would be\n'
'''
{
"devices": {
"Alice": {
"device-id": "HT4CWJT03204",
"model-name": "Nexus 9",
"os-version": "6.0",
"api-level": "23",
"screen-size": "xlarge",
"app-root": "/path/to/flutter-app",
"app-path": "/path/to/main.dart"
},
"Bob": {
...
}
...
}
}
'''
'"nickname" will be used as the identifier of the device that matches '
'the corresponding properties in the test spec. You will use nicknames '
'to establish connections between flutter drivers and devices in your '
'test scripts.\n'
'"device-id" is the unique id of your device.\n'
'"model-name" is the device model name.\n'
'"os-version" is the operating system version of your device.\n'
'"api-level" is Android specific and refers to the API level of your device.\n'
'"screen-size" is the screen diagonal size measured in inches. The candidate '
'values are "small"(<3.5"), "normal"(>=3.5" && <5"), "large"(>=5" && <8") '
'and "xlarge"(>=8").\n'
'"app-root" is the path of your flutter application directory.\n'
'"app-path" is the path of the instrumented version of your app main function.\n'
;
const String testTemplate =
'''
import 'dart:async';
// add flutter_driver, test, mdtest to your pubspec/yaml
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';
import 'package:mdtest/driver_util.dart';
void main() {
group('Group 1', () {
// Create a flutter driver map that maps each nickname with a flutter driver
DriverMap driverMap;
setUpAll(() async {
driverMap = new DriverMap();
// Other setup functions
// ...
});
tearDownAll(() async {
if (driverMap != null) {
driverMap.closeAll();
}
// Other tear down functions
// ...
});
test('test 1', () async {
// Send tap request to each connected driver
List<FlutterDriver> drivers = await Future.wait(driverMap.values);
await Future.forEach(drivers, (FlutterDriver driver) async {
await driver.tap(find.byValueKey(...));
});
// Get text from each connected driver and compare the result
await Future.forEach(drivers, (FlutterDriver driver) async {
String result = await driver.getText(find.byValueKey(textKey));
expect(result, equals('...'));
});
// An alternative to send tap request to each connected driver
await Future.wait(
drivers.map(
(FlutterDriver driver) => driver.tap(find.byValueKey(buttonKey))
)
);
});
test('test 2', () async {
FlutterDriver driver1 = await driverMap['nickname1'];
FlutterDriver driver2 = await driverMap['nickname2'];
await driver1.tap(find.byValueKey(...));
await driver2.tap(find.byValueKey(...));
String result1 = await driver1.getText(find.byValueKey(...));
expect(result1, equals('...'));
String result2 = await driver2.getText(find.byValueKey(...));
expect(result2, equals('...'));
});
// More tests go here
// ...
});
// More groups go here
// ...
}
''';
const String testGuide =
'mdtest provide a DriverMap class which maps each nickname in the test spec '
'to a flutter driver. Users can get a flutter driver instance by saying `'
'FlutterDriver driver = await driverMap[nickname];` '
'DriverMap will lazy initialize a flutter driver instance the first time '
'you invoke the [] operator.\n'
'Once you get access to a flutter driver, you can use it to automate your '
'flutter app. For more detailed usage, please refer to the generated test '
'template.'
;
class CreateCommand extends MDTestCommand {
@override
final String name = 'create';
@override
final String description = 'create a test spec/script template for the user to fill in';
@override
Future<int> runCore() async {
printInfo('Running "mdtest create command" ...');
String specTemplatePath = argResults['spec-template'];
String testTemplatePath = argResults['test-template'];
if (specTemplatePath == null && testTemplatePath == null) {
printError('You must provide a path for either spec or test template.');
return 1;
}
if (specTemplatePath != null) {
File file = createNewFile('$specTemplatePath');
file.writeAsStringSync(specTemplate);
String absolutePath = normalizePath(Directory.current.path, specTemplatePath);
printInfo('Template test spec written to $absolutePath');
printGuide(specGuide);
}
if (testTemplatePath != null) {
File file = createNewFile('$testTemplatePath');
file.writeAsStringSync(testTemplate);
String absolutePath = normalizePath(Directory.current.path, testTemplatePath);
printInfo('Template test written to $absolutePath');
printGuide(testGuide);
}
return 0;
}
void printGuide(String guide) {
guide.split('\n').forEach((String line) => printInfo(line));
}
CreateCommand() {
usesSpecTemplateOption();
usesTestTemplateOption();
}
}