How to find an Element without a key

1.5k views Asked by At

i'm still new in using flutter driver in testing, but as far as i know there are few identifiers that we can use to locate / identify elements, like By Text, By Type, etc

But the problem is, the app that i want to test doesn't have the identifier that i can use to locate them (please correct me if i'm wrong).. the widget code of the app looks like this

  Widget _buildNextButton() {
    return Align(
      alignment: Alignment.bottomRight,
      child: Container(
        child: IconButton(
          icon: Icon(Icons.arrow_forward),
          onPressed: () => _controller.nextPage(),
        ),
      ),
    );
  }

where that widget is on a class that extends StatefulWidget.

How can i locate that icon in my test script and click it? can i use something like this? And what type of finder should i use? (byValueKey? bySemanticLabel? byType? or what?)

static final arrowKey = find.byValueKey(LoginKey.nextButton);
TestDriverUtil.tap(driver, arrowKey);
2

There are 2 answers

4
Parth Dave On BEST ANSWER

We have text and value checks here in Flutter Driver but if you don't have that you can always go the the hierarchy of app. what I mean by hierarchy is so button has fix or specific parent right?

Let's take your example here, We have Align > Container > IconButton > Icon widget hierarchy which will not be true for others like there might be IconButton but not with the Container parent. or StreamBuilder or anything that we can think of.

Widget _buildNextButton() {
    return Align(
      alignment: Alignment.bottomRight,
      child: Container(
        child: IconButton(
          icon: Icon(Icons.arrow_forward),
          onPressed: () => print("clicked button"),
        ),
      ),
    );
  }

This hierarchy should be at least ideal for top bottom or bottom top approach.

Now what I mean by Top to bottom approach is Align must have IconButton and for bottom to up approach we are saying IconButton must have Align widget as parent.

Here i have taken top down approach so what I'm checking from below code is finding IconButton who is decendent of Align Widget. also i added firstMatchOnly true as I was checking what happens if same hierarchy appears for both so

test('IconButton find and tap test', () async {
  var findIconButton = find.descendant(of: find.byType("Align"), matching: find.byType("IconButton"), firstMatchOnly: true);
  await driver.waitFor(findIconButton);
  await driver.tap(findIconButton);

  await Future.delayed(Duration(seconds: 3));
});

to check for multiple IconButtons with same Align as parent, we need to have some difference like parent should be having Text view or other widget.

find.descendant(of: find.ancestor(
                  of: find.byValue("somevalue"),
                  matching: find.byType("CustomWidgetClass")), matching: find.byType("IconButton"), firstMatchOnly: true)

usually I go something like above where I have split the code in seperate file and check for that widget.

But ultimately find something unique about that widget and you can work on that.

4
Nadeem Abbas On
**In Lib directory dart class for connecting that widget**

class Testing extends StatelessWidget {

  Testing();

  // This widget is the root of your application.
  Widget build(BuildContext context) {

    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: YourClass(), // Next button containing class that need to test
    );
  }
}

**In Test directory**

testWidgets('Next widget field test', (WidgetTester tester) async {

      // Build our app and trigger a frame.
      await tester.pumpWidget(Testing());
      // find Widget
      var buttonFind = find.byIcon(Icons.arrow_forward);
      expect(buttonFind, findsOneWidget);

      IconButton iconButton = tester.firstWidget(buttonFind);
      expect(iconButton.color, Colors.blue);
    });