0

I'm developing flutter integration tests with flutter driver and want to use the semantic labels to find widgets (i.e. find.bySemanticsLabel('my-label')), specifically TextFormFields. However, finding widgets by semantics doesn't work unless I enable the flag showSemanticsDebugger: true, on my MaterialApp. Is there a way to get that to work without having the semantics overlay on?

As a second complication, the driver.tap causes the flutter_driver to filter out non-tappable widgets and for some reason it believes that the text input field is not tappable when selecting it via its semantics label.

I'm using flutter_gherkin to run the tests, but I have debugged the deserialization of the finders and they turn up correctly on the app-side, so I don't think that is part of the problem.

So my questions boil down to:

  1. How can I use find.bySemanticsLabel to select a widget?
  2. How can I tap on a TextFormField when finding it via a semantics label?

This is how I use the driver:

final finder = find.bySemanticsLabel('Your email address');
driver.tap(finder);

Here's a minimal app that shows the problem:

import 'package:flutter/material.dart';
import 'package:flutter_driver/driver_extension.dart';

void main() {
  enableFlutterDriverExtension();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      showSemanticsDebugger: true, // without this, the driver doesn't find the widget
      title: 'Flutter Demo',
      onGenerateRoute: (settings) {
        switch (settings.name) {
          case '/login':
            return MaterialPageRoute(builder: (context) => Login());
        }
      },
      initialRoute: '/login',
    );
  }
}

class Login extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Form(
        child: Column(children: [
          TextFormField(
            decoration: InputDecoration(
              hintText: 'Your email address',
            ),
          ),
          TextFormField(
            decoration: InputDecoration(
              hintText: 'Your password',
            ),
          ),
        ]),
      ),
    );
  }
}

t.animal
  • 3,012
  • 1
  • 24
  • 25
  • I guess the solution is not to use flutter_driver (it has been discontinued anyhow) and use integration_test . – t.animal Jun 10 '22 at 15:45

1 Answers1

0

With your code I would expect that you need to call

final finder =  find.byWidgetPredicate(
 (widget) => widget is TextFormField 
            && widget.decoration?.hintText == 'Your email address');

Alternatively, wrap your field in a Semantics:

Semantics(
  container: true,
  textField: true,
  label: 'loginInputEmail',
  child: TextFormField(
   decoration: InputDecoration(
     hintText: 'Your email address',
   ),
  ),
),

Then you can find your widget using

final emailFinder = find.bySemanticsLabel(RegExp('loginInputEmail'));
robert_enough
  • 371
  • 1
  • 8
  • The `CommonFinders` in flutter_driver doesn't have a `byWidgetPredicate` method. https://api.flutter.dev/flutter/flutter_driver/CommonFinders-class.html – t.animal Jun 10 '22 at 15:44