Flutter widget test tap - would not hit test on the specified widget

Viewed 2963

My widget test is failing after the following warning is outputted:

flutter: Warning: A call to tap() with finder "exactly one widget with text "Tab 2" (ignoring offstage widgets): Text("Tab 2", softWrap: no wrapping except at line break characters, overflow: fade, dependencies: [MediaQuery, DefaultTextStyle])" derived an Offset (Offset(600.0, 23.0)) that would not hit test on the specified widget. flutter: Maybe the widget is actually off-screen, or another widget is obscuring it, or the widget cannot receive pointer events.

The tap is never executed so the next part of the test fails. I put some delays in the test and it appears that the test is attempting to tap the correct widget - it is not offscreen, not obscured, and was able to receive pointer events in the past - not sure why it's currently failing.

Here is a minimal reproducible example:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: TabBar(
            labelColor: Color(0xff8391e4),
            tabs: [
              Tab(text: 'Tab 1'),
              Tab(text: 'Tab 2'),
            ],
          ),
          body: TabBarView(
            children: <Widget>[
              Text('Tab 1 Text'),
              Text('Tab 2 Text'),
            ],
          ),
        ),
      ),
    );
  }
}

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('My Test', (WidgetTester tester) async {
    await tester.pumpWidget(MyApp());
    await tester.pumpAndSettle();

    // Warning thrown on this tap - tap never executed
    await tester.tap(find.text('Tab 2'));
    await tester.pumpAndSettle();

    // Test fails here
    expect(find.text('Tab 2 Text'), findsOneWidget);
  });
}
2 Answers

Try to set ensureVisible() before tap():

// Warning thrown on this tap - tap never executed
await tester.ensureVisible(find.text('Tab 2'));
await tester.tap(find.text('Tab 2'));
await tester.pumpAndSettle();

I found a solution to my problem, but it may not be a universal solution. The app that this test is for is exclusively a web app so it's designed to run on larger screen sizes. When I'd run the test on chrome it would pass, but would fail when run heedlessly.

To fix, I run the test at a larger screen size and it now passes heedlessly. So if you run into the A call to tap() ... that would not hit test on the specified widget error, adjusting the screen size might fix the issue.

  testWidgets('My test', (WidgetTester tester) async {
      // Here we use physicalSizeTestValue to adjust the test screen size to
      // simulate running on a desktop computer which the app was designed for
      tester.binding.window.physicalSizeTestValue = Size(1080, 1920);
      tester.binding.window.devicePixelRatioTestValue = 1.0;
Related