Flutter Test: Testing if a checkbox is checked on build
I found the solution.
final checkboxFinder = find.byKey(Key('aKey'));
var checkbox = tester.firstWidget(checkboxFinder) as Checkbox;
expect(checkbox.value, false);
await tester.tap(checkboxFinder);
await tester.pump();
checkbox = tester.firstWidget(checkboxFinder) as Checkbox;
expect(checkbox.value, true);
I think it works the same way with find.byType(Checkbox)
.
Tom Ryan
Updated on December 26, 2022Comments
-
Tom Ryan over 1 year
I have a dynamic form system that builds widgets based on a json. One of the components that can be parsed is a Checkbox and a default value is passed to determine whether or not it is checked/unchecked initially. I'm writing a unit test for this and am running into trouble with semantics.
My test begins with checking the widget has been built (the following test is successful)
//create form await tester.pumpWidget(buildTestableWidget(testWidget)); //setup Finder Finder widgetFinder = find.widgetWithText(FormCheckbox, "test checkbox"); //test for widget expect(widgetFinder, findsOneWidget);
The
FormCheckbox
class is as followsclass FormCheckbox extends StatefulWidget { final forms.Checkbox component; FormCheckbox(this.component) : super(key: Key("${component.propertyKey().getId()}")); _FormCheckboxState createState() => _FormCheckboxState(component); } class _FormCheckboxState extends State<FormCheckbox> { _FormCheckboxState(this._component) { this.boxValue = _component.isDefaultSelected(); } final forms.Checkbox _component; bool boxValue; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(left: 16, right: 16, top: 6, bottom: 6), child: ListTile( leading: Material( child: Checkbox( value: boxValue, onChanged: (bool newValue) { setState(() { boxValue = newValue; }); })), title: Text("${_component.getLabel()}"), )); } String validator(String value) { //TODO: Implement validator throw UnimplementedError(); } }
Which despite everything else, has a
Checkbox
component as a child which defaults to a boolean I can set (which I can confirm is definitely working properly).I would expect, from looking at flutter's own tests for checkboxes here that I can use
getSemantics
and expect it to equal amatchedSemantics
within whichisChecked = true
as shown here//test default value expect( tester.getSemantics(find.byType(Checkbox)), matchesSemantics( isChecked: true, hasEnabledState: true, isEnabled: true, ));
However the isChecked state is remaining as false, even after a tap with
await tester.tap(find.byKey(Key("1")));
The error message given is
Expected: has semantics with actions: [] with flags: [ SemanticsFlag:SemanticsFlag.isChecked, SemanticsFlag:SemanticsFlag.hasEnabledState, SemanticsFlag:SemanticsFlag.isEnabled ] Actual: SemanticsNode:<SemanticsNode#5(Rect.fromLTRB(0.0, 0.0, 800.0, 68.0), tags: [RenderViewport.twoPane], flags: [hasEnabledState, isEnabled], label: "test checkbox", textDirection: ltr)> Which: flags were: [hasEnabledState, isEnabled]
What am I missing here? Why is a created Checkbox object with value: true not giving a semantics value of isChecked = true
-
Jarin Rocks about 2 yearsI t works. But why we have to again create checkbox widget after pumping. //checkbox = tester.firstWidget(checkboxFinder) as Checkbox;
-
lsaudon about 2 yearsThis is to see that the "checkbox" has gone from false to true. @JarinRocks