Flutter testing find.byValueKey() for item in drop down menu doesn't work
I recreated your case. Instead of using key
property on DropdownMenuItem
, you need to use it inside it's child, ie, in Text
widget. That way, since the flutter driver will look for text to be selected when dropdown menu is open, the key
property will come into play when menu items are displayed and then easier to click on whatever option we pass in the test. It worked well. Updated working code below:
final List<DropdownMenuItem<String>> _dropDownMenuSigns = menuSigns
.map<DropdownMenuItem<String>>((String value) => DropdownMenuItem<String>(
// key: new ValueKey('sign_$value'),
value: value,
child: new Text(value, key: Key('sign_$value'),), // use key here on text
))
.toList();
driver test:
class AstroSignValidation extends GivenWithWorld<FlutterWorld> {
@override
Future<void> executeStep() async {
await FlutterDriverUtils.getText(world.driver, find.text('Choose a sign'));
await FlutterDriverUtils.tap(world.driver, find.byValueKey('sign_list')); // open drop down menu is ok
await FlutterDriverUtils.tap(world.driver, find.byValueKey('sign_virgo')); // selects sign properly
print('selected sign');
}
RegExp get pattern => RegExp(r"I expect the user enters sign");
}
And test passes :
Note: I directly used Given
statement in feature file and accordingly extended GivenWithWorld
class in my test. You'll need to use it per your needs.
Hope this answers your question.
Michael Bouhier
Updated on December 14, 2022Comments
-
Michael Bouhier 3 minutes
My test doesn't found the item in drop down menu with a value key. It's works with getText() and the value.
I create a dynamic function to fill every items with a value, a child with
Text(value)
and a key withKey('sign_$value_item')
;This is my full form in the app:
static const menuSigns = <String>[ 'aries', 'taurus', 'gemini', 'cancer', 'leo', 'virgo', 'libra', 'scorpio', 'sagittarius', 'capricorn', 'aquarius', 'pisces' ]; final List<DropdownMenuItem<String>> _dropDownMenuSigns = menuSigns .map<DropdownMenuItem<String>>((String value) => DropdownMenuItem<String>( key: new ValueKey('sign_$value_item'), // i even try with new Key('sign_$value') value: value, child: new Text(value), )) .toList(); @override Widget build(BuildContext context) { return Form( key: _formKey, child: Container( margin: EdgeInsets.fromLTRB(_hPad, 16.0, _hPad, 0), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Center( child: Container( padding: EdgeInsets.fromLTRB(0, 0, 0, 16.0), width: CustomTheme.customFormSize.width(context), child: DropdownButton( key: Key('sign_list'), isExpanded: true, value: _sign, style: CustomTheme.style.dropDownMenu(context), hint: Text('Choose a sign'), icon: Icon(Icons.arrow_drop_down_circle), onChanged: ((newValue) { setState(() { _sign = newValue; }); }), items: _dropDownMenuSigns, ), ), ), ], ), ), ); }
And strange things, the test works with the Key if the length of value is very long, for exemple more 10 characters.
This is my test:
import 'package:flutter_driver/flutter_driver.dart'; import 'package:flutter_gherkin/flutter_gherkin.dart'; import 'package:gherkin/gherkin.dart'; class AstroSignValidation extends AndWithWorld<FlutterWorld> { @override Future<void> executeStep() async { await FlutterDriverUtils.getText(world.driver, find.text('AstroDay')); await FlutterDriverUtils.tap(world.driver, find.byValueKey('sign_list')); // open drop down menu is ok await FlutterDriverUtils.tap(world.driver, find.byValueKey('sign_cancer_item')); // here test not passed } RegExp get pattern => RegExp(r"I expect the user enters sign"); }
Edit: This is my feature file :
Feature: Get Astro day User should be able to get successfully his astro after cliking astro button. Scenario: User get astro in successfully Given I expect the "user" 1 sign And I expect the user enters day When user hits Show your astro button Then user should land on result screen