275 lines
8.3 KiB
Dart
275 lines
8.3 KiB
Dart
// ignore_for_file: avoid_print
|
|
import 'dart:async';
|
|
|
|
import 'package:aves/model/source/enums.dart';
|
|
import 'package:flutter_driver/flutter_driver.dart';
|
|
import 'package:path/path.dart' as p;
|
|
import 'package:test/test.dart';
|
|
|
|
import 'constants.dart';
|
|
import 'utils/adb_utils.dart';
|
|
import 'utils/driver_extension.dart';
|
|
|
|
late FlutterDriver driver;
|
|
|
|
void main() {
|
|
group('[Aves app]', () {
|
|
setUpAll(() async {
|
|
await copyContent(sourcePicturesDir, targetPicturesDir);
|
|
await grantPermissions('deckers.thibault.aves.debug', [
|
|
'android.permission.READ_EXTERNAL_STORAGE',
|
|
'android.permission.WRITE_EXTERNAL_STORAGE',
|
|
'android.permission.ACCESS_MEDIA_LOCATION',
|
|
]);
|
|
driver = await FlutterDriver.connect();
|
|
});
|
|
|
|
tearDownAll(() async {
|
|
await removeDirectory(targetPicturesDir);
|
|
unawaited(driver.close());
|
|
});
|
|
|
|
agreeToTerms();
|
|
visitAbout();
|
|
visitSettings();
|
|
sortCollection();
|
|
groupCollection();
|
|
visitMap();
|
|
selectFirstAlbum();
|
|
searchAlbum();
|
|
showViewer();
|
|
goToNextImage();
|
|
toggleOverlay();
|
|
zoom();
|
|
showInfoMetadata();
|
|
scrollOffImage();
|
|
|
|
test('contemplation', () async {
|
|
await Future.delayed(const Duration(seconds: 5));
|
|
});
|
|
}, timeout: const Timeout(Duration(seconds: 30)));
|
|
}
|
|
|
|
void agreeToTerms() {
|
|
test('[welcome] agree to terms', () async {
|
|
// delay to avoid flaky failures when widget binding is not ready from the start
|
|
await Future.delayed(const Duration(seconds: 3));
|
|
|
|
await driver.scroll(find.text('Terms of Service'), 0, -300, const Duration(milliseconds: 500));
|
|
|
|
await driver.tap(find.byValueKey('agree-checkbox'));
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
|
|
await driver.tap(find.byValueKey('continue-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
// wait for collection loading
|
|
await driver.waitForCondition(const NoPendingPlatformMessages());
|
|
});
|
|
}
|
|
|
|
void visitAbout() {
|
|
test('[collection] visit about page', () async {
|
|
await driver.tap(find.byValueKey('appbar-leading-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
await driver.tap(find.byValueKey('drawer-about-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
await pressDeviceBackButton();
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
});
|
|
}
|
|
|
|
void visitSettings() {
|
|
test('[collection] visit settings page', () async {
|
|
await driver.tap(find.byValueKey('appbar-leading-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
await driver.tap(find.byValueKey('drawer-settings-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
await pressDeviceBackButton();
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
});
|
|
}
|
|
|
|
void sortCollection() {
|
|
test('[collection] sort', () async {
|
|
await driver.tap(find.byValueKey('appbar-menu-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
await driver.tap(find.byValueKey('menu-sort'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
await driver.tap(find.byValueKey(EntrySortFactor.date.toString()));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
});
|
|
}
|
|
|
|
void groupCollection() {
|
|
test('[collection] group', () async {
|
|
await driver.tap(find.byValueKey('appbar-menu-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
await driver.tap(find.byValueKey('menu-group'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
await driver.tap(find.byValueKey(EntryGroupFactor.album.toString()));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
});
|
|
}
|
|
|
|
void visitMap() {
|
|
test('[collection] visit map', () async {
|
|
await driver.tap(find.byValueKey('appbar-menu-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
await driver.tap(find.byValueKey('menu-map'));
|
|
// wait for heavy Google map initialization
|
|
await Future.delayed(const Duration(seconds: 3));
|
|
|
|
final mapView = find.byValueKey('map_view');
|
|
|
|
print('* hide overlay');
|
|
await driver.tap(mapView);
|
|
await Future.delayed(const Duration(seconds: 2));
|
|
|
|
print('* show overlay');
|
|
await driver.tap(mapView);
|
|
await Future.delayed(const Duration(seconds: 2));
|
|
|
|
await pressDeviceBackButton();
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
});
|
|
}
|
|
|
|
void selectFirstAlbum() {
|
|
test('[collection] select first album', () async {
|
|
await driver.tap(find.byValueKey('appbar-leading-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
// prefix must match `AlbumListPage.routeName`
|
|
await driver.tap(find.byValueKey('/albums-tile'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
// wait for collection loading
|
|
await driver.waitForCondition(const NoPendingPlatformMessages());
|
|
|
|
// delay to avoid flaky descendant resolution
|
|
await Future.delayed(const Duration(seconds: 2));
|
|
await driver.tap(find.descendant(
|
|
of: find.byValueKey('filter-grid'),
|
|
matching: find.byType('MetaData'),
|
|
firstMatchOnly: true,
|
|
));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
});
|
|
}
|
|
|
|
void searchAlbum() {
|
|
test('[collection] search album', () async {
|
|
await driver.tap(find.byValueKey('menu-search'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
const albumPath = targetPicturesDirEmulated;
|
|
final albumDisplayName = p.split(albumPath).last;
|
|
await driver.tap(find.byType('TextField'));
|
|
await driver.enterText(albumDisplayName);
|
|
|
|
final albumChip = find.byValueKey('album-$albumPath');
|
|
await driver.waitFor(albumChip);
|
|
await driver.tap(albumChip);
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
});
|
|
}
|
|
|
|
void showViewer() {
|
|
test('[collection] show viewer', () async {
|
|
// delay to avoid flaky descendant resolution
|
|
await Future.delayed(const Duration(seconds: 2));
|
|
await driver.tap(find.descendant(
|
|
of: find.byValueKey('collection-grid'),
|
|
matching: find.byType('MetaData'),
|
|
firstMatchOnly: true,
|
|
));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
await Future.delayed(const Duration(seconds: 2));
|
|
});
|
|
}
|
|
|
|
void goToNextImage() {
|
|
test('[viewer] show next image', () async {
|
|
final horizontalPageView = find.byValueKey('horizontal-pageview');
|
|
await driver.scroll(horizontalPageView, -600, 0, const Duration(milliseconds: 400));
|
|
await Future.delayed(const Duration(seconds: 2));
|
|
});
|
|
}
|
|
|
|
void toggleOverlay() {
|
|
test('[viewer] toggle overlay', () async {
|
|
final imageView = find.byValueKey('image_view');
|
|
|
|
print('* hide overlay');
|
|
await driver.tap(imageView);
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
|
|
print('* show overlay');
|
|
await driver.tap(imageView);
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
});
|
|
}
|
|
|
|
void zoom() {
|
|
test('[viewer] zoom cycle', () async {
|
|
final imageView = find.byValueKey('image_view');
|
|
|
|
await driver.doubleTap(imageView);
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
|
|
await driver.doubleTap(imageView);
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
|
|
await driver.doubleTap(imageView);
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
});
|
|
}
|
|
|
|
void showInfoMetadata() {
|
|
test('[viewer] show info', () async {
|
|
final verticalPageView = find.byValueKey('vertical-pageview');
|
|
|
|
print('* scroll down to info');
|
|
await driver.scroll(verticalPageView, 0, -600, const Duration(milliseconds: 400));
|
|
await Future.delayed(const Duration(seconds: 2));
|
|
|
|
print('* scroll down to metadata details');
|
|
await driver.scroll(verticalPageView, 0, -800, const Duration(milliseconds: 600));
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
|
|
print('* toggle GPS metadata');
|
|
final gpsTile = find.descendant(
|
|
of: find.byValueKey('tilecard-GPS'),
|
|
matching: find.byType('ListTile'),
|
|
);
|
|
await driver.tap(gpsTile);
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
await driver.tap(gpsTile);
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
|
|
print('* scroll up to show app bar');
|
|
await driver.scroll(verticalPageView, 0, 100, const Duration(milliseconds: 400));
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
|
|
print('* back to image');
|
|
await driver.tap(find.byValueKey('back-button'));
|
|
await driver.waitUntilNoTransientCallbacks();
|
|
});
|
|
}
|
|
|
|
void scrollOffImage() {
|
|
test('[viewer] scroll off', () async {
|
|
await driver.scroll(find.byValueKey('image_view'), 0, 800, const Duration(milliseconds: 600));
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
});
|
|
}
|