What are the possible reasons why a widget isn't found by key in a test, even if it's in the widget tree?
So in my app, I have some categories of websites and each category has a + button so users can add their own. Now, I want to test that the page opens correctly when the + button is pressed. If I just do:
await tester.tap(find.byIcon(Icons.add));
The test fails because it finds too many widgets and doesn't know which one to tap. So I figured I'd give keys to my + buttons by wrapping them in a container like this:
Container(
key: ValueKey('add_website_' + category.toLowerCase()),
child: AddWebsiteButton(), // the tappable widget that contains an Icon(Icons.add)
)
Now in my test, I call:
expect(find.byKey(ValueKey('add_website_learning')), findsOneWidget);
And, lo and behold, it fails:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _KeyFinder:<zero widgets with key [<'add_website_learning'>] (ignoring offstage widgets)>
Which: means none were found but one was expected
If I call debugDumpApp() just before the call above, I can see that the Container with that key is actually in the widget tree:
...
└KeyedSubtree-[Key <[<add_website_learning>]>]
└AutomaticKeepAlive(state: _AutomaticKeepAliveState#470b4(handles: no notifications ever received))
└KeepAlive(keepAlive: false)
└NotificationListener<KeepAliveNotification>
└IndexedSemantics(index: 4, renderObject: RenderIndexedSemantics#02bbd relayoutBoundary=up3 NEEDS-PAINT)
└RepaintBoundary(renderObject: RenderRepaintBoundary#8170e relayoutBoundary=up4 NEEDS-PAINT)
└Container-[<add_website_learning>]
└Tooltip("Add website", dependencies: [_LocalizationsScope-[GlobalKey#55b7a], _InheritedTheme, TickerMode-[<CrossFadeState.showSecond>]], state: _TooltipState#87315(ticker inactive))
└GestureDetector(startBehavior: start)
...
I tried making sure it's in view by calling ensureVisible, but that also fails saying it can't find the widget.
What am I doing wrong?