Write Test for Flutter FutureBuilder - flutter

In my app after press button it's opening another screen, a form (StatefulWidget) which is loading from FutureBuilder. I need to write test class for this,
But in log it says when executing form is not finished build. This is test code,
await tester.tap(find.byIcon(Icons.add));
await tester.pump(const Duration(seconds: 1));
await tester.runAsync(() async {
when(tester.tap(find.byKey(Key("add_new_form")))).thenAnswer((_) => Future.delayed(Duration(seconds: 30), () => []));
await tester.pumpAndSettle(Duration(seconds: 10), EnginePhase.build, Duration(minutes: 1));
await tester.pump();
await tester.pump(const Duration(seconds: 1));
await tester.pump(const Duration(seconds: 1));
expect(find.byKey(Key("form")), findsOneWidget);
});
how to write test class for flutter FutureBuilder ?? I have seen two questions relates to FutureBuilder but they are different from my situation. Any help would be appreciated.

Related

Flutter test widgets, go to another screen failed

I'm writting my very first widget tests in dart. I have to check if clicking on a button bring us to the next screen.
What am I doing wrong here?
testWidgets('Tapping staring the meeting button leads to conference screen', (widgetTester) async {
await widgetTester.pumpWidget(const MaterialApp(home: WelcomeScreen()));
await widgetTester.enterText(find.byKey(const Key('nameInput')), 'User');
await widgetTester.enterText(find.byKey(const Key('titleInput')), 'Title');
await widgetTester.enterText(find.byKey(const Key('passwordInput')), 'Password');
expect(find.byType(CallToActionButton), findsOneWidget);
await widgetTester.tap(find.byType(CallToActionButton));
await widgetTester.pump();
expect(find.byType(ConferenceScreen), findsOneWidget);
});

Integration test Flutter: How to press keys from keyboard in a app , at the very last step

**At the very last bold step please help me with the code every thing is working and at the stage of keyboard it is not working
testWidgets('アカウントをお持ちの方はこちら', (WidgetTester tester) async {
await app.main();
await tester.pumpAndSettle();
await tester.pumpAndSettle(const Duration(seconds: 2));
expect(find.text('アカウントをお持ちの方はこちら'), findsOneWidget);
Finder signinbutton = find.text('アカウントをお持ちの方はこちら');
await tester.tap(signinbutton);
await tester.pumpAndSettle();
expect(find.text('ログイン画面へ'), findsOneWidget);
Finder loginbutton = find.text("ログイン画面へ");
await tester.tap(loginbutton);
await tester.pumpAndSettle();
expect(find.text('携帯電話番号'), findsOneWidget);
Finder mobilenumber = find.text("携帯電話番号");
await tester.tap(mobilenumber);
await tester.pumpAndSettle(const Duration(seconds: 2));
**expect(find.text('携帯電話番号'), findsOneWidget);
Finder textBoxForPhone = find.text('携帯電話番号');
await tester.enterText(textBoxForPhone, '08009090909');
await tester.tap(textBoxForPhone);
await tester.pumpAndSettle();**
});
}

How to test a LongPressDraggable in Flutter

I want to test a LongPressDraggable in Flutter.
The WidgetTester provide methods like longPress or several drag methods.
But there is no "longPressDrag" or something like this.
The first idea was to run a longPress and a drag. But after the longPress the widget tester doesnt hold the widget and i can't drag it.
await tester.longPress(from);
await tester.timedDrag(from, offset, Duration(milliseconds: time));
A workaround is to use the timedDrag and run it super slow.
This works but takes a lot of time.
await tester.timedDrag(from, offset, Duration(seconds: 15));
Is there a correct way to test the widget?
Use the startGesture method to start your own gesture. The "Finger is pressed" until you call geseture.up(). Between start and up use gesture.moveTo to move the cursor and tester.pump(duration) to stay still at a certain position to trigger the long-press.
Example code from the flutter repo in draggable_test.dart
final Offset firstLocation = tester.getCenter(find.text('Source'));
final TestGesture gesture = await tester.startGesture(firstLocation, pointer: 7);
await tester.pump();
expect(targetMoveCount['Target 1'], equals(0));
expect(targetMoveCount['Target 2'], equals(0));
final Offset secondLocation = tester.getCenter(find.text('Target 1'));
await gesture.moveTo(secondLocation);
await tester.pump();
expect(targetMoveCount['Target 1'], equals(1));
expect(targetMoveCount['Target 2'], equals(0));
final Offset thirdLocation = tester.getCenter(find.text('Target 2'));
await gesture.moveTo(thirdLocation);
await tester.pump();
expect(targetMoveCount['Target 1'], equals(1));
expect(targetMoveCount['Target 2'], equals(1));
await gesture.moveTo(secondLocation);
await tester.pump();
expect(targetMoveCount['Target 1'], equals(2));
expect(targetMoveCount['Target 2'], equals(1));
await gesture.up();
await tester.pump();

