Last active
September 6, 2024 11:31
-
-
Save KoalityJustin/910c9a5dd1ddb43c34de9770f4dac11f to your computer and use it in GitHub Desktop.
All You Need
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:math'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_test/flutter_test.dart'; | |
extension TestingHelpers on WidgetTester { | |
/// Helper method for tapping a finder, and for optionally choosing the index | |
/// if the finder finds multiple and if we should scroll to before tapping. | |
Future<void> tapFinder( | |
Finder finder, { | |
int index = 0, | |
bool scrollTo = false, | |
bool useScrollable = false, | |
bool warnIfMissed = false, | |
}) async { | |
expect(finder, findsWidgets); | |
final maxIndex = min(index, finder.evaluate().length - 1); | |
final honedFinder = finder.at(maxIndex); | |
if (scrollTo) { | |
await ensureVisible(honedFinder); | |
await pumpAndSettle(); | |
} | |
if (useScrollable) { | |
final scrollable = find.byType(Scrollable).first; | |
await scrollUntilVisible(honedFinder, 300, scrollable: scrollable); | |
await pumpAndSettle(); | |
} | |
await tap(honedFinder, warnIfMissed: warnIfMissed); | |
await pumpAndSettle(); | |
} | |
Future<void> tapKey( | |
String keyName, { | |
int index = 0, | |
bool scrollTo = true, | |
bool useScrollable = false, | |
bool skipOffstage = false, | |
}) async { | |
final finder = find.byKey(ValueKey(keyName), skipOffstage: skipOffstage); | |
await tapFinder( | |
finder, | |
index: index, | |
scrollTo: scrollTo, | |
useScrollable: useScrollable, | |
); | |
} | |
Future<void> tapText( | |
String text, { | |
int index = 0, | |
bool scrollTo = true, | |
bool useScrollable = false, | |
bool skipOffstage = false, | |
}) async { | |
final finder = find.text(text, skipOffstage: skipOffstage); | |
await tapFinder( | |
finder, | |
index: index, | |
scrollTo: scrollTo, | |
useScrollable: useScrollable, | |
); | |
} | |
Future<void> tapIcon( | |
IconData icon, { | |
int index = 0, | |
bool scrollTo = false, | |
bool useScrollable = false, | |
bool skipOffstage = false, | |
}) async { | |
final finder = find.byIcon(icon, skipOffstage: skipOffstage); | |
await tapFinder( | |
finder, | |
index: index, | |
scrollTo: scrollTo, | |
useScrollable: useScrollable, | |
); | |
} | |
Future<void> tapBackButton({bool skipOffstage = false}) async { | |
final finder = find.byType(BackButton, skipOffstage: skipOffstage); | |
await tapFinder(finder); | |
} | |
Future<void> wait(int ms) async { | |
await Future<void>.delayed(Duration(milliseconds: ms)); | |
} | |
Future<void> waitFor( | |
Finder finder, { | |
Duration interval = const Duration(milliseconds: 16), | |
Duration timeout = const Duration(seconds: 10), | |
Matcher matcher = findsWidgets, | |
bool immediateCheck = false, | |
bool scrollTo = true, | |
bool useScrollable = false, | |
int index = 0, | |
}) async { | |
final stopwatch = Stopwatch()..start(); | |
// If our matcher is to NOT find anything, we want to wait the interval once | |
// and then check. | |
if (immediateCheck) { | |
await pumpAndSettle(); | |
await Future<void>.delayed(interval); | |
expect(finder, matcher); | |
return; | |
} else { | |
while (stopwatch.elapsed < timeout) { | |
await Future<void>.delayed(interval); | |
await pump(); | |
final foundSomething = finder.evaluate().isNotEmpty; | |
if (foundSomething) { | |
await findIt( | |
finder: finder, | |
interval: interval, | |
scrollTo: scrollTo, | |
useScrollable: useScrollable, | |
index: index, | |
); | |
expect(finder, matcher); | |
stopwatch.stop(); | |
return; | |
} | |
} | |
} | |
expect(finder, matcher); | |
} | |
Future<void> waitForText( | |
String text, { | |
Duration interval = const Duration(milliseconds: 16), | |
Duration timeout = const Duration(seconds: 10), | |
Matcher matcher = findsWidgets, | |
bool skipOffstage = true, | |
bool immediateCheck = false, | |
bool scrollTo = true, | |
bool useScrollable = false, | |
int index = 0, | |
}) async { | |
final stopwatch = Stopwatch()..start(); | |
// If our matcher is to NOT find anything, we want to wait the interval once | |
// and then check. | |
final finder = find.text(text, skipOffstage: skipOffstage); | |
if (immediateCheck) { | |
await pumpAndSettle(); | |
await Future<void>.delayed(interval); | |
expect(finder, matcher); | |
return; | |
} else { | |
while (stopwatch.elapsed < timeout) { | |
await Future<void>.delayed(interval); | |
await pump(); | |
final foundSomething = finder.evaluate().isNotEmpty; | |
if (foundSomething) { | |
await findIt( | |
finder: finder, | |
interval: interval, | |
scrollTo: scrollTo, | |
useScrollable: useScrollable, | |
index: index, | |
); | |
expect(finder, matcher); | |
stopwatch.stop(); | |
return; | |
} | |
} | |
} | |
expect(finder, matcher); | |
} | |
Future<void> waitForTextContaining( | |
String text, { | |
Duration interval = const Duration(milliseconds: 16), | |
Duration timeout = const Duration(seconds: 10), | |
Matcher matcher = findsWidgets, | |
bool skipOffstage = true, | |
bool immediateCheck = false, | |
bool scrollTo = true, | |
bool useScrollable = false, | |
int index = 0, | |
}) async { | |
final stopwatch = Stopwatch()..start(); | |
// If our matcher is to NOT find anything, we want to wait the interval once | |
// and then check. | |
final finder = find.textContaining(text, skipOffstage: skipOffstage); | |
if (immediateCheck) { | |
await pumpAndSettle(); | |
await Future<void>.delayed(interval); | |
expect(finder, matcher); | |
return; | |
} else { | |
while (stopwatch.elapsed < timeout) { | |
await Future<void>.delayed(interval); | |
await pump(); | |
final foundSomething = finder.evaluate().isNotEmpty; | |
if (foundSomething) { | |
await findIt( | |
finder: finder, | |
interval: interval, | |
scrollTo: scrollTo, | |
useScrollable: useScrollable, | |
index: index, | |
); | |
expect(finder, matcher); | |
stopwatch.stop(); | |
return; | |
} | |
} | |
} | |
expect(finder, matcher); | |
} | |
Future<void> findIt({ | |
required Finder finder, | |
required Duration interval, | |
bool scrollTo = true, | |
bool useScrollable = false, | |
int index = 0, | |
}) async { | |
if (scrollTo) { | |
if (useScrollable) { | |
final scroll = find.byType(Scrollable).first; | |
await scrollUntilVisible( | |
finder, | |
300, | |
scrollable: scroll, | |
duration: interval, | |
); | |
await pumpAndSettle(); | |
} else { | |
final maxIndex = min(index, finder.evaluate().length - 1); | |
final honedFinder = finder.at(maxIndex); | |
await ensureVisible(honedFinder); | |
await pumpAndSettle(); | |
} | |
} | |
} | |
Future<void> input( | |
String text, { | |
int index = 0, | |
Finder? finder, | |
String? key, | |
bool skipOffstage = false, | |
TextInputAction? action = TextInputAction.done, | |
}) async { | |
late final Finder finder; | |
if (key != null) { | |
finder = find.byKey(ValueKey(key), skipOffstage: skipOffstage); | |
} else { | |
finder = find.byType(EditableText, skipOffstage: skipOffstage); | |
} | |
expect(finder, findsWidgets); | |
final maxIndex = max(index, finder.evaluate().length - 1); | |
await tapFinder(finder.at(maxIndex)); | |
await enterText(finder.at(maxIndex), text); | |
await pump(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment