I experience flakiness in my flutter driver tests.
The following code:
await driver.tap(find.byValueKey('first-name-field'));
await driver.enterText('');
await Future.delayed(Duration(milliseconds: 17), () {});
expect(
await driver.getText(find.byValueKey('first-name-error')),
equals('Field can't be empty.'),
);
await driver.enterText('$#@');
await Future.delayed(Duration(milliseconds: 17), () {});
expect(
await driver.getText(find.byValueKey('first-name-error')),
equals('Field contains unsupported characters.'),
);
await driver.enterText('Chris');
await Future.delayed(Duration(milliseconds: 17), () {});
await driver.waitForAbsent('first-name-error');
It has about 90% success rate, however 10% of the times I'm expecting "Field contains unsupported characters.", but I still have "Field can't be empty".
How the code works - TextEditingController listener is reporting change to ViewModel. ViewModel has a stream that provides error as string or null, View uses StreamBuilder to display error label or hide it.
To mitigate this issue I introduced a single frame delay (17 miliseconds) - it helped a bit, but still is flaky. I could extend the delay, but this comes with the cost of slower tests. I found a method that should make this test better:
await driver.waitFor(find.text('Field can't be empty.!'))
However, I don't want just to find any text on the screen, I want to inspect specifically first-name-error, as there is also last-name-error on the same screen.