How to wait until the Finder is visible for next code execution in Flutter integration test?

Information:
I have created a sample Flutter unit test to test the login screen where I have email & password as input field and a login button.
Requirement:
Need to test false cases and for that, I have written code as per the below steps.
Open main.dart
Filled the email & password field
onTap event is done on the login button. Over here API will be called and loader is displayed on the screen until API gets a success or failure response.
Need to check if failure dialog is displayed with a message.
Issue/Query:
Now when the API is calling I want to wait when the loader is visible until the loader is gone. So, as of now I just put a manual delay to execute the next code but I want to make it dynamic. So, let me know how we can put dynamic delay based on the loader visible?
Code:
void main() {
group('App Test', () {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('Login Fail Test', (WidgetTester tester) async {
await app.main();
await tester.pumpAndSettle();
await tester.pump(new Duration(seconds: 2));
final emailField = find.byType(TextFormField).first;
final passwordField = find.byType(TextFormField).last;
final loginButton = find.byType(RaisedButton).first;
await tester.enterText(emailField, 'Test');
await tester.pumpAndSettle();
await tester.pump(new Duration(seconds: 1));
await tester.enterText(passwordField, 'Test123');
await tester.pumpAndSettle();
await tester.pump(new Duration(seconds: 1));
await tester.tap(loginButton);
await tester.pumpAndSettle();
await tester.pump(new Duration(seconds: 3));
final dialog = find.byType(AlertDialog).first;
await tester.element(dialog);
await tester.pumpAndSettle();
await tester.pump(new Duration(seconds: 1));
final dialogButton = find.byType(FlatButton).first;
await tester.tap(dialogButton);
await tester.pumpAndSettle();
await tester.pump(new Duration(seconds: 2));
});
}
I have a file called utils.dart for functionality like this. In this case I use the following function which will basically poll until the finder is valid
// utils.dart
Future<void> pumpUntilFound(
WidgetTester tester,
Finder finder, {
Duration timeout = const Duration(seconds: 10),
}) async {
bool timerDone = false;
final timer = Timer(timeout, () => timerDone = true);
while (timerDone != true) {
await tester.pump();
final found = tester.any(finder);
if (found) {
timerDone = true;
}
}
timer.cancel();
}
You can also make it throw an exception if it times out, but the error messages aren't helpful, so I usually follow it up with an expect
It would look like
// my_test.dart
final fab = find.byKey(const ValueKey('fab'));
await pumpUntilFound(widgetTester, fab);
expect(fab, findsOneWidget);
Try wrapping like this:
testWidgets('test',
(WidgetTester tester) async {
await tester.runAsync(() async {
// test code here
});
});
If you use:
await tester.pumpAndSettle();
And then:
final widget = find.byKey(Key('whatever'));
It will find dinamically

Hit the the enter/done/return button in Flutter integration test after enter a text

await tester.enterText(mySearchField, 'my search text');
await tester.showKeyboard(mySearchField);
await tester.sendKeyDownEvent(LogicalKeyboardKey.enter);
// do something to wait for 2 seconds
await tester.pumpAndSettle();
await Future.delayed(const Duration(seconds: 10), () {});
I'am trying to hit the done/enter/submit button on the virtual keyboard after enter a text in a search field..
how to do that, and how to wait for the result (async request)...
await simulateKeyDownEvent(LogicalKeyboardKey.accept);