test driver: fixed flaky descendant resolution

This commit is contained in:
Thibault Deckers 2021-08-22 11:16:34 +09:00
parent 4ea1701462
commit c0e11a68fa
16 changed files with 34 additions and 10 deletions

View file

@ -133,6 +133,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
tooltip = MaterialLocalizations.of(context).openAppDrawerTooltip;
}
return IconButton(
// key is expected by test driver
key: const Key('appbar-leading-button'),
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
@ -188,6 +189,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
final canAddShortcuts = snapshot.data ?? false;
return MenuIconTheme(
child: PopupMenuButton<EntrySetAction>(
// key is expected by test driver
key: const Key('appbar-menu-button'),
itemBuilder: (context) {
final groupable = collection.sortFactor == EntrySortFactor.date;
@ -201,11 +203,13 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
return [
_toMenuItem(
EntrySetAction.sort,
// key is expected by test driver
key: const Key('menu-sort'),
),
if (groupable)
_toMenuItem(
EntrySetAction.group,
// key is expected by test driver
key: const Key('menu-group'),
),
if (appMode == AppMode.main) ...[

View file

@ -56,6 +56,7 @@ class _CollectionPageState extends State<CollectionPage> {
child: ChangeNotifierProvider<CollectionLens>.value(
value: collection,
child: const CollectionGrid(
// key is expected by test driver
key: Key('collection-grid'),
),
),

View file

@ -48,6 +48,7 @@ class AvesExpansionTile extends StatelessWidget {
accentColor: Colors.white,
),
child: ExpansionTileCard(
// key is expected by test driver
key: Key('tilecard-$value'),
value: value,
expandedNotifier: expandedNotifier,

View file

@ -51,6 +51,7 @@ class _AvesSelectionDialogState<T> extends State<AvesSelectionDialog<T>> {
Widget _buildRadioListTile(T value, String title) {
final subtitle = widget.optionSubtitleBuilder?.call(value);
return ReselectableRadioListTile<T>(
// key is expected by test driver
key: Key(value.toString()),
value: value,
groupValue: _selectedValue,

View file

@ -142,6 +142,7 @@ class _AppDrawerState extends State<AppDrawer> {
runSpacing: 8,
children: [
OutlinedButton.icon(
// key is expected by test driver
key: const Key('drawer-about-button'),
onPressed: () => goTo(AboutPage.routeName, (_) => const AboutPage()),
icon: const Icon(AIcons.info),
@ -178,6 +179,7 @@ class _AppDrawerState extends State<AppDrawer> {
),
),
OutlinedButton.icon(
// key is expected by test driver
key: const Key('drawer-settings-button'),
onPressed: () => goTo(SettingsPage.routeName, (_) => const SettingsPage()),
icon: const Icon(AIcons.settings),

View file

@ -24,6 +24,7 @@ class PageNavTile extends StatelessWidget {
top: false,
bottom: false,
child: ListTile(
// key is expected by test driver
key: Key('$routeName-tile'),
leading: DrawerPageIcon(route: routeName),
title: DrawerPageTitle(route: routeName),

View file

@ -98,6 +98,7 @@ class _FilterGridAppBarState<T extends CollectionFilter> extends State<FilterGri
tooltip = MaterialLocalizations.of(context).openAppDrawerTooltip;
}
return IconButton(
// key is expected by test driver
key: const Key('appbar-leading-button'),
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
@ -170,7 +171,6 @@ class _FilterGridAppBarState<T extends CollectionFilter> extends State<FilterGri
...buttonActions,
MenuIconTheme(
child: PopupMenuButton<ChipSetAction>(
key: const Key('appbar-menu-button'),
itemBuilder: (context) {
final selectedItems = selection.selectedItems;
final hasSelection = selectedItems.isNotEmpty;

View file

@ -90,6 +90,8 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
child: AnimatedBuilder(
animation: covers,
builder: (context, child) => FilterGrid<T>(
// key is expected by test driver
key: const Key('filter-grid'),
settingsRouteKey: settingsRouteKey,
appBar: appBar,
appBarHeight: appBarHeight,

View file

@ -39,7 +39,6 @@ class FilterNavigationPage<T extends CollectionFilter> extends StatelessWidget {
return SelectionProvider<FilterGridItem<T>>(
child: Builder(
builder: (context) => FilterGridPage<T>(
key: const Key('filter-grid-page'),
appBar: FilterGridAppBar<T>(
source: source,
title: title,

View file

@ -17,6 +17,7 @@ class CollectionSearchButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return IconButton(
// key is expected by test driver
key: const Key('search-button'),
icon: const Icon(AIcons.search),
onPressed: () => _goToSearch(context),

View file

@ -38,6 +38,7 @@ class _MultiEntryScrollerState extends State<MultiEntryScroller> with AutomaticK
return MagnifierGestureDetectorScope(
axis: const [Axis.horizontal, Axis.vertical],
child: PageView.builder(
// key is expected by test driver
key: const Key('horizontal-pageview'),
scrollDirection: Axis.horizontal,
controller: pageController,
@ -81,6 +82,7 @@ class _MultiEntryScrollerState extends State<MultiEntryScroller> with AutomaticK
Widget _buildViewer(AvesEntry mainEntry, {AvesEntry? pageEntry}) {
return EntryPageView(
// key is expected by test driver
key: const Key('imageview'),
mainEntry: mainEntry,
pageEntry: pageEntry ?? mainEntry,

View file

@ -131,6 +131,7 @@ class _ViewerVerticalPageViewState extends State<ViewerVerticalPageView> {
child: child,
),
child: PageView(
// key is expected by test driver
key: const Key('vertical-pageview'),
scrollDirection: Axis.vertical,
controller: widget.verticalPager,

View file

@ -22,6 +22,7 @@ class InfoAppBar extends StatelessWidget {
Widget build(BuildContext context) {
return SliverAppBar(
leading: IconButton(
// key is expected by test driver
key: const Key('back-button'),
icon: const Icon(AIcons.goUp),
onPressed: onBackPressed,

View file

@ -109,6 +109,7 @@ class _WelcomePageState extends State<WelcomePage> {
text: context.l10n.welcomeCrashReportToggle,
),
LabeledCheckbox(
// key is expected by test driver
key: const Key('agree-checkbox'),
value: _hasAcceptedTerms,
onChanged: (v) {
@ -120,6 +121,7 @@ class _WelcomePageState extends State<WelcomePage> {
);
final button = ElevatedButton(
// key is expected by test driver
key: const Key('continue-button'),
onPressed: _hasAcceptedTerms
? () {

View file

@ -129,10 +129,11 @@ void selectFirstAlbum() {
// wait for collection loading
await driver.waitForCondition(const NoPendingPlatformMessages());
// TODO TLAD fix finder
// delay to avoid flaky descendant resolution
await Future.delayed(const Duration(seconds: 2));
await driver.tap(find.descendant(
of: find.byValueKey('filter-grid-page'),
matching: find.byType('CoveredFilterChip'),
of: find.byValueKey('filter-grid'),
matching: find.byType('MetaData'),
firstMatchOnly: true,
));
await driver.waitUntilNoTransientCallbacks();
@ -158,9 +159,11 @@ void searchAlbum() {
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('DecoratedThumbnail'),
matching: find.byType('MetaData'),
firstMatchOnly: true,
));
await driver.waitUntilNoTransientCallbacks();

View file

@ -3,10 +3,13 @@ import 'dart:io';
import 'package:path/path.dart' as p;
String get adb {
final env = Platform.environment;
// e.g. C:\Users\<username>\AppData\Local\Android\Sdk
final sdkDir = env['ANDROID_SDK_ROOT'] ?? env['ANDROID_SDK']!;
return p.join(sdkDir, 'platform-tools', Platform.isWindows ? 'adb.exe' : 'adb');
if (Platform.isWindows) {
final env = Platform.environment;
// e.g. C:\Users\<username>\AppData\Local\Android\Sdk
final sdkDir = env['ANDROID_SDK_ROOT'] ?? env['ANDROID_SDK']!;
return p.join(sdkDir, 'platform-tools', 'adb.exe');
}
return 'adb';
}
/*