SyncFusion Calendar Flutter widget unclear how to test it - flutter

I used the widget to build a basic application for self learning purpose. I would like to widget test what I am done but there's something unclear to me on the topic. In the widget test I wrote this:
// Render the widget.
await tester.pumpWidget(MaterialApp(
title: 'Firestore test', home: Calendar(firestore: firestore)));
// Let the snapshots stream fire a snapshot.
await tester.idle();
// Re-render.
await tester.pump();
// Verify the output.
expect(find.text('Appointments'), findsOneWidget);
expect(find.text('No selected date'), findsOneWidget);
With last line that verifies that without any interaction the SyncFusion calendar should display "No selected date" in the agenda. That line fails as no widget are found. I also tried to do a test with the tap to a given date to display the events for a day, but the tap does not work as well.
// pre filled data before
// ...
await tester.pumpWidget(MaterialApp(
title: 'Firestore test', home: Calendar(firestore: firestore)));
// Let the snapshots stream fire a snapshot.
await tester.idle();
// Re-render.
await tester.pump();
await tester.tap(find.text(datetime.day.toString()));
await tester.pumpAndSettle();
await tester.pump();
// Verify the output.
expect(find.text('Appointments'), findsOneWidget);
expect(find.text('Mark', skipOffstage: false), findsOneWidget);
Could you help me understand what I am missing in order to verify the above behaviour?

Related

Flutter Test: Look for a widget inside of another widget

I am looking for the way to see that the widget I have found in the test, has certain text inside. In my case I want to look for the specific text not inside the complete RadioButtonGroup but inside of the found ElevatedButton --> firstButton. Is it possible?
testWidgets('Horizontal Radio Group builds a Row', (tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: simpleRadio
));
expect(find.byType(Row), findsOneWidget);
expect(find.byType(Column), findsNothing);
var optionButtons = find.byType(ElevatedButton);
expect(optionButtons, findsNWidgets(2));
ElevatedButton firstButton = tester.firstWidget(optionButtons);
});
Looking for something like: expect(firstButton.findByText('bla'), findsOneWidget);
I think what you're looking for is widgetWithText. This'll find a widget of widgetType that has a Text descendant with the given text.
So for your example, something like:
expect(find.widgetWithText(ElevatedButton, 'bla'), findsOneWidget);

Flutter integration test for UI and HTTP call

I have a simple login screen that calls login API and I trying to wait for the second screen after ProgressIndicator finishes and the new screen comes.
But It shows loading ProgressIndicator then it never goes to the second screen and expects function fails
So what should I do or what is similar to waitFor but for Flutter integration_test library?
My testing code
await tester.tap(find.byKey(const Key('loginButton')));
await tester.pumpAndSettle();
await tester.ensureVisible(find.byKey(const Key('loadingWidget')));
await tester.pumpAndSettle();
await tester.ensureVisible(find.byType(DetailsScreen));
expect(find.text('Log In'), findsNothing);
Here is the login button onTap
BlocProvider.of<LoginBloc>(context).add(
LoginEvent.loginWithEmail(
email: emailController.text,
password: passwordController.text,
),
);
You should use pumpAndSettle method of WidgetTester to wait until animations end. Your code will be like this:
testWidgets("Login test", (tester) async {
...
await tester.tap(find.byKey(ValueKey('Login')));
await tester.pumpAndSettle();
...
}
My goal is integration test so I replaced integration_test with the default Flutter driver and I was able to waitFor while animation by using
await driver.runUnsynchronized(() async {
//wait for something
});
More info: https://github.com/flutter/flutter/issues/36244
And I mock my Dio HTTP client by the following library
http_mock_adapter

flutter test finds two `SnackBar`s with the same key, when there is only one built

I am widget-testing the app in flutter, there is 3 conditions under the block listener on the gui side of the app.
two of the three conditions determine the building of the two different SnackBars, those two SnackBars has different Keys (error-snackbar and success-snackbar), when test is run it says:
2 of the widget with the same key<'error-snackbar'> was found.
because of this I need to expect two widget with findsNWidget(2)
this is the code of the test:
testWidgets("Expects email to be invalid and shows error SnackBar",
(WidgetTester tester) async {
await tester.runAsync(() async {
//build the tree of widgets
final widget = _buildTestableStateWidget();
await tester.pumpWidget(widget);
await tester.pumpAndSettle();
accountBloc.emit(AccountState(
event: event,
error: ErrorModel(key: 'ERROR_GENERAL'),
loading: true,
));
await tester.pumpAndSettle();
expect(find.byKey(Key("error-snackbar")), findsNWidgets(2));
});
});
Any Idea why this is happening ?
just comment if you need more code and I will provide it.
"Keys must be unique amongst the Elements with the same parent."
https://api.flutter.dev/flutter/foundation/Key-class.html
Since you are trying to find 2 widgets with the same key, do they share a common parent? Then it's not allowed. You should try to build the finder in another way, Keys are made to find a specific widget.

widget test, testing a button with CircularProgressIndicator

I have two tests that after a click on a button I want to test if a CircularProgressIndicator will appear on the button.
The problem is after the tap and the tester.pump(), it can't find the CircularProgressIndicator causing the test to fail, I tried with pumpAndSettle() and also add a Duration(seconds:x) but got the same error
It's weird because the tests were ok before I update the flutter sdk to 1.22.0, upgrade my flutterFire packages and migrate to use the Android embbeding V2.
testWidgets("Should show loading button when click on request button ",
(WidgetTester tester) async {
await tester.pumpWidget(
_buildWidget(
home: FinancialDialogBill(
paymentId: "fakePaymentId",
additionalValueType: AdditionalValueType.fee,
billValues: billValues,
installmentList: installments,
),
),
);
expect(find.byKey(financialDialogBillRequestButton), findsOneWidget);
expect(find.byKey(financialDialogBillRequestButtonLoading), findsNothing);
await tester.tap(find.byKey(financialDialogBillRequestButton));
await tester.pump();
expect(
find.byKey(financialDialogBillRequestButtonLoading), findsOneWidget);
expect(find.byKey(financialDialogBillRequestButton), findsNothing);
});
});
A bit late, but i ran into this issue as well, the shortest workaround i found i just to try/catch the timeout error...
try {
await tester.pumpAndSettle();
} catch (err) {}
expect(find.byKey(financialDialogBillRequestButtonLoading), findsOneWidget);
expect(find.byKey(financialDialogBillRequestButton), findsNothing);
Happy if it can help someone before a better solution is found.

Same code generating different goldens images on different machines

I added a screenshot test for a screen on my flutter app and was adding my project on Circle CI, but for some reason, the image generated on the ci and on my machine are slightly different and the test is failing.
Bellow you can see the snippet of code of the test:
Future<BudgetList> loadState(WidgetTester tester) async {
final screen = BudgetList();
mockBloc = MockBloc();
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.dark(),
home: Provider.value(
value: mockBloc,
child: screen,
),
),
);
return screen;
}
group('When the budget list is open', () {
testWidgets('It should be displayed', (tester) async {
await loadState(tester);
await expectLater(
find.byType(BudgetList),
matchesGoldenFile('screenshots/with-items.png'),
);
});
});
This is the image generated on my machine:
This is the image generated on circleci:
Does someone know how to make sure that the same golden image is generated every time independently of the machine?