This might get tricky due to datePicker
implementation and design changes that go in time.
Sometimes Material Design specification can change and the underlying Widget
s for datePicker
can be modified too.
We want to extract the current Widget
so we can manipulate them.
The current date picker looks like this:
We clearly see that we can try couple approaches here for setting dates:
- either click the edit button and go to the input mode
- try < > arrows to change months -1/+1
- select a day
- click April 2022 and pick a year
For the current state of knowledge the datePicker
code looks like this:
date picker test source code.
What is interesting for us are those parts of code (Finder
s) that Flutter team uses to manipulate this datePicker
. Couple of them are:
final Finder nextMonthIcon = find.byWidgetPredicate((Widget w) => w is IconButton && (w.tooltip?.startsWith('Next month') ?? false));
final Finder previousMonthIcon = find.byWidgetPredicate((Widget w) => w is IconButton && (w.tooltip?.startsWith('Previous month') ?? false));
final Finder switchToInputIcon = find.byIcon(Icons.edit);
So the Flutter team uses those Finder
s to manipulate this date picker and we should find an approach to set the whole date (day, month and year) in a predictable and reliable manner.
Warning!
Do remember that your instrumented test can be in a different language so you might localise your 'Next month' or 'Previous month'. Or you can search for those texts in the test debug console with the help of: find.byWidgetPredicate((Widget w) => w is IconButton)
. You will get couple results and you can browse them.
Another warning!
Using month change arrows for setting the date (or setting only a part of the date i.e. just a day) is dangerous as the widget shows the current date. If you were to run this test a day/month/year after, you can land into wrong results, especially when your tests have code like: Make two taps on "<" arrow.
Hence, I am suggesting switching to the input mode and hardcoding the date so you get predictable test runs in the future.
To sum it up, here's the whole example. I am using edit mode and hardcoding the date.
Full code for PL locale:
// switch to edit mode. Using Icons.edit did not work
// hence I manually found it with the help of tooltip text
final Finder switchToInputIcon = find.byWidgetPredicate((Widget w) =>
w is IconButton && (w.tooltip == 'Przełącz na wpisywanie'));
await tester.tap(switchToInputIcon);
await tester.pumpAndSettle();
// I know that the widget starts with the current date
// so I obtain the EditableText with the help of current year value finder
var currentDt = DateTime.now();
final EditableText input = tester.widget<EditableText>(find.textContaining(currentDt.year.toString()).first);
// I am hardcoding the date.
// This is for PL locale. For example for US you would need something like: 06/21/2024
input.controller.text = "21.06.2024";
await tester.pumpAndSettle();
// Confirm the date dialog and close it
// "OK" might be different in other languages
await tester.tap(find.text('OK'));
await tester.pumpAndSettle();