tests: show fullscreen, info

This commit is contained in:
Thibault Deckers 2020-08-20 19:29:35 +09:00
parent 8e13625192
commit 55c6209bee
7 changed files with 68 additions and 21 deletions

View file

@ -186,7 +186,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
)), )),
Builder( Builder(
builder: (context) => PopupMenuButton<CollectionAction>( builder: (context) => PopupMenuButton<CollectionAction>(
key: Key('menu-button'), key: Key('appbar-menu-button'),
itemBuilder: (context) { itemBuilder: (context) {
final hasSelection = collection.selection.isNotEmpty; final hasSelection = collection.selection.isNotEmpty;
return [ return [

View file

@ -499,6 +499,7 @@ class _FullscreenVerticalPageViewState extends State<FullscreenVerticalPageView>
child: child, child: child,
), ),
child: PageView( child: PageView(
key: Key('vertical-pageview'),
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
controller: widget.verticalPager, controller: widget.verticalPager,
physics: PhotoViewPageViewScrollPhysics(parent: PageScrollPhysics()), physics: PhotoViewPageViewScrollPhysics(parent: PageScrollPhysics()),

View file

@ -37,6 +37,7 @@ class MultiImagePageState extends State<MultiImagePage> with AutomaticKeepAliveC
return PhotoViewGestureDetectorScope( return PhotoViewGestureDetectorScope(
axis: [Axis.horizontal, Axis.vertical], axis: [Axis.horizontal, Axis.vertical],
child: PageView.builder( child: PageView.builder(
key: Key('horizontal-pageview'),
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
controller: widget.pageController, controller: widget.pageController,
physics: PhotoViewPageViewScrollPhysics(parent: BouncingScrollPhysics()), physics: PhotoViewPageViewScrollPhysics(parent: BouncingScrollPhysics()),
@ -45,6 +46,7 @@ class MultiImagePageState extends State<MultiImagePage> with AutomaticKeepAliveC
final entry = entries[index]; final entry = entries[index];
return ClipRect( return ClipRect(
child: ImageView( child: ImageView(
key: Key('imageview'),
entry: entry, entry: entry,
heroTag: widget.collection.heroTag(entry), heroTag: widget.collection.heroTag(entry),
onScaleChanged: widget.onScaleChanged, onScaleChanged: widget.onScaleChanged,

View file

@ -20,12 +20,13 @@ class ImageView extends StatelessWidget {
final List<Tuple2<String, IjkMediaController>> videoControllers; final List<Tuple2<String, IjkMediaController>> videoControllers;
const ImageView({ const ImageView({
Key key,
this.entry, this.entry,
this.heroTag, this.heroTag,
this.onScaleChanged, this.onScaleChanged,
this.onTap, this.onTap,
this.videoControllers, this.videoControllers,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -133,6 +133,7 @@ class _TopOverlayRow extends StatelessWidget {
OverlayButton( OverlayButton(
scale: scale, scale: scale,
child: PopupMenuButton<EntryAction>( child: PopupMenuButton<EntryAction>(
key: Key('entry-menu-button'),
itemBuilder: (context) => [ itemBuilder: (context) => [
...inAppActions.map(_buildPopupMenuItem), ...inAppActions.map(_buildPopupMenuItem),
PopupMenuDivider(), PopupMenuDivider(),

View file

@ -1,5 +1,3 @@
import 'dart:io';
import 'package:aves/model/source/enums.dart'; import 'package:aves/model/source/enums.dart';
import 'package:flutter_driver/flutter_driver.dart'; import 'package:flutter_driver/flutter_driver.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
@ -14,6 +12,7 @@ void main() {
FlutterDriver driver; FlutterDriver driver;
setUpAll(() async { setUpAll(() async {
print('adb=${[adb, ...adbDeviceParam].join(' ')}');
await copyContent(sourcePicturesDir, targetPicturesDir); await copyContent(sourcePicturesDir, targetPicturesDir);
await grantPermissions('deckers.thibault.aves.debug', [ await grantPermissions('deckers.thibault.aves.debug', [
'android.permission.READ_EXTERNAL_STORAGE', 'android.permission.READ_EXTERNAL_STORAGE',
@ -30,8 +29,6 @@ void main() {
} }
}); });
final appBarTitleFinder = find.byValueKey('appbar-title');
test('agree to terms and reach home', () async { test('agree to terms and reach home', () async {
await driver.scroll(find.text('Terms of Service'), 0, -300, Duration(milliseconds: 500)); await driver.scroll(find.text('Terms of Service'), 0, -300, Duration(milliseconds: 500));
@ -39,16 +36,17 @@ void main() {
expect(await isEnabled(driver, buttonFinder), equals(false)); expect(await isEnabled(driver, buttonFinder), equals(false));
await driver.tap(find.byValueKey('agree-checkbox')); await driver.tap(find.byValueKey('agree-checkbox'));
await driver.waitUntilNoTransientCallbacks(); await Future.delayed(Duration(seconds: 1));
expect(await isEnabled(driver, buttonFinder), equals(true)); expect(await isEnabled(driver, buttonFinder), equals(true));
await driver.tap(buttonFinder); await driver.tap(buttonFinder);
await driver.waitUntilNoTransientCallbacks(); await driver.waitUntilNoTransientCallbacks();
expect(await driver.getText(appBarTitleFinder), 'Aves');
expect(await driver.getText(find.byValueKey('appbar-title')), 'Aves');
}); });
test('sort and group', () async { test('sort collection', () async {
await driver.tap(find.byValueKey('menu-button')); await driver.tap(find.byValueKey('appbar-menu-button'));
await driver.waitUntilNoTransientCallbacks(); await driver.waitUntilNoTransientCallbacks();
await driver.tap(find.byValueKey('menu-sort')); await driver.tap(find.byValueKey('menu-sort'));
@ -56,8 +54,10 @@ void main() {
await driver.tap(find.byValueKey(SortFactor.date.toString())); await driver.tap(find.byValueKey(SortFactor.date.toString()));
await driver.tap(find.byValueKey('apply-button')); await driver.tap(find.byValueKey('apply-button'));
});
await driver.tap(find.byValueKey('menu-button')); test('group collection', () async {
await driver.tap(find.byValueKey('appbar-menu-button'));
await driver.waitUntilNoTransientCallbacks(); await driver.waitUntilNoTransientCallbacks();
await driver.tap(find.byValueKey('menu-group')); await driver.tap(find.byValueKey('menu-group'));
@ -81,7 +81,32 @@ void main() {
}); });
test('show fullscreen', () async { test('show fullscreen', () async {
sleep(Duration(seconds: 5)); await driver.tap(find.byType('DecoratedThumbnail'));
await driver.waitUntilNoTransientCallbacks();
await Future.delayed(Duration(seconds: 2));
final imageViewFinder = find.byValueKey('imageview');
print('* hide overlay');
await driver.tap(imageViewFinder);
await Future.delayed(Duration(seconds: 1));
print('* show overlay');
await driver.tap(imageViewFinder);
await Future.delayed(Duration(seconds: 1));
});
test('show info', () async {
final verticalPageViewFinder = find.byValueKey('vertical-pageview');
print('* scroll to info');
await driver.scroll(verticalPageViewFinder, 0, -600, Duration(milliseconds: 400));
await Future.delayed(Duration(seconds: 1));
// TODO TLAD find.pageBack
// print('* back to image');
// await driver.tap(find.pageBack());
// await Future.delayed(Duration(seconds: 5));
}); });
}, timeout: Timeout(Duration(seconds: 10))); }, timeout: Timeout(Duration(seconds: 10)));
} }

View file

@ -3,18 +3,40 @@ import 'dart:io';
import 'package:flutter_driver/flutter_driver.dart'; import 'package:flutter_driver/flutter_driver.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
// conditions
Future<bool> isEnabled(FlutterDriver driver, SerializableFinder widgetFinder) async {
Map widgetDiagnostics = await driver.getWidgetDiagnostics(widgetFinder);
return widgetDiagnostics['properties'].firstWhere((property) => property['name'] == 'enabled')['value'];
}
// ADB
String get adb { String get adb {
final env = Platform.environment; final env = Platform.environment;
final sdkDir = env['ANDROID_SDK_ROOT'] ?? env['ANDROID_SDK']; final sdkDir = env['ANDROID_SDK_ROOT'] ?? env['ANDROID_SDK'];
return path.join(sdkDir, 'platform-tools', Platform.isWindows ? 'adb.exe' : 'adb'); return path.join(sdkDir, 'platform-tools', Platform.isWindows ? 'adb.exe' : 'adb');
} }
/*
If there's only one emulator running or only one device connected,
the adb command is sent to that device by default.
If multiple emulators are running and/or multiple devices are attached,
you need to use the -d, -e, or -s option to specify the target device
to which the command should be directed.
*/
const List<String> adbDeviceParam = ['-e']; // '[-d]', '[-e]', or '[-s, <serial_number>]'
Future<void> runAdb(List<String> args) async {
await Process.runSync(adb, [...adbDeviceParam, ...args]);
}
Future<void> createDirectory(String dir) async { Future<void> createDirectory(String dir) async {
await Process.run(adb, ['shell', 'mkdir -p', dir.replaceAll(' ', '\\ ')]); await runAdb(['shell', 'mkdir -p', dir.replaceAll(' ', '\\ ')]);
} }
Future<void> removeDirectory(String dir) async { Future<void> removeDirectory(String dir) async {
await Process.run(adb, ['shell', 'rm -r', dir.replaceAll(' ', '\\ ')]); await runAdb(['shell', 'rm -r', dir.replaceAll(' ', '\\ ')]);
} }
Future<void> copyContent(String sourceDir, String targetDir) async { Future<void> copyContent(String sourceDir, String targetDir) async {
@ -22,14 +44,9 @@ Future<void> copyContent(String sourceDir, String targetDir) async {
// `push source/* target/` works only when the target directory exists, and fails when `target` contains spaces // `push source/* target/` works only when the target directory exists, and fails when `target` contains spaces
// `push source/ target/` works only when the target directory does not exist // `push source/ target/` works only when the target directory does not exist
await removeDirectory(targetDir); await removeDirectory(targetDir);
await Process.run(adb, ['push', sourceDir, targetDir]); await runAdb(['push', sourceDir, targetDir]);
} }
Future<void> grantPermissions(String packageName, Iterable<String> permissions) async { Future<void> grantPermissions(String packageName, Iterable<String> permissions) async {
await Future.forEach(permissions, (permission) => Process.run(adb, ['shell', 'pm', 'grant', packageName, permission])); await Future.forEach(permissions, (permission) => runAdb(['shell', 'pm', 'grant', packageName, permission]));
}
Future<bool> isEnabled(FlutterDriver driver, SerializableFinder widgetFinder) async {
Map widgetDiagnostics = await driver.getWidgetDiagnostics(widgetFinder);
return widgetDiagnostics['properties'].firstWhere((property) => property['name'] == 'enabled')['value'];
} }